mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge m-c to b2g-inbound
This commit is contained in:
commit
f0fc43923a
@ -79,6 +79,9 @@ TextAttrsMgr::GetAttributes(nsIPersistentProperties* aAttributes,
|
||||
if (mOffsetAcc) {
|
||||
offsetNode = mOffsetAcc->GetContent();
|
||||
offsetElm = nsCoreUtils::GetDOMElementFor(offsetNode);
|
||||
NS_ASSERTION(offsetElm, "No element for offset accessible!");
|
||||
if (!offsetElm)
|
||||
return;
|
||||
frame = offsetElm->GetPrimaryFrame();
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,12 @@ XPCOMUtils.defineLazyGetter(this, 'WebConsoleUtils', function() {
|
||||
return devtools.require("devtools/toolkit/webconsole/utils").Utils;
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, 'EventLoopLagFront', function() {
|
||||
const {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
return devtools.require("devtools/server/actors/eventlooplag").EventLoopLagFront;
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* The Widget Panel is an on-device developer tool that displays widgets,
|
||||
* showing visual debug information about apps. Each widget corresponds to a
|
||||
@ -358,4 +364,67 @@ let consoleWatcher = {
|
||||
return source;
|
||||
}
|
||||
};
|
||||
|
||||
devtoolsWidgetPanel.registerWatcher(consoleWatcher);
|
||||
|
||||
|
||||
let jankWatcher = {
|
||||
_client: null,
|
||||
_fronts: new Map(),
|
||||
_active: false,
|
||||
|
||||
init: function(client) {
|
||||
this._client = client;
|
||||
|
||||
SettingsListener.observe('devtools.hud.jank', false,
|
||||
this.settingsListener.bind(this));
|
||||
},
|
||||
|
||||
settingsListener: function(value) {
|
||||
if (this._active == value) {
|
||||
return;
|
||||
}
|
||||
this._active = value;
|
||||
|
||||
// Toggle the state of existing fronts.
|
||||
let fronts = this._fronts;
|
||||
for (let app of fronts.keys()) {
|
||||
if (value) {
|
||||
fronts.get(app).start();
|
||||
} else {
|
||||
fronts.get(app).stop();
|
||||
app.metrics.set('jank', 0);
|
||||
app.display();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
trackApp: function(app) {
|
||||
app.metrics.set('jank', 0);
|
||||
|
||||
let front = new EventLoopLagFront(this._client, app.actor);
|
||||
this._fronts.set(app, front);
|
||||
|
||||
front.on('event-loop-lag', time => {
|
||||
app.metrics.set('jank', time);
|
||||
|
||||
if (!app.display()) {
|
||||
devtoolsWidgetPanel.log('jank: ' + time + 'ms');
|
||||
}
|
||||
});
|
||||
|
||||
if (this._active) {
|
||||
front.start();
|
||||
}
|
||||
},
|
||||
|
||||
untrackApp: function(app) {
|
||||
let fronts = this._fronts;
|
||||
if (fronts.has(app)) {
|
||||
fronts.get(app).destroy();
|
||||
fronts.delete(app);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
devtoolsWidgetPanel.registerWatcher(jankWatcher);
|
||||
|
@ -50,6 +50,9 @@
|
||||
<command id="cmd_findPrevious"
|
||||
oncommand="gFindBar.onFindAgainCommand(true);"
|
||||
observes="isImage"/>
|
||||
#ifdef XP_MACOSX
|
||||
<command id="cmd_findSelection" oncommand="gFindBar.onFindSelectionCommand();"/>
|
||||
#endif
|
||||
<!-- work-around bug 392512 -->
|
||||
<command id="Browser:AddBookmarkAs"
|
||||
oncommand="PlacesCommandHook.bookmarkCurrentPage(true, PlacesUtils.bookmarksMenuFolderId);"/>
|
||||
@ -350,6 +353,9 @@
|
||||
<key id="key_find" key="&findOnCmd.commandkey;" command="cmd_find" modifiers="accel"/>
|
||||
<key id="key_findAgain" key="&findAgainCmd.commandkey;" command="cmd_findAgain" modifiers="accel"/>
|
||||
<key id="key_findPrevious" key="&findAgainCmd.commandkey;" command="cmd_findPrevious" modifiers="accel,shift"/>
|
||||
#ifdef XP_MACOSX
|
||||
<key id="key_findSelection" key="&findSelectionCmd.commandkey;" command="cmd_findSelection" modifiers="accel"/>
|
||||
#endif
|
||||
<key keycode="&findAgainCmd.commandkey2;" command="cmd_findAgain"/>
|
||||
<key keycode="&findAgainCmd.commandkey2;" command="cmd_findPrevious" modifiers="shift"/>
|
||||
|
||||
|
@ -3037,17 +3037,7 @@
|
||||
filter.addProgressListener(tabListener, nsIWebProgress.NOTIFY_ALL);
|
||||
this.mTabListeners[0] = tabListener;
|
||||
this.mTabFilters[0] = filter;
|
||||
|
||||
try {
|
||||
// We assume this can only fail because mCurrentBrowser's docShell
|
||||
// hasn't been created, yet. This may be caused by code accessing
|
||||
// gBrowser before the window has finished loading.
|
||||
this._addProgressListenerForInitialTab();
|
||||
} catch (e) {
|
||||
// The binding was constructed too early, wait until the initial
|
||||
// tab's document is ready, then add the progress listener.
|
||||
this._waitForInitialContentDocument();
|
||||
}
|
||||
this.webProgress.addProgressListener(filter, nsIWebProgress.NOTIFY_ALL);
|
||||
|
||||
this.style.backgroundColor =
|
||||
Services.prefs.getBoolPref("browser.display.use_system_colors") ?
|
||||
@ -3083,31 +3073,6 @@
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="_addProgressListenerForInitialTab">
|
||||
<body><![CDATA[
|
||||
this.webProgress.addProgressListener(this.mTabFilters[0], Ci.nsIWebProgress.NOTIFY_ALL);
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="_waitForInitialContentDocument">
|
||||
<body><![CDATA[
|
||||
let obs = (subject, topic) => {
|
||||
if (this.browsers[0].contentWindow == subject) {
|
||||
Services.obs.removeObserver(obs, topic);
|
||||
this._addProgressListenerForInitialTab();
|
||||
}
|
||||
};
|
||||
|
||||
// We use content-document-global-created as an approximation for
|
||||
// "docShell is initialized". We can do this because in the
|
||||
// mTabProgressListener we care most about the STATE_STOP notification
|
||||
// that will reset mBlank. That means it's important to at least add
|
||||
// the progress listener before the initial about:blank load stops
|
||||
// if we can't do it before the load starts.
|
||||
Services.obs.addObserver(obs, "content-document-global-created", false);
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<destructor>
|
||||
<![CDATA[
|
||||
for (var i = 0; i < this.mTabListeners.length; ++i) {
|
||||
|
@ -11,6 +11,9 @@ let texts = [
|
||||
"To err is human; to forgive is not company policy."
|
||||
];
|
||||
|
||||
let Clipboard = Cc["@mozilla.org/widget/clipboard;1"].getService(Ci.nsIClipboard);
|
||||
let HasFindClipboard = Clipboard.supportsFindClipboard();
|
||||
|
||||
function addTabWithText(aText, aCallback) {
|
||||
let newTab = gBrowser.addTab("data:text/html,<h1 id='h1'>" + aText + "</h1>");
|
||||
tabs.push(newTab);
|
||||
@ -61,7 +64,9 @@ function continueTests1() {
|
||||
// Confirm the first tab is still correct, ensure re-hiding works as expected
|
||||
gBrowser.selectedTab = tabs[0];
|
||||
ok(!gFindBar.hidden, "First tab shows find bar!");
|
||||
is(gFindBar._findField.value, texts[0], "First tab persists find value!");
|
||||
// When the Find Clipboard is supported, this test not relevant.
|
||||
if (!HasFindClipboard)
|
||||
is(gFindBar._findField.value, texts[0], "First tab persists find value!");
|
||||
ok(gFindBar.getElement("highlight").checked,
|
||||
"Highlight button state persists!");
|
||||
|
||||
@ -94,7 +99,8 @@ function continueTests2() {
|
||||
ok(gFindBar.hidden, "Fourth tab doesn't show find bar!");
|
||||
is(gFindBar, gBrowser.getFindBar(), "Find bar is right one!");
|
||||
gFindBar.open();
|
||||
is(gFindBar._findField.value, texts[1],
|
||||
let toTest = HasFindClipboard ? texts[2] : texts[1];
|
||||
is(gFindBar._findField.value, toTest,
|
||||
"Fourth tab has second tab's find value!");
|
||||
|
||||
newWindow = gBrowser.replaceTabWithWindow(tabs.pop());
|
||||
@ -104,7 +110,8 @@ function continueTests2() {
|
||||
// Test that findbar gets restored when a tab is moved to a new window.
|
||||
function checkNewWindow() {
|
||||
ok(!newWindow.gFindBar.hidden, "New window shows find bar!");
|
||||
is(newWindow.gFindBar._findField.value, texts[1],
|
||||
let toTest = HasFindClipboard ? texts[2] : texts[1];
|
||||
is(newWindow.gFindBar._findField.value, toTest,
|
||||
"New window find bar has correct find value!");
|
||||
ok(!newWindow.gFindBar.getElement("find-next").disabled,
|
||||
"New window findbar has enabled buttons!");
|
||||
|
@ -2,7 +2,10 @@
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
let Ci = Components.interfaces;
|
||||
const {Ci: interfaces, Cc: classes} = Components;
|
||||
|
||||
let Clipboard = Cc["@mozilla.org/widget/clipboard;1"].getService(Ci.nsIClipboard);
|
||||
let HasFindClipboard = Clipboard.supportsFindClipboard();
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
@ -37,7 +40,10 @@ function onFocus(win) {
|
||||
let findBar = win.gFindBar;
|
||||
selectText(win.content);
|
||||
findBar.onFindCommand();
|
||||
is(findBar._findField.value, "Select Me", "Findbar is initialized with selection");
|
||||
// When the OS supports the Find Clipboard (OSX), the find field value is
|
||||
// persisted across Fx sessions, thus not useful to test.
|
||||
if (!HasFindClipboard)
|
||||
is(findBar._findField.value, "Select Me", "Findbar is initialized with selection");
|
||||
findBar.close();
|
||||
win.close();
|
||||
finish();
|
||||
|
@ -614,6 +614,7 @@ you can use these alternative items. Otherwise, their values should be empty. -
|
||||
<!ENTITY findAgainCmd.accesskey "g">
|
||||
<!ENTITY findAgainCmd.commandkey "g">
|
||||
<!ENTITY findAgainCmd.commandkey2 "VK_F3">
|
||||
<!ENTITY findSelectionCmd.commandkey "e">
|
||||
|
||||
<!ENTITY spellAddDictionaries.label "Add Dictionaries…">
|
||||
<!ENTITY spellAddDictionaries.accesskey "A">
|
||||
|
@ -2434,11 +2434,11 @@ richlistitem[type~="action"][actiontype="switchtab"][selected="true"] > .ac-url-
|
||||
.panel-promo-box {
|
||||
margin: 8px -16px -16px -16px;
|
||||
padding: 8px 16px;
|
||||
background: #e5e5e5;
|
||||
border-top: 1px solid hsla(0,0%,0%,.1);
|
||||
background-color: hsla(210,4%,10%,.07);
|
||||
border-top: 1px solid hsla(210,4%,10%,.12);
|
||||
border-radius: 0 0 5px 5px;
|
||||
box-shadow: 0 -1px hsla(0,0%,100%,.5) inset, 0 1px 1px hsla(0,0%,0%,.03) inset;
|
||||
color: #808080;
|
||||
color: hsl(0,0%,30%);
|
||||
}
|
||||
|
||||
.panel-promo-icon {
|
||||
@ -3214,6 +3214,10 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
|
||||
}
|
||||
}
|
||||
|
||||
#identity-popup {
|
||||
margin-top: 1px;
|
||||
}
|
||||
|
||||
#identity-popup > .panel-arrowcontainer > .panel-arrowcontent {
|
||||
padding: 0;
|
||||
}
|
||||
@ -3223,7 +3227,8 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
|
||||
}
|
||||
|
||||
#identity-popup-button-container {
|
||||
background: linear-gradient(to bottom, rgba(0,0,0,0.04) 60%, transparent);
|
||||
background-color: hsla(210,4%,10%,.07);
|
||||
border-top: 1px solid hsla(210,4%,10%,.12);
|
||||
padding: 16px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
@ -4022,7 +4027,6 @@ toolbar[mode="icons"] > *|* > .toolbarbutton-badge[badge]:not([badge=""]):-moz-l
|
||||
}
|
||||
|
||||
#social-share-panel {
|
||||
margin-top: 3px;
|
||||
max-height: 600px;
|
||||
min-height: 100px;
|
||||
max-width: 800px;
|
||||
|
@ -4,6 +4,10 @@
|
||||
|
||||
/*** Panel and outer controls ***/
|
||||
|
||||
#downloadsPanel {
|
||||
margin-top: -1px;
|
||||
}
|
||||
|
||||
#downloadsPanel > .panel-arrowcontainer > .panel-arrowcontent {
|
||||
padding: 0;
|
||||
}
|
||||
@ -19,8 +23,8 @@
|
||||
}
|
||||
|
||||
#downloadsFooter {
|
||||
border-bottom-left-radius: 6px;
|
||||
border-bottom-right-radius: 6px;
|
||||
border-bottom-left-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
}
|
||||
|
||||
#downloadsHistory {
|
||||
@ -29,11 +33,6 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#downloadsPanel:not([hasdownloads]) > #downloadsFooter > #downloadsHistory {
|
||||
border-top-left-radius: 6px;
|
||||
border-top-right-radius: 6px;
|
||||
}
|
||||
|
||||
#downloadsPanel[hasdownloads] > #downloadsFooter {
|
||||
background: #e5e5e5;
|
||||
border-top: 1px solid hsla(0,0%,0%,.1);
|
||||
@ -49,18 +48,13 @@
|
||||
#downloadsPanel[keyfocus] > #downloadsFooter > #downloadsHistory:focus {
|
||||
outline: 2px -moz-mac-focusring solid;
|
||||
outline-offset: -2px;
|
||||
-moz-outline-radius-bottomleft: 5px;
|
||||
-moz-outline-radius-bottomright: 5px;
|
||||
-moz-outline-radius-bottomleft: 4px;
|
||||
-moz-outline-radius-bottomright: 4px;
|
||||
}
|
||||
|
||||
#downloadsPanel:not([hasdownloads]) > #downloadsFooter > #downloadsHistory:focus {
|
||||
-moz-outline-radius-topleft: 5px;
|
||||
-moz-outline-radius-topright: 5px;
|
||||
}
|
||||
|
||||
#downloadsPanel:not([hasdownloads]) > #downloadsFooter > #downloadsHistory:focus > .button-box {
|
||||
border-bottom-left-radius: 6px;
|
||||
border-bottom-right-radius: 6px;
|
||||
-moz-outline-radius-topleft: 4px;
|
||||
-moz-outline-radius-topright: 4px;
|
||||
}
|
||||
|
||||
/*** Downloads Summary and List items ***/
|
||||
|
@ -30,11 +30,10 @@
|
||||
padding: 4px;
|
||||
background-color: hsla(0,0%,100%,.97);
|
||||
background-clip: padding-box;
|
||||
border-right: 1px solid hsla(210,4%,10%,.2);
|
||||
border-left: 1px solid hsla(210,4%,10%,.2);
|
||||
border-left: 1px solid hsla(210,4%,10%,.3);
|
||||
box-shadow: 0 3px 5px hsla(210,4%,10%,.1),
|
||||
0 0 7px hsla(210,4%,10%,.1);
|
||||
color: #222426;
|
||||
color: hsl(0,0%,15%);
|
||||
-moz-margin-start: @exitSubviewGutterWidth@;
|
||||
}
|
||||
|
||||
@ -68,19 +67,13 @@
|
||||
.panel-subview-header,
|
||||
.subviewbutton.panel-subview-footer {
|
||||
padding: 12px;
|
||||
background-color: hsla(210,4%,10%,.04);
|
||||
}
|
||||
|
||||
.panel-subview-header {
|
||||
margin: -4px -4px 4px;
|
||||
box-shadow: 0 -1px 0 hsla(210,4%,10%,.08) inset;
|
||||
color: #797c80;
|
||||
}
|
||||
|
||||
.subviewbutton.panel-subview-footer {
|
||||
margin: 4px -4px -4px;
|
||||
box-shadow: 0 1px 0 hsla(210,4%,10%,.08) inset;
|
||||
border-radius: 0;
|
||||
background-color: hsla(210,4%,10%,.05);
|
||||
box-shadow: 0 -1px 0 hsla(210,4%,10%,.05) inset;
|
||||
color: hsl(0,0%,50%);
|
||||
}
|
||||
|
||||
.cui-widget-panelview .panel-subview-header {
|
||||
@ -201,8 +194,8 @@ toolbaritem[cui-areatype="menu-panel"][sdkstylewidget="true"]:not(.panel-wide-it
|
||||
}
|
||||
|
||||
/* Help SDK buttons fit in. */
|
||||
toolbarpaletteitem[place="palette"] > toolbarbutton[sdk-button="true"] > .toolbarbutton-icon,
|
||||
toolbarbutton[sdk-button="true"][cui-areatype="menu-panel"] > .toolbarbutton-icon {
|
||||
toolbarpaletteitem[place="palette"] > #personal-bookmarks > #bookmarks-toolbar-placeholder,
|
||||
#personal-bookmarks[cui-areatype="menu-panel"] > #bookmarks-toolbar-placeholder {
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
}
|
||||
@ -320,20 +313,19 @@ toolbarpaletteitem[place="palette"] > toolbaritem > toolbarbutton {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
flex-direction: column;
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
box-shadow: 0 -1px 0 rgba(0,0,0,.15);
|
||||
background-color: hsla(210,4%,10%,.07);
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#PanelUI-footer-inner {
|
||||
display: flex;
|
||||
box-shadow: 0 -1px 0 rgba(0,0,0,.15);
|
||||
border-top: 1px solid hsla(210,4%,10%,.14);
|
||||
}
|
||||
|
||||
#PanelUI-footer-inner > toolbarseparator {
|
||||
border: 0;
|
||||
border-left: 1px solid rgba(0,0,0,0.1);
|
||||
border-left: 1px solid hsla(210,4%,10%,.14);
|
||||
margin: 7px 0 7px;
|
||||
-moz-appearance: none;
|
||||
}
|
||||
@ -352,15 +344,16 @@ toolbarpaletteitem[place="palette"] > toolbaritem > toolbarbutton {
|
||||
-moz-appearance: none;
|
||||
box-shadow: none;
|
||||
background-image: none;
|
||||
border: 1px solid transparent;
|
||||
border-bottom-style: none;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
transition: background-color;
|
||||
-moz-box-orient: horizontal;
|
||||
}
|
||||
|
||||
#PanelUI-fxa-status {
|
||||
border-bottom-style: solid;
|
||||
border-top: 1px solid hsla(210,4%,10%,.14);
|
||||
border-bottom: 1px solid transparent;
|
||||
margin-bottom: -1px;
|
||||
}
|
||||
|
||||
#PanelUI-fxa-status > .toolbarbutton-text {
|
||||
@ -451,18 +444,26 @@ toolbarpaletteitem[place="palette"] > toolbaritem > toolbarbutton {
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
#PanelUI-fxa-status:not([disabled]):hover,
|
||||
#PanelUI-help:not([disabled]):hover,
|
||||
#PanelUI-customize:hover,
|
||||
#PanelUI-quit:not([disabled]):hover {
|
||||
outline: 1px solid rgba(0,0,0,0.1);
|
||||
background-color: rgba(0,0,0,0.1);
|
||||
box-shadow: none;
|
||||
outline: 1px solid hsla(210,4%,10%,.07);
|
||||
background-color: hsla(210,4%,10%,.07);
|
||||
}
|
||||
|
||||
#PanelUI-fxa-status:not([disabled]):hover {
|
||||
background-color: rgba(0,0,0,0.1);
|
||||
border-bottom-color: rgba(0,0,0,0.1);
|
||||
box-shadow: 0 -1px 0 rgba(0,0,0,0.2);
|
||||
#PanelUI-fxa-status:not([disabled]):hover:active,
|
||||
#PanelUI-help:not([disabled]):hover:active,
|
||||
#PanelUI-customize:hover:active,
|
||||
#PanelUI-quit:not([disabled]):hover:active {
|
||||
outline: 1px solid hsla(210,4%,10%,.12);
|
||||
background-color: hsla(210,4%,10%,.12);
|
||||
box-shadow: 0 1px 0 hsla(210,4%,10%,.05) inset;
|
||||
}
|
||||
|
||||
#PanelUI-fxa-status:not([disabled]):hover,
|
||||
#PanelUI-fxa-status:not([disabled]):hover:active {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
#PanelUI-quit:not([disabled]):hover {
|
||||
@ -472,6 +473,7 @@ toolbarpaletteitem[place="palette"] > toolbaritem > toolbarbutton {
|
||||
|
||||
#PanelUI-quit:not([disabled]):hover:active {
|
||||
background-color: #ad3434;
|
||||
outline-color: #992e2e;
|
||||
}
|
||||
|
||||
#customization-panelHolder #PanelUI-customize {
|
||||
@ -552,12 +554,12 @@ panelview .toolbarbutton-1@buttonStateHover@,
|
||||
#edit-controls@inAnyPanel@ > toolbarbutton@buttonStateHover@,
|
||||
#zoom-controls@inAnyPanel@ > toolbarbutton@buttonStateHover@ {
|
||||
background-color: hsla(210,4%,10%,.08);
|
||||
border-color: hsla(210,4%,10%,.1);
|
||||
border-color: hsla(210,4%,10%,.11);
|
||||
}
|
||||
|
||||
#edit-controls@inAnyPanel@@buttonStateHover@,
|
||||
#zoom-controls@inAnyPanel@@buttonStateHover@ {
|
||||
border-color: hsla(210,4%,10%,.1);
|
||||
border-color: hsla(210,4%,10%,.11);
|
||||
}
|
||||
|
||||
panelview .toolbarbutton-1@buttonStateActive@,
|
||||
@ -565,9 +567,28 @@ panelview .toolbarbutton-1@buttonStateActive@,
|
||||
.widget-overflow-list .toolbarbutton-1@buttonStateActive@,
|
||||
#edit-controls@inAnyPanel@ > toolbarbutton@buttonStateActive@,
|
||||
#zoom-controls@inAnyPanel@ > toolbarbutton@buttonStateActive@ {
|
||||
background-color: hsla(210,4%,10%,.12);
|
||||
border-color: hsla(210,4%,10%,.14);
|
||||
box-shadow: 0 1px 0 hsla(210,4%,10%,.03) inset;
|
||||
}
|
||||
|
||||
.subviewbutton.panel-subview-footer {
|
||||
margin: 4px -4px -4px;
|
||||
background-color: hsla(210,4%,10%,.07);
|
||||
border-top: 1px solid hsla(210,4%,10%,.12);
|
||||
border-radius: 0;
|
||||
color: hsl(0,0%,25%)
|
||||
}
|
||||
|
||||
.subviewbutton.panel-subview-footer@buttonStateHover@ {
|
||||
background-color: hsla(210,4%,10%,.1);
|
||||
border-top: 1px solid hsla(210,4%,10%,.12);
|
||||
}
|
||||
|
||||
.subviewbutton.panel-subview-footer@buttonStateActive@ {
|
||||
background-color: hsla(210,4%,10%,.15);
|
||||
border-color: hsla(210,4%,10%,.15);
|
||||
box-shadow: 0 1px 0 0 hsla(210,4%,10%,.05) inset;
|
||||
border-top: 1px solid hsla(210,4%,10%,.12);
|
||||
box-shadow: 0 1px 0 hsla(210,4%,10%,.05) inset;
|
||||
}
|
||||
|
||||
#BMB_bookmarksPopup > .subviewbutton {
|
||||
|
@ -175,12 +175,6 @@
|
||||
box-shadow: 0 0 0 1px rgba(0,0,0,0.5);
|
||||
}
|
||||
|
||||
.variables-view-scope:focus > .title,
|
||||
.variable-or-property:focus > .title {
|
||||
background: #3689b2; /* fg-color2 */
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* CodeMirror specific styles.
|
||||
* Best effort to match the existing theme, some of the colors
|
||||
* are duplicated here to prevent weirdness in the main theme. */
|
||||
|
@ -174,12 +174,6 @@
|
||||
box-shadow: 0 0 0 1px #EFEFEF;
|
||||
}
|
||||
|
||||
.variables-view-scope:focus > .title,
|
||||
.variable-or-property:focus > .title {
|
||||
background: #4c9ed9; /* fg-color2 */
|
||||
color: #f5f7fa;
|
||||
}
|
||||
|
||||
/* CodeMirror specific styles.
|
||||
* Best effort to match the existing theme, some of the colors
|
||||
* are duplicated here to prevent weirdness in the main theme. */
|
||||
|
@ -561,6 +561,18 @@
|
||||
color: #585959; /* Grey foreground text */
|
||||
}
|
||||
|
||||
.theme-dark .variables-view-scope:focus > .title,
|
||||
.theme-dark .variable-or-property:focus > .title {
|
||||
background-color: #1d4f73; /* Selection colors */
|
||||
color: #f5f7fa;
|
||||
}
|
||||
|
||||
.theme-light .variables-view-scope:focus > .title,
|
||||
.theme-light .variable-or-property:focus > .title {
|
||||
background-color: #4c9ed9; /* Selection colors */
|
||||
color: #f5f7fa;
|
||||
}
|
||||
|
||||
.variables-view-scope > .title {
|
||||
border-top-width: 1px;
|
||||
border-top-style: solid;
|
||||
|
@ -26,7 +26,8 @@
|
||||
}
|
||||
|
||||
.click-to-play-plugins-notification-button-container {
|
||||
background: linear-gradient(rgba(0,0,0,0.04) 60%, transparent);
|
||||
background-color: hsla(210,4%,10%,.07);
|
||||
border-top: 1px solid hsla(210,4%,10%,.12);
|
||||
padding: 10px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
@ -11,7 +11,9 @@
|
||||
#include "ImageContainer.h"
|
||||
#include "ImageTypes.h"
|
||||
#include "prmem.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
#include "nsIFilePicker.h"
|
||||
#include "nsIPrefService.h"
|
||||
#include "nsIPrefBranch.h"
|
||||
|
||||
@ -164,18 +166,38 @@ MediaEngineDefaultVideoSource::Snapshot(uint32_t aDuration, nsIDOMFile** aFile)
|
||||
#ifndef MOZ_WIDGET_ANDROID
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
#else
|
||||
if (!AndroidBridge::Bridge()) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
nsAutoString filePath;
|
||||
nsCOMPtr<nsIFilePicker> filePicker = do_CreateInstance("@mozilla.org/filepicker;1");
|
||||
if (!filePicker)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsXPIDLString title;
|
||||
nsContentUtils::GetLocalizedString(nsContentUtils::eFORMS_PROPERTIES, "Browse", title);
|
||||
int16_t mode = static_cast<int16_t>(nsIFilePicker::modeOpen);
|
||||
|
||||
nsresult rv = filePicker->Init(nullptr, title, mode);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
filePicker->AppendFilters(nsIFilePicker::filterImages);
|
||||
|
||||
// XXX - This API should be made async
|
||||
PRInt16 dialogReturn;
|
||||
rv = filePicker->Show(&dialogReturn);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (dialogReturn == nsIFilePicker::returnCancel) {
|
||||
*aFile = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsAutoString filePath;
|
||||
AndroidBridge::Bridge()->ShowFilePickerForMimeType(filePath, NS_LITERAL_STRING("image/*"));
|
||||
nsCOMPtr<nsIFile> localFile;
|
||||
filePicker->GetFile(getter_AddRefs(localFile));
|
||||
|
||||
nsCOMPtr<nsIFile> file;
|
||||
nsresult rv = NS_NewLocalFile(filePath, false, getter_AddRefs(file));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!localFile) {
|
||||
*aFile = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_ADDREF(*aFile = new nsDOMFileFile(file));
|
||||
nsCOMPtr<nsIDOMFile> domFile = new nsDOMFileFile(localFile);
|
||||
domFile.forget(aFile);
|
||||
return NS_OK;
|
||||
#endif
|
||||
}
|
||||
|
@ -30,9 +30,16 @@
|
||||
#include "mozilla/layers/PCompositorChild.h"
|
||||
#include "mozilla/net/NeckoChild.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#if defined(MOZ_CONTENT_SANDBOX) && defined(XP_UNIX) && !defined(XP_MACOSX)
|
||||
|
||||
#if defined(MOZ_CONTENT_SANDBOX)
|
||||
#if defined(XP_WIN)
|
||||
#define TARGET_SANDBOX_EXPORTS
|
||||
#include "mozilla/sandboxTarget.h"
|
||||
#elif defined(XP_UNIX) && !defined(XP_MACOSX)
|
||||
#include "mozilla/Sandbox.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "mozilla/unused.h"
|
||||
|
||||
#include "nsIConsoleListener.h"
|
||||
@ -593,12 +600,17 @@ ContentChild::RecvSetProcessPrivileges(const ChildPrivileges& aPrivs)
|
||||
aPrivs;
|
||||
// If this fails, we die.
|
||||
SetCurrentProcessPrivileges(privs);
|
||||
#if defined(MOZ_CONTENT_SANDBOX) && defined(XP_UNIX) && !defined(XP_MACOSX)
|
||||
|
||||
#if defined(MOZ_CONTENT_SANDBOX)
|
||||
#if defined(XP_WIN)
|
||||
mozilla::SandboxTarget::Instance()->StartSandbox();
|
||||
#else if defined(XP_UNIX) && !defined(XP_MACOSX)
|
||||
// SetCurrentProcessSandbox should be moved close to process initialization
|
||||
// time if/when possible. SetCurrentProcessPrivileges should probably be
|
||||
// moved as well. Right now this is set ONLY if we receive the
|
||||
// RecvSetProcessPrivileges message. See bug 880808.
|
||||
SetCurrentProcessSandbox();
|
||||
#endif
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "sandbox/chromium/base/basictypes.h"
|
||||
#include "sandbox/win/src/sandbox.h"
|
||||
#include "sandbox/win/src/sandbox_factory.h"
|
||||
#include "mozilla/sandboxTarget.h"
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
@ -67,14 +68,27 @@ InitializeBinder(void *aDummy) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
|
||||
static bool gIsSandboxEnabled = false;
|
||||
void StartSandboxCallback()
|
||||
{
|
||||
if (gIsSandboxEnabled) {
|
||||
sandbox::TargetServices* target_service =
|
||||
sandbox::SandboxFactory::GetTargetServices();
|
||||
target_service->LowerToken();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
bool isNuwa = false;
|
||||
bool isSandboxEnabled = false;
|
||||
for (int i = 1; i < argc; i++) {
|
||||
isNuwa |= strcmp(argv[i], "-nuwa") == 0;
|
||||
isSandboxEnabled |= strcmp(argv[i], "-sandbox") == 0;
|
||||
#if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
|
||||
gIsSandboxEnabled |= strcmp(argv[i], "-sandbox") == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
@ -100,24 +114,6 @@ main(int argc, char* argv[])
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
|
||||
if (isSandboxEnabled) {
|
||||
sandbox::TargetServices* target_service =
|
||||
sandbox::SandboxFactory::GetTargetServices();
|
||||
if (!target_service) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
sandbox::ResultCode result = target_service->Init();
|
||||
if (result != sandbox::SBOX_ALL_OK) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
// Initialization is finished, switch to the lowered token
|
||||
target_service->LowerToken();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Check for the absolute minimum number of args we need to move
|
||||
// forward here. We expect the last arg to be the child process type.
|
||||
if (argc < 1)
|
||||
@ -132,6 +128,22 @@ main(int argc, char* argv[])
|
||||
mozilla::SanitizeEnvironmentVariables();
|
||||
SetDllDirectory(L"");
|
||||
}
|
||||
|
||||
#ifdef MOZ_CONTENT_SANDBOX
|
||||
if (gIsSandboxEnabled) {
|
||||
sandbox::TargetServices* target_service =
|
||||
sandbox::SandboxFactory::GetTargetServices();
|
||||
if (!target_service) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
sandbox::ResultCode result = target_service->Init();
|
||||
if (result != sandbox::SBOX_ALL_OK) {
|
||||
return 2;
|
||||
}
|
||||
mozilla::SandboxTarget::Instance()->SetStartSandboxCallback(StartSandboxCallback);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
nsresult rv = XRE_InitChildProcess(argc, argv, proctype);
|
||||
|
@ -21,3 +21,11 @@ LOCAL_INCLUDES += [
|
||||
'/toolkit/xre',
|
||||
'/xpcom/base',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_CONTENT_SANDBOX'] and CONFIG['OS_ARCH'] == 'WINNT':
|
||||
# For sandbox includes and the include dependencies those have
|
||||
LOCAL_INCLUDES += [
|
||||
'/security',
|
||||
'/security/sandbox',
|
||||
'/security/sandbox/chromium',
|
||||
]
|
||||
|
@ -826,7 +826,6 @@ StructTypeRepresentation::fieldNamed(jsid id) const
|
||||
|
||||
uint32_t unused;
|
||||
JSAtom *atom = JSID_TO_ATOM(id);
|
||||
AutoThreadSafeAccess ts(atom);
|
||||
|
||||
if (atom->isIndex(&unused))
|
||||
return nullptr;
|
||||
|
@ -2865,12 +2865,10 @@ frontend::EmitFunctionScript(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNo
|
||||
RootedFunction fun(cx, bce->script->functionNonDelazifying());
|
||||
JS_ASSERT(fun->isInterpreted());
|
||||
|
||||
if (fun->isInterpretedLazy()) {
|
||||
AutoLockForCompilation lock(cx);
|
||||
if (fun->isInterpretedLazy())
|
||||
fun->setUnlazifiedScript(bce->script);
|
||||
} else {
|
||||
else
|
||||
fun->setScript(bce->script);
|
||||
}
|
||||
|
||||
bce->tellDebuggerAboutCompiledScript(cx);
|
||||
|
||||
|
@ -191,9 +191,6 @@ class BarrieredCell : public gc::Cell
|
||||
|
||||
static MOZ_ALWAYS_INLINE void readBarrier(T *thing) {
|
||||
#ifdef JSGC_INCREMENTAL
|
||||
// Off thread Ion compilation never occurs when barriers are active.
|
||||
js::AutoThreadSafeAccess ts(thing);
|
||||
|
||||
JS::shadow::Zone *shadowZone = thing->shadowZoneFromAnyThread();
|
||||
if (shadowZone->needsBarrier()) {
|
||||
MOZ_ASSERT(!RuntimeFromMainThreadIsHeapMajorCollecting(shadowZone));
|
||||
|
@ -1109,37 +1109,9 @@ InFreeList(ArenaHeader *aheader, void *thing)
|
||||
|
||||
} /* namespace gc */
|
||||
|
||||
// Ion compilation mainly occurs off the main thread, and may run while the
|
||||
// main thread is performing arbitrary VM operations, excepting GC activity.
|
||||
// The below class is used to mark functions and other operations which can
|
||||
// safely be performed off thread without racing. When running with thread
|
||||
// safety checking on, any access to a GC thing outside of AutoThreadSafeAccess
|
||||
// will cause an access violation.
|
||||
class MOZ_STACK_CLASS AutoThreadSafeAccess
|
||||
{
|
||||
public:
|
||||
#if defined(DEBUG) && defined(JS_CPU_X64) && !defined(XP_WIN)
|
||||
#define JS_CAN_CHECK_THREADSAFE_ACCESSES
|
||||
|
||||
JSRuntime *runtime;
|
||||
gc::ArenaHeader *arena;
|
||||
|
||||
AutoThreadSafeAccess(const gc::Cell *cell MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
|
||||
~AutoThreadSafeAccess();
|
||||
#else
|
||||
AutoThreadSafeAccess(const gc::Cell *cell MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
}
|
||||
~AutoThreadSafeAccess() {}
|
||||
#endif
|
||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
};
|
||||
|
||||
gc::AllocKind
|
||||
gc::Cell::tenuredGetAllocKind() const
|
||||
{
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return arenaHeader()->getAllocKind();
|
||||
}
|
||||
|
||||
|
@ -136,10 +136,7 @@ ICStubIterator::unlink(JSContext *cx)
|
||||
JS_ASSERT(currentStub_ != fallbackStub_);
|
||||
JS_ASSERT(!unlinked_);
|
||||
|
||||
{
|
||||
AutoLockForCompilation lock(cx);
|
||||
fallbackStub_->unlinkStub(cx->zone(), previousStub_, currentStub_);
|
||||
}
|
||||
fallbackStub_->unlinkStub(cx->zone(), previousStub_, currentStub_);
|
||||
|
||||
// Mark the current iterator position as unlinked, so operator++ works properly.
|
||||
unlinked_ = true;
|
||||
@ -1066,7 +1063,7 @@ DoProfilerFallback(JSContext *cx, BaselineFrame *frame, ICProfiler_Fallback *stu
|
||||
ICStub *optStub = compiler.getStub(compiler.getStubSpace(script));
|
||||
if (!optStub)
|
||||
return false;
|
||||
stub->addNewStub(cx, optStub);
|
||||
stub->addNewStub(optStub);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1797,7 +1794,7 @@ DoCompareFallback(JSContext *cx, BaselineFrame *frame, ICCompare_Fallback *stub,
|
||||
if (!int32Stub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, int32Stub);
|
||||
stub->addNewStub(int32Stub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1815,7 +1812,7 @@ DoCompareFallback(JSContext *cx, BaselineFrame *frame, ICCompare_Fallback *stub,
|
||||
if (!doubleStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, doubleStub);
|
||||
stub->addNewStub(doubleStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1830,7 +1827,7 @@ DoCompareFallback(JSContext *cx, BaselineFrame *frame, ICCompare_Fallback *stub,
|
||||
if (!doubleStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, doubleStub);
|
||||
stub->addNewStub(doubleStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1841,7 +1838,7 @@ DoCompareFallback(JSContext *cx, BaselineFrame *frame, ICCompare_Fallback *stub,
|
||||
if (!booleanStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, booleanStub);
|
||||
stub->addNewStub(booleanStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1854,7 +1851,7 @@ DoCompareFallback(JSContext *cx, BaselineFrame *frame, ICCompare_Fallback *stub,
|
||||
if (!optStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, optStub);
|
||||
stub->addNewStub(optStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1866,7 +1863,7 @@ DoCompareFallback(JSContext *cx, BaselineFrame *frame, ICCompare_Fallback *stub,
|
||||
if (!stringStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, stringStub);
|
||||
stub->addNewStub(stringStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1878,7 +1875,7 @@ DoCompareFallback(JSContext *cx, BaselineFrame *frame, ICCompare_Fallback *stub,
|
||||
if (!objectStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, objectStub);
|
||||
stub->addNewStub(objectStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1896,7 +1893,7 @@ DoCompareFallback(JSContext *cx, BaselineFrame *frame, ICCompare_Fallback *stub,
|
||||
if (!objectStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, objectStub);
|
||||
stub->addNewStub(objectStub);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -2207,7 +2204,7 @@ DoToBoolFallback(JSContext *cx, BaselineFrame *frame, ICToBool_Fallback *stub, H
|
||||
if (!int32Stub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, int32Stub);
|
||||
stub->addNewStub(int32Stub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2218,7 +2215,7 @@ DoToBoolFallback(JSContext *cx, BaselineFrame *frame, ICToBool_Fallback *stub, H
|
||||
if (!doubleStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, doubleStub);
|
||||
stub->addNewStub(doubleStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2229,7 +2226,7 @@ DoToBoolFallback(JSContext *cx, BaselineFrame *frame, ICToBool_Fallback *stub, H
|
||||
if (!stringStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, stringStub);
|
||||
stub->addNewStub(stringStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2239,7 +2236,7 @@ DoToBoolFallback(JSContext *cx, BaselineFrame *frame, ICToBool_Fallback *stub, H
|
||||
if (!nilStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, nilStub);
|
||||
stub->addNewStub(nilStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2250,7 +2247,7 @@ DoToBoolFallback(JSContext *cx, BaselineFrame *frame, ICToBool_Fallback *stub, H
|
||||
if (!objStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, objStub);
|
||||
stub->addNewStub(objStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2542,11 +2539,11 @@ DoBinaryArithFallback(JSContext *cx, BaselineFrame *frame, ICBinaryArith_Fallbac
|
||||
}
|
||||
|
||||
if (ret.isDouble())
|
||||
stub->setSawDoubleResult(cx);
|
||||
stub->setSawDoubleResult();
|
||||
|
||||
// Check to see if a new stub should be generated.
|
||||
if (stub->numOptimizedStubs() >= ICBinaryArith_Fallback::MAX_OPTIMIZED_STUBS) {
|
||||
stub->noteUnoptimizableOperands(cx);
|
||||
stub->noteUnoptimizableOperands();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2559,7 +2556,7 @@ DoBinaryArithFallback(JSContext *cx, BaselineFrame *frame, ICBinaryArith_Fallbac
|
||||
ICStub *strcatStub = compiler.getStub(compiler.getStubSpace(script));
|
||||
if (!strcatStub)
|
||||
return false;
|
||||
stub->addNewStub(cx, strcatStub);
|
||||
stub->addNewStub(strcatStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2572,7 +2569,7 @@ DoBinaryArithFallback(JSContext *cx, BaselineFrame *frame, ICBinaryArith_Fallbac
|
||||
ICStub *strcatStub = compiler.getStub(compiler.getStubSpace(script));
|
||||
if (!strcatStub)
|
||||
return false;
|
||||
stub->addNewStub(cx, strcatStub);
|
||||
stub->addNewStub(strcatStub);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -2588,13 +2585,13 @@ DoBinaryArithFallback(JSContext *cx, BaselineFrame *frame, ICBinaryArith_Fallbac
|
||||
ICStub *arithStub = compiler.getStub(compiler.getStubSpace(script));
|
||||
if (!arithStub)
|
||||
return false;
|
||||
stub->addNewStub(cx, arithStub);
|
||||
stub->addNewStub(arithStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Handle only int32 or double.
|
||||
if (!lhs.isNumber() || !rhs.isNumber()) {
|
||||
stub->noteUnoptimizableOperands(cx);
|
||||
stub->noteUnoptimizableOperands();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2618,7 +2615,7 @@ DoBinaryArithFallback(JSContext *cx, BaselineFrame *frame, ICBinaryArith_Fallbac
|
||||
ICStub *doubleStub = compiler.getStub(compiler.getStubSpace(script));
|
||||
if (!doubleStub)
|
||||
return false;
|
||||
stub->addNewStub(cx, doubleStub);
|
||||
stub->addNewStub(doubleStub);
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
@ -2636,7 +2633,7 @@ DoBinaryArithFallback(JSContext *cx, BaselineFrame *frame, ICBinaryArith_Fallbac
|
||||
ICStub *int32Stub = compilerInt32.getStub(compilerInt32.getStubSpace(script));
|
||||
if (!int32Stub)
|
||||
return false;
|
||||
stub->addNewStub(cx, int32Stub);
|
||||
stub->addNewStub(int32Stub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2655,7 +2652,7 @@ DoBinaryArithFallback(JSContext *cx, BaselineFrame *frame, ICBinaryArith_Fallbac
|
||||
ICStub *optStub = compiler.getStub(compiler.getStubSpace(script));
|
||||
if (!optStub)
|
||||
return false;
|
||||
stub->addNewStub(cx, optStub);
|
||||
stub->addNewStub(optStub);
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
@ -2663,7 +2660,7 @@ DoBinaryArithFallback(JSContext *cx, BaselineFrame *frame, ICBinaryArith_Fallbac
|
||||
}
|
||||
}
|
||||
|
||||
stub->noteUnoptimizableOperands(cx);
|
||||
stub->noteUnoptimizableOperands();
|
||||
return true;
|
||||
}
|
||||
#if defined(_MSC_VER)
|
||||
@ -3058,7 +3055,7 @@ DoUnaryArithFallback(JSContext *cx, BaselineFrame *frame, ICUnaryArith_Fallback
|
||||
ICStub *int32Stub = compiler.getStub(compiler.getStubSpace(script));
|
||||
if (!int32Stub)
|
||||
return false;
|
||||
stub->addNewStub(cx, int32Stub);
|
||||
stub->addNewStub(int32Stub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3072,7 +3069,7 @@ DoUnaryArithFallback(JSContext *cx, BaselineFrame *frame, ICUnaryArith_Fallback
|
||||
ICStub *doubleStub = compiler.getStub(compiler.getStubSpace(script));
|
||||
if (!doubleStub)
|
||||
return false;
|
||||
stub->addNewStub(cx, doubleStub);
|
||||
stub->addNewStub(doubleStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3757,7 +3754,7 @@ static bool TryAttachNativeGetElemStub(JSContext *cx, HandleScript script, jsbyt
|
||||
if (!newStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3809,7 +3806,7 @@ static bool TryAttachNativeGetElemStub(JSContext *cx, HandleScript script, jsbyt
|
||||
if (!newStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3843,7 +3840,7 @@ TryAttachGetElemStub(JSContext *cx, JSScript *script, jsbytecode *pc, ICGetElem_
|
||||
if (!stringStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, stringStub);
|
||||
stub->addNewStub(stringStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3861,7 +3858,7 @@ TryAttachGetElemStub(JSContext *cx, JSScript *script, jsbytecode *pc, ICGetElem_
|
||||
if (!argsStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, argsStub);
|
||||
stub->addNewStub(argsStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3883,7 +3880,7 @@ TryAttachGetElemStub(JSContext *cx, JSScript *script, jsbytecode *pc, ICGetElem_
|
||||
if (!argsStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, argsStub);
|
||||
stub->addNewStub(argsStub);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -3898,7 +3895,7 @@ TryAttachGetElemStub(JSContext *cx, JSScript *script, jsbytecode *pc, ICGetElem_
|
||||
if (!denseStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, denseStub);
|
||||
stub->addNewStub(denseStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3934,7 +3931,7 @@ TryAttachGetElemStub(JSContext *cx, JSScript *script, jsbytecode *pc, ICGetElem_
|
||||
if (!typedArrayStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, typedArrayStub);
|
||||
stub->addNewStub(typedArrayStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3942,13 +3939,13 @@ TryAttachGetElemStub(JSContext *cx, JSScript *script, jsbytecode *pc, ICGetElem_
|
||||
// be cached by either Baseline or Ion. Indicate this in the cache so that
|
||||
// Ion does not generate a cache for this op.
|
||||
if (!obj->isNative() && !obj->is<TypedArrayObject>())
|
||||
stub->noteNonNativeAccess(cx);
|
||||
stub->noteNonNativeAccess();
|
||||
|
||||
// GetElem operations which could access negative indexes generally can't
|
||||
// be optimized without the potential for bailouts, as we can't statically
|
||||
// determine that an object has no properties on such indexes.
|
||||
if (rhs.isNumber() && rhs.toNumber() < 0)
|
||||
stub->noteNegativeIndex(cx);
|
||||
stub->noteNegativeIndex();
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -5014,7 +5011,7 @@ DoSetElemFallback(JSContext *cx, BaselineFrame *frame, ICSetElem_Fallback *stub,
|
||||
if (!denseStub->addUpdateStubForValue(cx, script, obj, JSID_VOIDHANDLE, rhs))
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, denseStub);
|
||||
stub->addNewStub(denseStub);
|
||||
} else if (!addingCase &&
|
||||
!DenseSetElemStubExists(cx, ICStub::SetElem_Dense, stub, obj))
|
||||
{
|
||||
@ -5028,7 +5025,7 @@ DoSetElemFallback(JSContext *cx, BaselineFrame *frame, ICSetElem_Fallback *stub,
|
||||
if (!denseStub->addUpdateStubForValue(cx, script, obj, JSID_VOIDHANDLE, rhs))
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, denseStub);
|
||||
stub->addNewStub(denseStub);
|
||||
}
|
||||
}
|
||||
|
||||
@ -5061,7 +5058,7 @@ DoSetElemFallback(JSContext *cx, BaselineFrame *frame, ICSetElem_Fallback *stub,
|
||||
if (!typedArrayStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, typedArrayStub);
|
||||
stub->addNewStub(typedArrayStub);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -5111,13 +5108,13 @@ ICSetElem_Fallback::Compiler::generateStubCode(MacroAssembler &masm)
|
||||
}
|
||||
|
||||
void
|
||||
BaselineScript::noteArrayWriteHole(JSContext *cx, uint32_t pcOffset)
|
||||
BaselineScript::noteArrayWriteHole(uint32_t pcOffset)
|
||||
{
|
||||
ICEntry &entry = icEntryFromPCOffset(pcOffset);
|
||||
ICFallbackStub *stub = entry.fallbackStub();
|
||||
|
||||
if (stub->isSetElem_Fallback())
|
||||
stub->toSetElem_Fallback()->noteArrayWriteHole(cx);
|
||||
stub->toSetElem_Fallback()->noteArrayWriteHole();
|
||||
}
|
||||
|
||||
//
|
||||
@ -5639,7 +5636,7 @@ TryAttachGlobalNameStub(JSContext *cx, HandleScript script, ICGetName_Fallback *
|
||||
if (!newStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -5729,7 +5726,7 @@ TryAttachScopeNameStub(JSContext *cx, HandleScript script, ICGetName_Fallback *s
|
||||
if (!newStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -5936,7 +5933,7 @@ DoGetIntrinsicFallback(JSContext *cx, BaselineFrame *frame, ICGetIntrinsic_Fallb
|
||||
if (!newStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -5984,7 +5981,7 @@ TryAttachLengthStub(JSContext *cx, JSScript *script, ICGetProp_Fallback *stub, H
|
||||
return false;
|
||||
|
||||
*attached = true;
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -5996,7 +5993,7 @@ TryAttachLengthStub(JSContext *cx, JSScript *script, ICGetProp_Fallback *stub, H
|
||||
return false;
|
||||
|
||||
*attached = true;
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -6013,7 +6010,7 @@ TryAttachLengthStub(JSContext *cx, JSScript *script, ICGetProp_Fallback *stub, H
|
||||
return false;
|
||||
|
||||
*attached = true;
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
return true;
|
||||
}
|
||||
if (obj->is<TypedArrayObject>()) {
|
||||
@ -6025,7 +6022,7 @@ TryAttachLengthStub(JSContext *cx, JSScript *script, ICGetProp_Fallback *stub, H
|
||||
return false;
|
||||
|
||||
*attached = true;
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -6041,7 +6038,7 @@ TryAttachLengthStub(JSContext *cx, JSScript *script, ICGetProp_Fallback *stub, H
|
||||
return false;
|
||||
|
||||
*attached = true;
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -6124,7 +6121,7 @@ TryAttachNativeGetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc,
|
||||
if (!newStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
*attached = true;
|
||||
return true;
|
||||
}
|
||||
@ -6155,7 +6152,7 @@ TryAttachNativeGetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc,
|
||||
if (!newStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
*attached = true;
|
||||
return true;
|
||||
}
|
||||
@ -6202,7 +6199,7 @@ TryAttachNativeGetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc,
|
||||
}
|
||||
if (!newStub)
|
||||
return false;
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
*attached = true;
|
||||
return true;
|
||||
}
|
||||
@ -6222,7 +6219,7 @@ TryAttachNativeGetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc,
|
||||
ICStub *newStub = compiler.getStub(compiler.getStubSpace(script));
|
||||
if (!newStub)
|
||||
return false;
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
*attached = true;
|
||||
return true;
|
||||
}
|
||||
@ -6277,7 +6274,7 @@ TryAttachPrimitiveGetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc
|
||||
if (!newStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
*attached = true;
|
||||
return true;
|
||||
}
|
||||
@ -6364,7 +6361,7 @@ DoGetPropFallback(JSContext *cx, BaselineFrame *frame, ICGetProp_Fallback *stub,
|
||||
}
|
||||
|
||||
JS_ASSERT(!attached);
|
||||
stub->noteUnoptimizableAccess(cx);
|
||||
stub->noteUnoptimizableAccess();
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -7109,13 +7106,13 @@ ICGetProp_ArgumentsLength::Compiler::generateStubCode(MacroAssembler &masm)
|
||||
}
|
||||
|
||||
void
|
||||
BaselineScript::noteAccessedGetter(JSContext *cx, uint32_t pcOffset)
|
||||
BaselineScript::noteAccessedGetter(uint32_t pcOffset)
|
||||
{
|
||||
ICEntry &entry = icEntryFromPCOffset(pcOffset);
|
||||
ICFallbackStub *stub = entry.fallbackStub();
|
||||
|
||||
if (stub->isGetProp_Fallback())
|
||||
stub->toGetProp_Fallback()->noteAccessedGetter(cx);
|
||||
stub->toGetProp_Fallback()->noteAccessedGetter();
|
||||
}
|
||||
|
||||
//
|
||||
@ -7156,7 +7153,7 @@ TryAttachSetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc, ICSetPr
|
||||
if (!newStub->addUpdateStubForValue(cx, script, obj, id, rhs))
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
*attached = true;
|
||||
return true;
|
||||
}
|
||||
@ -7174,7 +7171,7 @@ TryAttachSetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc, ICSetPr
|
||||
if (!newStub->addUpdateStubForValue(cx, script, obj, id, rhs))
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
*attached = true;
|
||||
return true;
|
||||
}
|
||||
@ -7196,7 +7193,7 @@ TryAttachSetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc, ICSetPr
|
||||
if (!newStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
*attached = true;
|
||||
return true;
|
||||
}
|
||||
@ -7215,7 +7212,7 @@ TryAttachSetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc, ICSetPr
|
||||
if (!newStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
*attached = true;
|
||||
return true;
|
||||
}
|
||||
@ -7290,7 +7287,7 @@ DoSetPropFallback(JSContext *cx, BaselineFrame *frame, ICSetProp_Fallback *stub,
|
||||
return true;
|
||||
|
||||
JS_ASSERT(!attached);
|
||||
stub->noteUnoptimizableAccess(cx);
|
||||
stub->noteUnoptimizableAccess();
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -7796,7 +7793,7 @@ TryAttachFunApplyStub(JSContext *cx, ICCall_Fallback *stub, HandleScript script,
|
||||
if (!newStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -7813,7 +7810,7 @@ TryAttachFunApplyStub(JSContext *cx, ICCall_Fallback *stub, HandleScript script,
|
||||
if (!newStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -7957,7 +7954,7 @@ TryAttachCallStub(JSContext *cx, ICCall_Fallback *stub, HandleScript script, jsb
|
||||
stub->unlinkStubsWithKind(cx, ICStub::Call_Scripted);
|
||||
|
||||
// Add new generalized stub.
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -7986,7 +7983,7 @@ TryAttachCallStub(JSContext *cx, ICCall_Fallback *stub, HandleScript script, jsb
|
||||
if (!newStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -8023,7 +8020,7 @@ TryAttachCallStub(JSContext *cx, ICCall_Fallback *stub, HandleScript script, jsb
|
||||
if (!newStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -9155,7 +9152,7 @@ DoIteratorMoreFallback(JSContext *cx, BaselineFrame *frame, ICIteratorMore_Fallb
|
||||
ICStub *newStub = compiler.getStub(compiler.getStubSpace(frame->script()));
|
||||
if (!newStub)
|
||||
return false;
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -9229,7 +9226,7 @@ DoIteratorNextFallback(JSContext *cx, BaselineFrame *frame, ICIteratorNext_Fallb
|
||||
return false;
|
||||
|
||||
if (!res.isString() && !stub->hasNonStringResult())
|
||||
stub->setHasNonStringResult(cx);
|
||||
stub->setHasNonStringResult();
|
||||
|
||||
if (iteratorObject->is<PropertyIteratorObject>() &&
|
||||
!stub->hasStub(ICStub::IteratorNext_Native))
|
||||
@ -9238,7 +9235,7 @@ DoIteratorNextFallback(JSContext *cx, BaselineFrame *frame, ICIteratorNext_Fallb
|
||||
ICStub *newStub = compiler.getStub(compiler.getStubSpace(frame->script()));
|
||||
if (!newStub)
|
||||
return false;
|
||||
stub->addNewStub(cx, newStub);
|
||||
stub->addNewStub(newStub);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -9402,7 +9399,7 @@ DoTypeOfFallback(JSContext *cx, BaselineFrame *frame, ICTypeOf_Fallback *stub, H
|
||||
ICStub *typeOfStub = compiler.getStub(compiler.getStubSpace(frame->script()));
|
||||
if (!typeOfStub)
|
||||
return false;
|
||||
stub->addNewStub(cx, typeOfStub);
|
||||
stub->addNewStub(typeOfStub);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -9489,7 +9486,7 @@ DoRetSubFallback(JSContext *cx, BaselineFrame *frame, ICRetSub_Fallback *stub,
|
||||
if (!optStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(cx, optStub);
|
||||
stub->addNewStub(optStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -835,8 +835,7 @@ class ICFallbackStub : public ICStub
|
||||
}
|
||||
|
||||
// Add a new stub to the IC chain terminated by this fallback stub.
|
||||
void addNewStub(JSContext *cx, ICStub *stub) {
|
||||
AutoLockForCompilation lock(cx);
|
||||
void addNewStub(ICStub *stub) {
|
||||
JS_ASSERT(*lastStubPtrAddr_ == this);
|
||||
JS_ASSERT(stub->next() == nullptr);
|
||||
stub->setNext(this);
|
||||
@ -2442,15 +2441,13 @@ class ICBinaryArith_Fallback : public ICFallbackStub
|
||||
bool sawDoubleResult() const {
|
||||
return extra_ & SAW_DOUBLE_RESULT_BIT;
|
||||
}
|
||||
void setSawDoubleResult(JSContext *cx) {
|
||||
AutoLockForCompilation lock(cx);
|
||||
void setSawDoubleResult() {
|
||||
extra_ |= SAW_DOUBLE_RESULT_BIT;
|
||||
}
|
||||
bool hadUnoptimizableOperands() const {
|
||||
return extra_ & UNOPTIMIZABLE_OPERANDS_BIT;
|
||||
}
|
||||
void noteUnoptimizableOperands(JSContext *cx) {
|
||||
AutoLockForCompilation lock(cx);
|
||||
void noteUnoptimizableOperands() {
|
||||
extra_ |= UNOPTIMIZABLE_OPERANDS_BIT;
|
||||
}
|
||||
|
||||
@ -2851,16 +2848,14 @@ class ICGetElem_Fallback : public ICMonitoredFallbackStub
|
||||
return space->allocate<ICGetElem_Fallback>(code);
|
||||
}
|
||||
|
||||
void noteNonNativeAccess(JSContext *cx) {
|
||||
AutoLockForCompilation lock(cx);
|
||||
void noteNonNativeAccess() {
|
||||
extra_ |= EXTRA_NON_NATIVE;
|
||||
}
|
||||
bool hasNonNativeAccess() const {
|
||||
return extra_ & EXTRA_NON_NATIVE;
|
||||
}
|
||||
|
||||
void noteNegativeIndex(JSContext *cx) {
|
||||
AutoLockForCompilation lock(cx);
|
||||
void noteNegativeIndex() {
|
||||
extra_ |= EXTRA_NEGATIVE_INDEX;
|
||||
}
|
||||
bool hasNegativeIndex() const {
|
||||
@ -3448,8 +3443,7 @@ class ICSetElem_Fallback : public ICFallbackStub
|
||||
return space->allocate<ICSetElem_Fallback>(code);
|
||||
}
|
||||
|
||||
void noteArrayWriteHole(JSContext *cx) {
|
||||
AutoLockForCompilation lock(cx);
|
||||
void noteArrayWriteHole() {
|
||||
extra_ = 1;
|
||||
}
|
||||
bool hasArrayWriteHole() const {
|
||||
@ -4024,16 +4018,14 @@ class ICGetProp_Fallback : public ICMonitoredFallbackStub
|
||||
static const size_t UNOPTIMIZABLE_ACCESS_BIT = 0;
|
||||
static const size_t ACCESSED_GETTER_BIT = 1;
|
||||
|
||||
void noteUnoptimizableAccess(JSContext *cx) {
|
||||
AutoLockForCompilation lock(cx);
|
||||
void noteUnoptimizableAccess() {
|
||||
extra_ |= (1u << UNOPTIMIZABLE_ACCESS_BIT);
|
||||
}
|
||||
bool hadUnoptimizableAccess() const {
|
||||
return extra_ & (1u << UNOPTIMIZABLE_ACCESS_BIT);
|
||||
}
|
||||
|
||||
void noteAccessedGetter(JSContext *cx) {
|
||||
AutoLockForCompilation lock(cx);
|
||||
void noteAccessedGetter() {
|
||||
extra_ |= (1u << ACCESSED_GETTER_BIT);
|
||||
}
|
||||
bool hasAccessedGetter() const {
|
||||
@ -4840,8 +4832,7 @@ class ICSetProp_Fallback : public ICFallbackStub
|
||||
}
|
||||
|
||||
static const size_t UNOPTIMIZABLE_ACCESS_BIT = 0;
|
||||
void noteUnoptimizableAccess(JSContext *cx) {
|
||||
AutoLockForCompilation lock(cx);
|
||||
void noteUnoptimizableAccess() {
|
||||
extra_ |= (1u << UNOPTIMIZABLE_ACCESS_BIT);
|
||||
}
|
||||
bool hadUnoptimizableAccess() const {
|
||||
@ -5742,8 +5733,7 @@ class ICIteratorNext_Fallback : public ICFallbackStub
|
||||
return space->allocate<ICIteratorNext_Fallback>(code);
|
||||
}
|
||||
|
||||
void setHasNonStringResult(JSContext *cx) {
|
||||
AutoLockForCompilation lock(cx);
|
||||
void setHasNonStringResult() {
|
||||
JS_ASSERT(extra_ == 0);
|
||||
extra_ = 1;
|
||||
}
|
||||
|
@ -18,8 +18,6 @@ using mozilla::DebugOnly;
|
||||
bool
|
||||
SetElemICInspector::sawOOBDenseWrite() const
|
||||
{
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
|
||||
if (!icEntry_)
|
||||
return false;
|
||||
|
||||
@ -40,8 +38,6 @@ SetElemICInspector::sawOOBDenseWrite() const
|
||||
bool
|
||||
SetElemICInspector::sawOOBTypedArrayWrite() const
|
||||
{
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
|
||||
if (!icEntry_)
|
||||
return false;
|
||||
|
||||
@ -58,8 +54,6 @@ SetElemICInspector::sawOOBTypedArrayWrite() const
|
||||
bool
|
||||
SetElemICInspector::sawDenseWrite() const
|
||||
{
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
|
||||
if (!icEntry_)
|
||||
return false;
|
||||
|
||||
@ -74,8 +68,6 @@ SetElemICInspector::sawDenseWrite() const
|
||||
bool
|
||||
SetElemICInspector::sawTypedArrayWrite() const
|
||||
{
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
|
||||
if (!icEntry_)
|
||||
return false;
|
||||
|
||||
@ -90,8 +82,6 @@ SetElemICInspector::sawTypedArrayWrite() const
|
||||
bool
|
||||
BaselineInspector::maybeShapesForPropertyOp(jsbytecode *pc, ShapeVector &shapes)
|
||||
{
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
|
||||
// Return a list of shapes seen by the baseline IC for the current op.
|
||||
// An empty list indicates no shapes are known, or there was an uncacheable
|
||||
// access.
|
||||
@ -149,8 +139,6 @@ BaselineInspector::maybeShapesForPropertyOp(jsbytecode *pc, ShapeVector &shapes)
|
||||
ICStub *
|
||||
BaselineInspector::monomorphicStub(jsbytecode *pc)
|
||||
{
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
|
||||
if (!hasBaselineScript())
|
||||
return nullptr;
|
||||
|
||||
@ -168,8 +156,6 @@ BaselineInspector::monomorphicStub(jsbytecode *pc)
|
||||
bool
|
||||
BaselineInspector::dimorphicStub(jsbytecode *pc, ICStub **pfirst, ICStub **psecond)
|
||||
{
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
|
||||
if (!hasBaselineScript())
|
||||
return false;
|
||||
|
||||
@ -190,8 +176,6 @@ BaselineInspector::dimorphicStub(jsbytecode *pc, ICStub **pfirst, ICStub **pseco
|
||||
MIRType
|
||||
BaselineInspector::expectedResultType(jsbytecode *pc)
|
||||
{
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
|
||||
// Look at the IC entries for this op to guess what type it will produce,
|
||||
// returning MIRType_None otherwise.
|
||||
|
||||
@ -238,8 +222,6 @@ CanUseInt32Compare(ICStub::Kind kind)
|
||||
MCompare::CompareType
|
||||
BaselineInspector::expectedCompareType(jsbytecode *pc)
|
||||
{
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
|
||||
ICStub *first = monomorphicStub(pc), *second = nullptr;
|
||||
if (!first && !dimorphicStub(pc, &first, &second))
|
||||
return MCompare::Compare_Unknown;
|
||||
@ -322,8 +304,6 @@ TryToSpecializeBinaryArithOp(ICStub **stubs,
|
||||
MIRType
|
||||
BaselineInspector::expectedBinaryArithSpecialization(jsbytecode *pc)
|
||||
{
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
|
||||
MIRType result;
|
||||
ICStub *stubs[2];
|
||||
|
||||
@ -352,8 +332,6 @@ BaselineInspector::expectedBinaryArithSpecialization(jsbytecode *pc)
|
||||
bool
|
||||
BaselineInspector::hasSeenNonNativeGetElement(jsbytecode *pc)
|
||||
{
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
|
||||
if (!hasBaselineScript())
|
||||
return false;
|
||||
|
||||
@ -368,8 +346,6 @@ BaselineInspector::hasSeenNonNativeGetElement(jsbytecode *pc)
|
||||
bool
|
||||
BaselineInspector::hasSeenNegativeIndexGetElement(jsbytecode *pc)
|
||||
{
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
|
||||
if (!hasBaselineScript())
|
||||
return false;
|
||||
|
||||
@ -384,8 +360,6 @@ BaselineInspector::hasSeenNegativeIndexGetElement(jsbytecode *pc)
|
||||
bool
|
||||
BaselineInspector::hasSeenAccessedGetter(jsbytecode *pc)
|
||||
{
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
|
||||
if (!hasBaselineScript())
|
||||
return false;
|
||||
|
||||
@ -400,8 +374,6 @@ BaselineInspector::hasSeenAccessedGetter(jsbytecode *pc)
|
||||
bool
|
||||
BaselineInspector::hasSeenNonStringIterNext(jsbytecode *pc)
|
||||
{
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
|
||||
JS_ASSERT(JSOp(*pc) == JSOP_ITERNEXT);
|
||||
|
||||
if (!hasBaselineScript())
|
||||
@ -416,8 +388,6 @@ BaselineInspector::hasSeenNonStringIterNext(jsbytecode *pc)
|
||||
bool
|
||||
BaselineInspector::hasSeenDoubleResult(jsbytecode *pc)
|
||||
{
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
|
||||
if (!hasBaselineScript())
|
||||
return false;
|
||||
|
||||
@ -437,8 +407,6 @@ BaselineInspector::hasSeenDoubleResult(jsbytecode *pc)
|
||||
JSObject *
|
||||
BaselineInspector::getTemplateObject(jsbytecode *pc)
|
||||
{
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
|
||||
if (!hasBaselineScript())
|
||||
return nullptr;
|
||||
|
||||
@ -466,8 +434,6 @@ BaselineInspector::getTemplateObject(jsbytecode *pc)
|
||||
JSObject *
|
||||
BaselineInspector::getTemplateObjectForNative(jsbytecode *pc, Native native)
|
||||
{
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
|
||||
if (!hasBaselineScript())
|
||||
return nullptr;
|
||||
|
||||
@ -501,8 +467,6 @@ BaselineInspector::templateCallObject()
|
||||
JSObject *
|
||||
BaselineInspector::commonGetPropFunction(jsbytecode *pc, Shape **lastProperty, JSFunction **commonGetter)
|
||||
{
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
|
||||
const ICEntry &entry = icEntryFromPC(pc);
|
||||
for (ICStub *stub = entry.firstStub(); stub; stub = stub->next()) {
|
||||
if (stub->isGetProp_CallScripted() || stub->isGetProp_CallNative()) {
|
||||
@ -518,8 +482,6 @@ BaselineInspector::commonGetPropFunction(jsbytecode *pc, Shape **lastProperty, J
|
||||
JSObject *
|
||||
BaselineInspector::commonSetPropFunction(jsbytecode *pc, Shape **lastProperty, JSFunction **commonSetter)
|
||||
{
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
|
||||
const ICEntry &entry = icEntryFromPC(pc);
|
||||
for (ICStub *stub = entry.firstStub(); stub; stub = stub->next()) {
|
||||
if (stub->isSetProp_CallScripted() || stub->isSetProp_CallNative()) {
|
||||
|
@ -294,8 +294,8 @@ struct BaselineScript
|
||||
|
||||
void toggleSPS(bool enable);
|
||||
|
||||
void noteAccessedGetter(JSContext *cx, uint32_t pcOffset);
|
||||
void noteArrayWriteHole(JSContext *cx, uint32_t pcOffset);
|
||||
void noteAccessedGetter(uint32_t pcOffset);
|
||||
void noteArrayWriteHole(uint32_t pcOffset);
|
||||
|
||||
static size_t offsetOfFlags() {
|
||||
return offsetof(BaselineScript, flags_);
|
||||
|
@ -3568,7 +3568,6 @@ CodeGenerator::visitNewCallObject(LNewCallObject *lir)
|
||||
Register obj = ToRegister(lir->output());
|
||||
|
||||
JSObject *templateObj = lir->mir()->templateObject();
|
||||
AutoThreadSafeAccess ts(templateObj);
|
||||
|
||||
// If we have a template object, we can inline call object creation.
|
||||
OutOfLineCode *ool;
|
||||
|
@ -252,15 +252,6 @@ CompileCompartment::setSingletonsAsValues()
|
||||
return JS::CompartmentOptionsRef(compartment()).setSingletonsAsValues();
|
||||
}
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
AutoLockForCompilation::AutoLockForCompilation(CompileCompartment *compartment
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
init(compartment->compartment()->runtimeFromAnyThread());
|
||||
}
|
||||
#endif
|
||||
|
||||
JitCompileOptions::JitCompileOptions()
|
||||
: cloneSingletons_(false),
|
||||
spsSlowAssertionsEnabled_(false)
|
||||
|
@ -102,8 +102,6 @@ class CompileCompartment
|
||||
{
|
||||
JSCompartment *compartment();
|
||||
|
||||
friend class js::AutoLockForCompilation;
|
||||
|
||||
public:
|
||||
static CompileCompartment *get(JSCompartment *comp);
|
||||
|
||||
|
@ -52,7 +52,6 @@
|
||||
using namespace js;
|
||||
using namespace js::jit;
|
||||
|
||||
using mozilla::Maybe;
|
||||
using mozilla::ThreadLocal;
|
||||
|
||||
// Assert that JitCode is gc::Cell aligned.
|
||||
@ -492,8 +491,6 @@ JitCompartment::ensureIonStubsExist(JSContext *cx)
|
||||
void
|
||||
jit::FinishOffThreadBuilder(IonBuilder *builder)
|
||||
{
|
||||
builder->script()->runtimeFromMainThread()->removeCompilationThread();
|
||||
|
||||
ExecutionMode executionMode = builder->info().executionMode();
|
||||
|
||||
// Clear the recompiling flag if it would have failed.
|
||||
@ -1565,9 +1562,6 @@ AttachFinishedCompilations(JSContext *cx)
|
||||
// operation callback and can't propagate failures.
|
||||
cx->clearPendingException();
|
||||
}
|
||||
} else {
|
||||
if (builder->abortReason() == AbortReason_Disable)
|
||||
SetIonScript(builder->script(), builder->info().executionMode(), ION_DISABLED_SCRIPT);
|
||||
}
|
||||
|
||||
FinishOffThreadBuilder(builder);
|
||||
@ -1722,6 +1716,14 @@ IonCompile(JSContext *cx, JSScript *script,
|
||||
builderScript->ionScript()->setRecompiling();
|
||||
}
|
||||
|
||||
IonSpewNewFunction(graph, builderScript);
|
||||
|
||||
bool succeeded = builder->build();
|
||||
builder->clearForBackEnd();
|
||||
|
||||
if (!succeeded)
|
||||
return builder->abortReason();
|
||||
|
||||
// If possible, compile the script off thread.
|
||||
if (OffThreadCompilationAvailable(cx)) {
|
||||
if (!recompile)
|
||||
@ -1742,42 +1744,12 @@ IonCompile(JSContext *cx, JSScript *script,
|
||||
return AbortReason_NoAbort;
|
||||
}
|
||||
|
||||
Maybe<AutoEnterIonCompilation> ionCompiling;
|
||||
if (!cx->runtime()->profilingScripts && !IonSpewEnabled(IonSpew_Logs)) {
|
||||
// Compilation with script profiling is only done on the main thread,
|
||||
// and may modify scripts directly. Same for logging. It is only
|
||||
// enabled when offthread compilation is disabled. So don't watch for
|
||||
// proper use of the compilation lock.
|
||||
ionCompiling.construct();
|
||||
}
|
||||
|
||||
Maybe<AutoProtectHeapForIonCompilation> protect;
|
||||
if (js_JitOptions.checkThreadSafety &&
|
||||
cx->runtime()->gcIncrementalState == gc::NO_INCREMENTAL &&
|
||||
!cx->runtime()->profilingScripts)
|
||||
{
|
||||
protect.construct(cx->runtime());
|
||||
}
|
||||
|
||||
IonSpewNewFunction(graph, builderScript);
|
||||
|
||||
bool succeeded = builder->build();
|
||||
builder->clearForBackEnd();
|
||||
|
||||
if (!succeeded)
|
||||
return builder->abortReason();
|
||||
|
||||
ScopedJSDeletePtr<CodeGenerator> codegen(CompileBackEnd(builder));
|
||||
if (!codegen) {
|
||||
IonSpew(IonSpew_Abort, "Failed during back-end compilation.");
|
||||
return AbortReason_Disable;
|
||||
}
|
||||
|
||||
if (!protect.empty())
|
||||
protect.destroy();
|
||||
if (!ionCompiling.empty())
|
||||
ionCompiling.destroy();
|
||||
|
||||
bool success = codegen->link(cx, builder->constraints());
|
||||
|
||||
IonSpewEndFunction();
|
||||
|
@ -140,21 +140,13 @@ IonBuilder::IonBuilder(JSContext *analysisContext, CompileCompartment *comp,
|
||||
script_ = info->script();
|
||||
pc = info->startPC();
|
||||
|
||||
#ifdef DEBUG
|
||||
lock();
|
||||
JS_ASSERT(script()->hasBaselineScript());
|
||||
unlock();
|
||||
#endif
|
||||
JS_ASSERT(!!analysisContext == (info->executionMode() == DefinitePropertiesAnalysis));
|
||||
}
|
||||
|
||||
void
|
||||
IonBuilder::clearForBackEnd()
|
||||
{
|
||||
// This case should only be hit if there was a failure while building.
|
||||
if (!lock_.empty())
|
||||
lock_.destroy();
|
||||
|
||||
JS_ASSERT(!analysisContext);
|
||||
baselineFrame_ = nullptr;
|
||||
|
||||
@ -292,8 +284,6 @@ IonBuilder::getPolyCallTargets(types::TemporaryTypeSet *calleeTypes, bool constr
|
||||
fun = &obj->as<JSFunction>();
|
||||
} else {
|
||||
types::TypeObject *typeObj = calleeTypes->getTypeObject(i);
|
||||
AutoThreadSafeAccess ts(typeObj);
|
||||
|
||||
JS_ASSERT(typeObj);
|
||||
if (!typeObj->interpretedFunction) {
|
||||
targets.clear();
|
||||
@ -593,16 +583,12 @@ IonBuilder::pushLoop(CFGState::State initial, jsbytecode *stopAt, MBasicBlock *e
|
||||
bool
|
||||
IonBuilder::init()
|
||||
{
|
||||
lock();
|
||||
|
||||
if (!types::TypeScript::FreezeTypeSets(constraints(), script(),
|
||||
&thisTypes, &argTypes, &typeArray))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
unlock();
|
||||
|
||||
if (!analysis().init(alloc(), gsn))
|
||||
return false;
|
||||
|
||||
@ -721,8 +707,6 @@ IonBuilder::build()
|
||||
if (!traverseBytecode())
|
||||
return false;
|
||||
|
||||
unlock();
|
||||
|
||||
if (!maybeAddOsrTypeBarriers())
|
||||
return false;
|
||||
|
||||
@ -882,7 +866,6 @@ IonBuilder::buildInline(IonBuilder *callerBuilder, MResumePoint *callerResumePoi
|
||||
if (!traverseBytecode())
|
||||
return false;
|
||||
|
||||
unlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -937,9 +920,6 @@ IonBuilder::initParameters()
|
||||
// interpreter and didn't accumulate type information, try to use that OSR
|
||||
// frame to determine possible initial types for 'this' and parameters.
|
||||
|
||||
// For unknownProperties() tests under addType.
|
||||
lock();
|
||||
|
||||
if (thisTypes->empty() && baselineFrame_) {
|
||||
if (!thisTypes->addType(baselineFrame_->thisType, alloc_->lifoAlloc()))
|
||||
return false;
|
||||
@ -963,8 +943,6 @@ IonBuilder::initParameters()
|
||||
current->initSlot(info().argSlotUnchecked(i), param);
|
||||
}
|
||||
|
||||
unlock();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -987,8 +965,6 @@ IonBuilder::initScopeChain(MDefinition *callee)
|
||||
if (!script()->compileAndGo())
|
||||
return abort("non-CNG global scripts are not supported");
|
||||
|
||||
lock();
|
||||
|
||||
if (JSFunction *fun = info().funMaybeLazy()) {
|
||||
if (!callee) {
|
||||
MCallee *calleeIns = MCallee::New(alloc());
|
||||
@ -1014,8 +990,6 @@ IonBuilder::initScopeChain(MDefinition *callee)
|
||||
scope = constant(ObjectValue(script()->global()));
|
||||
}
|
||||
|
||||
unlock();
|
||||
|
||||
current->setScopeChain(scope);
|
||||
return true;
|
||||
}
|
||||
@ -1209,14 +1183,6 @@ IonBuilder::maybeAddOsrTypeBarriers()
|
||||
bool
|
||||
IonBuilder::traverseBytecode()
|
||||
{
|
||||
// Always hold the compilation lock when traversing bytecode, though release
|
||||
// it before reacquiring it every few opcodes so that the main thread does not
|
||||
// block for long when updating compilation data.
|
||||
lock();
|
||||
|
||||
size_t lockOpcodeCount = 0;
|
||||
static const size_t LOCK_OPCODE_GRANULARITY = 5;
|
||||
|
||||
for (;;) {
|
||||
JS_ASSERT(pc < info().limitPC());
|
||||
|
||||
@ -1291,12 +1257,6 @@ IonBuilder::traverseBytecode()
|
||||
if (!inspectOpcode(op))
|
||||
return false;
|
||||
|
||||
if (++lockOpcodeCount == LOCK_OPCODE_GRANULARITY) {
|
||||
unlock();
|
||||
lock();
|
||||
lockOpcodeCount = 0;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
for (size_t i = 0; i < popped.length(); i++) {
|
||||
switch (op) {
|
||||
@ -3881,21 +3841,17 @@ IonBuilder::inlineScriptedCall(CallInfo &callInfo, JSFunction *target)
|
||||
JSScript *calleeScript = target->nonLazyScript();
|
||||
BaselineInspector inspector(calleeScript);
|
||||
|
||||
// Improve type information of |this| when not set.
|
||||
if (callInfo.constructing() &&
|
||||
!callInfo.thisArg()->resultTypeSet() &&
|
||||
calleeScript->types)
|
||||
{
|
||||
AutoThreadSafeAccess ts(calleeScript);
|
||||
|
||||
// Improve type information of |this| when not set.
|
||||
if (callInfo.constructing() &&
|
||||
!callInfo.thisArg()->resultTypeSet() &&
|
||||
calleeScript->types)
|
||||
{
|
||||
types::StackTypeSet *types = types::TypeScript::ThisTypes(calleeScript);
|
||||
if (!types->unknown()) {
|
||||
MTypeBarrier *barrier =
|
||||
MTypeBarrier::New(alloc(), callInfo.thisArg(), types->clone(alloc_->lifoAlloc()));
|
||||
current->add(barrier);
|
||||
callInfo.setThis(barrier);
|
||||
}
|
||||
types::StackTypeSet *types = types::TypeScript::ThisTypes(calleeScript);
|
||||
if (!types->unknown()) {
|
||||
MTypeBarrier *barrier =
|
||||
MTypeBarrier::New(alloc(), callInfo.thisArg(), types->clone(alloc_->lifoAlloc()));
|
||||
current->add(barrier);
|
||||
callInfo.setThis(barrier);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3911,8 +3867,6 @@ IonBuilder::inlineScriptedCall(CallInfo &callInfo, JSFunction *target)
|
||||
MIRGraphReturns returns(alloc());
|
||||
AutoAccumulateReturns aar(graph(), returns);
|
||||
|
||||
unlock();
|
||||
|
||||
// Build the graph.
|
||||
IonBuilder inlineBuilder(analysisContext, compartment, options, &alloc(), &graph(), constraints(),
|
||||
&inspector, info, &optimizationInfo(), nullptr, inliningDepth_ + 1,
|
||||
@ -3927,7 +3881,6 @@ IonBuilder::inlineScriptedCall(CallInfo &callInfo, JSFunction *target)
|
||||
// Inlining the callee failed. Mark the callee as uninlineable only if
|
||||
// the inlining was aborted for a non-exception reason.
|
||||
if (inlineBuilder.abortReason_ == AbortReason_Disable) {
|
||||
AutoThreadSafeAccess ts(calleeScript);
|
||||
calleeScript->setUninlineable();
|
||||
abortReason_ = AbortReason_Inlining;
|
||||
} else if (inlineBuilder.abortReason_ == AbortReason_Inlining) {
|
||||
@ -3937,8 +3890,6 @@ IonBuilder::inlineScriptedCall(CallInfo &callInfo, JSFunction *target)
|
||||
return false;
|
||||
}
|
||||
|
||||
lock();
|
||||
|
||||
// Create return block.
|
||||
jsbytecode *postCall = GetNextPc(pc);
|
||||
MBasicBlock *returnBlock = newBlock(nullptr, postCall);
|
||||
@ -3957,7 +3908,6 @@ IonBuilder::inlineScriptedCall(CallInfo &callInfo, JSFunction *target)
|
||||
// Accumulate return values.
|
||||
if (returns.empty()) {
|
||||
// Inlining of functions that have no exit is not supported.
|
||||
AutoThreadSafeAccess ts(calleeScript);
|
||||
calleeScript->setUninlineable();
|
||||
abortReason_ = AbortReason_Inlining;
|
||||
return false;
|
||||
@ -4618,7 +4568,6 @@ IonBuilder::createDeclEnvObject(MDefinition *callee, MDefinition *scope)
|
||||
// Get a template CallObject that we'll use to generate inline object
|
||||
// creation.
|
||||
DeclEnvObject *templateObj = inspector->templateDeclEnvObject();
|
||||
AutoThreadSafeAccess ts(templateObj);
|
||||
|
||||
// One field is added to the function to handle its name. This cannot be a
|
||||
// dynamic slot because there is still plenty of room on the DeclEnv object.
|
||||
@ -4646,12 +4595,11 @@ IonBuilder::createCallObject(MDefinition *callee, MDefinition *scope)
|
||||
// Get a template CallObject that we'll use to generate inline object
|
||||
// creation.
|
||||
CallObject *templateObj = inspector->templateCallObject();
|
||||
AutoThreadSafeAccess ts(templateObj);
|
||||
|
||||
// If the CallObject needs dynamic slots, allocate those now.
|
||||
MInstruction *slots;
|
||||
if (templateObj->hasDynamicSlots()) {
|
||||
size_t nslots = JSObject::dynamicSlotsCount(templateObj->numFixedSlotsForCompilation(),
|
||||
size_t nslots = JSObject::dynamicSlotsCount(templateObj->numFixedSlots(),
|
||||
templateObj->lastProperty()->slotSpan(templateObj->getClass()),
|
||||
templateObj->getClass());
|
||||
slots = MNewSlots::New(alloc(), nslots);
|
||||
@ -4677,8 +4625,8 @@ IonBuilder::createCallObject(MDefinition *callee, MDefinition *scope)
|
||||
unsigned slot = i.scopeSlot();
|
||||
unsigned formal = i.frameIndex();
|
||||
MDefinition *param = current->getSlot(info().argSlotUnchecked(formal));
|
||||
if (slot >= templateObj->numFixedSlotsForCompilation())
|
||||
current->add(MStoreSlot::New(alloc(), slots, slot - templateObj->numFixedSlotsForCompilation(), param));
|
||||
if (slot >= templateObj->numFixedSlots())
|
||||
current->add(MStoreSlot::New(alloc(), slots, slot - templateObj->numFixedSlots(), param));
|
||||
else
|
||||
current->add(MStoreFixedSlot::New(alloc(), callObj, slot, param));
|
||||
}
|
||||
@ -4750,13 +4698,10 @@ IonBuilder::createThisScriptedSingleton(JSFunction *target, MDefinition *callee)
|
||||
if (!templateObject->hasTenuredProto() || templateObject->getProto() != proto)
|
||||
return nullptr;
|
||||
|
||||
{
|
||||
AutoThreadSafeAccess ts(target->nonLazyScript());
|
||||
if (!target->nonLazyScript()->types)
|
||||
return nullptr;
|
||||
if (!types::TypeScript::ThisTypes(target->nonLazyScript())->hasType(types::Type::ObjectType(templateObject)))
|
||||
return nullptr;
|
||||
}
|
||||
if (!target->nonLazyScript()->types)
|
||||
return nullptr;
|
||||
if (!types::TypeScript::ThisTypes(target->nonLazyScript())->hasType(types::Type::ObjectType(templateObject)))
|
||||
return nullptr;
|
||||
|
||||
// For template objects with NewScript info, the appropriate allocation
|
||||
// kind to use may change due to dynamic property adds. In these cases
|
||||
@ -5157,8 +5102,6 @@ IonBuilder::testNeedsArgumentCheck(JSFunction *target, CallInfo &callInfo)
|
||||
|
||||
JSScript *targetScript = target->nonLazyScript();
|
||||
|
||||
AutoThreadSafeAccess ts(targetScript);
|
||||
|
||||
if (!targetScript->types)
|
||||
return true;
|
||||
|
||||
@ -5357,7 +5300,6 @@ IonBuilder::jsop_eval(uint32_t argc)
|
||||
string->getOperand(1)->toConstant()->value().isString())
|
||||
{
|
||||
JSAtom *atom = &string->getOperand(1)->toConstant()->value().toString()->asAtom();
|
||||
AutoThreadSafeAccess ts(atom);
|
||||
|
||||
if (StringEqualsAscii(atom, "()")) {
|
||||
MDefinition *name = string->getOperand(0);
|
||||
@ -5431,7 +5373,6 @@ IonBuilder::jsop_newarray(uint32_t count)
|
||||
types::TemporaryTypeSet::DoubleConversion conversion =
|
||||
ins->resultTypeSet()->convertDoubleElements(constraints());
|
||||
|
||||
AutoThreadSafeAccess ts(templateObject);
|
||||
if (conversion == types::TemporaryTypeSet::AlwaysConvertToDoubles)
|
||||
templateObject->setShouldConvertDoubleElements();
|
||||
else
|
||||
@ -5514,7 +5455,6 @@ IonBuilder::jsop_initelem_array()
|
||||
current->add(elements);
|
||||
|
||||
JSObject *templateObject = obj->toNewArray()->templateObject();
|
||||
AutoThreadSafeAccess ts(templateObject);
|
||||
|
||||
if (templateObject->shouldConvertDoubleElements()) {
|
||||
MInstruction *valueDouble = MToDouble::New(alloc(), value);
|
||||
@ -5556,7 +5496,6 @@ IonBuilder::jsop_initprop(PropertyName *name)
|
||||
MDefinition *obj = current->peek(-1);
|
||||
|
||||
JSObject *templateObject = obj->toNewObject()->templateObject();
|
||||
AutoThreadSafeAccess ts(templateObject);
|
||||
|
||||
Shape *shape = templateObject->lastProperty()->searchLinear(NameToId(name));
|
||||
|
||||
@ -9179,9 +9118,6 @@ IonBuilder::jsop_regexp(RegExpObject *reobj)
|
||||
// then check if this regex object only flows into known natives and can
|
||||
// avoid cloning in this case.
|
||||
|
||||
// RegExpObjects embedded in scripts are immutable.
|
||||
AutoThreadSafeAccess ts(reobj);
|
||||
|
||||
bool mustClone = true;
|
||||
types::TypeObjectKey *typeObj = types::TypeObjectKey::get(&script()->global());
|
||||
if (!typeObj->hasFlags(constraints(), types::OBJECT_FLAG_REGEXP_FLAGS_SET)) {
|
||||
|
@ -787,17 +787,6 @@ class IonBuilder : public MIRGenerator
|
||||
// Constraints for recording dependencies on type information.
|
||||
types::CompilerConstraintList *constraints_;
|
||||
|
||||
mozilla::Maybe<AutoLockForCompilation> lock_;
|
||||
|
||||
void lock() {
|
||||
if (!analysisContext)
|
||||
lock_.construct(compartment);
|
||||
}
|
||||
void unlock() {
|
||||
if (!analysisContext)
|
||||
lock_.destroy();
|
||||
}
|
||||
|
||||
// Basic analysis information about the script.
|
||||
BytecodeAnalysis analysis_;
|
||||
BytecodeAnalysis &analysis() {
|
||||
|
@ -82,7 +82,6 @@ class JitCode : public gc::BarrieredCell<JitCode>
|
||||
|
||||
public:
|
||||
uint8_t *raw() const {
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return code_;
|
||||
}
|
||||
size_t instructionsSize() const {
|
||||
|
@ -787,10 +787,6 @@ MacroAssembler::initGCThing(const Register &obj, JSObject *templateObject)
|
||||
{
|
||||
// Fast initialization of an empty object returned by NewGCThing().
|
||||
|
||||
AutoThreadSafeAccess ts0(templateObject);
|
||||
AutoThreadSafeAccess ts1(templateObject->lastProperty());
|
||||
AutoThreadSafeAccess ts2(templateObject->lastProperty()->base()); // For isNative() assertions.
|
||||
|
||||
JS_ASSERT(!templateObject->hasDynamicElements());
|
||||
|
||||
storePtr(ImmGCPtr(templateObject->lastProperty()), Address(obj, JSObject::offsetOfShape()));
|
||||
@ -822,7 +818,7 @@ MacroAssembler::initGCThing(const Register &obj, JSObject *templateObject)
|
||||
|
||||
// Fixed slots of non-array objects are required to be initialized.
|
||||
// Use the values currently in the template object.
|
||||
size_t nslots = Min(templateObject->numFixedSlotsForCompilation(),
|
||||
size_t nslots = Min(templateObject->numFixedSlots(),
|
||||
templateObject->lastProperty()->slotSpan(templateObject->getClass()));
|
||||
for (unsigned i = 0; i < nslots; i++) {
|
||||
storeValue(templateObject->getFixedSlot(i),
|
||||
|
@ -33,10 +33,6 @@ JitOptions::JitOptions()
|
||||
// RangeAnalysis results.
|
||||
checkRangeAnalysis = false;
|
||||
|
||||
// Whether to protect the GC heap during Ion compilation and ensure that
|
||||
// only threadsafe operations are performed on it.
|
||||
checkThreadSafety = false;
|
||||
|
||||
// Whether Ion should compile try-catch statements.
|
||||
compileTryCatch = true;
|
||||
|
||||
|
@ -45,7 +45,6 @@ struct JitOptions
|
||||
bool checkOsiPointRegisters;
|
||||
#endif
|
||||
bool checkRangeAnalysis;
|
||||
bool checkThreadSafety;
|
||||
bool compileTryCatch;
|
||||
bool disableGvn;
|
||||
bool disableLicm;
|
||||
|
@ -257,13 +257,10 @@ IonBuilder::inlineArray(CallInfo &callInfo)
|
||||
|
||||
types::TemporaryTypeSet::DoubleConversion conversion =
|
||||
getInlineReturnTypeSet()->convertDoubleElements(constraints());
|
||||
{
|
||||
AutoThreadSafeAccess ts(templateObject);
|
||||
if (conversion == types::TemporaryTypeSet::AlwaysConvertToDoubles)
|
||||
templateObject->setShouldConvertDoubleElements();
|
||||
else
|
||||
templateObject->clearShouldConvertDoubleElements();
|
||||
}
|
||||
if (conversion == types::TemporaryTypeSet::AlwaysConvertToDoubles)
|
||||
templateObject->setShouldConvertDoubleElements();
|
||||
else
|
||||
templateObject->clearShouldConvertDoubleElements();
|
||||
|
||||
MNewArray *ins = MNewArray::New(alloc(), constraints(), initLength, templateObject,
|
||||
templateObject->type()->initialHeap(constraints()),
|
||||
|
@ -788,8 +788,6 @@ MStringLength::foldsTo(TempAllocator &alloc, bool useValueNumbers)
|
||||
if ((type() == MIRType_Int32) && (string()->isConstant())) {
|
||||
Value value = string()->toConstant()->value();
|
||||
JSAtom *atom = &value.toString()->asAtom();
|
||||
|
||||
AutoThreadSafeAccess ts(atom);
|
||||
return MConstant::New(alloc, Int32Value(atom->length()));
|
||||
}
|
||||
|
||||
@ -2607,7 +2605,6 @@ MBeta::printOpcode(FILE *fp) const
|
||||
bool
|
||||
MNewObject::shouldUseVM() const
|
||||
{
|
||||
AutoThreadSafeAccess ts(templateObject());
|
||||
return templateObject()->hasSingletonType() ||
|
||||
templateObject()->hasDynamicSlots();
|
||||
}
|
||||
|
@ -279,7 +279,6 @@ CodeGeneratorShared::encode(LSnapshot *snapshot)
|
||||
|
||||
#ifdef DEBUG
|
||||
if (GetIonContext()->cx) {
|
||||
AutoThreadSafeAccess ts(script);
|
||||
uint32_t stackDepth;
|
||||
bool reachablePC;
|
||||
if (!ReconstructStackDepth(GetIonContext()->cx, script, bailPC, &stackDepth, &reachablePC))
|
||||
|
@ -31,7 +31,6 @@ namespace js {
|
||||
inline jsid
|
||||
AtomToId(JSAtom *atom)
|
||||
{
|
||||
AutoThreadSafeAccess ts(atom);
|
||||
JS_STATIC_ASSERT(JSID_INT_MIN == 0);
|
||||
|
||||
uint32_t index;
|
||||
|
@ -29,8 +29,6 @@ BooleanGetPrimitiveValue(HandleObject obj, JSContext *cx)
|
||||
inline bool
|
||||
EmulatesUndefined(JSObject *obj)
|
||||
{
|
||||
AutoThreadSafeAccess ts0(obj);
|
||||
AutoThreadSafeAccess ts1(obj->typeRaw());
|
||||
JSObject *actual = MOZ_LIKELY(!obj->is<WrapperObject>()) ? obj : UncheckedUnwrap(obj);
|
||||
return actual->getClass()->emulatesUndefined();
|
||||
}
|
||||
|
@ -116,7 +116,6 @@ js::ExistingCloneFunctionAtCallsite(const CallsiteCloneTable &table, JSFunction
|
||||
JS_ASSERT(fun->nonLazyScript()->shouldCloneAtCallsite());
|
||||
JS_ASSERT(!fun->nonLazyScript()->enclosingStaticScope());
|
||||
JS_ASSERT(types::UseNewTypeForClone(fun));
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
|
||||
/*
|
||||
* If we start allocating function objects in the nursery, then the callsite
|
||||
@ -154,8 +153,6 @@ js::CloneFunctionAtCallsite(JSContext *cx, HandleFunction fun, HandleScript scri
|
||||
typedef CallsiteCloneKey Key;
|
||||
typedef CallsiteCloneTable Table;
|
||||
|
||||
AutoLockForCompilation lock(cx);
|
||||
|
||||
Table &table = cx->compartment()->callsiteClones;
|
||||
if (!table.initialized() && !table.init())
|
||||
return nullptr;
|
||||
|
@ -1087,69 +1087,6 @@ class AutoLockForExclusiveAccess
|
||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
};
|
||||
|
||||
class AutoLockForCompilation
|
||||
{
|
||||
#ifdef JS_THREADSAFE
|
||||
JSRuntime *runtime;
|
||||
|
||||
void init(JSRuntime *rt) {
|
||||
runtime = rt;
|
||||
if (runtime->numCompilationThreads) {
|
||||
runtime->assertCanLock(CompilationLock);
|
||||
PR_Lock(runtime->compilationLock);
|
||||
#ifdef DEBUG
|
||||
runtime->compilationLockOwner = PR_GetCurrentThread();
|
||||
#endif
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
JS_ASSERT(!runtime->mainThreadHasCompilationLock);
|
||||
runtime->mainThreadHasCompilationLock = true;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
AutoLockForCompilation(ExclusiveContext *cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM) {
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
if (cx->isJSContext())
|
||||
init(cx->asJSContext()->runtime());
|
||||
else
|
||||
runtime = nullptr;
|
||||
}
|
||||
AutoLockForCompilation(jit::CompileCompartment *compartment MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
|
||||
~AutoLockForCompilation() {
|
||||
if (runtime) {
|
||||
if (runtime->numCompilationThreads) {
|
||||
JS_ASSERT(runtime->compilationLockOwner == PR_GetCurrentThread());
|
||||
#ifdef DEBUG
|
||||
runtime->compilationLockOwner = nullptr;
|
||||
#endif
|
||||
PR_Unlock(runtime->compilationLock);
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
JS_ASSERT(runtime->mainThreadHasCompilationLock);
|
||||
runtime->mainThreadHasCompilationLock = false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
#else // JS_THREADSAFE
|
||||
public:
|
||||
AutoLockForCompilation(ExclusiveContext *cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM) {
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
}
|
||||
AutoLockForCompilation(jit::CompileCompartment *compartment MOZ_GUARD_OBJECT_NOTIFIER_PARAM) {
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
}
|
||||
~AutoLockForCompilation() {
|
||||
// An empty destructor is needed to avoid warnings from clang about
|
||||
// unused local variables of this type.
|
||||
}
|
||||
#endif // JS_THREADSAFE
|
||||
|
||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
};
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
@ -22,14 +22,7 @@ JSCompartment::initGlobal(js::GlobalObject &global)
|
||||
js::GlobalObject *
|
||||
JSCompartment::maybeGlobal() const
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (global_) {
|
||||
js::AutoThreadSafeAccess ts0(global_);
|
||||
js::AutoThreadSafeAccess ts1(global_->lastProperty());
|
||||
js::AutoThreadSafeAccess ts2(global_->lastProperty()->base());
|
||||
JS_ASSERT(global_->compartment() == this);
|
||||
}
|
||||
#endif
|
||||
JS_ASSERT_IF(global_, global_->compartment() == this);
|
||||
return global_;
|
||||
}
|
||||
|
||||
|
@ -1150,7 +1150,6 @@ JSFunction::createScriptForLazilyInterpretedFunction(JSContext *cx, HandleFuncti
|
||||
RootedScript script(cx, lazy->maybeScript());
|
||||
|
||||
if (script) {
|
||||
AutoLockForCompilation lock(cx);
|
||||
fun->setUnlazifiedScript(script);
|
||||
// Remember the lazy script on the compiled script, so it can be
|
||||
// stored on the function again in case of re-lazification.
|
||||
@ -1167,7 +1166,6 @@ JSFunction::createScriptForLazilyInterpretedFunction(JSContext *cx, HandleFuncti
|
||||
if (!script)
|
||||
return false;
|
||||
|
||||
AutoLockForCompilation lock(cx);
|
||||
fun->setUnlazifiedScript(script);
|
||||
return true;
|
||||
}
|
||||
@ -1196,10 +1194,7 @@ JSFunction::createScriptForLazilyInterpretedFunction(JSContext *cx, HandleFuncti
|
||||
fun->initAtom(script->functionNonDelazifying()->displayAtom());
|
||||
clonedScript->setFunction(fun);
|
||||
|
||||
{
|
||||
AutoLockForCompilation lock(cx);
|
||||
fun->setUnlazifiedScript(clonedScript);
|
||||
}
|
||||
fun->setUnlazifiedScript(clonedScript);
|
||||
|
||||
CallNewScriptHook(cx, clonedScript, fun);
|
||||
|
||||
|
@ -105,12 +105,10 @@ class JSFunction : public JSObject
|
||||
}
|
||||
|
||||
size_t nargs() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return nargs_;
|
||||
}
|
||||
|
||||
uint16_t flags() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return flags_;
|
||||
}
|
||||
|
||||
@ -134,14 +132,10 @@ class JSFunction : public JSObject
|
||||
return flags() & SH_WRAPPABLE;
|
||||
}
|
||||
|
||||
// Functions can change between being lazily interpreted and having scripts
|
||||
// when under the compilation lock.
|
||||
bool isInterpretedLazy() const {
|
||||
JS_ASSERT(js::CurrentThreadCanReadCompilationData());
|
||||
return flags() & INTERPRETED_LAZY;
|
||||
}
|
||||
bool hasScript() const {
|
||||
JS_ASSERT(js::CurrentThreadCanReadCompilationData());
|
||||
return flags() & INTERPRETED;
|
||||
}
|
||||
|
||||
@ -238,7 +232,6 @@ class JSFunction : public JSObject
|
||||
void initAtom(JSAtom *atom) { atom_.init(atom); }
|
||||
|
||||
JSAtom *displayAtom() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return atom_;
|
||||
}
|
||||
|
||||
@ -258,7 +251,6 @@ class JSFunction : public JSObject
|
||||
* activations (stack frames) of the function.
|
||||
*/
|
||||
JSObject *environment() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
JS_ASSERT(isInterpreted());
|
||||
return u.i.env_;
|
||||
}
|
||||
@ -332,8 +324,6 @@ class JSFunction : public JSObject
|
||||
}
|
||||
|
||||
JSScript *nonLazyScript() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
JS_ASSERT(js::CurrentThreadCanReadCompilationData());
|
||||
JS_ASSERT(hasScript());
|
||||
JS_ASSERT(u.i.s.script_);
|
||||
return u.i.s.script_;
|
||||
@ -355,16 +345,12 @@ class JSFunction : public JSObject
|
||||
}
|
||||
|
||||
js::LazyScript *lazyScript() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
JS_ASSERT(isInterpretedLazy() && u.i.s.lazy_);
|
||||
JS_ASSERT(js::CurrentThreadCanReadCompilationData());
|
||||
return u.i.s.lazy_;
|
||||
}
|
||||
|
||||
js::LazyScript *lazyScriptOrNull() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
JS_ASSERT(isInterpretedLazy());
|
||||
JS_ASSERT(js::CurrentThreadCanReadCompilationData());
|
||||
return u.i.s.lazy_;
|
||||
}
|
||||
|
||||
@ -398,7 +384,6 @@ class JSFunction : public JSObject
|
||||
void setUnlazifiedScript(JSScript *script) {
|
||||
// Note: createScriptForLazilyInterpretedFunction triggers a barrier on
|
||||
// lazy script before it is overwritten here.
|
||||
JS_ASSERT(js::CurrentThreadCanWriteCompilationData());
|
||||
JS_ASSERT(isInterpretedLazy());
|
||||
if (!lazyScript()->maybeScript())
|
||||
lazyScript()->initScript(script);
|
||||
@ -415,7 +400,6 @@ class JSFunction : public JSObject
|
||||
}
|
||||
|
||||
JSNative native() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
JS_ASSERT(isNative());
|
||||
return u.n.native;
|
||||
}
|
||||
@ -440,7 +424,6 @@ class JSFunction : public JSObject
|
||||
}
|
||||
|
||||
const JSJitInfo *jitInfo() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
JS_ASSERT(isNative());
|
||||
return u.n.jitinfo;
|
||||
}
|
||||
|
@ -688,9 +688,6 @@ TypeScript::FreezeTypeSets(CompilerConstraintList *constraints, JSScript *script
|
||||
TemporaryTypeSet **pArgTypes,
|
||||
TemporaryTypeSet **pBytecodeTypes)
|
||||
{
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
AutoThreadSafeAccess ts(script);
|
||||
|
||||
LifoAlloc *alloc = constraints->alloc();
|
||||
StackTypeSet *existing = script->types->typeArray();
|
||||
|
||||
@ -810,7 +807,6 @@ TypeObjectKey::proto()
|
||||
bool
|
||||
ObjectImpl::hasTenuredProto() const
|
||||
{
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return type_->hasTenuredProto();
|
||||
}
|
||||
|
||||
@ -856,7 +852,6 @@ HeapTypeSetKey
|
||||
TypeObjectKey::property(jsid id)
|
||||
{
|
||||
JS_ASSERT(!unknownProperties());
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
|
||||
HeapTypeSetKey property;
|
||||
property.object_ = this;
|
||||
@ -1513,10 +1508,8 @@ ObjectStateChange(ExclusiveContext *cxArg, TypeObject *object, bool markingUnkno
|
||||
HeapTypeSet *types = object->maybeGetProperty(JSID_EMPTY);
|
||||
|
||||
/* Mark as unknown after getting the types, to avoid assertion. */
|
||||
if (markingUnknown) {
|
||||
AutoLockForCompilation lock(cxArg);
|
||||
if (markingUnknown)
|
||||
object->addFlags(OBJECT_FLAG_DYNAMIC_MASK | OBJECT_FLAG_UNKNOWN_PROPERTIES);
|
||||
}
|
||||
|
||||
if (types) {
|
||||
if (JSContext *cx = cxArg->maybeJSContext()) {
|
||||
@ -2336,7 +2329,6 @@ TypeCompartment::markSetsUnknown(JSContext *cx, TypeObject *target)
|
||||
}
|
||||
}
|
||||
|
||||
AutoLockForCompilation lock(cx);
|
||||
target->addFlags(OBJECT_FLAG_SETS_MARKED_UNKNOWN);
|
||||
}
|
||||
|
||||
@ -2756,28 +2748,9 @@ TypeCompartment::newTypedObject(JSContext *cx, IdValuePair *properties, size_t n
|
||||
// TypeObject
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef DEBUG
|
||||
void
|
||||
TypeObject::assertCanAccessProto() const
|
||||
{
|
||||
// The proto pointer for type objects representing singletons may move.
|
||||
JS_ASSERT_IF(singleton(), CurrentThreadCanReadCompilationData());
|
||||
|
||||
// Any proto pointer which is in the nursery may be moved, and may not be
|
||||
// accessed during off thread compilation.
|
||||
#if defined(JSGC_GENERATIONAL) && defined(JS_THREADSAFE)
|
||||
PerThreadData *pt = TlsPerThreadData.get();
|
||||
TaggedProto proto(proto_);
|
||||
JS_ASSERT_IF(proto.isObject() && !proto.toObject()->isTenured(),
|
||||
!pt || !pt->ionCompiling);
|
||||
#endif
|
||||
}
|
||||
#endif // DEBUG
|
||||
|
||||
void
|
||||
TypeObject::setProto(JSContext *cx, TaggedProto proto)
|
||||
{
|
||||
JS_ASSERT(CurrentThreadCanWriteCompilationData());
|
||||
JS_ASSERT(singleton());
|
||||
|
||||
if (proto.isObject() && IsInsideNursery(cx->runtime(), proto.toObject()))
|
||||
@ -3056,10 +3029,7 @@ TypeObject::setFlags(ExclusiveContext *cx, TypeObjectFlags flags)
|
||||
singleton()->lastProperty()->hasObjectFlag(BaseShape::ITERATED_SINGLETON));
|
||||
}
|
||||
|
||||
{
|
||||
AutoLockForCompilation lock(cx);
|
||||
addFlags(flags);
|
||||
}
|
||||
addFlags(flags);
|
||||
|
||||
InferSpew(ISpewOps, "%s: setFlags 0x%x", TypeObjectString(this), flags);
|
||||
|
||||
@ -3104,10 +3074,8 @@ void
|
||||
TypeObject::clearAddendum(ExclusiveContext *cx)
|
||||
{
|
||||
JS_ASSERT(!(flags() & OBJECT_FLAG_ADDENDUM_CLEARED));
|
||||
{
|
||||
AutoLockForCompilation lock(cx);
|
||||
addFlags(OBJECT_FLAG_ADDENDUM_CLEARED);
|
||||
}
|
||||
|
||||
addFlags(OBJECT_FLAG_ADDENDUM_CLEARED);
|
||||
|
||||
/*
|
||||
* It is possible for the object to not have a new script or other
|
||||
@ -3521,10 +3489,7 @@ CheckNewScriptProperties(JSContext *cx, TypeObject *type, JSFunction *fun)
|
||||
#endif
|
||||
new (newScript) TypeNewScript();
|
||||
|
||||
{
|
||||
AutoLockForCompilation lock(cx);
|
||||
type->setAddendum(newScript);
|
||||
}
|
||||
type->setAddendum(newScript);
|
||||
|
||||
if (!newScript) {
|
||||
cx->compartment()->types.setPendingNukeTypes(cx);
|
||||
@ -3692,10 +3657,7 @@ JSScript::makeTypes(JSContext *cx)
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
new (&typeArray[i]) StackTypeSet();
|
||||
|
||||
{
|
||||
AutoLockForCompilation lock(cx);
|
||||
types = typeScript;
|
||||
}
|
||||
types = typeScript;
|
||||
|
||||
#ifdef DEBUG
|
||||
for (unsigned i = 0; i < nTypeSets(); i++) {
|
||||
@ -3825,12 +3787,8 @@ JSObject::splicePrototype(JSContext *cx, const Class *clasp, Handle<TaggedProto>
|
||||
return true;
|
||||
}
|
||||
|
||||
{
|
||||
AutoLockForCompilation lock(cx);
|
||||
type->setClasp(clasp);
|
||||
type->setProto(cx, proto);
|
||||
}
|
||||
|
||||
type->setClasp(clasp);
|
||||
type->setProto(cx, proto);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3883,10 +3841,7 @@ JSObject::makeLazyType(JSContext *cx, HandleObject obj)
|
||||
if (obj->is<JSFunction>() && obj->as<JSFunction>().isInterpreted())
|
||||
type->interpretedFunction = &obj->as<JSFunction>();
|
||||
|
||||
{
|
||||
AutoLockForCompilation lock(cx);
|
||||
obj->type_ = type;
|
||||
}
|
||||
obj->type_ = type;
|
||||
|
||||
return type;
|
||||
}
|
||||
@ -4628,7 +4583,6 @@ TypeScript::printTypes(JSContext *cx, HandleScript script) const
|
||||
void
|
||||
TypeObject::setAddendum(TypeObjectAddendum *addendum)
|
||||
{
|
||||
JS_ASSERT(CurrentThreadCanWriteCompilationData());
|
||||
this->addendum = addendum;
|
||||
}
|
||||
|
||||
|
@ -27,11 +27,6 @@ namespace js {
|
||||
|
||||
class TypeDescr;
|
||||
|
||||
#ifdef DEBUG
|
||||
bool CurrentThreadCanWriteCompilationData();
|
||||
bool CurrentThreadCanReadCompilationData();
|
||||
#endif
|
||||
|
||||
class TaggedProto
|
||||
{
|
||||
public:
|
||||
@ -890,12 +885,6 @@ struct TypeObject : gc::BarrieredCell<TypeObject>
|
||||
/* Prototype shared by objects using this type. */
|
||||
HeapPtrObject proto_;
|
||||
|
||||
#ifdef DEBUG
|
||||
void assertCanAccessProto() const;
|
||||
#else
|
||||
void assertCanAccessProto() const {}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Whether there is a singleton JS object with this type. That JS object
|
||||
* must appear in type sets instead of this; we include the back reference
|
||||
@ -906,24 +895,19 @@ struct TypeObject : gc::BarrieredCell<TypeObject>
|
||||
public:
|
||||
|
||||
const Class *clasp() const {
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return clasp_;
|
||||
}
|
||||
|
||||
void setClasp(const Class *clasp) {
|
||||
JS_ASSERT(CurrentThreadCanWriteCompilationData());
|
||||
JS_ASSERT(singleton());
|
||||
clasp_ = clasp;
|
||||
}
|
||||
|
||||
TaggedProto proto() const {
|
||||
AutoThreadSafeAccess ts(this);
|
||||
assertCanAccessProto();
|
||||
return TaggedProto(proto_);
|
||||
}
|
||||
|
||||
JSObject *singleton() const {
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return singleton_;
|
||||
}
|
||||
|
||||
@ -965,42 +949,30 @@ struct TypeObject : gc::BarrieredCell<TypeObject>
|
||||
public:
|
||||
|
||||
TypeObjectFlags flags() const {
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return flags_;
|
||||
}
|
||||
|
||||
void addFlags(TypeObjectFlags flags) {
|
||||
JS_ASSERT(CurrentThreadCanWriteCompilationData());
|
||||
flags_ |= flags;
|
||||
}
|
||||
|
||||
void clearFlags(TypeObjectFlags flags) {
|
||||
JS_ASSERT(CurrentThreadCanWriteCompilationData());
|
||||
flags_ &= ~flags;
|
||||
}
|
||||
|
||||
bool hasNewScript() const {
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return addendum && addendum->isNewScript();
|
||||
}
|
||||
|
||||
TypeNewScript *newScript() {
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return addendum->asNewScript();
|
||||
}
|
||||
|
||||
bool hasTypedObject() {
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return addendum && addendum->isTypedObject();
|
||||
}
|
||||
|
||||
TypeTypedObject *typedObject() {
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return addendum->asTypedObject();
|
||||
}
|
||||
|
||||
|
@ -87,7 +87,6 @@ Type::ObjectType(JSObject *obj)
|
||||
/* static */ inline Type
|
||||
Type::ObjectType(TypeObject *obj)
|
||||
{
|
||||
AutoThreadSafeAccess ts(obj);
|
||||
if (obj->singleton())
|
||||
return Type(uintptr_t(obj->singleton()) | 1);
|
||||
return Type(uintptr_t(obj));
|
||||
@ -178,7 +177,6 @@ IdToTypeId(jsid id)
|
||||
*/
|
||||
if (JSID_IS_STRING(id)) {
|
||||
JSAtom *atom = JSID_TO_ATOM(id);
|
||||
js::AutoThreadSafeAccess ts(atom);
|
||||
JS::TwoByteChars cp = atom->range();
|
||||
if (cp.length() > 0 && (JS7_ISDEC(cp[0]) || cp[0] == '-')) {
|
||||
for (size_t i = 1; i < cp.length(); ++i) {
|
||||
@ -565,7 +563,6 @@ TypeScript::NumTypeSets(JSScript *script)
|
||||
/* static */ inline StackTypeSet *
|
||||
TypeScript::ThisTypes(JSScript *script)
|
||||
{
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
return script->types->typeArray() + script->nTypeSets() + analyze::ThisSlot();
|
||||
}
|
||||
|
||||
@ -579,7 +576,6 @@ TypeScript::ThisTypes(JSScript *script)
|
||||
TypeScript::ArgTypes(JSScript *script, unsigned i)
|
||||
{
|
||||
JS_ASSERT(i < script->functionNonDelazifying()->nargs());
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
return script->types->typeArray() + script->nTypeSets() + analyze::ArgSlot(i);
|
||||
}
|
||||
|
||||
@ -1128,12 +1124,9 @@ ConstraintTypeSet::addType(ExclusiveContext *cxArg, Type type)
|
||||
if (hasType(type))
|
||||
return;
|
||||
|
||||
{
|
||||
AutoLockForCompilation lock(cxArg);
|
||||
if (!TypeSet::addType(type, &cxArg->typeLifoAlloc())) {
|
||||
cxArg->compartment()->types.setPendingNukeTypes(cxArg);
|
||||
return;
|
||||
}
|
||||
if (!TypeSet::addType(type, &cxArg->typeLifoAlloc())) {
|
||||
cxArg->compartment()->types.setPendingNukeTypes(cxArg);
|
||||
return;
|
||||
}
|
||||
|
||||
InferSpew(ISpewOps, "addType: %sT%p%s %s",
|
||||
@ -1277,7 +1270,6 @@ inline TypeObject::TypeObject(const Class *clasp, TaggedProto proto, TypeObjectF
|
||||
inline uint32_t
|
||||
TypeObject::basePropertyCount() const
|
||||
{
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
return (flags() & OBJECT_FLAG_PROPERTY_COUNT_MASK) >> OBJECT_FLAG_PROPERTY_COUNT_SHIFT;
|
||||
}
|
||||
|
||||
@ -1302,27 +1294,21 @@ TypeObject::getProperty(ExclusiveContext *cx, jsid id)
|
||||
if (HeapTypeSet *types = maybeGetProperty(id))
|
||||
return types;
|
||||
|
||||
uint32_t propertyCount;
|
||||
Property **pprop;
|
||||
{
|
||||
AutoLockForCompilation lock(cx);
|
||||
uint32_t propertyCount = basePropertyCount();
|
||||
Property **pprop = HashSetInsert<jsid,Property,Property>
|
||||
(cx->typeLifoAlloc(), propertySet, propertyCount, id);
|
||||
if (!pprop) {
|
||||
cx->compartment()->types.setPendingNukeTypes(cx);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
propertyCount = basePropertyCount();
|
||||
pprop = HashSetInsert<jsid,Property,Property>
|
||||
(cx->typeLifoAlloc(), propertySet, propertyCount, id);
|
||||
if (!pprop) {
|
||||
cx->compartment()->types.setPendingNukeTypes(cx);
|
||||
return nullptr;
|
||||
}
|
||||
JS_ASSERT(!*pprop);
|
||||
|
||||
JS_ASSERT(!*pprop);
|
||||
|
||||
setBasePropertyCount(propertyCount);
|
||||
if (!addProperty(cx, id, pprop)) {
|
||||
setBasePropertyCount(0);
|
||||
propertySet = nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
setBasePropertyCount(propertyCount);
|
||||
if (!addProperty(cx, id, pprop)) {
|
||||
setBasePropertyCount(0);
|
||||
propertySet = nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (propertyCount == OBJECT_FLAG_PROPERTY_COUNT_LIMIT) {
|
||||
@ -1350,9 +1336,6 @@ TypeObject::maybeGetProperty(jsid id)
|
||||
JS_ASSERT(JSID_IS_VOID(id) || JSID_IS_EMPTY(id) || JSID_IS_STRING(id));
|
||||
JS_ASSERT_IF(!JSID_IS_EMPTY(id), id == IdToTypeId(id));
|
||||
JS_ASSERT(!unknownProperties());
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
|
||||
AutoThreadSafeAccess ts(this);
|
||||
|
||||
Property *prop = HashSetLookup<jsid,Property,Property>
|
||||
(propertySet, basePropertyCount(), id);
|
||||
|
@ -2048,7 +2048,6 @@ GlobalObject::initIteratorClasses(JSContext *cx, Handle<GlobalObject *> global)
|
||||
if (!LinkConstructorAndPrototype(cx, genFunction, genFunctionProto))
|
||||
return false;
|
||||
|
||||
AutoLockForCompilation lock(cx);
|
||||
global->setSlot(STAR_GENERATOR_OBJECT_PROTO, ObjectValue(*genObjectProto));
|
||||
global->setConstructor(JSProto_GeneratorFunction, ObjectValue(*genFunction));
|
||||
global->setPrototype(JSProto_GeneratorFunction, ObjectValue(*genFunctionProto));
|
||||
|
@ -2250,12 +2250,9 @@ JSObject::TradeGuts(JSContext *cx, JSObject *a, JSObject *b, TradeGutsReserved &
|
||||
* Swap the object's types, to restore their initial type information.
|
||||
* The prototypes and classes of the objects were swapped in ReserveForTradeGuts.
|
||||
*/
|
||||
{
|
||||
AutoLockForCompilation lock(cx);
|
||||
TypeObject *tmp = a->type_;
|
||||
a->type_ = b->type_;
|
||||
b->type_ = tmp;
|
||||
}
|
||||
TypeObject *tmp = a->type_;
|
||||
a->type_ = b->type_;
|
||||
b->type_ = tmp;
|
||||
|
||||
/* Don't try to swap a JSFunction for a plain function JSObject. */
|
||||
JS_ASSERT_IF(a->is<JSFunction>(), a->tenuredSizeOfThis() == b->tenuredSizeOfThis());
|
||||
@ -2287,12 +2284,9 @@ JSObject::TradeGuts(JSContext *cx, JSObject *a, JSObject *b, TradeGutsReserved &
|
||||
char tmp[mozilla::tl::Max<sizeof(JSFunction), sizeof(JSObject_Slots16)>::value];
|
||||
JS_ASSERT(size <= sizeof(tmp));
|
||||
|
||||
{
|
||||
AutoLockForCompilation lock(cx);
|
||||
js_memcpy(tmp, a, size);
|
||||
js_memcpy(a, b, size);
|
||||
js_memcpy(b, tmp, size);
|
||||
}
|
||||
js_memcpy(tmp, a, size);
|
||||
js_memcpy(a, b, size);
|
||||
js_memcpy(b, tmp, size);
|
||||
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
/*
|
||||
@ -2330,12 +2324,9 @@ JSObject::TradeGuts(JSContext *cx, JSObject *a, JSObject *b, TradeGutsReserved &
|
||||
void *bpriv = b->hasPrivate() ? b->getPrivate() : nullptr;
|
||||
|
||||
char tmp[sizeof(JSObject)];
|
||||
{
|
||||
AutoLockForCompilation lock(cx);
|
||||
js_memcpy(&tmp, a, sizeof tmp);
|
||||
js_memcpy(a, b, sizeof tmp);
|
||||
js_memcpy(b, &tmp, sizeof tmp);
|
||||
}
|
||||
js_memcpy(&tmp, a, sizeof tmp);
|
||||
js_memcpy(a, b, sizeof tmp);
|
||||
js_memcpy(b, &tmp, sizeof tmp);
|
||||
|
||||
if (a->isNative())
|
||||
a->shape_->setNumFixedSlots(reserved.newafixed);
|
||||
@ -2785,12 +2776,6 @@ JSObject::growSlots(ThreadSafeContext *cx, HandleObject obj, uint32_t oldCount,
|
||||
}
|
||||
}
|
||||
|
||||
// Global slots may be read during off thread compilation, and updates to
|
||||
// their slot pointers need to be synchronized.
|
||||
Maybe<AutoLockForCompilation> lock;
|
||||
if (obj->is<GlobalObject>())
|
||||
lock.construct(cx->asExclusiveContext());
|
||||
|
||||
if (!oldCount) {
|
||||
obj->slots = AllocateSlots(cx, obj, newCount);
|
||||
if (!obj->slots)
|
||||
@ -2835,12 +2820,6 @@ JSObject::shrinkSlots(ThreadSafeContext *cx, HandleObject obj, uint32_t oldCount
|
||||
|
||||
JS_ASSERT_IF(!obj->is<ArrayObject>(), newCount >= SLOT_CAPACITY_MIN);
|
||||
|
||||
// Global slots may be read during off thread compilation, and updates to
|
||||
// their slot pointers need to be synchronized.
|
||||
Maybe<AutoLockForCompilation> lock;
|
||||
if (obj->is<GlobalObject>())
|
||||
lock.construct(cx->asExclusiveContext());
|
||||
|
||||
HeapSlot *newslots = ReallocateSlots(cx, obj, obj->slots, oldCount, newCount);
|
||||
if (!newslots)
|
||||
return; /* Leave slots at its old size. */
|
||||
@ -3227,10 +3206,7 @@ js::SetClassAndProto(JSContext *cx, HandleObject obj,
|
||||
MarkTypeObjectUnknownProperties(cx, obj->type(), true);
|
||||
MarkTypeObjectUnknownProperties(cx, type, true);
|
||||
|
||||
{
|
||||
AutoLockForCompilation lock(cx);
|
||||
obj->setType(type);
|
||||
}
|
||||
obj->setType(type);
|
||||
|
||||
*succeeded = true;
|
||||
return true;
|
||||
@ -4303,7 +4279,7 @@ NativeGetInline(JSContext *cx,
|
||||
case JSOP_GETPROP:
|
||||
case JSOP_CALLPROP:
|
||||
case JSOP_LENGTH:
|
||||
script->baselineScript()->noteAccessedGetter(cx, script->pcToOffset(pc));
|
||||
script->baselineScript()->noteAccessedGetter(script->pcToOffset(pc));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -5697,8 +5673,6 @@ DumpProperty(JSObject *obj, Shape &shape)
|
||||
bool
|
||||
JSObject::uninlinedIsProxy() const
|
||||
{
|
||||
AutoThreadSafeAccess ts0(this);
|
||||
AutoThreadSafeAccess ts1(type_);
|
||||
return is<ProxyObject>();
|
||||
}
|
||||
|
||||
|
@ -289,10 +289,6 @@ class JSObject : public js::ObjectImpl
|
||||
}
|
||||
|
||||
bool isBoundFunction() const {
|
||||
// Note: This function can race when it is called during off thread compilation.
|
||||
js::AutoThreadSafeAccess ts0(this);
|
||||
js::AutoThreadSafeAccess ts1(lastProperty());
|
||||
js::AutoThreadSafeAccess ts2(lastProperty()->base());
|
||||
return lastProperty()->hasObjectFlag(js::BaseShape::BOUND_FUNCTION);
|
||||
}
|
||||
|
||||
@ -354,10 +350,6 @@ class JSObject : public js::ObjectImpl
|
||||
return lastProperty()->entryCount();
|
||||
}
|
||||
|
||||
uint32_t propertyCountForCompilation() const {
|
||||
return lastProperty()->entryCountForCompilation();
|
||||
}
|
||||
|
||||
bool hasShapeTable() const {
|
||||
return lastProperty()->hasTable();
|
||||
}
|
||||
@ -376,13 +368,13 @@ class JSObject : public js::ObjectImpl
|
||||
|
||||
/* Whether a slot is at a fixed offset from this object. */
|
||||
bool isFixedSlot(size_t slot) {
|
||||
return slot < numFixedSlotsForCompilation();
|
||||
return slot < numFixedSlots();
|
||||
}
|
||||
|
||||
/* Index into the dynamic slots array to use for a dynamic slot. */
|
||||
size_t dynamicSlotIndex(size_t slot) {
|
||||
JS_ASSERT(slot >= numFixedSlotsForCompilation());
|
||||
return slot - numFixedSlotsForCompilation();
|
||||
JS_ASSERT(slot >= numFixedSlots());
|
||||
return slot - numFixedSlots();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -400,9 +400,6 @@ JSObject::clearType(JSContext *cx, js::HandleObject obj)
|
||||
inline void
|
||||
JSObject::setType(js::types::TypeObject *newType)
|
||||
{
|
||||
// Note: This is usually called for newly created objects that haven't
|
||||
// escaped to script yet, so don't require that the compilation lock be
|
||||
// held here.
|
||||
JS_ASSERT(newType);
|
||||
JS_ASSERT(!hasSingletonType());
|
||||
type_ = newType;
|
||||
@ -999,11 +996,8 @@ DefineConstructorAndPrototype(JSContext *cx, Handle<GlobalObject*> global,
|
||||
JS_ASSERT(!global->nativeLookup(cx, id));
|
||||
|
||||
/* Set these first in case AddTypePropertyId looks for this class. */
|
||||
{
|
||||
AutoLockForCompilation lock(cx);
|
||||
global->setConstructor(key, ObjectValue(*ctor));
|
||||
global->setPrototype(key, ObjectValue(*proto));
|
||||
}
|
||||
global->setConstructor(key, ObjectValue(*ctor));
|
||||
global->setPrototype(key, ObjectValue(*proto));
|
||||
global->setConstructorPropertySlot(key, ObjectValue(*ctor));
|
||||
|
||||
if (!global->addDataProperty(cx, id, GlobalObject::constructorPropertySlot(key), 0)) {
|
||||
|
@ -3167,10 +3167,7 @@ JSScript::argumentsOptimizationFailed(JSContext *cx, HandleScript script)
|
||||
|
||||
JS_ASSERT(!script->isGenerator());
|
||||
|
||||
{
|
||||
AutoLockForCompilation lock(cx);
|
||||
script->needsArgsObj_ = true;
|
||||
}
|
||||
script->needsArgsObj_ = true;
|
||||
|
||||
#ifdef JS_ION
|
||||
/*
|
||||
@ -3230,14 +3227,12 @@ JSScript::argumentsOptimizationFailed(JSContext *cx, HandleScript script)
|
||||
bool
|
||||
JSScript::varIsAliased(uint32_t varSlot)
|
||||
{
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return bindings.bindingIsAliased(bindings.numArgs() + varSlot);
|
||||
}
|
||||
|
||||
bool
|
||||
JSScript::formalIsAliased(unsigned argSlot)
|
||||
{
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return bindings.bindingIsAliased(argSlot);
|
||||
}
|
||||
|
||||
|
@ -249,8 +249,6 @@ class Bindings
|
||||
if (!callObjShape_)
|
||||
return false;
|
||||
|
||||
// Binding shapes are immutable once constructed.
|
||||
AutoThreadSafeAccess ts(callObjShape_);
|
||||
return !callObjShape_->isEmptyShape();
|
||||
}
|
||||
|
||||
@ -554,10 +552,6 @@ class ScriptSourceObject : public JSObject
|
||||
const ReadOnlyCompileOptions &options);
|
||||
|
||||
ScriptSource *source() {
|
||||
// Script source objects are immutable.
|
||||
AutoThreadSafeAccess ts0(this);
|
||||
AutoThreadSafeAccess ts1(lastProperty());
|
||||
AutoThreadSafeAccess ts2(lastProperty()->base());
|
||||
return static_cast<ScriptSource *>(getReservedSlot(SOURCE_SLOT).toPrivate());
|
||||
}
|
||||
|
||||
@ -638,22 +632,18 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
|
||||
(and arguments if this is a function script) */
|
||||
|
||||
bool hasAnyAliasedBindings() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return bindings.hasAnyAliasedBindings();
|
||||
}
|
||||
|
||||
js::Binding *bindingArray() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return bindings.bindingArray();
|
||||
}
|
||||
|
||||
unsigned numArgs() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return bindings.numArgs();
|
||||
}
|
||||
|
||||
js::Shape *callObjShape() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return bindings.callObjShape();
|
||||
}
|
||||
|
||||
@ -889,11 +879,9 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
|
||||
|
||||
// Script bytecode is immutable after creation.
|
||||
jsbytecode *code() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return code_;
|
||||
}
|
||||
size_t length() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return length_;
|
||||
}
|
||||
|
||||
@ -917,94 +905,77 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
|
||||
}
|
||||
|
||||
size_t mainOffset() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return mainOffset_;
|
||||
}
|
||||
|
||||
size_t lineno() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return lineno_;
|
||||
}
|
||||
|
||||
size_t column() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return column_;
|
||||
}
|
||||
|
||||
void setColumn(size_t column) { column_ = column; }
|
||||
|
||||
size_t nfixed() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return function_ ? bindings.numVars() : 0;
|
||||
}
|
||||
|
||||
size_t nslots() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return nslots_;
|
||||
}
|
||||
|
||||
size_t staticLevel() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return staticLevel_;
|
||||
}
|
||||
|
||||
size_t nTypeSets() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return nTypeSets_;
|
||||
}
|
||||
|
||||
size_t funLength() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return funLength_;
|
||||
}
|
||||
|
||||
size_t sourceStart() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return sourceStart_;
|
||||
}
|
||||
|
||||
size_t sourceEnd() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return sourceEnd_;
|
||||
}
|
||||
|
||||
bool noScriptRval() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return noScriptRval_;
|
||||
}
|
||||
|
||||
bool savedCallerFun() const { return savedCallerFun_; }
|
||||
|
||||
bool strict() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return strict_;
|
||||
}
|
||||
|
||||
bool explicitUseStrict() const { return explicitUseStrict_; }
|
||||
|
||||
bool compileAndGo() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return compileAndGo_;
|
||||
}
|
||||
|
||||
bool selfHosted() const { return selfHosted_; }
|
||||
bool bindingsAccessedDynamically() const { return bindingsAccessedDynamically_; }
|
||||
bool funHasExtensibleScope() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return funHasExtensibleScope_;
|
||||
}
|
||||
bool funNeedsDeclEnvObject() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return funNeedsDeclEnvObject_;
|
||||
}
|
||||
bool funHasAnyAliasedFormal() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return funHasAnyAliasedFormal_;
|
||||
}
|
||||
|
||||
bool hasSingletons() const { return hasSingletons_; }
|
||||
bool treatAsRunOnce() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return treatAsRunOnce_;
|
||||
}
|
||||
bool hasRunOnce() const { return hasRunOnce_; }
|
||||
@ -1034,17 +1005,14 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
|
||||
void setDirectlyInsideEval() { directlyInsideEval_ = true; }
|
||||
|
||||
bool usesArgumentsAndApply() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return usesArgumentsAndApply_;
|
||||
}
|
||||
void setUsesArgumentsAndApply() { usesArgumentsAndApply_ = true; }
|
||||
|
||||
bool shouldCloneAtCallsite() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return shouldCloneAtCallsite_;
|
||||
}
|
||||
bool shouldInline() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return shouldInline_;
|
||||
}
|
||||
|
||||
@ -1052,29 +1020,23 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
|
||||
void setShouldInline() { shouldInline_ = true; }
|
||||
|
||||
bool isCallsiteClone() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return isCallsiteClone_;
|
||||
}
|
||||
bool isGeneratorExp() const { return isGeneratorExp_; }
|
||||
|
||||
bool failedBoundsCheck() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return failedBoundsCheck_;
|
||||
}
|
||||
bool failedShapeGuard() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return failedShapeGuard_;
|
||||
}
|
||||
bool hadFrequentBailouts() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return hadFrequentBailouts_;
|
||||
}
|
||||
bool uninlineable() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return uninlineable_;
|
||||
}
|
||||
bool invalidatedIdempotentCache() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return invalidatedIdempotentCache_;
|
||||
}
|
||||
|
||||
@ -1095,7 +1057,6 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
|
||||
|
||||
/* See ContextFlags::funArgumentsHasLocalBinding comment. */
|
||||
bool argumentsHasVarBinding() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return argsHasVarBinding_;
|
||||
}
|
||||
jsbytecode *argumentsBytecode() const { JS_ASSERT(code()[0] == JSOP_ARGUMENTS); return code(); }
|
||||
@ -1105,7 +1066,6 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
|
||||
}
|
||||
|
||||
js::GeneratorKind generatorKind() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return js::GeneratorKindFromBits(generatorKindBits_);
|
||||
}
|
||||
bool isGenerator() const { return generatorKind() != js::NotGenerator; }
|
||||
@ -1130,8 +1090,6 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
|
||||
*/
|
||||
bool analyzedArgsUsage() const { return !needsArgsAnalysis_; }
|
||||
bool needsArgsObj() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
JS_ASSERT(js::CurrentThreadCanReadCompilationData());
|
||||
JS_ASSERT(analyzedArgsUsage());
|
||||
return needsArgsObj_;
|
||||
}
|
||||
@ -1156,17 +1114,9 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
|
||||
}
|
||||
|
||||
bool hasIonScript() const {
|
||||
// Note: While a script's baseline script is protected by the
|
||||
// compilation lock, writes to the ion script are not. This helps lock
|
||||
// ordering issues in CodeGenerator::link. Tests of script->ion during
|
||||
// off thread compilation can therefore race, though these are fairly
|
||||
// benign and the IonScript itself is never accessed.
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return ion && ion != ION_DISABLED_SCRIPT && ion != ION_COMPILING_SCRIPT;
|
||||
}
|
||||
bool canIonCompile() const {
|
||||
// Note: see above comment.
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return ion != ION_DISABLED_SCRIPT;
|
||||
}
|
||||
|
||||
@ -1192,8 +1142,6 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
|
||||
}
|
||||
|
||||
bool hasBaselineScript() const {
|
||||
JS_ASSERT(js::CurrentThreadCanReadCompilationData());
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return baseline && baseline != BASELINE_DISABLED_SCRIPT;
|
||||
}
|
||||
bool canBaselineCompile() const {
|
||||
@ -1201,7 +1149,6 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
|
||||
}
|
||||
js::jit::BaselineScript *baselineScript() const {
|
||||
JS_ASSERT(hasBaselineScript());
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return baseline;
|
||||
}
|
||||
inline void setBaselineScript(JSContext *maybecx, js::jit::BaselineScript *baselineScript);
|
||||
@ -1213,7 +1160,6 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
|
||||
}
|
||||
|
||||
bool canParallelIonCompile() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return parallelIon != ION_DISABLED_SCRIPT;
|
||||
}
|
||||
|
||||
@ -1264,21 +1210,19 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
|
||||
/*
|
||||
* Original compiled function for the script, if it has a function.
|
||||
* nullptr for global and eval scripts.
|
||||
* The delazifying variant ensures that the function isn't lazy, but can
|
||||
* only be used under a compilation lock. The non-delazifying variant
|
||||
* can be used off-thread and without the lock, but must only be used
|
||||
* after earlier code has called ensureNonLazyCanonicalFunction and
|
||||
* while the function can't have been relazified.
|
||||
* The delazifying variant ensures that the function isn't lazy. The
|
||||
* non-delazifying variant must only be used after earlier code has
|
||||
* called ensureNonLazyCanonicalFunction and while the function can't
|
||||
* have been relazified.
|
||||
*/
|
||||
inline JSFunction *functionDelazifying() const;
|
||||
JSFunction *functionNonDelazifying() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return function_;
|
||||
}
|
||||
inline void setFunction(JSFunction *fun);
|
||||
/*
|
||||
* Takes a compilation lock and de-lazifies the canonical function. Must
|
||||
* be called before entering code that expects the function to be non-lazy.
|
||||
* De-lazifies the canonical function. Must be called before entering code
|
||||
* that expects the function to be non-lazy.
|
||||
*/
|
||||
inline void ensureNonLazyCanonicalFunction(JSContext *cx);
|
||||
|
||||
@ -1294,7 +1238,6 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
|
||||
|
||||
void setSourceObject(JSObject *object);
|
||||
JSObject *sourceObject() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return sourceObject_;
|
||||
}
|
||||
js::ScriptSource *scriptSource() const;
|
||||
@ -1335,7 +1278,6 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
|
||||
JSObject *enclosingStaticScope() const {
|
||||
if (isCallsiteClone())
|
||||
return nullptr;
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return enclosingScopeOrOriginalFunction_;
|
||||
}
|
||||
|
||||
@ -1345,8 +1287,6 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
|
||||
|
||||
public:
|
||||
uint32_t getUseCount() const {
|
||||
// Note: We ignore races when reading the use count of a script off thread.
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return useCount;
|
||||
}
|
||||
uint32_t incUseCount(uint32_t amount = 1) { return useCount += amount; }
|
||||
@ -1381,7 +1321,6 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
|
||||
jssrcnote *notes() { return (jssrcnote *)(code() + length()); }
|
||||
|
||||
bool hasArray(ArrayKind kind) {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return (hasArrayBits & (1 << kind));
|
||||
}
|
||||
void setHasArray(ArrayKind kind) { hasArrayBits |= (1 << kind); }
|
||||
@ -1405,31 +1344,26 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
|
||||
|
||||
js::ConstArray *consts() {
|
||||
JS_ASSERT(hasConsts());
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return reinterpret_cast<js::ConstArray *>(data + constsOffset());
|
||||
}
|
||||
|
||||
js::ObjectArray *objects() {
|
||||
JS_ASSERT(hasObjects());
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return reinterpret_cast<js::ObjectArray *>(data + objectsOffset());
|
||||
}
|
||||
|
||||
js::ObjectArray *regexps() {
|
||||
JS_ASSERT(hasRegexps());
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return reinterpret_cast<js::ObjectArray *>(data + regexpsOffset());
|
||||
}
|
||||
|
||||
js::TryNoteArray *trynotes() {
|
||||
JS_ASSERT(hasTrynotes());
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return reinterpret_cast<js::TryNoteArray *>(data + trynotesOffset());
|
||||
}
|
||||
|
||||
js::BlockScopeArray *blockScopes() {
|
||||
JS_ASSERT(hasBlockScopes());
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return reinterpret_cast<js::BlockScopeArray *>(data + blockScopesOffset());
|
||||
}
|
||||
|
||||
@ -1438,7 +1372,6 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
|
||||
size_t natoms() const { return natoms_; }
|
||||
|
||||
js::HeapPtrAtom &getAtom(size_t index) const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
JS_ASSERT(index < natoms());
|
||||
return atoms[index];
|
||||
}
|
||||
@ -1795,7 +1728,6 @@ class LazyScript : public gc::BarrieredCell<LazyScript>
|
||||
}
|
||||
|
||||
bool usesArgumentsAndApply() const {
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return usesArgumentsAndApply_;
|
||||
}
|
||||
void setUsesArgumentsAndApply() {
|
||||
@ -1820,11 +1752,9 @@ class LazyScript : public gc::BarrieredCell<LazyScript>
|
||||
return sourceObject()->source();
|
||||
}
|
||||
uint32_t begin() const {
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return begin_;
|
||||
}
|
||||
uint32_t end() const {
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return end_;
|
||||
}
|
||||
uint32_t lineno() const {
|
||||
|
@ -58,8 +58,6 @@ LazyScript::functionDelazifying(JSContext *cx) const
|
||||
inline JSFunction *
|
||||
JSScript::functionDelazifying() const
|
||||
{
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
JS_ASSERT(js::CurrentThreadCanWriteCompilationData());
|
||||
if (function_ && function_->isInterpretedLazy()) {
|
||||
function_->setUnlazifiedScript(const_cast<JSScript *>(this));
|
||||
// If this script has a LazyScript, make sure the LazyScript has a
|
||||
@ -81,19 +79,15 @@ inline void
|
||||
JSScript::ensureNonLazyCanonicalFunction(JSContext *cx)
|
||||
{
|
||||
// Infallibly delazify the canonical script.
|
||||
if (function_ && function_->isInterpretedLazy()) {
|
||||
js::AutoLockForCompilation lock(cx);
|
||||
if (function_ && function_->isInterpretedLazy())
|
||||
functionDelazifying();
|
||||
}
|
||||
}
|
||||
|
||||
inline JSFunction *
|
||||
JSScript::getFunction(size_t index)
|
||||
{
|
||||
JSFunction *fun = &getObject(index)->as<JSFunction>();
|
||||
#ifdef DEBUG
|
||||
JS_ASSERT_IF(fun->isNative(), IsAsmJSModuleNative(fun->native()));
|
||||
#endif
|
||||
return fun;
|
||||
}
|
||||
|
||||
@ -138,7 +132,6 @@ JSScript::global() const
|
||||
* A JSScript always marks its compartment's global (via bindings) so we
|
||||
* can assert that maybeGlobal is non-null here.
|
||||
*/
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
return *compartment()->maybeGlobal();
|
||||
}
|
||||
|
||||
@ -149,14 +142,16 @@ JSScript::principals()
|
||||
}
|
||||
|
||||
inline JSFunction *
|
||||
JSScript::donorFunction() const {
|
||||
JSScript::donorFunction() const
|
||||
{
|
||||
if (!isCallsiteClone())
|
||||
return nullptr;
|
||||
return &enclosingScopeOrOriginalFunction_->as<JSFunction>();
|
||||
}
|
||||
|
||||
inline void
|
||||
JSScript::setIsCallsiteClone(JSObject *fun) {
|
||||
JSScript::setIsCallsiteClone(JSObject *fun)
|
||||
{
|
||||
JS_ASSERT(shouldCloneAtCallsite());
|
||||
shouldCloneAtCallsite_ = false;
|
||||
isCallsiteClone_ = true;
|
||||
@ -166,14 +161,12 @@ JSScript::setIsCallsiteClone(JSObject *fun) {
|
||||
}
|
||||
|
||||
inline void
|
||||
JSScript::setBaselineScript(JSContext *maybecx, js::jit::BaselineScript *baselineScript) {
|
||||
JSScript::setBaselineScript(JSContext *maybecx, js::jit::BaselineScript *baselineScript)
|
||||
{
|
||||
#ifdef JS_ION
|
||||
if (hasBaselineScript())
|
||||
js::jit::BaselineScript::writeBarrierPre(tenuredZone(), baseline);
|
||||
#endif
|
||||
mozilla::Maybe<js::AutoLockForCompilation> lock;
|
||||
if (maybecx)
|
||||
lock.construct(maybecx);
|
||||
baseline = baselineScript;
|
||||
updateBaselineOrIonRaw();
|
||||
}
|
||||
|
@ -4254,8 +4254,6 @@ js::CompareStrings(JSContext *cx, JSString *str1, JSString *str2, int32_t *resul
|
||||
int32_t
|
||||
js::CompareAtoms(JSAtom *atom1, JSAtom *atom2)
|
||||
{
|
||||
AutoThreadSafeAccess ts0(atom1);
|
||||
AutoThreadSafeAccess ts1(atom2);
|
||||
return CompareChars(atom1->chars(), atom1->length(), atom2->chars(), atom2->length());
|
||||
}
|
||||
|
||||
|
@ -93,8 +93,6 @@ js::StartOffThreadIonCompile(JSContext *cx, jit::IonBuilder *builder)
|
||||
if (!WorkerThreadState().ionWorklist().append(builder))
|
||||
return false;
|
||||
|
||||
cx->runtime()->addCompilationThread();
|
||||
|
||||
WorkerThreadState().notifyAll(GlobalWorkerThreadState::PRODUCER);
|
||||
return true;
|
||||
}
|
||||
@ -649,8 +647,6 @@ GlobalWorkerThreadState::finishParseTask(JSContext *maybecx, JSRuntime *rt, void
|
||||
JSObject *newProto = GetClassPrototypePure(&parseTask->scopeChain->global(), key);
|
||||
JS_ASSERT(newProto);
|
||||
|
||||
// Note: this is safe to do without requiring the compilation lock, as
|
||||
// the new type is not yet available to compilation threads.
|
||||
object->setProtoUnchecked(newProto);
|
||||
}
|
||||
|
||||
@ -791,11 +787,7 @@ WorkerThread::handleIonWorkload()
|
||||
jit::IonContext ictx(jit::CompileRuntime::get(rt),
|
||||
jit::CompileCompartment::get(ionBuilder->script()->compartment()),
|
||||
&ionBuilder->alloc());
|
||||
AutoEnterIonCompilation ionCompiling;
|
||||
bool succeeded = ionBuilder->build();
|
||||
ionBuilder->clearForBackEnd();
|
||||
if (succeeded)
|
||||
ionBuilder->setBackgroundCodegen(jit::CompileBackEnd(ionBuilder));
|
||||
ionBuilder->setBackgroundCodegen(jit::CompileBackEnd(ionBuilder));
|
||||
}
|
||||
|
||||
FinishOffThreadIonCompile(ionBuilder);
|
||||
|
@ -83,9 +83,6 @@ js::UncheckedUnwrap(JSObject *wrapped, bool stopAtOuter, unsigned *flagsp)
|
||||
{
|
||||
unsigned flags = 0;
|
||||
while (true) {
|
||||
AutoThreadSafeAccess ts0(wrapped);
|
||||
AutoThreadSafeAccess ts1(wrapped->typeRaw());
|
||||
AutoThreadSafeAccess ts2(wrapped->lastProperty());
|
||||
if (!wrapped->is<WrapperObject>() ||
|
||||
MOZ_UNLIKELY(stopAtOuter && wrapped->getClass()->ext.innerObject))
|
||||
{
|
||||
|
@ -5511,9 +5511,6 @@ ProcessArgs(JSContext *cx, JSObject *obj_, OptionParser *op)
|
||||
if (op->getBoolOption("ion-check-range-analysis"))
|
||||
jit::js_JitOptions.checkRangeAnalysis = true;
|
||||
|
||||
if (op->getBoolOption("ion-check-thread-safety"))
|
||||
jit::js_JitOptions.checkThreadSafety = true;
|
||||
|
||||
if (const char *str = op->getStringOption("ion-inlining")) {
|
||||
if (strcmp(str, "on") == 0)
|
||||
jit::js_JitOptions.disableInlining = false;
|
||||
@ -5788,8 +5785,6 @@ main(int argc, char **argv, char **envp)
|
||||
"Range analysis (default: on, off to disable)")
|
||||
|| !op.addBoolOption('\0', "ion-check-range-analysis",
|
||||
"Range analysis checking")
|
||||
|| !op.addBoolOption('\0', "ion-check-thread-safety",
|
||||
"IonBuilder thread safety checking")
|
||||
|| !op.addStringOption('\0', "ion-inlining", "on/off",
|
||||
"Inline methods where possible (default: on, off to disable)")
|
||||
|| !op.addStringOption('\0', "ion-osr", "on/off",
|
||||
@ -5898,15 +5893,8 @@ main(int argc, char **argv, char **envp)
|
||||
if (!JS_Init())
|
||||
return 1;
|
||||
|
||||
// When doing thread safety checks for VM accesses made during Ion compilation,
|
||||
// we rely on protected memory and only the main thread should be active.
|
||||
JSUseHelperThreads useHelperThreads =
|
||||
op.getBoolOption("ion-check-thread-safety")
|
||||
? JS_NO_HELPER_THREADS
|
||||
: JS_USE_HELPER_THREADS;
|
||||
|
||||
/* Use the same parameters as the browser in xpcjsruntime.cpp. */
|
||||
rt = JS_NewRuntime(32L * 1024L * 1024L, useHelperThreads);
|
||||
rt = JS_NewRuntime(32L * 1024L * 1024L, JS_USE_HELPER_THREADS);
|
||||
if (!rt)
|
||||
return 1;
|
||||
gTimeoutFunc = NullValue();
|
||||
|
@ -554,14 +554,14 @@ GlobalObject::getOrCreateEval(JSContext *cx, Handle<GlobalObject*> global,
|
||||
{
|
||||
if (!global->getOrCreateObjectPrototype(cx))
|
||||
return false;
|
||||
eval.set(&global->getSlotForCompilation(EVAL).toObject());
|
||||
eval.set(&global->getSlot(EVAL).toObject());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
GlobalObject::valueIsEval(Value val)
|
||||
{
|
||||
Value eval = getSlotForCompilation(EVAL);
|
||||
Value eval = getSlot(EVAL);
|
||||
return eval.isObject() && eval == val;
|
||||
}
|
||||
|
||||
@ -788,10 +788,6 @@ GlobalObject::addIntrinsicValue(JSContext *cx, HandleId id, HandleValue value)
|
||||
{
|
||||
RootedObject holder(cx, intrinsicsHolder());
|
||||
|
||||
// Work directly with the shape machinery underlying the object, so that we
|
||||
// don't take the compilation lock until we are ready to update the object
|
||||
// without triggering a GC.
|
||||
|
||||
uint32_t slot = holder->slotSpan();
|
||||
RootedShape last(cx, holder->lastProperty());
|
||||
Rooted<UnownedBaseShape*> base(cx, last->base()->unowned());
|
||||
@ -801,7 +797,6 @@ GlobalObject::addIntrinsicValue(JSContext *cx, HandleId id, HandleValue value)
|
||||
if (!shape)
|
||||
return false;
|
||||
|
||||
AutoLockForCompilation lock(cx);
|
||||
if (!JSObject::setLastProperty(cx, holder, shape))
|
||||
return false;
|
||||
|
||||
|
@ -158,7 +158,7 @@ class GlobalObject : public JSObject
|
||||
public:
|
||||
Value getConstructor(JSProtoKey key) const {
|
||||
JS_ASSERT(key <= JSProto_LIMIT);
|
||||
return getSlotForCompilation(APPLICATION_SLOTS + key);
|
||||
return getSlot(APPLICATION_SLOTS + key);
|
||||
}
|
||||
static bool ensureConstructor(JSContext *cx, Handle<GlobalObject*> global, JSProtoKey key);
|
||||
static bool initConstructor(JSContext *cx, Handle<GlobalObject*> global, JSProtoKey key);
|
||||
@ -170,7 +170,7 @@ class GlobalObject : public JSObject
|
||||
|
||||
Value getPrototype(JSProtoKey key) const {
|
||||
JS_ASSERT(key <= JSProto_LIMIT);
|
||||
return getSlotForCompilation(APPLICATION_SLOTS + JSProto_LIMIT + key);
|
||||
return getSlot(APPLICATION_SLOTS + JSProto_LIMIT + key);
|
||||
}
|
||||
|
||||
void setPrototype(JSProtoKey key, const Value &value) {
|
||||
@ -457,19 +457,6 @@ class GlobalObject : public JSObject
|
||||
return &self->getSlot(slot).toObject();
|
||||
}
|
||||
|
||||
Value getSlotForCompilation(uint32_t slot) const {
|
||||
// This method should only be used for slots that are either eagerly
|
||||
// initialized on creation of the global or only change under the
|
||||
// compilation lock. Note that the dynamic slots pointer for global
|
||||
// objects can only change under the compilation lock.
|
||||
JS_ASSERT(slot < JSCLASS_RESERVED_SLOTS(getClass()));
|
||||
uint32_t fixed = numFixedSlotsForCompilation();
|
||||
AutoThreadSafeAccess ts(this);
|
||||
if (slot < fixed)
|
||||
return fixedSlots()[slot];
|
||||
return slots[slot - fixed];
|
||||
}
|
||||
|
||||
public:
|
||||
static JSObject *getOrCreateIteratorPrototype(JSContext *cx,
|
||||
Handle<GlobalObject*> global)
|
||||
@ -547,18 +534,13 @@ class GlobalObject : public JSObject
|
||||
}
|
||||
|
||||
JSObject *intrinsicsHolder() {
|
||||
JS_ASSERT(!getSlotForCompilation(INTRINSICS).isUndefined());
|
||||
return &getSlotForCompilation(INTRINSICS).toObject();
|
||||
JS_ASSERT(!getSlot(INTRINSICS).isUndefined());
|
||||
return &getSlot(INTRINSICS).toObject();
|
||||
}
|
||||
|
||||
bool maybeGetIntrinsicValue(jsid id, Value *vp) {
|
||||
JS_ASSERT(CurrentThreadCanReadCompilationData());
|
||||
JSObject *holder = intrinsicsHolder();
|
||||
|
||||
AutoThreadSafeAccess ts0(holder);
|
||||
AutoThreadSafeAccess ts1(holder->lastProperty());
|
||||
AutoThreadSafeAccess ts2(holder->lastProperty()->base());
|
||||
|
||||
if (Shape *shape = holder->nativeLookupPure(id)) {
|
||||
*vp = holder->getSlot(shape->slot());
|
||||
return true;
|
||||
@ -596,8 +578,7 @@ class GlobalObject : public JSObject
|
||||
unsigned nargs, MutableHandleValue funVal);
|
||||
|
||||
RegExpStatics *getRegExpStatics() const {
|
||||
JSObject &resObj = getSlotForCompilation(REGEXP_STATICS).toObject();
|
||||
AutoThreadSafeAccess ts(&resObj);
|
||||
JSObject &resObj = getSlot(REGEXP_STATICS).toObject();
|
||||
return static_cast<RegExpStatics *>(resObj.getPrivate(/* nfixed = */ 1));
|
||||
}
|
||||
|
||||
|
@ -1320,7 +1320,7 @@ SetObjectElementOperation(JSContext *cx, Handle<JSObject*> obj, HandleId id, con
|
||||
if ((uint32_t)i >= length) {
|
||||
// Annotate script if provided with information (e.g. baseline)
|
||||
if (script && script->hasBaselineScript() && *pc == JSOP_SETELEM)
|
||||
script->baselineScript()->noteArrayWriteHole(cx, script->pcToOffset(pc));
|
||||
script->baselineScript()->noteArrayWriteHole(script->pcToOffset(pc));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -334,25 +334,6 @@ js::ObjectImpl::nativeLookupPure(jsid id)
|
||||
return Shape::searchNoHashify(lastProperty(), id);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
js::ObjectImpl::numFixedSlotsForCompilation() const
|
||||
{
|
||||
// This is an alternative method for getting the number of fixed slots
|
||||
// in an object. It requires more logic and memory accesses than
|
||||
// numFixedSlots() but is safe to be called from the compilation thread,
|
||||
// even if the main thread is actively mutating the VM.
|
||||
if (static_cast<const JSObject *>(this)->is<ArrayObject>())
|
||||
return 0;
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
// The compiler does not have access to nursery things, so if this object
|
||||
// is in the nursery we can fall back to numFixedSlots().
|
||||
if (IsInsideNursery(GetGCThingRuntime(this), this))
|
||||
return numFixedSlots();
|
||||
#endif
|
||||
gc::AllocKind kind = tenuredGetAllocKind();
|
||||
return gc::GetGCKindSlots(kind, getClass());
|
||||
}
|
||||
|
||||
uint32_t
|
||||
js::ObjectImpl::dynamicSlotsCount(uint32_t nfixed, uint32_t span, const Class *clasp)
|
||||
{
|
||||
|
@ -984,14 +984,12 @@ class ObjectImpl : public gc::BarrieredCell<ObjectImpl>
|
||||
|
||||
public:
|
||||
TaggedProto getTaggedProto() const {
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return type_->proto();
|
||||
}
|
||||
|
||||
bool hasTenuredProto() const;
|
||||
|
||||
const Class *getClass() const {
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return type_->clasp();
|
||||
}
|
||||
|
||||
@ -1206,8 +1204,6 @@ class ObjectImpl : public gc::BarrieredCell<ObjectImpl>
|
||||
}
|
||||
|
||||
types::TypeObject *typeRaw() const {
|
||||
AutoThreadSafeAccess ts0(this);
|
||||
AutoThreadSafeAccess ts1(type_);
|
||||
return type_;
|
||||
}
|
||||
|
||||
@ -1215,14 +1211,11 @@ class ObjectImpl : public gc::BarrieredCell<ObjectImpl>
|
||||
return reinterpret_cast<const shadow::Object *>(this)->numFixedSlots();
|
||||
}
|
||||
|
||||
uint32_t numFixedSlotsForCompilation() const;
|
||||
|
||||
/*
|
||||
* Whether this is the only object which has its specified type. This
|
||||
* object will have its type constructed lazily as needed by analysis.
|
||||
*/
|
||||
bool hasSingletonType() const {
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return !!type_->singleton();
|
||||
}
|
||||
|
||||
@ -1231,7 +1224,6 @@ class ObjectImpl : public gc::BarrieredCell<ObjectImpl>
|
||||
* might have a lazy type, use getType() below, otherwise type().
|
||||
*/
|
||||
bool hasLazyType() const {
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return type_->lazy();
|
||||
}
|
||||
|
||||
@ -1391,7 +1383,7 @@ class ObjectImpl : public gc::BarrieredCell<ObjectImpl>
|
||||
}
|
||||
|
||||
const Value &getFixedSlot(uint32_t slot) const {
|
||||
MOZ_ASSERT(slot < numFixedSlotsForCompilation());
|
||||
MOZ_ASSERT(slot < numFixedSlots());
|
||||
return fixedSlots()[slot];
|
||||
}
|
||||
|
||||
@ -1478,7 +1470,7 @@ class ObjectImpl : public gc::BarrieredCell<ObjectImpl>
|
||||
* Private pointers are stored immediately after the last fixed slot of
|
||||
* the object.
|
||||
*/
|
||||
MOZ_ASSERT(nfixed == numFixedSlotsForCompilation());
|
||||
MOZ_ASSERT(nfixed == numFixedSlots());
|
||||
MOZ_ASSERT(hasPrivate());
|
||||
HeapSlot *end = &fixedSlots()[nfixed];
|
||||
return *reinterpret_cast<void**>(end);
|
||||
@ -1555,10 +1547,6 @@ MOZ_ALWAYS_INLINE Zone *
|
||||
BarrieredCell<ObjectImpl>::zoneFromAnyThread() const
|
||||
{
|
||||
const ObjectImpl* obj = static_cast<const ObjectImpl*>(this);
|
||||
|
||||
// Note: This read of obj->shape_ may race, though the zone fetched will be the same.
|
||||
AutoThreadSafeAccess ts(obj->shape_);
|
||||
|
||||
return obj->shape_->zoneFromAnyThread();
|
||||
}
|
||||
|
||||
|
@ -80,9 +80,6 @@ PerThreadData::PerThreadData(JSRuntime *runtime)
|
||||
#endif
|
||||
dtoaState(nullptr),
|
||||
suppressGC(0),
|
||||
#ifdef DEBUG
|
||||
ionCompiling(false),
|
||||
#endif
|
||||
activeCompilations(0)
|
||||
{}
|
||||
|
||||
@ -132,12 +129,6 @@ JSRuntime::JSRuntime(JSUseHelperThreads useHelperThreads)
|
||||
exclusiveAccessOwner(nullptr),
|
||||
mainThreadHasExclusiveAccess(false),
|
||||
numExclusiveThreads(0),
|
||||
compilationLock(nullptr),
|
||||
#ifdef DEBUG
|
||||
compilationLockOwner(nullptr),
|
||||
mainThreadHasCompilationLock(false),
|
||||
#endif
|
||||
numCompilationThreads(0),
|
||||
#else
|
||||
operationCallbackLockTaken(false),
|
||||
#endif
|
||||
@ -280,7 +271,6 @@ JSRuntime::JSRuntime(JSUseHelperThreads useHelperThreads)
|
||||
decimalSeparator(0),
|
||||
numGrouping(0),
|
||||
#endif
|
||||
heapProtected_(false),
|
||||
mathCache_(nullptr),
|
||||
activeCompilations_(0),
|
||||
keepAtoms_(0),
|
||||
@ -360,10 +350,6 @@ JSRuntime::init(uint32_t maxbytes)
|
||||
exclusiveAccessLock = PR_NewLock();
|
||||
if (!exclusiveAccessLock)
|
||||
return false;
|
||||
|
||||
compilationLock = PR_NewLock();
|
||||
if (!compilationLock)
|
||||
return false;
|
||||
#endif
|
||||
|
||||
if (!mainThread.init())
|
||||
@ -495,10 +481,6 @@ JSRuntime::~JSRuntime()
|
||||
JS_ASSERT(!numExclusiveThreads);
|
||||
mainThreadHasExclusiveAccess = true;
|
||||
|
||||
JS_ASSERT(!compilationLockOwner);
|
||||
if (compilationLock)
|
||||
PR_DestroyLock(compilationLock);
|
||||
|
||||
JS_ASSERT(!operationCallbackOwner);
|
||||
if (operationCallbackLock)
|
||||
PR_DestroyLock(operationCallbackLock);
|
||||
@ -859,76 +841,6 @@ JSRuntime::activeGCInAtomsZone()
|
||||
return zone->needsBarrier() || zone->isGCScheduled() || zone->wasGCStarted();
|
||||
}
|
||||
|
||||
#ifdef JS_CAN_CHECK_THREADSAFE_ACCESSES
|
||||
|
||||
AutoProtectHeapForIonCompilation::AutoProtectHeapForIonCompilation(JSRuntime *rt MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
|
||||
: runtime(rt)
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
|
||||
JS_ASSERT(!runtime->heapProtected_);
|
||||
runtime->heapProtected_ = true;
|
||||
|
||||
for (GCChunkSet::Range r(rt->gcChunkSet.all()); !r.empty(); r.popFront()) {
|
||||
Chunk *chunk = r.front();
|
||||
// Note: Don't protect the last page in the chunk, which stores
|
||||
// immutable info and needs to be accessible for runtimeFromAnyThread()
|
||||
// in AutoThreadSafeAccess.
|
||||
if (mprotect(chunk, ChunkSize - sizeof(Arena), PROT_NONE))
|
||||
MOZ_CRASH();
|
||||
}
|
||||
}
|
||||
|
||||
AutoProtectHeapForIonCompilation::~AutoProtectHeapForIonCompilation()
|
||||
{
|
||||
JS_ASSERT(runtime->heapProtected_);
|
||||
JS_ASSERT(runtime->unprotectedArenas.empty());
|
||||
runtime->heapProtected_ = false;
|
||||
|
||||
for (GCChunkSet::Range r(runtime->gcChunkSet.all()); !r.empty(); r.popFront()) {
|
||||
Chunk *chunk = r.front();
|
||||
if (mprotect(chunk, ChunkSize - sizeof(Arena), PROT_READ | PROT_WRITE))
|
||||
MOZ_CRASH();
|
||||
}
|
||||
}
|
||||
|
||||
AutoThreadSafeAccess::AutoThreadSafeAccess(const Cell *cell MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
|
||||
: runtime(cell->runtimeFromAnyThread()), arena(nullptr)
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
|
||||
if (!runtime->heapProtected_)
|
||||
return;
|
||||
|
||||
ArenaHeader *base = cell->arenaHeader();
|
||||
for (size_t i = 0; i < runtime->unprotectedArenas.length(); i++) {
|
||||
if (base == runtime->unprotectedArenas[i])
|
||||
return;
|
||||
}
|
||||
|
||||
arena = base;
|
||||
|
||||
if (mprotect(arena, sizeof(Arena), PROT_READ | PROT_WRITE))
|
||||
MOZ_CRASH();
|
||||
|
||||
if (!runtime->unprotectedArenas.append(arena))
|
||||
MOZ_CRASH();
|
||||
}
|
||||
|
||||
AutoThreadSafeAccess::~AutoThreadSafeAccess()
|
||||
{
|
||||
if (!arena)
|
||||
return;
|
||||
|
||||
if (mprotect(arena, sizeof(Arena), PROT_NONE))
|
||||
MOZ_CRASH();
|
||||
|
||||
JS_ASSERT(arena == runtime->unprotectedArenas.back());
|
||||
runtime->unprotectedArenas.popBack();
|
||||
}
|
||||
|
||||
#endif // JS_CAN_CHECK_THREADSAFE_ACCESSES
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
|
||||
void
|
||||
@ -993,8 +905,6 @@ JSRuntime::assertCanLock(RuntimeLock which)
|
||||
JS_ASSERT(exclusiveAccessOwner != PR_GetCurrentThread());
|
||||
case WorkerThreadStateLock:
|
||||
JS_ASSERT(!WorkerThreadState().isLocked());
|
||||
case CompilationLock:
|
||||
JS_ASSERT(compilationLockOwner != PR_GetCurrentThread());
|
||||
case OperationCallbackLock:
|
||||
JS_ASSERT(!currentThreadOwnsOperationCallbackLock());
|
||||
case GCLock:
|
||||
@ -1006,64 +916,6 @@ JSRuntime::assertCanLock(RuntimeLock which)
|
||||
#endif // JS_THREADSAFE
|
||||
}
|
||||
|
||||
AutoEnterIonCompilation::AutoEnterIonCompilation(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_IN_IMPL)
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
PerThreadData *pt = js::TlsPerThreadData.get();
|
||||
JS_ASSERT(!pt->ionCompiling);
|
||||
pt->ionCompiling = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
AutoEnterIonCompilation::~AutoEnterIonCompilation()
|
||||
{
|
||||
#ifdef JS_THREADSAFE
|
||||
PerThreadData *pt = js::TlsPerThreadData.get();
|
||||
JS_ASSERT(pt->ionCompiling);
|
||||
pt->ionCompiling = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
js::CurrentThreadCanWriteCompilationData()
|
||||
{
|
||||
#ifdef JS_THREADSAFE
|
||||
PerThreadData *pt = TlsPerThreadData.get();
|
||||
|
||||
// Data can only be read from during compilation.
|
||||
if (pt->ionCompiling)
|
||||
return false;
|
||||
|
||||
// Ignore what threads with exclusive contexts are doing; these never have
|
||||
// run scripts or have associated compilation threads.
|
||||
JSRuntime *rt = pt->runtimeIfOnOwnerThread();
|
||||
if (!rt)
|
||||
return true;
|
||||
|
||||
return rt->currentThreadHasCompilationLock();
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
js::CurrentThreadCanReadCompilationData()
|
||||
{
|
||||
#ifdef JS_THREADSAFE
|
||||
PerThreadData *pt = TlsPerThreadData.get();
|
||||
|
||||
// Data can always be read from freely outside of compilation.
|
||||
if (!pt || !pt->ionCompiling)
|
||||
return true;
|
||||
|
||||
return pt->runtime_->currentThreadHasCompilationLock();
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
js::AssertCurrentThreadCanLock(RuntimeLock which)
|
||||
{
|
||||
|
@ -483,7 +483,6 @@ AtomStateOffsetToName(const JSAtomState &atomState, size_t offset)
|
||||
enum RuntimeLock {
|
||||
ExclusiveAccessLock,
|
||||
WorkerThreadStateLock,
|
||||
CompilationLock,
|
||||
OperationCallbackLock,
|
||||
GCLock
|
||||
};
|
||||
@ -553,7 +552,6 @@ class PerThreadData : public PerThreadDataFriendFields
|
||||
friend class js::jit::JitActivation;
|
||||
friend class js::AsmJSActivation;
|
||||
#ifdef DEBUG
|
||||
friend bool js::CurrentThreadCanReadCompilationData();
|
||||
friend void js::AssertCurrentThreadCanLock(RuntimeLock which);
|
||||
#endif
|
||||
|
||||
@ -603,11 +601,6 @@ class PerThreadData : public PerThreadDataFriendFields
|
||||
*/
|
||||
int32_t suppressGC;
|
||||
|
||||
#ifdef DEBUG
|
||||
// Whether this thread is actively Ion compiling.
|
||||
bool ionCompiling;
|
||||
#endif
|
||||
|
||||
// Number of active bytecode compilation on this thread.
|
||||
unsigned activeCompilations;
|
||||
|
||||
@ -658,8 +651,6 @@ class MarkingValidator;
|
||||
typedef Vector<JS::Zone *, 4, SystemAllocPolicy> ZoneVector;
|
||||
|
||||
class AutoLockForExclusiveAccess;
|
||||
class AutoLockForCompilation;
|
||||
class AutoProtectHeapForIonCompilation;
|
||||
|
||||
void RecomputeStackLimit(JSRuntime *rt, StackKind kind);
|
||||
|
||||
@ -774,28 +765,6 @@ struct JSRuntime : public JS::shadow::Runtime,
|
||||
|
||||
friend class js::AutoLockForExclusiveAccess;
|
||||
|
||||
/*
|
||||
* Lock taken when using data that can be modified by the main thread but
|
||||
* read by Ion compilation threads. Any time either the main thread writes
|
||||
* such data or the compilation thread reads it, this lock must be taken.
|
||||
* Note that no externally visible data is modified by the compilation
|
||||
* thread, so the main thread never needs to take this lock when reading.
|
||||
*/
|
||||
PRLock *compilationLock;
|
||||
#ifdef DEBUG
|
||||
PRThread *compilationLockOwner;
|
||||
bool mainThreadHasCompilationLock;
|
||||
#endif
|
||||
|
||||
/* Number of in flight Ion compilations. */
|
||||
size_t numCompilationThreads;
|
||||
|
||||
friend class js::AutoLockForCompilation;
|
||||
#ifdef DEBUG
|
||||
friend bool js::CurrentThreadCanWriteCompilationData();
|
||||
friend bool js::CurrentThreadCanReadCompilationData();
|
||||
#endif
|
||||
|
||||
public:
|
||||
void setUsedByExclusiveThread(JS::Zone *zone);
|
||||
void clearUsedByExclusiveThread(JS::Zone *zone);
|
||||
@ -821,41 +790,6 @@ struct JSRuntime : public JS::shadow::Runtime,
|
||||
#endif
|
||||
}
|
||||
|
||||
void addCompilationThread() {
|
||||
#ifdef JS_THREADSAFE
|
||||
numCompilationThreads++;
|
||||
#else
|
||||
MOZ_ASSUME_UNREACHABLE("No threads");
|
||||
#endif
|
||||
}
|
||||
void removeCompilationThread() {
|
||||
#ifdef JS_THREADSAFE
|
||||
JS_ASSERT(numCompilationThreads);
|
||||
numCompilationThreads--;
|
||||
#else
|
||||
MOZ_ASSUME_UNREACHABLE("No threads");
|
||||
#endif
|
||||
}
|
||||
|
||||
bool compilationThreadsPresent() const {
|
||||
#ifdef JS_THREADSAFE
|
||||
return numCompilationThreads > 0;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
bool currentThreadHasCompilationLock() {
|
||||
#ifdef JS_THREADSAFE
|
||||
return (!numCompilationThreads && mainThreadHasCompilationLock) ||
|
||||
compilationLockOwner == PR_GetCurrentThread();
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
#endif // DEBUG
|
||||
|
||||
/* Embedders can use this zone however they wish. */
|
||||
JS::Zone *systemZone;
|
||||
|
||||
@ -1474,18 +1408,6 @@ struct JSRuntime : public JS::shadow::Runtime,
|
||||
const char *numGrouping;
|
||||
#endif
|
||||
|
||||
friend class js::AutoProtectHeapForIonCompilation;
|
||||
friend class js::AutoThreadSafeAccess;
|
||||
mozilla::DebugOnly<bool> heapProtected_;
|
||||
#ifdef DEBUG
|
||||
js::Vector<js::gc::ArenaHeader *, 0, js::SystemAllocPolicy> unprotectedArenas;
|
||||
|
||||
public:
|
||||
bool heapProtected() {
|
||||
return heapProtected_;
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
js::MathCache *mathCache_;
|
||||
js::MathCache *createMathCache(JSContext *cx);
|
||||
@ -2083,43 +2005,6 @@ class RuntimeAllocPolicy
|
||||
|
||||
extern const JSSecurityCallbacks NullSecurityCallbacks;
|
||||
|
||||
// Debugging RAII class which marks the current thread as performing an Ion
|
||||
// compilation, for use by CurrentThreadCan{Read,Write}CompilationData
|
||||
class AutoEnterIonCompilation
|
||||
{
|
||||
public:
|
||||
#ifdef DEBUG
|
||||
AutoEnterIonCompilation(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM);
|
||||
~AutoEnterIonCompilation();
|
||||
#else
|
||||
AutoEnterIonCompilation(MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
}
|
||||
#endif
|
||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
};
|
||||
|
||||
// Debugging RAII class which protects the entire GC heap for the duration of an
|
||||
// Ion compilation. When used only the main thread will be active and all
|
||||
// accesses to GC things must be wrapped by an AutoThreadSafeAccess instance.
|
||||
class AutoProtectHeapForIonCompilation
|
||||
{
|
||||
public:
|
||||
#ifdef JS_CAN_CHECK_THREADSAFE_ACCESSES
|
||||
JSRuntime *runtime;
|
||||
|
||||
AutoProtectHeapForIonCompilation(JSRuntime *rt MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
|
||||
~AutoProtectHeapForIonCompilation();
|
||||
#else
|
||||
AutoProtectHeapForIonCompilation(JSRuntime *rt MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
}
|
||||
#endif
|
||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
};
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
@ -76,10 +76,8 @@ StaticScopeIter<allowGC>::scopeShape() const
|
||||
{
|
||||
JS_ASSERT(hasDynamicScopeObject());
|
||||
JS_ASSERT(type() != NAMED_LAMBDA);
|
||||
if (type() == BLOCK) {
|
||||
AutoThreadSafeAccess ts(&block());
|
||||
if (type() == BLOCK)
|
||||
return block().lastProperty();
|
||||
}
|
||||
return funScript()->callObjShape();
|
||||
}
|
||||
|
||||
|
@ -200,7 +200,6 @@ class ScopeObject : public JSObject
|
||||
* enclosing scope of a ScopeObject is necessarily non-null.
|
||||
*/
|
||||
inline JSObject &enclosingScope() const {
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return getFixedSlot(SCOPE_CHAIN_SLOT).toObject();
|
||||
}
|
||||
|
||||
@ -252,7 +251,6 @@ class CallObject : public ScopeObject
|
||||
|
||||
/* True if this is for a strict mode eval frame. */
|
||||
bool isForEval() const {
|
||||
AutoThreadSafeAccess ts(this);
|
||||
JS_ASSERT(getFixedSlot(CALLEE_SLOT).isObjectOrNull());
|
||||
JS_ASSERT_IF(getFixedSlot(CALLEE_SLOT).isObject(),
|
||||
getFixedSlot(CALLEE_SLOT).toObject().is<JSFunction>());
|
||||
@ -264,7 +262,6 @@ class CallObject : public ScopeObject
|
||||
* only be called if !isForEval.)
|
||||
*/
|
||||
JSFunction &callee() const {
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return getFixedSlot(CALLEE_SLOT).toObject().as<JSFunction>();
|
||||
}
|
||||
|
||||
@ -410,7 +407,7 @@ class BlockObject : public NestedScopeObject
|
||||
|
||||
/* Return the number of variables associated with this block. */
|
||||
uint32_t slotCount() const {
|
||||
return propertyCountForCompilation();
|
||||
return propertyCount();
|
||||
}
|
||||
|
||||
/*
|
||||
@ -464,9 +461,6 @@ class StaticBlockObject : public BlockObject
|
||||
* variable of the block isAliased.
|
||||
*/
|
||||
bool needsClone() {
|
||||
// The first variable slot will always indicate whether the object has
|
||||
// any aliased vars. Bypass slotValue() to allow testing this off thread.
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return !getFixedSlot(RESERVED_SLOTS).isFalse();
|
||||
}
|
||||
|
||||
|
@ -1026,13 +1026,11 @@ class Shape : public gc::BarrieredCell<Shape>
|
||||
|
||||
void popFront() {
|
||||
JS_ASSERT(!empty());
|
||||
AutoThreadSafeAccess ts(cursor);
|
||||
cursor = cursor->parent;
|
||||
}
|
||||
};
|
||||
|
||||
const Class *getObjectClass() const {
|
||||
AutoThreadSafeAccess ts(base());
|
||||
return base()->clasp;
|
||||
}
|
||||
JSObject *getObjectParent() const { return base()->parent; }
|
||||
@ -1092,7 +1090,6 @@ class Shape : public gc::BarrieredCell<Shape>
|
||||
};
|
||||
|
||||
bool inDictionary() const {
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return (flags & IN_DICTIONARY) != 0;
|
||||
}
|
||||
unsigned getFlags() const { return flags & PUBLIC_FLAGS; }
|
||||
@ -1158,20 +1155,14 @@ class Shape : public gc::BarrieredCell<Shape>
|
||||
BaseShape *base() const { return base_.get(); }
|
||||
|
||||
bool hasSlot() const {
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return (attrs & JSPROP_SHARED) == 0;
|
||||
}
|
||||
uint32_t slot() const { JS_ASSERT(hasSlot() && !hasMissingSlot()); return maybeSlot(); }
|
||||
uint32_t maybeSlot() const {
|
||||
// Note: Reading a shape's slot off thread can race against main thread
|
||||
// updates to the number of linear searches on the shape, which is
|
||||
// stored in the same slotInfo field. We tolerate this.
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return slotInfo & SLOT_MASK;
|
||||
}
|
||||
|
||||
bool isEmptyShape() const {
|
||||
AutoThreadSafeAccess ts(this);
|
||||
JS_ASSERT_IF(JSID_IS_EMPTY(propid_), hasMissingSlot());
|
||||
return JSID_IS_EMPTY(propid_);
|
||||
}
|
||||
@ -1193,8 +1184,6 @@ class Shape : public gc::BarrieredCell<Shape>
|
||||
}
|
||||
|
||||
uint32_t numFixedSlots() const {
|
||||
// Note: The same race applies here as in maybeSlot().
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return (slotInfo >> FIXED_SLOTS_SHIFT);
|
||||
}
|
||||
|
||||
@ -1216,7 +1205,6 @@ class Shape : public gc::BarrieredCell<Shape>
|
||||
}
|
||||
|
||||
const EncapsulatedId &propid() const {
|
||||
AutoThreadSafeAccess ts(this);
|
||||
JS_ASSERT(!isEmptyShape());
|
||||
JS_ASSERT(!JSID_IS_VOID(propid_));
|
||||
return propid_;
|
||||
@ -1224,7 +1212,6 @@ class Shape : public gc::BarrieredCell<Shape>
|
||||
EncapsulatedId &propidRef() { JS_ASSERT(!JSID_IS_VOID(propid_)); return propid_; }
|
||||
jsid propidRaw() const {
|
||||
// Return the actual jsid, not an internal reference.
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return propid();
|
||||
}
|
||||
|
||||
@ -1241,8 +1228,6 @@ class Shape : public gc::BarrieredCell<Shape>
|
||||
bool configurable() const { return (attrs & JSPROP_PERMANENT) == 0; }
|
||||
bool enumerable() const { return (attrs & JSPROP_ENUMERATE) != 0; }
|
||||
bool writable() const {
|
||||
// JS_ASSERT(isDataDescriptor());
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return (attrs & JSPROP_READONLY) == 0;
|
||||
}
|
||||
bool hasGetterValue() const { return attrs & JSPROP_GETTER; }
|
||||
@ -1279,10 +1264,6 @@ class Shape : public gc::BarrieredCell<Shape>
|
||||
uint32_t entryCount() {
|
||||
if (hasTable())
|
||||
return table().entryCount;
|
||||
return entryCountForCompilation();
|
||||
}
|
||||
|
||||
uint32_t entryCountForCompilation() {
|
||||
uint32_t count = 0;
|
||||
for (Shape::Range<NoGC> r(this); !r.empty(); r.popFront())
|
||||
++count;
|
||||
@ -1649,7 +1630,6 @@ Shape::searchLinear(jsid id)
|
||||
JS_ASSERT(!inDictionary());
|
||||
|
||||
for (Shape *shape = this; shape; ) {
|
||||
AutoThreadSafeAccess ts(shape);
|
||||
if (shape->propidRef() == id)
|
||||
return shape;
|
||||
shape = shape->parent;
|
||||
|
@ -382,7 +382,6 @@ class JSString : public js::gc::BarrieredCell<JSString>
|
||||
|
||||
MOZ_ALWAYS_INLINE
|
||||
JSAtom &asAtom() const {
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
JS_ASSERT(isAtom());
|
||||
return *(JSAtom *)this;
|
||||
}
|
||||
@ -1015,7 +1014,6 @@ JSString::base() const
|
||||
inline js::PropertyName *
|
||||
JSAtom::asPropertyName()
|
||||
{
|
||||
js::AutoThreadSafeAccess ts(this);
|
||||
#ifdef DEBUG
|
||||
uint32_t dummy;
|
||||
JS_ASSERT(!isIndex(&dummy));
|
||||
|
@ -1195,8 +1195,6 @@ TypedArrayObject::isArrayIndex(jsid id, uint32_t *ip)
|
||||
void
|
||||
TypedArrayObject::neuter(JSContext *cx)
|
||||
{
|
||||
AutoLockForCompilation lock(cx);
|
||||
|
||||
setSlot(LENGTH_SLOT, Int32Value(0));
|
||||
setSlot(BYTELENGTH_SLOT, Int32Value(0));
|
||||
setSlot(BYTEOFFSET_SLOT, Int32Value(0));
|
||||
|
@ -311,11 +311,9 @@ class TypedArrayObject : public ArrayBufferViewObject
|
||||
return tarr->getFixedSlot(BYTEOFFSET_SLOT);
|
||||
}
|
||||
static Value byteLengthValue(TypedArrayObject *tarr) {
|
||||
AutoThreadSafeAccess ts(tarr);
|
||||
return tarr->getFixedSlot(BYTELENGTH_SLOT);
|
||||
}
|
||||
static Value lengthValue(TypedArrayObject *tarr) {
|
||||
AutoThreadSafeAccess ts(tarr);
|
||||
return tarr->getFixedSlot(LENGTH_SLOT);
|
||||
}
|
||||
|
||||
@ -333,11 +331,9 @@ class TypedArrayObject : public ArrayBufferViewObject
|
||||
}
|
||||
|
||||
uint32_t type() const {
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return getFixedSlot(TYPE_SLOT).toInt32();
|
||||
}
|
||||
void *viewData() const {
|
||||
AutoThreadSafeAccess ts(this);
|
||||
return static_cast<void*>(getPrivate(DATA_SLOT));
|
||||
}
|
||||
|
||||
|
@ -238,82 +238,6 @@ public class ActivityHandlerHelper implements GeckoEventListener {
|
||||
});
|
||||
}
|
||||
|
||||
private Intent getFilePickerIntent(Context context, String aMimeType) {
|
||||
ArrayList<Intent> intents = new ArrayList<Intent>();
|
||||
final Prompt.PromptListItem[] items =
|
||||
getItemsAndIntentsForFilePicker(context, aMimeType, intents);
|
||||
|
||||
if (intents.size() == 0) {
|
||||
Log.i(LOGTAG, "no activities for the file picker!");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (intents.size() == 1) {
|
||||
return intents.get(0);
|
||||
}
|
||||
|
||||
final PromptService ps = GeckoAppShell.getGeckoInterface().getPromptService();
|
||||
final String title = getFilePickerTitle(context, aMimeType);
|
||||
|
||||
// Runnable has to be called to show an intent-like
|
||||
// context menu UI using the PromptService.
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override public void run() {
|
||||
ps.show(title, "", items, false, null);
|
||||
}
|
||||
});
|
||||
|
||||
String promptServiceResult = ps.getResponse(null);
|
||||
int itemId = -1;
|
||||
try {
|
||||
itemId = new JSONObject(promptServiceResult).getInt("button");
|
||||
|
||||
if (itemId == -1) {
|
||||
return null;
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
Log.e(LOGTAG, "result from promptservice was invalid: ", e);
|
||||
return null;
|
||||
}
|
||||
|
||||
return intents.get(itemId);
|
||||
}
|
||||
|
||||
boolean showFilePicker(Activity parentActivity, String aMimeType, ActivityResultHandler handler) {
|
||||
Intent intent = getFilePickerIntent(parentActivity, aMimeType);
|
||||
|
||||
if (intent == null) {
|
||||
return false;
|
||||
}
|
||||
parentActivity.startActivityForResult(intent, mActivityResultHandlerMap.put(handler));
|
||||
return true;
|
||||
}
|
||||
|
||||
String showFilePicker(Activity parentActivity, String aMimeType) {
|
||||
Intent intent = getFilePickerIntent(parentActivity, aMimeType);
|
||||
|
||||
if (intent == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
if (intent.getAction().equals(MediaStore.ACTION_IMAGE_CAPTURE)) {
|
||||
parentActivity.startActivityForResult(intent, mActivityResultHandlerMap.put(mCameraImageResultHandler));
|
||||
} else if (intent.getAction().equals(MediaStore.ACTION_VIDEO_CAPTURE)) {
|
||||
parentActivity.startActivityForResult(intent, mActivityResultHandlerMap.put(mCameraVideoResultHandler));
|
||||
} else if (intent.getAction().equals(Intent.ACTION_GET_CONTENT)) {
|
||||
parentActivity.startActivityForResult(intent, mActivityResultHandlerMap.put(mFilePickerResultHandlerSync));
|
||||
} else {
|
||||
Log.e(LOGTAG, "We should not get an intent with another action!");
|
||||
return "";
|
||||
}
|
||||
|
||||
String filePickerResult;
|
||||
while (null == (filePickerResult = mFilePickerResult.poll())) {
|
||||
GeckoAppShell.processNextNativeEvent(true);
|
||||
}
|
||||
return filePickerResult;
|
||||
}
|
||||
|
||||
/* Allows the user to pick an activity to load files from using a list prompt. Then opens the activity and
|
||||
* sends the file returned to the passed in handler. If a null handler is passed in, will still
|
||||
* pick and launch the file picker, but will throw away the result.
|
||||
|
@ -31,7 +31,7 @@ import org.mozilla.gecko.prompts.Prompt;
|
||||
import org.mozilla.gecko.toolbar.AutocompleteHandler;
|
||||
import org.mozilla.gecko.toolbar.BrowserToolbar;
|
||||
import org.mozilla.gecko.util.Clipboard;
|
||||
import org.mozilla.gecko.util.EventDispatcher;
|
||||
import org.mozilla.gecko.EventDispatcher;
|
||||
import org.mozilla.gecko.util.GamepadUtils;
|
||||
import org.mozilla.gecko.util.HardwareUtils;
|
||||
import org.mozilla.gecko.util.MenuUtils;
|
||||
|
@ -6,7 +6,7 @@ package org.mozilla.gecko;
|
||||
|
||||
import org.mozilla.gecko.gfx.Layer;
|
||||
import org.mozilla.gecko.gfx.LayerView;
|
||||
import org.mozilla.gecko.util.EventDispatcher;
|
||||
import org.mozilla.gecko.EventDispatcher;
|
||||
import org.mozilla.gecko.util.GeckoEventListener;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
|
||||
|
@ -2,7 +2,11 @@
|
||||
* 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/. */
|
||||
|
||||
package org.mozilla.gecko.util;
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import org.mozilla.gecko.GeckoAppShell;
|
||||
import org.mozilla.gecko.GeckoEvent;
|
||||
import org.mozilla.gecko.util.GeckoEventListener;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
@ -14,6 +18,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
public final class EventDispatcher {
|
||||
private static final String LOGTAG = "GeckoEventDispatcher";
|
||||
private static final String GUID = "__guid__";
|
||||
|
||||
private final Map<String, CopyOnWriteArrayList<GeckoEventListener>> mEventListeners
|
||||
= new HashMap<String, CopyOnWriteArrayList<GeckoEventListener>>();
|
||||
@ -52,18 +57,16 @@ public final class EventDispatcher {
|
||||
}
|
||||
}
|
||||
|
||||
public String dispatchEvent(String message) {
|
||||
public void dispatchEvent(String message) {
|
||||
try {
|
||||
JSONObject json = new JSONObject(message);
|
||||
return dispatchEvent(json);
|
||||
dispatchEvent(json);
|
||||
} catch (Exception e) {
|
||||
Log.e(LOGTAG, "dispatchEvent: malformed JSON.", e);
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
public String dispatchEvent(JSONObject json) {
|
||||
public void dispatchEvent(JSONObject json) {
|
||||
// {
|
||||
// "type": "value",
|
||||
// "event_specific": "value",
|
||||
@ -87,29 +90,29 @@ public final class EventDispatcher {
|
||||
|
||||
if (listeners == null || listeners.size() == 0) {
|
||||
Log.d(LOGTAG, "dispatchEvent: no listeners registered for event '" + type + "'");
|
||||
return "";
|
||||
return;
|
||||
}
|
||||
|
||||
String response = null;
|
||||
|
||||
for (GeckoEventListener listener : listeners) {
|
||||
listener.handleMessage(type, json);
|
||||
if (listener instanceof GeckoEventResponder) {
|
||||
String newResponse = ((GeckoEventResponder)listener).getResponse(json);
|
||||
if (response != null && newResponse != null) {
|
||||
Log.e(LOGTAG, "Received two responses for message of type " + type);
|
||||
}
|
||||
response = newResponse;
|
||||
}
|
||||
}
|
||||
|
||||
if (response != null)
|
||||
return response;
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.e(LOGTAG, "handleGeckoMessage throws " + e, e);
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
public static void sendResponse(JSONObject message, JSONObject response) {
|
||||
try {
|
||||
response.put(GUID, message.getString(GUID));
|
||||
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent(message.getString("type") + ":Return", response.toString()));
|
||||
} catch(Exception ex) { }
|
||||
}
|
||||
|
||||
public static void sendError(JSONObject message, JSONObject error) {
|
||||
try {
|
||||
error.put(GUID, message.getString(GUID));
|
||||
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent(message.getString("type") + ":Error", error.toString()));
|
||||
} catch(Exception ex) { }
|
||||
}
|
||||
}
|
@ -23,9 +23,7 @@ import org.mozilla.gecko.preferences.GeckoPreferences;
|
||||
import org.mozilla.gecko.updater.UpdateService;
|
||||
import org.mozilla.gecko.updater.UpdateServiceHelper;
|
||||
import org.mozilla.gecko.util.ActivityResultHandler;
|
||||
import org.mozilla.gecko.util.EventDispatcher;
|
||||
import org.mozilla.gecko.util.GeckoEventListener;
|
||||
import org.mozilla.gecko.util.GeckoEventResponder;
|
||||
import org.mozilla.gecko.util.HardwareUtils;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
import org.mozilla.gecko.util.UiAsyncTask;
|
||||
@ -134,7 +132,6 @@ public abstract class GeckoApp
|
||||
ContextGetter,
|
||||
GeckoAppShell.GeckoInterface,
|
||||
GeckoEventListener,
|
||||
GeckoEventResponder,
|
||||
GeckoMenu.Callback,
|
||||
GeckoMenu.MenuPresenter,
|
||||
LocationListener,
|
||||
@ -187,7 +184,6 @@ public abstract class GeckoApp
|
||||
protected GeckoProfile mProfile;
|
||||
public static int mOrientation;
|
||||
protected boolean mIsRestoringActivity;
|
||||
private String mCurrentResponse = "";
|
||||
|
||||
private ContactService mContactService;
|
||||
private PromptService mPromptService;
|
||||
@ -685,7 +681,7 @@ public abstract class GeckoApp
|
||||
}
|
||||
JSONObject handlersJSON = new JSONObject();
|
||||
handlersJSON.put("apps", new JSONArray(appList));
|
||||
mCurrentResponse = handlersJSON.toString();
|
||||
EventDispatcher.sendResponse(message, handlersJSON);
|
||||
} else if (event.equals("Intent:Open")) {
|
||||
GeckoAppShell.openUriExternal(message.optString("url"),
|
||||
message.optString("mime"), message.optString("packageName"),
|
||||
@ -693,7 +689,9 @@ public abstract class GeckoApp
|
||||
} else if (event.equals("Locale:Set")) {
|
||||
setLocale(message.getString("locale"));
|
||||
} else if (event.equals("NativeApp:IsDebuggable")) {
|
||||
mCurrentResponse = getIsDebuggable() ? "true" : "false";
|
||||
JSONObject ret = new JSONObject();
|
||||
ret.put("isDebuggable", getIsDebuggable() ? "true" : "false");
|
||||
EventDispatcher.sendResponse(message, ret);
|
||||
} else if (event.equals("SystemUI:Visibility")) {
|
||||
setSystemUiVisible(message.getBoolean("visible"));
|
||||
}
|
||||
@ -702,12 +700,6 @@ public abstract class GeckoApp
|
||||
}
|
||||
}
|
||||
|
||||
public String getResponse(JSONObject origMessage) {
|
||||
String res = mCurrentResponse;
|
||||
mCurrentResponse = "";
|
||||
return res;
|
||||
}
|
||||
|
||||
void onStatePurged() { }
|
||||
|
||||
/**
|
||||
|
@ -18,7 +18,6 @@ import org.mozilla.gecko.mozglue.JNITarget;
|
||||
import org.mozilla.gecko.mozglue.RobocopTarget;
|
||||
import org.mozilla.gecko.prompts.PromptService;
|
||||
import org.mozilla.gecko.util.ActivityResultHandler;
|
||||
import org.mozilla.gecko.util.EventDispatcher;
|
||||
import org.mozilla.gecko.util.GeckoEventListener;
|
||||
import org.mozilla.gecko.util.HardwareUtils;
|
||||
import org.mozilla.gecko.util.ProxySelector;
|
||||
@ -1427,20 +1426,6 @@ public class GeckoAppShell
|
||||
getGeckoInterface().setFullScreen(fullscreen);
|
||||
}
|
||||
|
||||
@WrapElementForJNI(stubName = "ShowFilePickerForExtensionsWrapper")
|
||||
public static String showFilePickerForExtensions(String aExtensions) {
|
||||
if (getGeckoInterface() != null)
|
||||
return sActivityHelper.showFilePicker(getGeckoInterface().getActivity(), getMimeTypeFromExtensions(aExtensions));
|
||||
return "";
|
||||
}
|
||||
|
||||
@WrapElementForJNI(stubName = "ShowFilePickerForMimeTypeWrapper")
|
||||
public static String showFilePickerForMimeType(String aMimeType) {
|
||||
if (getGeckoInterface() != null)
|
||||
return sActivityHelper.showFilePicker(getGeckoInterface().getActivity(), aMimeType);
|
||||
return "";
|
||||
}
|
||||
|
||||
@WrapElementForJNI
|
||||
public static void performHapticFeedback(boolean aIsLongPress) {
|
||||
// Don't perform haptic feedback if a vibration is currently playing,
|
||||
@ -2345,8 +2330,8 @@ public class GeckoAppShell
|
||||
}
|
||||
|
||||
@WrapElementForJNI(stubName = "HandleGeckoMessageWrapper")
|
||||
public static String handleGeckoMessage(String message) {
|
||||
return sEventDispatcher.dispatchEvent(message);
|
||||
public static void handleGeckoMessage(String message) {
|
||||
sEventDispatcher.dispatchEvent(message);
|
||||
}
|
||||
|
||||
@WrapElementForJNI
|
||||
@ -2630,17 +2615,6 @@ public class GeckoAppShell
|
||||
return true;
|
||||
}
|
||||
|
||||
static native void notifyFilePickerResult(String filePath, long id);
|
||||
|
||||
@WrapElementForJNI(stubName = "ShowFilePickerAsyncWrapper")
|
||||
public static void showFilePickerAsync(String aMimeType, final long id) {
|
||||
sActivityHelper.showFilePickerAsync(getGeckoInterface().getActivity(), aMimeType, new ActivityHandlerHelper.FileResultHandler() {
|
||||
public void gotFile(String filename) {
|
||||
GeckoAppShell.notifyFilePickerResult(filename, id);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@WrapElementForJNI
|
||||
public static void notifyWakeLockChanged(String topic, String state) {
|
||||
if (getGeckoInterface() != null)
|
||||
|
@ -5,9 +5,7 @@
|
||||
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import org.mozilla.gecko.util.EventDispatcher;
|
||||
import org.mozilla.gecko.util.GeckoEventListener;
|
||||
import org.mozilla.gecko.util.GeckoEventResponder;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
@ -140,7 +138,7 @@ class JavaAddonManager implements GeckoEventListener {
|
||||
}
|
||||
}
|
||||
|
||||
private static class CallbackWrapper implements GeckoEventResponder {
|
||||
private static class CallbackWrapper implements GeckoEventListener {
|
||||
private final Handler.Callback mDelegate;
|
||||
private Bundle mBundle;
|
||||
|
||||
@ -184,16 +182,14 @@ class JavaAddonManager implements GeckoEventListener {
|
||||
Message msg = new Message();
|
||||
msg.setData(mBundle);
|
||||
mDelegate.handleMessage(msg);
|
||||
|
||||
JSONObject obj = new JSONObject();
|
||||
obj.put("response", mBundle.getString("response"));
|
||||
EventDispatcher.sendResponse(json, obj);
|
||||
mBundle = null;
|
||||
} catch (Exception e) {
|
||||
Log.e(LOGTAG, "Caught exception thrown from wrapped addon message handler", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getResponse(JSONObject origMessage) {
|
||||
String response = mBundle.getString("response");
|
||||
mBundle = null;
|
||||
return response;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import org.mozilla.gecko.background.common.GlobalConstants;
|
||||
import org.mozilla.gecko.util.EventDispatcher;
|
||||
import org.mozilla.gecko.EventDispatcher;
|
||||
import org.mozilla.gecko.util.GeckoEventListener;
|
||||
|
||||
import org.json.JSONException;
|
||||
|
@ -5,8 +5,8 @@
|
||||
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import org.mozilla.gecko.util.EventDispatcher;
|
||||
import org.mozilla.gecko.util.GeckoEventResponder;
|
||||
import org.mozilla.gecko.EventDispatcher;
|
||||
import org.mozilla.gecko.util.GeckoEventListener;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
@ -24,14 +24,12 @@ import java.util.HashMap;
|
||||
* Helper class to get, set, and observe Android Shared Preferences.
|
||||
*/
|
||||
public final class SharedPreferencesHelper
|
||||
implements GeckoEventResponder
|
||||
implements GeckoEventListener
|
||||
{
|
||||
public static final String LOGTAG = "GeckoAndSharedPrefs";
|
||||
|
||||
protected final Context mContext;
|
||||
|
||||
protected String mResponse;
|
||||
|
||||
// mListeners is not synchronized because it is only updated in
|
||||
// handleObserve, which is called from Gecko serially.
|
||||
protected final Map<String, SharedPreferences.OnSharedPreferenceChangeListener> mListeners;
|
||||
@ -117,7 +115,7 @@ public final class SharedPreferencesHelper
|
||||
* must include a String name, and a String type in ["bool", "int",
|
||||
* "string"].
|
||||
*/
|
||||
private String handleGet(JSONObject message) throws JSONException {
|
||||
private JSONArray handleGet(JSONObject message) throws JSONException {
|
||||
if (!message.has("branch")) {
|
||||
Log.e(LOGTAG, "No branch specified for SharedPreference:Get; aborting.");
|
||||
return null;
|
||||
@ -156,7 +154,7 @@ public final class SharedPreferencesHelper
|
||||
jsonValues.put(jsonValue);
|
||||
}
|
||||
|
||||
return jsonValues.toString();
|
||||
return jsonValues;
|
||||
}
|
||||
|
||||
private static class ChangeListener
|
||||
@ -225,8 +223,6 @@ public final class SharedPreferencesHelper
|
||||
public void handleMessage(String event, JSONObject message) {
|
||||
// Everything here is synchronous and serial, so we need not worry about
|
||||
// overwriting an in-progress response.
|
||||
mResponse = null;
|
||||
|
||||
try {
|
||||
if (event.equals("SharedPreferences:Set")) {
|
||||
if (Log.isLoggable(LOGTAG, Log.VERBOSE)) {
|
||||
@ -237,9 +233,9 @@ public final class SharedPreferencesHelper
|
||||
if (Log.isLoggable(LOGTAG, Log.VERBOSE)) {
|
||||
Log.v(LOGTAG, "Got SharedPreferences:Get message.");
|
||||
}
|
||||
// Synchronous and serial, so we are the only consumer of
|
||||
// mResponse and can write to it freely.
|
||||
mResponse = handleGet(message);
|
||||
JSONObject obj = new JSONObject();
|
||||
obj.put("values", handleGet(message));
|
||||
EventDispatcher.sendResponse(message, obj);
|
||||
} else if (event.equals("SharedPreferences:Observe")) {
|
||||
if (Log.isLoggable(LOGTAG, Log.VERBOSE)) {
|
||||
Log.v(LOGTAG, "Got SharedPreferences:Observe message.");
|
||||
@ -254,9 +250,4 @@ public final class SharedPreferencesHelper
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getResponse(JSONObject origMessage) {
|
||||
return mResponse;
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ import org.mozilla.gecko.gfx.Layer;
|
||||
import org.mozilla.gecko.gfx.LayerView;
|
||||
import org.mozilla.gecko.menu.GeckoMenu;
|
||||
import org.mozilla.gecko.menu.GeckoMenuItem;
|
||||
import org.mozilla.gecko.util.EventDispatcher;
|
||||
import org.mozilla.gecko.EventDispatcher;
|
||||
import org.mozilla.gecko.util.FloatUtils;
|
||||
import org.mozilla.gecko.util.GeckoEventListener;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
|
@ -101,6 +101,8 @@ public class BrowserContract {
|
||||
public static final class Favicons implements CommonColumns, DateSyncColumns {
|
||||
private Favicons() {}
|
||||
|
||||
public static final String TABLE_NAME = "favicons";
|
||||
|
||||
public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "favicons");
|
||||
|
||||
public static final String URL = "url";
|
||||
@ -112,6 +114,8 @@ public class BrowserContract {
|
||||
public static final class Thumbnails implements CommonColumns {
|
||||
private Thumbnails() {}
|
||||
|
||||
public static final String TABLE_NAME = "thumbnails";
|
||||
|
||||
public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "thumbnails");
|
||||
|
||||
public static final String URL = "url";
|
||||
@ -122,6 +126,10 @@ public class BrowserContract {
|
||||
public static final class Bookmarks implements CommonColumns, URLColumns, FaviconColumns, SyncColumns {
|
||||
private Bookmarks() {}
|
||||
|
||||
public static final String TABLE_NAME = "bookmarks";
|
||||
|
||||
public static final String VIEW_WITH_FAVICONS = "bookmarks_with_favicons";
|
||||
|
||||
public static final int FIXED_ROOT_ID = 0;
|
||||
public static final int FAKE_DESKTOP_FOLDER_ID = -1;
|
||||
public static final int FIXED_READING_LIST_ID = -2;
|
||||
@ -173,6 +181,11 @@ public class BrowserContract {
|
||||
@RobocopTarget
|
||||
public static final class History implements CommonColumns, URLColumns, HistoryColumns, FaviconColumns, SyncColumns {
|
||||
private History() {}
|
||||
|
||||
public static final String TABLE_NAME = "history";
|
||||
|
||||
public static final String VIEW_WITH_FAVICONS = "history_with_favicons";
|
||||
|
||||
public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "history");
|
||||
public static final Uri CONTENT_OLD_URI = Uri.withAppendedPath(AUTHORITY_URI, "history/old");
|
||||
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/browser-history";
|
||||
@ -183,6 +196,11 @@ public class BrowserContract {
|
||||
@RobocopTarget
|
||||
public static final class Combined implements CommonColumns, URLColumns, HistoryColumns, FaviconColumns {
|
||||
private Combined() {}
|
||||
|
||||
public static final String VIEW_NAME = "combined";
|
||||
|
||||
public static final String VIEW_WITH_FAVICONS = "combined_with_favicons";
|
||||
|
||||
public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "combined");
|
||||
|
||||
public static final int DISPLAY_NORMAL = 0;
|
||||
@ -316,4 +334,47 @@ public class BrowserContract {
|
||||
public static final String IMAGE_URL = "image_url";
|
||||
public static final String CREATED = "created";
|
||||
}
|
||||
|
||||
/*
|
||||
* Contains names and schema definitions for tables and views
|
||||
* no longer being used by current ContentProviders. These values are used
|
||||
* to make incremental updates to the schema during a database upgrade. Will be
|
||||
* removed with bug 947018.
|
||||
*/
|
||||
static final class Obsolete {
|
||||
public static final String TABLE_IMAGES = "images";
|
||||
public static final String VIEW_BOOKMARKS_WITH_IMAGES = "bookmarks_with_images";
|
||||
public static final String VIEW_HISTORY_WITH_IMAGES = "history_with_images";
|
||||
public static final String VIEW_COMBINED_WITH_IMAGES = "combined_with_images";
|
||||
|
||||
public static final class Images implements CommonColumns, SyncColumns {
|
||||
private Images() {}
|
||||
|
||||
public static final String URL = "url_key";
|
||||
public static final String FAVICON_URL = "favicon_url";
|
||||
public static final String FAVICON = "favicon";
|
||||
public static final String THUMBNAIL = "thumbnail";
|
||||
public static final String _ID = "_id";
|
||||
public static final String GUID = "guid";
|
||||
public static final String DATE_CREATED = "created";
|
||||
public static final String DATE_MODIFIED = "modified";
|
||||
public static final String IS_DELETED = "deleted";
|
||||
}
|
||||
|
||||
public static final class Combined {
|
||||
private Combined() {}
|
||||
|
||||
public static final String THUMBNAIL = "thumbnail";
|
||||
}
|
||||
|
||||
static final String TABLE_BOOKMARKS_JOIN_IMAGES = Bookmarks.TABLE_NAME + " LEFT OUTER JOIN " +
|
||||
Obsolete.TABLE_IMAGES + " ON " + DBUtils.qualifyColumn(Bookmarks.TABLE_NAME, Bookmarks.URL) + " = " +
|
||||
DBUtils.qualifyColumn(Obsolete.TABLE_IMAGES, Obsolete.Images.URL);
|
||||
|
||||
static final String TABLE_HISTORY_JOIN_IMAGES = History.TABLE_NAME + " LEFT OUTER JOIN " +
|
||||
Obsolete.TABLE_IMAGES + " ON " + DBUtils.qualifyColumn(Bookmarks.TABLE_NAME, History.URL) + " = " +
|
||||
DBUtils.qualifyColumn(Obsolete.TABLE_IMAGES, Obsolete.Images.URL);
|
||||
|
||||
static final String FAVICON_DB = "favicon_urls.db";
|
||||
}
|
||||
}
|
||||
|
1748
mobile/android/base/db/BrowserDatabaseHelper.java
Normal file
1748
mobile/android/base/db/BrowserDatabaseHelper.java
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -81,4 +81,19 @@ public class DBUtils {
|
||||
Log.d(LOGTAG, "Failed to unlock database");
|
||||
GeckoAppShell.listOfOpenFiles();
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that 0-byte arrays aren't added as favicon or thumbnail data.
|
||||
* @param values ContentValues of query
|
||||
* @param columnName Name of data column to verify
|
||||
*/
|
||||
public static void stripEmptyByteArray(ContentValues values, String columnName) {
|
||||
if (values.containsKey(columnName)) {
|
||||
byte[] data = values.getAsByteArray(columnName);
|
||||
if (data == null || data.length == 0) {
|
||||
Log.w(LOGTAG, "Tried to insert an empty or non-byte-array image. Ignoring.");
|
||||
values.putNull(columnName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
270
mobile/android/base/db/TransactionalProvider.java
Normal file
270
mobile/android/base/db/TransactionalProvider.java
Normal file
@ -0,0 +1,270 @@
|
||||
/* 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/. */
|
||||
|
||||
package org.mozilla.gecko.db;
|
||||
|
||||
import org.mozilla.gecko.db.PerProfileDatabases.DatabaseHelperFactory;
|
||||
|
||||
import android.content.ContentProvider;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.SQLException;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
/*
|
||||
* Abstract class containing methods needed to make a SQLite-based content provider with a
|
||||
* database helper of type T. Abstract methods insertInTransaction, deleteInTransaction and
|
||||
* updateInTransaction all called within a DB transaction so failed modifications can be rolled-back.
|
||||
*/
|
||||
public abstract class TransactionalProvider<T extends SQLiteOpenHelper> extends ContentProvider {
|
||||
private static final String LOGTAG = "GeckoTransProvider";
|
||||
protected Context mContext;
|
||||
protected PerProfileDatabases<T> mDatabases;
|
||||
|
||||
/*
|
||||
* Returns the name of the database file. Used to get a path
|
||||
* to the DB file.
|
||||
*
|
||||
* @return name of the database file
|
||||
*/
|
||||
abstract protected String getDatabaseName();
|
||||
|
||||
/*
|
||||
* Creates and returns an instance of a DB helper. Given a
|
||||
* context and a path to the DB file
|
||||
*
|
||||
* @param context to use to create the database helper
|
||||
* @param databasePath path to the DB file
|
||||
* @return instance of the database helper
|
||||
*/
|
||||
abstract protected T createDatabaseHelper(Context context, String databasePath);
|
||||
|
||||
/*
|
||||
* Inserts an item into the database within a DB transaction.
|
||||
*
|
||||
* @param uri query URI
|
||||
* @param values column values to be inserted
|
||||
* @return a URI for the newly inserted item
|
||||
*/
|
||||
abstract protected Uri insertInTransaction(Uri uri, ContentValues values);
|
||||
|
||||
/*
|
||||
* Deletes items from the database within a DB transaction.
|
||||
*
|
||||
* @param uri query URI
|
||||
* @param selection An optional filter to match rows to update.
|
||||
* @param selectionArgs arguments for the selection
|
||||
* @return number of rows impacted by the deletion
|
||||
*/
|
||||
abstract protected int deleteInTransaction(Uri uri, String selection, String[] selectionArgs);
|
||||
|
||||
/*
|
||||
* Updates the database within a DB transaction.
|
||||
*
|
||||
* @param uri Query URI
|
||||
* @param values A set of column_name/value pairs to add to the database.
|
||||
* @param selection An optional filter to match rows to update.
|
||||
* @param selectionArgs Arguments for the selection
|
||||
* @return number of rows impacted by the update
|
||||
*/
|
||||
abstract protected int updateInTransaction(Uri uri, ContentValues values, String selection, String[] selectionArgs);
|
||||
|
||||
/*
|
||||
* Fetches a readable database based on the profile indicated in the
|
||||
* passed URI. If the URI does not contain a profile param, the default profile
|
||||
* is used.
|
||||
*
|
||||
* @param uri content URI optionally indicating the profile of the user
|
||||
* @return instance of a readable SQLiteDatabase
|
||||
*/
|
||||
protected SQLiteDatabase getReadableDatabase(Uri uri) {
|
||||
String profile = null;
|
||||
if (uri != null) {
|
||||
profile = uri.getQueryParameter(BrowserContract.PARAM_PROFILE);
|
||||
}
|
||||
|
||||
return mDatabases.getDatabaseHelperForProfile(profile, isTest(uri)).getReadableDatabase();
|
||||
}
|
||||
|
||||
/*
|
||||
* Fetches a writeable database based on the profile indicated in the
|
||||
* passed URI. If the URI does not contain a profile param, the default profile
|
||||
* is used
|
||||
*
|
||||
* @param uri content URI optionally indicating the profile of the user
|
||||
* @return instance of a writeable SQLiteDatabase
|
||||
*/
|
||||
protected SQLiteDatabase getWritableDatabase(Uri uri) {
|
||||
String profile = null;
|
||||
if (uri != null) {
|
||||
profile = uri.getQueryParameter(BrowserContract.PARAM_PROFILE);
|
||||
}
|
||||
|
||||
return mDatabases.getDatabaseHelperForProfile(profile, isTest(uri)).getWritableDatabase();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreate() {
|
||||
synchronized (this) {
|
||||
mContext = getContext();
|
||||
mDatabases = new PerProfileDatabases<T>(
|
||||
getContext(), getDatabaseName(), new DatabaseHelperFactory<T>() {
|
||||
@Override
|
||||
public T makeDatabaseHelper(Context context, String databasePath) {
|
||||
return createDatabaseHelper(context, databasePath);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int delete(Uri uri, String selection, String[] selectionArgs) {
|
||||
trace("Calling delete on URI: " + uri);
|
||||
|
||||
final SQLiteDatabase db = getWritableDatabase(uri);
|
||||
int deleted = 0;
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 11) {
|
||||
trace("Beginning delete transaction: " + uri);
|
||||
db.beginTransaction();
|
||||
try {
|
||||
deleted = deleteInTransaction(uri, selection, selectionArgs);
|
||||
db.setTransactionSuccessful();
|
||||
trace("Successful delete transaction: " + uri);
|
||||
} finally {
|
||||
db.endTransaction();
|
||||
}
|
||||
} else {
|
||||
deleted = deleteInTransaction(uri, selection, selectionArgs);
|
||||
}
|
||||
|
||||
if (deleted > 0) {
|
||||
getContext().getContentResolver().notifyChange(uri, null);
|
||||
}
|
||||
|
||||
return deleted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uri insert(Uri uri, ContentValues values) {
|
||||
trace("Calling insert on URI: " + uri);
|
||||
|
||||
final SQLiteDatabase db = getWritableDatabase(uri);
|
||||
Uri result = null;
|
||||
try {
|
||||
if (Build.VERSION.SDK_INT >= 11) {
|
||||
trace("Beginning insert transaction: " + uri);
|
||||
db.beginTransaction();
|
||||
try {
|
||||
result = insertInTransaction(uri, values);
|
||||
db.setTransactionSuccessful();
|
||||
trace("Successful insert transaction: " + uri);
|
||||
} finally {
|
||||
db.endTransaction();
|
||||
}
|
||||
} else {
|
||||
result = insertInTransaction(uri, values);
|
||||
}
|
||||
} catch (SQLException sqle) {
|
||||
Log.e(LOGTAG, "exception in DB operation", sqle);
|
||||
} catch (UnsupportedOperationException uoe) {
|
||||
Log.e(LOGTAG, "don't know how to perform that insert", uoe);
|
||||
}
|
||||
|
||||
if (result != null) {
|
||||
getContext().getContentResolver().notifyChange(uri, null);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int update(Uri uri, ContentValues values, String selection,
|
||||
String[] selectionArgs) {
|
||||
trace("Calling update on URI: " + uri);
|
||||
|
||||
final SQLiteDatabase db = getWritableDatabase(uri);
|
||||
int updated = 0;
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 11) {
|
||||
trace("Beginning update transaction: " + uri);
|
||||
db.beginTransaction();
|
||||
try {
|
||||
updated = updateInTransaction(uri, values, selection, selectionArgs);
|
||||
db.setTransactionSuccessful();
|
||||
trace("Successful update transaction: " + uri);
|
||||
} finally {
|
||||
db.endTransaction();
|
||||
}
|
||||
} else {
|
||||
updated = updateInTransaction(uri, values, selection, selectionArgs);
|
||||
}
|
||||
|
||||
if (updated > 0) {
|
||||
getContext().getContentResolver().notifyChange(uri, null);
|
||||
}
|
||||
|
||||
return updated;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int bulkInsert(Uri uri, ContentValues[] values) {
|
||||
if (values == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int numValues = values.length;
|
||||
int successes = 0;
|
||||
|
||||
final SQLiteDatabase db = getWritableDatabase(uri);
|
||||
|
||||
db.beginTransaction();
|
||||
|
||||
try {
|
||||
for (int i = 0; i < numValues; i++) {
|
||||
insertInTransaction(uri, values[i]);
|
||||
successes++;
|
||||
}
|
||||
trace("Flushing DB bulkinsert...");
|
||||
db.setTransactionSuccessful();
|
||||
} finally {
|
||||
db.endTransaction();
|
||||
}
|
||||
|
||||
if (successes > 0) {
|
||||
mContext.getContentResolver().notifyChange(uri, null);
|
||||
}
|
||||
|
||||
return successes;
|
||||
}
|
||||
|
||||
protected boolean isTest(Uri uri) {
|
||||
String isTest = uri.getQueryParameter(BrowserContract.PARAM_IS_TEST);
|
||||
return !TextUtils.isEmpty(isTest);
|
||||
}
|
||||
|
||||
// Calculate these once, at initialization. isLoggable is too expensive to
|
||||
// have in-line in each log call.
|
||||
private static boolean logDebug = Log.isLoggable(LOGTAG, Log.DEBUG);
|
||||
private static boolean logVerbose = Log.isLoggable(LOGTAG, Log.VERBOSE);
|
||||
protected static void trace(String message) {
|
||||
if (logVerbose) {
|
||||
Log.v(LOGTAG, message);
|
||||
}
|
||||
}
|
||||
|
||||
protected static void debug(String message) {
|
||||
if (logDebug) {
|
||||
Log.d(LOGTAG, message);
|
||||
}
|
||||
}
|
||||
}
|
@ -12,7 +12,7 @@ import org.mozilla.gecko.Tabs;
|
||||
import org.mozilla.gecko.ZoomConstraints;
|
||||
import org.mozilla.gecko.mozglue.RobocopTarget;
|
||||
import org.mozilla.gecko.mozglue.generatorannotations.WrapElementForJNI;
|
||||
import org.mozilla.gecko.util.EventDispatcher;
|
||||
import org.mozilla.gecko.EventDispatcher;
|
||||
import org.mozilla.gecko.util.FloatUtils;
|
||||
|
||||
import android.content.Context;
|
||||
|
@ -11,7 +11,7 @@ import org.mozilla.gecko.PrefsHelper;
|
||||
import org.mozilla.gecko.Tab;
|
||||
import org.mozilla.gecko.Tabs;
|
||||
import org.mozilla.gecko.ZoomConstraints;
|
||||
import org.mozilla.gecko.util.EventDispatcher;
|
||||
import org.mozilla.gecko.EventDispatcher;
|
||||
import org.mozilla.gecko.util.FloatUtils;
|
||||
import org.mozilla.gecko.util.GamepadUtils;
|
||||
import org.mozilla.gecko.util.GeckoEventListener;
|
||||
|
@ -16,7 +16,7 @@ import org.mozilla.gecko.TouchEventInterceptor;
|
||||
import org.mozilla.gecko.ZoomConstraints;
|
||||
import org.mozilla.gecko.mozglue.generatorannotations.WrapElementForJNI;
|
||||
import org.mozilla.gecko.mozglue.RobocopTarget;
|
||||
import org.mozilla.gecko.util.EventDispatcher;
|
||||
import org.mozilla.gecko.EventDispatcher;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
|
@ -8,7 +8,7 @@ package org.mozilla.gecko.gfx;
|
||||
import org.mozilla.gecko.GeckoEvent;
|
||||
import org.mozilla.gecko.GeckoThread;
|
||||
import org.mozilla.gecko.mozglue.generatorannotations.WrapElementForJNI;
|
||||
import org.mozilla.gecko.util.EventDispatcher;
|
||||
import org.mozilla.gecko.EventDispatcher;
|
||||
import org.mozilla.gecko.util.GeckoEventListener;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
@ -6,7 +6,7 @@
|
||||
package org.mozilla.gecko.gfx;
|
||||
|
||||
import org.mozilla.gecko.GeckoAppShell;
|
||||
import org.mozilla.gecko.util.EventDispatcher;
|
||||
import org.mozilla.gecko.EventDispatcher;
|
||||
|
||||
import android.graphics.PointF;
|
||||
import android.view.KeyEvent;
|
||||
|
@ -7,7 +7,7 @@ package org.mozilla.gecko.gfx;
|
||||
|
||||
import org.mozilla.gecko.GeckoAppShell;
|
||||
import org.mozilla.gecko.GeckoEvent;
|
||||
import org.mozilla.gecko.util.EventDispatcher;
|
||||
import org.mozilla.gecko.EventDispatcher;
|
||||
import org.mozilla.gecko.util.GeckoEventListener;
|
||||
|
||||
import org.json.JSONException;
|
||||
|
@ -26,7 +26,7 @@ import org.mozilla.gecko.background.healthreport.HealthReportStorage.Measurement
|
||||
import org.mozilla.gecko.background.healthreport.HealthReportStorage.MeasurementFields.FieldSpec;
|
||||
import org.mozilla.gecko.background.healthreport.ProfileInformationCache;
|
||||
|
||||
import org.mozilla.gecko.util.EventDispatcher;
|
||||
import org.mozilla.gecko.EventDispatcher;
|
||||
import org.mozilla.gecko.util.GeckoEventListener;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
|
||||
|
@ -95,7 +95,6 @@ public class BrowserSearch extends HomeFragment
|
||||
private HomeListView mList;
|
||||
|
||||
// Client that performs search suggestion queries
|
||||
@RobocopTarget
|
||||
private volatile SuggestClient mSuggestClient;
|
||||
|
||||
// List of search engines from gecko
|
||||
@ -519,8 +518,8 @@ public class BrowserSearch extends HomeFragment
|
||||
// set yet. e.g. Robocop tests might set it directly before search
|
||||
// engines are loaded.
|
||||
if (mSuggestClient == null && !isPrivate) {
|
||||
mSuggestClient = new SuggestClient(getActivity(), suggestTemplate,
|
||||
SUGGESTION_TIMEOUT, SUGGESTION_MAX);
|
||||
setSuggestClient(new SuggestClient(getActivity(), suggestTemplate,
|
||||
SUGGESTION_TIMEOUT, SUGGESTION_MAX));
|
||||
}
|
||||
} else {
|
||||
searchEngines.add(engine);
|
||||
@ -545,6 +544,20 @@ public class BrowserSearch extends HomeFragment
|
||||
filterSuggestions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the private SuggestClient instance. Should only be called if the suggestClient is
|
||||
* null (i.e. has not yet been initialized or has been nulled). Non-private access is
|
||||
* for testing purposes only.
|
||||
*/
|
||||
@RobocopTarget
|
||||
public void setSuggestClient(final SuggestClient client) {
|
||||
if (mSuggestClient != null) {
|
||||
throw new IllegalStateException("Can only set the SuggestClient if it has not " +
|
||||
"yet been initialized!");
|
||||
}
|
||||
mSuggestClient = client;
|
||||
}
|
||||
|
||||
private void showSuggestionsOptIn() {
|
||||
// Return if the ViewStub was already inflated - an inflated ViewStub is removed from the
|
||||
// View hierarchy so a second call to findViewById will return null.
|
||||
|
@ -26,7 +26,7 @@ import java.util.ArrayList;
|
||||
/**
|
||||
* Use network-based search suggestions.
|
||||
*/
|
||||
class SuggestClient {
|
||||
public class SuggestClient {
|
||||
private static final String LOGTAG = "GeckoSuggestClient";
|
||||
private static final String USER_AGENT = GeckoAppShell.getGeckoInterface().getDefaultUAString();
|
||||
|
||||
@ -39,7 +39,7 @@ class SuggestClient {
|
||||
// the maximum number of suggestions to return
|
||||
private final int mMaxResults;
|
||||
|
||||
// used by robocop for testing; referenced via reflection
|
||||
// used by robocop for testing
|
||||
private boolean mCheckNetwork;
|
||||
|
||||
// used to make suggestions appear instantly after opt-in
|
||||
|
@ -41,12 +41,10 @@ gujar.sources += [
|
||||
'util/ActivityResultHandler.java',
|
||||
'util/ActivityResultHandlerMap.java',
|
||||
'util/Clipboard.java',
|
||||
'util/EventDispatcher.java',
|
||||
'util/FloatUtils.java',
|
||||
'util/GamepadUtils.java',
|
||||
'util/GeckoBackgroundThread.java',
|
||||
'util/GeckoEventListener.java',
|
||||
'util/GeckoEventResponder.java',
|
||||
'util/GeckoJarReader.java',
|
||||
'util/HardwareUtils.java',
|
||||
'util/INIParser.java',
|
||||
@ -112,6 +110,7 @@ gbjar.sources += [
|
||||
'CustomEditText.java',
|
||||
'DataReportingNotification.java',
|
||||
'db/BrowserContract.java',
|
||||
'db/BrowserDatabaseHelper.java',
|
||||
'db/BrowserDB.java',
|
||||
'db/BrowserProvider.java',
|
||||
'db/DBUtils.java',
|
||||
@ -122,9 +121,11 @@ gbjar.sources += [
|
||||
'db/PerProfileDatabases.java',
|
||||
'db/SQLiteBridgeContentProvider.java',
|
||||
'db/TabsProvider.java',
|
||||
'db/TransactionalProvider.java',
|
||||
'Distribution.java',
|
||||
'DoorHangerPopup.java',
|
||||
'EditBookmarkDialog.java',
|
||||
'EventDispatcher.java',
|
||||
'favicons/cache/FaviconCache.java',
|
||||
'favicons/cache/FaviconCacheElement.java',
|
||||
'favicons/cache/FaviconsForURL.java',
|
||||
|
@ -5,7 +5,6 @@
|
||||
|
||||
package org.mozilla.gecko.prompts;
|
||||
|
||||
import org.mozilla.gecko.util.GeckoEventResponder;
|
||||
import org.mozilla.gecko.GeckoEvent;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
import org.mozilla.gecko.widget.DateTimePicker;
|
||||
@ -54,7 +53,6 @@ import android.widget.TimePicker;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class Prompt implements OnClickListener, OnCancelListener, OnItemClickListener {
|
||||
@ -66,7 +64,6 @@ public class Prompt implements OnClickListener, OnCancelListener, OnItemClickLis
|
||||
private AlertDialog mDialog;
|
||||
|
||||
private final LayoutInflater mInflater;
|
||||
private ConcurrentLinkedQueue<String> mPromptQueue;
|
||||
private final Context mContext;
|
||||
private PromptCallback mCallback;
|
||||
private String mGuid;
|
||||
@ -80,16 +77,9 @@ public class Prompt implements OnClickListener, OnCancelListener, OnItemClickLis
|
||||
private static int mInputPaddingSize;
|
||||
private static int mMinRowSize;
|
||||
|
||||
public Prompt(Context context, ConcurrentLinkedQueue<String> queue) {
|
||||
this(context);
|
||||
mCallback = null;
|
||||
mPromptQueue = queue;
|
||||
}
|
||||
|
||||
public Prompt(Context context, PromptCallback callback) {
|
||||
this(context);
|
||||
mCallback = callback;
|
||||
mPromptQueue = null;
|
||||
}
|
||||
|
||||
private Prompt(Context context) {
|
||||
@ -415,10 +405,6 @@ public class Prompt implements OnClickListener, OnCancelListener, OnItemClickLis
|
||||
aReturn.put("guid", mGuid);
|
||||
} catch(JSONException ex) { }
|
||||
|
||||
if (mPromptQueue != null) {
|
||||
mPromptQueue.offer(aReturn.toString());
|
||||
}
|
||||
|
||||
// poke the Gecko thread in case it's waiting for new events
|
||||
GeckoAppShell.sendEventToGecko(GeckoEvent.createNoOpEvent());
|
||||
|
||||
|
@ -5,7 +5,6 @@
|
||||
|
||||
package org.mozilla.gecko.prompts;
|
||||
|
||||
import org.mozilla.gecko.util.GeckoEventResponder;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
import org.mozilla.gecko.widget.AllCapsTextView;
|
||||
import org.mozilla.gecko.widget.DateTimePicker;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user