Merge m-c to b2g-inbound

This commit is contained in:
Ryan VanderMeulen 2014-02-14 15:32:34 -05:00
commit f0fc43923a
163 changed files with 3646 additions and 3910 deletions

View File

@ -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();
}

View File

@ -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);

View File

@ -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"/>

View File

@ -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) {

View File

@ -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!");

View File

@ -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();

View File

@ -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">

View File

@ -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;

View File

@ -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 ***/

View File

@ -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 {

View File

@ -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. */

View File

@ -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. */

View File

@ -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;

View File

@ -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;
}

View File

@ -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
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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',
]

View File

@ -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;

View File

@ -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);

View File

@ -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));

View File

@ -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();
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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()) {

View File

@ -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_);

View File

@ -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;

View File

@ -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)

View File

@ -102,8 +102,6 @@ class CompileCompartment
{
JSCompartment *compartment();
friend class js::AutoLockForCompilation;
public:
static CompileCompartment *get(JSCompartment *comp);

View File

@ -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();

View File

@ -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)) {

View File

@ -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() {

View File

@ -82,7 +82,6 @@ class JitCode : public gc::BarrieredCell<JitCode>
public:
uint8_t *raw() const {
AutoThreadSafeAccess ts(this);
return code_;
}
size_t instructionsSize() const {

View File

@ -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),

View File

@ -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;

View File

@ -45,7 +45,6 @@ struct JitOptions
bool checkOsiPointRegisters;
#endif
bool checkRangeAnalysis;
bool checkThreadSafety;
bool compileTryCatch;
bool disableGvn;
bool disableLicm;

View File

@ -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()),

View File

@ -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();
}

View File

@ -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))

View File

@ -31,7 +31,6 @@ namespace js {
inline jsid
AtomToId(JSAtom *atom)
{
AutoThreadSafeAccess ts(atom);
JS_STATIC_ASSERT(JSID_INT_MIN == 0);
uint32_t index;

View File

@ -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();
}

View File

@ -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;

View File

@ -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

View File

@ -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_;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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();
}

View File

@ -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);

View File

@ -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));

View File

@ -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>();
}

View File

@ -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();
}
/*

View File

@ -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)) {

View File

@ -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);
}

View File

@ -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 {

View File

@ -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();
}

View File

@ -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());
}

View File

@ -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);

View File

@ -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))
{

View File

@ -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();

View File

@ -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;

View File

@ -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));
}

View File

@ -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

View File

@ -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)
{

View File

@ -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();
}

View File

@ -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)
{

View File

@ -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

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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;

View File

@ -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));

View File

@ -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));

View File

@ -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));
}

View File

@ -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.

View File

@ -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;

View File

@ -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;

View File

@ -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) { }
}
}

View File

@ -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() { }
/**

View File

@ -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)

View File

@ -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;
}
}
}

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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";
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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);
}
}
}
}

View 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);
}
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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.

View File

@ -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

View File

@ -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',

View File

@ -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());

View File

@ -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