mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
merge mozilla-inbound to mozilla-central a=merge
This commit is contained in:
commit
d80c849001
@ -99,7 +99,7 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
// Testing
|
// Testing
|
||||||
|
|
||||||
//gA11yEventDumpToConsole = true; // debug
|
gA11yEventDumpToConsole = true; // debug
|
||||||
|
|
||||||
var gQueue = null;
|
var gQueue = null;
|
||||||
function doTests()
|
function doTests()
|
||||||
@ -107,7 +107,7 @@
|
|||||||
testRelation(browserDocument(), RELATION_EMBEDS,
|
testRelation(browserDocument(), RELATION_EMBEDS,
|
||||||
getAccessible(currentTabDocument()));
|
getAccessible(currentTabDocument()));
|
||||||
|
|
||||||
//enableLogging("docload");
|
enableLogging("docload");
|
||||||
gQueue = new eventQueue();
|
gQueue = new eventQueue();
|
||||||
|
|
||||||
gQueue.push(new loadURI("about:about"));
|
gQueue.push(new loadURI("about:about"));
|
||||||
@ -115,7 +115,7 @@
|
|||||||
|
|
||||||
gQueue.onFinish = function()
|
gQueue.onFinish = function()
|
||||||
{
|
{
|
||||||
//disableLogging();
|
disableLogging();
|
||||||
closeBrowserWindow();
|
closeBrowserWindow();
|
||||||
}
|
}
|
||||||
gQueue.invoke();
|
gQueue.invoke();
|
||||||
|
@ -7,10 +7,11 @@
|
|||||||
"unpack": true
|
"unpack": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size": 12057960,
|
"size": 12072532,
|
||||||
"digest": "6105d6432943141cffb40020dc5ba3a793650bdeb3af9bd5e56d3796c5f03df9962a73e521646cd71fbfb5e266c1e74716ad722fb6055589dfb7d35175bca89e",
|
"digest": "3915f8ec396c56a8a92e6f9695b70f09ce9d1582359d1258e37e3fd43a143bc974410e4cfc27f500e095f34a8956206e0ebf799b7287f0f38def0d5e34ed71c9",
|
||||||
"algorithm": "sha512",
|
"algorithm": "sha512",
|
||||||
"filename": "gtk3.tar.xz",
|
"filename": "gtk3.tar.xz",
|
||||||
|
"setup": "setup.sh",
|
||||||
"unpack": true
|
"unpack": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -7,10 +7,11 @@
|
|||||||
"unpack": true
|
"unpack": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size": 12057960,
|
"size": 12072532,
|
||||||
"digest": "6105d6432943141cffb40020dc5ba3a793650bdeb3af9bd5e56d3796c5f03df9962a73e521646cd71fbfb5e266c1e74716ad722fb6055589dfb7d35175bca89e",
|
"digest": "3915f8ec396c56a8a92e6f9695b70f09ce9d1582359d1258e37e3fd43a143bc974410e4cfc27f500e095f34a8956206e0ebf799b7287f0f38def0d5e34ed71c9",
|
||||||
"algorithm": "sha512",
|
"algorithm": "sha512",
|
||||||
"filename": "gtk3.tar.xz",
|
"filename": "gtk3.tar.xz",
|
||||||
|
"setup": "setup.sh",
|
||||||
"unpack": true
|
"unpack": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -7,10 +7,11 @@
|
|||||||
"unpack": true
|
"unpack": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size": 12057960,
|
"size": 12072532,
|
||||||
"digest": "6105d6432943141cffb40020dc5ba3a793650bdeb3af9bd5e56d3796c5f03df9962a73e521646cd71fbfb5e266c1e74716ad722fb6055589dfb7d35175bca89e",
|
"digest": "3915f8ec396c56a8a92e6f9695b70f09ce9d1582359d1258e37e3fd43a143bc974410e4cfc27f500e095f34a8956206e0ebf799b7287f0f38def0d5e34ed71c9",
|
||||||
"algorithm": "sha512",
|
"algorithm": "sha512",
|
||||||
"filename": "gtk3.tar.xz",
|
"filename": "gtk3.tar.xz",
|
||||||
|
"setup": "setup.sh",
|
||||||
"unpack": true
|
"unpack": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -7,10 +7,11 @@
|
|||||||
"unpack": true
|
"unpack": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size": 12057960,
|
"size": 12072532,
|
||||||
"digest": "6105d6432943141cffb40020dc5ba3a793650bdeb3af9bd5e56d3796c5f03df9962a73e521646cd71fbfb5e266c1e74716ad722fb6055589dfb7d35175bca89e",
|
"digest": "3915f8ec396c56a8a92e6f9695b70f09ce9d1582359d1258e37e3fd43a143bc974410e4cfc27f500e095f34a8956206e0ebf799b7287f0f38def0d5e34ed71c9",
|
||||||
"algorithm": "sha512",
|
"algorithm": "sha512",
|
||||||
"filename": "gtk3.tar.xz",
|
"filename": "gtk3.tar.xz",
|
||||||
|
"setup": "setup.sh",
|
||||||
"unpack": true
|
"unpack": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -7,10 +7,11 @@
|
|||||||
"unpack": true
|
"unpack": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size": 12057960,
|
"size": 12072532,
|
||||||
"digest": "6105d6432943141cffb40020dc5ba3a793650bdeb3af9bd5e56d3796c5f03df9962a73e521646cd71fbfb5e266c1e74716ad722fb6055589dfb7d35175bca89e",
|
"digest": "3915f8ec396c56a8a92e6f9695b70f09ce9d1582359d1258e37e3fd43a143bc974410e4cfc27f500e095f34a8956206e0ebf799b7287f0f38def0d5e34ed71c9",
|
||||||
"algorithm": "sha512",
|
"algorithm": "sha512",
|
||||||
"filename": "gtk3.tar.xz",
|
"filename": "gtk3.tar.xz",
|
||||||
|
"setup": "setup.sh",
|
||||||
"unpack": true
|
"unpack": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -7,10 +7,11 @@
|
|||||||
"unpack": true
|
"unpack": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size": 12057960,
|
"size": 12072532,
|
||||||
"digest": "6105d6432943141cffb40020dc5ba3a793650bdeb3af9bd5e56d3796c5f03df9962a73e521646cd71fbfb5e266c1e74716ad722fb6055589dfb7d35175bca89e",
|
"digest": "3915f8ec396c56a8a92e6f9695b70f09ce9d1582359d1258e37e3fd43a143bc974410e4cfc27f500e095f34a8956206e0ebf799b7287f0f38def0d5e34ed71c9",
|
||||||
"algorithm": "sha512",
|
"algorithm": "sha512",
|
||||||
"filename": "gtk3.tar.xz",
|
"filename": "gtk3.tar.xz",
|
||||||
|
"setup": "setup.sh",
|
||||||
"unpack": true
|
"unpack": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -7,10 +7,11 @@
|
|||||||
"unpack": true
|
"unpack": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size": 12057960,
|
"size": 12072532,
|
||||||
"digest": "6105d6432943141cffb40020dc5ba3a793650bdeb3af9bd5e56d3796c5f03df9962a73e521646cd71fbfb5e266c1e74716ad722fb6055589dfb7d35175bca89e",
|
"digest": "3915f8ec396c56a8a92e6f9695b70f09ce9d1582359d1258e37e3fd43a143bc974410e4cfc27f500e095f34a8956206e0ebf799b7287f0f38def0d5e34ed71c9",
|
||||||
"algorithm": "sha512",
|
"algorithm": "sha512",
|
||||||
"filename": "gtk3.tar.xz",
|
"filename": "gtk3.tar.xz",
|
||||||
|
"setup": "setup.sh",
|
||||||
"unpack": true
|
"unpack": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -7,8 +7,8 @@
|
|||||||
"unpack": true
|
"unpack": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size": 11179576,
|
"size": 11189216,
|
||||||
"digest": "91567ce8e2bb8ab0ebc60c31e90731d88a1ea889fb71bcf55c735746a60fa7610b7e040ea3d8f727b6f692ae3ee703d6f3b30cdbd76fdf5617f77d9c38aa20ed",
|
"digest": "18bc52b0599b1308b667e282abb45f47597bfc98a5140cfcab8da71dacf89dd76d0dee22a04ce26fe7ad1f04e2d6596991f9e5b01fd2aaaab5542965f596b0e6",
|
||||||
"algorithm": "sha512",
|
"algorithm": "sha512",
|
||||||
"filename": "gtk3.tar.xz",
|
"filename": "gtk3.tar.xz",
|
||||||
"setup": "setup.sh",
|
"setup": "setup.sh",
|
||||||
|
@ -7,8 +7,8 @@
|
|||||||
"unpack": true
|
"unpack": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size": 12057960,
|
"size": 12072532,
|
||||||
"digest": "6105d6432943141cffb40020dc5ba3a793650bdeb3af9bd5e56d3796c5f03df9962a73e521646cd71fbfb5e266c1e74716ad722fb6055589dfb7d35175bca89e",
|
"digest": "3915f8ec396c56a8a92e6f9695b70f09ce9d1582359d1258e37e3fd43a143bc974410e4cfc27f500e095f34a8956206e0ebf799b7287f0f38def0d5e34ed71c9",
|
||||||
"algorithm": "sha512",
|
"algorithm": "sha512",
|
||||||
"filename": "gtk3.tar.xz",
|
"filename": "gtk3.tar.xz",
|
||||||
"setup": "setup.sh",
|
"setup": "setup.sh",
|
||||||
|
@ -30,9 +30,6 @@ pref("network.predictor.enabled", true);
|
|||||||
// No AccessibleCaret
|
// No AccessibleCaret
|
||||||
pref("layout.accessiblecaret.enabled", false);
|
pref("layout.accessiblecaret.enabled", false);
|
||||||
|
|
||||||
pref("gfx.vsync.hw-vsync.enabled", true);
|
|
||||||
pref("gfx.vsync.compositor", true);
|
|
||||||
|
|
||||||
// To be removed once bug 942756 is fixed.
|
// To be removed once bug 942756 is fixed.
|
||||||
pref("devtools.debugger.unix-domain-socket", "6000");
|
pref("devtools.debugger.unix-domain-socket", "6000");
|
||||||
|
|
||||||
|
@ -62,6 +62,12 @@ pref("extensions.blocklist.url", "https://blocklist.addons.mozilla.org/blocklist
|
|||||||
pref("extensions.blocklist.detailsURL", "https://www.mozilla.org/%LOCALE%/blocklist/");
|
pref("extensions.blocklist.detailsURL", "https://www.mozilla.org/%LOCALE%/blocklist/");
|
||||||
pref("extensions.blocklist.itemURL", "https://blocklist.addons.mozilla.org/%LOCALE%/%APP%/blocked/%blockID%");
|
pref("extensions.blocklist.itemURL", "https://blocklist.addons.mozilla.org/%LOCALE%/%APP%/blocked/%blockID%");
|
||||||
|
|
||||||
|
// Kinto blocklist preferences
|
||||||
|
pref("services.kinto.base", "https://firefox.settings.services.mozilla.com/v1");
|
||||||
|
pref("services.kinto.bucket", "blocklists");
|
||||||
|
pref("services.kinto.onecrl.collection", "certificates");
|
||||||
|
pref("services.kinto.onecrl.checked", 0);
|
||||||
|
|
||||||
pref("extensions.update.autoUpdateDefault", true);
|
pref("extensions.update.autoUpdateDefault", true);
|
||||||
|
|
||||||
pref("extensions.hotfix.id", "firefox-hotfix@mozilla.org");
|
pref("extensions.hotfix.id", "firefox-hotfix@mozilla.org");
|
||||||
|
@ -11,4 +11,5 @@ ac_add_options --enable-verify-mar
|
|||||||
|
|
||||||
mk_add_options MOZ_PGO=1
|
mk_add_options MOZ_PGO=1
|
||||||
|
|
||||||
|
. "$topsrcdir/build/mozconfig.rust"
|
||||||
. "$topsrcdir/build/mozconfig.common.override"
|
. "$topsrcdir/build/mozconfig.common.override"
|
||||||
|
@ -18,4 +18,5 @@ mk_add_options MOZ_PGO=1
|
|||||||
# defines.sh during the beta cycle
|
# defines.sh during the beta cycle
|
||||||
export BUILDING_RELEASE=1
|
export BUILDING_RELEASE=1
|
||||||
|
|
||||||
|
. "$topsrcdir/build/mozconfig.rust"
|
||||||
. "$topsrcdir/build/mozconfig.common.override"
|
. "$topsrcdir/build/mozconfig.common.override"
|
||||||
|
@ -10,5 +10,6 @@ fi
|
|||||||
ac_add_options --enable-official-branding
|
ac_add_options --enable-official-branding
|
||||||
ac_add_options --enable-verify-mar
|
ac_add_options --enable-verify-mar
|
||||||
|
|
||||||
|
. "$topsrcdir/build/mozconfig.rust"
|
||||||
. "$topsrcdir/build/mozconfig.common.override"
|
. "$topsrcdir/build/mozconfig.common.override"
|
||||||
. "$topsrcdir/build/mozconfig.cache"
|
. "$topsrcdir/build/mozconfig.cache"
|
||||||
|
@ -16,5 +16,6 @@ ac_add_options --enable-verify-mar
|
|||||||
# defines.sh during the beta cycle
|
# defines.sh during the beta cycle
|
||||||
export BUILDING_RELEASE=1
|
export BUILDING_RELEASE=1
|
||||||
|
|
||||||
|
. "$topsrcdir/build/mozconfig.rust"
|
||||||
. "$topsrcdir/build/mozconfig.common.override"
|
. "$topsrcdir/build/mozconfig.common.override"
|
||||||
. "$topsrcdir/build/mozconfig.cache"
|
. "$topsrcdir/build/mozconfig.cache"
|
||||||
|
@ -40,7 +40,6 @@ whitelist['nightly']['linux64'] += [
|
|||||||
'STRIP_FLAGS="--strip-debug"',
|
'STRIP_FLAGS="--strip-debug"',
|
||||||
'ac_add_options --with-ccache=/usr/bin/ccache',
|
'ac_add_options --with-ccache=/usr/bin/ccache',
|
||||||
'. "$topsrcdir/build/mozconfig.cache"',
|
'. "$topsrcdir/build/mozconfig.cache"',
|
||||||
'. "$topsrcdir/build/mozconfig.rust"',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
whitelist['nightly']['macosx-universal'] += [
|
whitelist['nightly']['macosx-universal'] += [
|
||||||
@ -53,7 +52,6 @@ whitelist['nightly']['macosx-universal'] += [
|
|||||||
'ac_add_options --disable-install-strip',
|
'ac_add_options --disable-install-strip',
|
||||||
'ac_add_options --enable-instruments',
|
'ac_add_options --enable-instruments',
|
||||||
'ac_add_options --enable-dtrace',
|
'ac_add_options --enable-dtrace',
|
||||||
'. "$topsrcdir/build/mozconfig.rust"',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
whitelist['nightly']['win32'] += [
|
whitelist['nightly']['win32'] += [
|
||||||
|
@ -7,10 +7,11 @@
|
|||||||
"unpack": true
|
"unpack": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size": 11179576,
|
"size": 11189216,
|
||||||
"digest": "91567ce8e2bb8ab0ebc60c31e90731d88a1ea889fb71bcf55c735746a60fa7610b7e040ea3d8f727b6f692ae3ee703d6f3b30cdbd76fdf5617f77d9c38aa20ed",
|
"digest": "18bc52b0599b1308b667e282abb45f47597bfc98a5140cfcab8da71dacf89dd76d0dee22a04ce26fe7ad1f04e2d6596991f9e5b01fd2aaaab5542965f596b0e6",
|
||||||
"algorithm": "sha512",
|
"algorithm": "sha512",
|
||||||
"filename": "gtk3.tar.xz",
|
"filename": "gtk3.tar.xz",
|
||||||
|
"setup": "setup.sh",
|
||||||
"unpack": true
|
"unpack": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -10,8 +10,8 @@
|
|||||||
"unpack": true
|
"unpack": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size": 12057960,
|
"size": 12072532,
|
||||||
"digest": "6105d6432943141cffb40020dc5ba3a793650bdeb3af9bd5e56d3796c5f03df9962a73e521646cd71fbfb5e266c1e74716ad722fb6055589dfb7d35175bca89e",
|
"digest": "3915f8ec396c56a8a92e6f9695b70f09ce9d1582359d1258e37e3fd43a143bc974410e4cfc27f500e095f34a8956206e0ebf799b7287f0f38def0d5e34ed71c9",
|
||||||
"algorithm": "sha512",
|
"algorithm": "sha512",
|
||||||
"filename": "gtk3.tar.xz",
|
"filename": "gtk3.tar.xz",
|
||||||
"setup": "setup.sh",
|
"setup": "setup.sh",
|
||||||
|
@ -10,10 +10,11 @@
|
|||||||
"unpack": true
|
"unpack": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size": 12057960,
|
"size": 12072532,
|
||||||
"digest": "6105d6432943141cffb40020dc5ba3a793650bdeb3af9bd5e56d3796c5f03df9962a73e521646cd71fbfb5e266c1e74716ad722fb6055589dfb7d35175bca89e",
|
"digest": "3915f8ec396c56a8a92e6f9695b70f09ce9d1582359d1258e37e3fd43a143bc974410e4cfc27f500e095f34a8956206e0ebf799b7287f0f38def0d5e34ed71c9",
|
||||||
"algorithm": "sha512",
|
"algorithm": "sha512",
|
||||||
"filename": "gtk3.tar.xz",
|
"filename": "gtk3.tar.xz",
|
||||||
|
"setup": "setup.sh",
|
||||||
"unpack": true
|
"unpack": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -10,10 +10,11 @@
|
|||||||
"unpack": true
|
"unpack": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size": 12057960,
|
"size": 12072532,
|
||||||
"digest": "6105d6432943141cffb40020dc5ba3a793650bdeb3af9bd5e56d3796c5f03df9962a73e521646cd71fbfb5e266c1e74716ad722fb6055589dfb7d35175bca89e",
|
"digest": "3915f8ec396c56a8a92e6f9695b70f09ce9d1582359d1258e37e3fd43a143bc974410e4cfc27f500e095f34a8956206e0ebf799b7287f0f38def0d5e34ed71c9",
|
||||||
"algorithm": "sha512",
|
"algorithm": "sha512",
|
||||||
"filename": "gtk3.tar.xz",
|
"filename": "gtk3.tar.xz",
|
||||||
|
"setup": "setup.sh",
|
||||||
"unpack": true
|
"unpack": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -7,10 +7,11 @@
|
|||||||
"unpack": true
|
"unpack": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size": 12057960,
|
"size": 12072532,
|
||||||
"digest": "6105d6432943141cffb40020dc5ba3a793650bdeb3af9bd5e56d3796c5f03df9962a73e521646cd71fbfb5e266c1e74716ad722fb6055589dfb7d35175bca89e",
|
"digest": "3915f8ec396c56a8a92e6f9695b70f09ce9d1582359d1258e37e3fd43a143bc974410e4cfc27f500e095f34a8956206e0ebf799b7287f0f38def0d5e34ed71c9",
|
||||||
"algorithm": "sha512",
|
"algorithm": "sha512",
|
||||||
"filename": "gtk3.tar.xz",
|
"filename": "gtk3.tar.xz",
|
||||||
|
"setup": "setup.sh",
|
||||||
"unpack": true
|
"unpack": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -10,10 +10,11 @@
|
|||||||
"unpack": true
|
"unpack": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size": 12057960,
|
"size": 12072532,
|
||||||
"digest": "6105d6432943141cffb40020dc5ba3a793650bdeb3af9bd5e56d3796c5f03df9962a73e521646cd71fbfb5e266c1e74716ad722fb6055589dfb7d35175bca89e",
|
"digest": "3915f8ec396c56a8a92e6f9695b70f09ce9d1582359d1258e37e3fd43a143bc974410e4cfc27f500e095f34a8956206e0ebf799b7287f0f38def0d5e34ed71c9",
|
||||||
"algorithm": "sha512",
|
"algorithm": "sha512",
|
||||||
"filename": "gtk3.tar.xz",
|
"filename": "gtk3.tar.xz",
|
||||||
|
"setup": "setup.sh",
|
||||||
"unpack": true
|
"unpack": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -5,10 +5,13 @@
|
|||||||
from __future__ import print_function, unicode_literals
|
from __future__ import print_function, unicode_literals
|
||||||
|
|
||||||
import errno
|
import errno
|
||||||
|
import json
|
||||||
import os
|
import os
|
||||||
import platform
|
import platform
|
||||||
|
import random
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
|
import uuid
|
||||||
import __builtin__
|
import __builtin__
|
||||||
|
|
||||||
from types import ModuleType
|
from types import ModuleType
|
||||||
@ -67,6 +70,7 @@ SEARCH_PATHS = [
|
|||||||
'config',
|
'config',
|
||||||
'dom/bindings',
|
'dom/bindings',
|
||||||
'dom/bindings/parser',
|
'dom/bindings/parser',
|
||||||
|
'dom/media/test/external',
|
||||||
'layout/tools/reftest',
|
'layout/tools/reftest',
|
||||||
'other-licenses/ply',
|
'other-licenses/ply',
|
||||||
'testing',
|
'testing',
|
||||||
@ -109,6 +113,7 @@ MACH_MODULES = [
|
|||||||
'addon-sdk/mach_commands.py',
|
'addon-sdk/mach_commands.py',
|
||||||
'build/valgrind/mach_commands.py',
|
'build/valgrind/mach_commands.py',
|
||||||
'dom/bindings/mach_commands.py',
|
'dom/bindings/mach_commands.py',
|
||||||
|
'dom/media/test/external/mach_commands.py',
|
||||||
'layout/tools/reftest/mach_commands.py',
|
'layout/tools/reftest/mach_commands.py',
|
||||||
'python/mach_commands.py',
|
'python/mach_commands.py',
|
||||||
'python/mach/mach/commands/commandinfo.py',
|
'python/mach/mach/commands/commandinfo.py',
|
||||||
@ -181,6 +186,14 @@ CATEGORIES = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Server to which to submit telemetry data
|
||||||
|
BUILD_TELEMETRY_SERVER = 'http://52.88.27.118/build-metrics-dev'
|
||||||
|
|
||||||
|
|
||||||
|
# We submit data to telemetry approximately every this many mach invocations
|
||||||
|
TELEMETRY_SUBMISSION_FREQUENCY = 10
|
||||||
|
|
||||||
|
|
||||||
def get_state_dir():
|
def get_state_dir():
|
||||||
"""Obtain the path to a directory to hold state.
|
"""Obtain the path to a directory to hold state.
|
||||||
|
|
||||||
@ -222,6 +235,47 @@ def bootstrap(topsrcdir, mozilla_dir=None):
|
|||||||
sys.path[0:0] = [os.path.join(mozilla_dir, path) for path in SEARCH_PATHS]
|
sys.path[0:0] = [os.path.join(mozilla_dir, path) for path in SEARCH_PATHS]
|
||||||
import mach.main
|
import mach.main
|
||||||
|
|
||||||
|
def telemetry_handler(context, data):
|
||||||
|
# We have not opted-in to telemetry
|
||||||
|
if 'BUILD_SYSTEM_TELEMETRY' not in os.environ:
|
||||||
|
return
|
||||||
|
|
||||||
|
telemetry_dir = os.path.join(get_state_dir()[0], 'telemetry')
|
||||||
|
try:
|
||||||
|
os.mkdir(telemetry_dir)
|
||||||
|
except OSError as e:
|
||||||
|
if e.errno != errno.EEXIST:
|
||||||
|
raise
|
||||||
|
outgoing_dir = os.path.join(telemetry_dir, 'outgoing')
|
||||||
|
try:
|
||||||
|
os.mkdir(outgoing_dir)
|
||||||
|
except OSError as e:
|
||||||
|
if e.errno != errno.EEXIST:
|
||||||
|
raise
|
||||||
|
|
||||||
|
# Add common metadata to help submit sorted data later on.
|
||||||
|
# For now, we'll just record the mach command that was invoked.
|
||||||
|
data['argv'] = sys.argv
|
||||||
|
|
||||||
|
with open(os.path.join(outgoing_dir, str(uuid.uuid4()) + '.json'),
|
||||||
|
'w') as f:
|
||||||
|
json.dump(data, f, sort_keys=True)
|
||||||
|
|
||||||
|
def should_skip_dispatch(context, handler):
|
||||||
|
# The user is performing a maintenance command.
|
||||||
|
if handler.name in ('bootstrap', 'doctor', 'mach-commands', 'mercurial-setup'):
|
||||||
|
return True
|
||||||
|
|
||||||
|
# We are running in automation.
|
||||||
|
if 'MOZ_AUTOMATION' in os.environ or 'TASK_ID' in os.environ:
|
||||||
|
return True
|
||||||
|
|
||||||
|
# The environment is likely a machine invocation.
|
||||||
|
if sys.stdin.closed or not sys.stdin.isatty():
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
def pre_dispatch_handler(context, handler, args):
|
def pre_dispatch_handler(context, handler, args):
|
||||||
"""Perform global checks before command dispatch.
|
"""Perform global checks before command dispatch.
|
||||||
|
|
||||||
@ -230,13 +284,7 @@ def bootstrap(topsrcdir, mozilla_dir=None):
|
|||||||
tools are up to date.
|
tools are up to date.
|
||||||
"""
|
"""
|
||||||
# Don't do anything when...
|
# Don't do anything when...
|
||||||
|
if should_skip_dispatch(context, handler):
|
||||||
# The user is performing a maintenance command.
|
|
||||||
if handler.name in ('bootstrap', 'doctor', 'mach-commands', 'mercurial-setup'):
|
|
||||||
return
|
|
||||||
|
|
||||||
# We are running in automation.
|
|
||||||
if 'MOZ_AUTOMATION' in os.environ or 'TASK_ID' in os.environ:
|
|
||||||
return
|
return
|
||||||
|
|
||||||
# User has disabled first run check.
|
# User has disabled first run check.
|
||||||
@ -245,10 +293,6 @@ def bootstrap(topsrcdir, mozilla_dir=None):
|
|||||||
if 'NO_MERCURIAL_SETUP_CHECK' in os.environ:
|
if 'NO_MERCURIAL_SETUP_CHECK' in os.environ:
|
||||||
return
|
return
|
||||||
|
|
||||||
# The environment is likely a machine invocation.
|
|
||||||
if sys.stdin.closed or not sys.stdin.isatty():
|
|
||||||
return
|
|
||||||
|
|
||||||
# Mercurial isn't managing this source checkout.
|
# Mercurial isn't managing this source checkout.
|
||||||
if not os.path.exists(os.path.join(topsrcdir, '.hg')):
|
if not os.path.exists(os.path.join(topsrcdir, '.hg')):
|
||||||
return
|
return
|
||||||
@ -269,6 +313,68 @@ def bootstrap(topsrcdir, mozilla_dir=None):
|
|||||||
print(NO_MERCURIAL_SETUP.format(mach=sys.argv[0]), file=sys.stderr)
|
print(NO_MERCURIAL_SETUP.format(mach=sys.argv[0]), file=sys.stderr)
|
||||||
sys.exit(2)
|
sys.exit(2)
|
||||||
|
|
||||||
|
def post_dispatch_handler(context, handler, args):
|
||||||
|
"""Perform global operations after command dispatch.
|
||||||
|
|
||||||
|
|
||||||
|
For now, we will use this to handle build system telemetry.
|
||||||
|
"""
|
||||||
|
# Don't do anything when...
|
||||||
|
if should_skip_dispatch(context, handler):
|
||||||
|
return
|
||||||
|
|
||||||
|
# We have not opted-in to telemetry
|
||||||
|
if 'BUILD_SYSTEM_TELEMETRY' not in os.environ:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Every n-th operation
|
||||||
|
if random.randint(1, TELEMETRY_SUBMISSION_FREQUENCY) != 1:
|
||||||
|
return
|
||||||
|
|
||||||
|
# No data to work with anyway
|
||||||
|
outgoing = os.path.join(get_state_dir()[0], 'telemetry', 'outgoing')
|
||||||
|
if not os.path.isdir(outgoing):
|
||||||
|
return
|
||||||
|
|
||||||
|
# We can't import requests until after it has been added during the
|
||||||
|
# bootstrapping below.
|
||||||
|
import requests
|
||||||
|
|
||||||
|
submitted = os.path.join(get_state_dir()[0], 'telemetry', 'submitted')
|
||||||
|
try:
|
||||||
|
os.mkdir(submitted)
|
||||||
|
except OSError as e:
|
||||||
|
if e.errno != errno.EEXIST:
|
||||||
|
raise
|
||||||
|
|
||||||
|
session = requests.Session()
|
||||||
|
for filename in os.listdir(outgoing):
|
||||||
|
path = os.path.join(outgoing, filename)
|
||||||
|
if os.path.isdir(path) or not path.endswith('.json'):
|
||||||
|
continue
|
||||||
|
with open(path, 'r') as f:
|
||||||
|
data = f.read()
|
||||||
|
r = session.post(BUILD_TELEMETRY_SERVER, data=data,
|
||||||
|
headers={'Content-Type': 'application/json'})
|
||||||
|
# TODO: some of these errors are likely not recoverable, as
|
||||||
|
# written, we'll retry indefinitely
|
||||||
|
if r.status_code != 200:
|
||||||
|
print('Error posting to telemetry: %s %s' %
|
||||||
|
(r.status_code, r.text))
|
||||||
|
continue
|
||||||
|
|
||||||
|
os.rename(os.path.join(outgoing, filename),
|
||||||
|
os.path.join(submitted, filename))
|
||||||
|
|
||||||
|
session.close()
|
||||||
|
|
||||||
|
# Discard submitted data that is >= 30 days old
|
||||||
|
now = time.time()
|
||||||
|
for filename in os.listdir(submitted):
|
||||||
|
ctime = os.stat(os.path.join(submitted, filename)).st_ctime
|
||||||
|
if now - ctime >= 60*60*24*30:
|
||||||
|
os.remove(os.path.join(submitted, filename))
|
||||||
|
|
||||||
def populate_context(context, key=None):
|
def populate_context(context, key=None):
|
||||||
if key is None:
|
if key is None:
|
||||||
return
|
return
|
||||||
@ -305,6 +411,12 @@ def bootstrap(topsrcdir, mozilla_dir=None):
|
|||||||
if key == 'pre_dispatch_handler':
|
if key == 'pre_dispatch_handler':
|
||||||
return pre_dispatch_handler
|
return pre_dispatch_handler
|
||||||
|
|
||||||
|
if key == 'telemetry_handler':
|
||||||
|
return telemetry_handler
|
||||||
|
|
||||||
|
if key == 'post_dispatch_handler':
|
||||||
|
return post_dispatch_handler
|
||||||
|
|
||||||
raise AttributeError(key)
|
raise AttributeError(key)
|
||||||
|
|
||||||
mach = mach.main.Mach(os.getcwd())
|
mach = mach.main.Mach(os.getcwd())
|
||||||
|
@ -13,7 +13,7 @@ import subprocess
|
|||||||
import sys
|
import sys
|
||||||
|
|
||||||
from automation import Automation
|
from automation import Automation
|
||||||
from devicemanager import DMError, DeviceManager
|
from mozdevice import DMError, DeviceManager
|
||||||
from mozlog import get_default_logger
|
from mozlog import get_default_logger
|
||||||
import mozcrash
|
import mozcrash
|
||||||
|
|
||||||
|
@ -118,18 +118,20 @@ cat <<EOF > $root_dir/gtk3/setup.sh
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
cd \$(dirname \$0)
|
cd \$(dirname \$0)
|
||||||
|
HERE=\$(pwd)
|
||||||
|
|
||||||
# pango expects absolute paths in pango.modules, and TOOLTOOL_DIR may vary...
|
# pango expects absolute paths in pango.modules, and TOOLTOOL_DIR may vary...
|
||||||
LD_LIBRARY_PATH=./usr/local/lib \
|
LD_LIBRARY_PATH=\$HERE/usr/local/lib \
|
||||||
PANGO_SYSCONFDIR=./usr/local/etc \
|
PANGO_SYSCONFDIR=\$HERE/usr/local/etc \
|
||||||
PANGO_LIBDIR=./usr/local/lib \
|
PANGO_LIBDIR=\$HERE/usr/local/lib \
|
||||||
./usr/local/bin/pango-querymodules > ./usr/local/etc/pango/pango.modules
|
\$HERE/usr/local/bin/pango-querymodules > \$HERE/usr/local/etc/pango/pango.modules
|
||||||
|
|
||||||
# same with gdb-pixbuf and loaders.cache
|
# same with gdb-pixbuf and loaders.cache
|
||||||
LD_LIBRARY_PATH=./usr/local/lib \
|
LD_LIBRARY_PATH=\$HERE/usr/local/lib \
|
||||||
GDK_PIXBUF_MODULE_FILE=./usr/local/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache \
|
GDK_PIXBUF_MODULE_FILE=\$HERE/usr/local/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache \
|
||||||
GDK_PIXBUF_MODULEDIR=./usr/local/lib/gdk-pixbuf-2.0/2.10.0/loaders \
|
GDK_PIXBUF_MODULEDIR=\$HERE/usr/local/lib/gdk-pixbuf-2.0/2.10.0/loaders \
|
||||||
./usr/local/bin/gdk-pixbuf-query-loaders > ./usr/local/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache
|
\$HERE/usr/local/bin/gdk-pixbuf-query-loaders > \
|
||||||
|
\$HERE/usr/local/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache
|
||||||
|
|
||||||
# The fontconfig version in the tooltool package has known uses of
|
# The fontconfig version in the tooltool package has known uses of
|
||||||
# uninitialized memory when creating its cache, and while most users
|
# uninitialized memory when creating its cache, and while most users
|
||||||
@ -137,7 +139,9 @@ GDK_PIXBUF_MODULEDIR=./usr/local/lib/gdk-pixbuf-2.0/2.10.0/loaders \
|
|||||||
# will create it. Combined with valgrind, this generates irrelevant
|
# will create it. Combined with valgrind, this generates irrelevant
|
||||||
# errors.
|
# errors.
|
||||||
# So create the fontconfig cache beforehand.
|
# So create the fontconfig cache beforehand.
|
||||||
./usr/local/bin/fc-cache
|
FONTCONFIG_PATH=\$HERE/usr/local/etc/fonts \
|
||||||
|
LD_LIBRARY_PATH=\$HERE/usr/local/lib \
|
||||||
|
\$HERE/usr/local/bin/fc-cache
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
chmod +x $root_dir/gtk3/setup.sh
|
chmod +x $root_dir/gtk3/setup.sh
|
||||||
|
@ -24,6 +24,3 @@ mk_add_options "export PANGO_LIBDIR=$TOOLTOOL_DIR/gtk3/usr/local/lib"
|
|||||||
mk_add_options "export GDK_PIXBUF_MODULE_FILE=$TOOLTOOL_DIR/gtk3/usr/local/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache"
|
mk_add_options "export GDK_PIXBUF_MODULE_FILE=$TOOLTOOL_DIR/gtk3/usr/local/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache"
|
||||||
mk_add_options "export GDK_PIXBUF_MODULEDIR=$TOOLTOOL_DIR/gtk3/usr/local/lib/gdk-pixbuf-2.0/2.10.0/loaders"
|
mk_add_options "export GDK_PIXBUF_MODULEDIR=$TOOLTOOL_DIR/gtk3/usr/local/lib/gdk-pixbuf-2.0/2.10.0/loaders"
|
||||||
mk_add_options "export LD_LIBRARY_PATH=$TOOLTOOL_DIR/gtk3/usr/local/lib"
|
mk_add_options "export LD_LIBRARY_PATH=$TOOLTOOL_DIR/gtk3/usr/local/lib"
|
||||||
|
|
||||||
# Until a tooltool with bug 1188571 landed is available everywhere
|
|
||||||
$TOOLTOOL_DIR/gtk3/setup.sh
|
|
||||||
|
@ -41,6 +41,8 @@ reAfterArg = "(?=[,)])"
|
|||||||
reMatchArg = re.compile(reBeforeArg + reArgType + reArgName + reArgDefault + reAfterArg)
|
reMatchArg = re.compile(reBeforeArg + reArgType + reArgName + reArgDefault + reAfterArg)
|
||||||
|
|
||||||
def get_normalized_signatures(signature, fileAnnot = None):
|
def get_normalized_signatures(signature, fileAnnot = None):
|
||||||
|
# Remove static
|
||||||
|
signature = signature.replace('static', '')
|
||||||
# Remove semicolon.
|
# Remove semicolon.
|
||||||
signature = signature.replace(';', ' ')
|
signature = signature.replace(';', ' ')
|
||||||
# Normalize spaces.
|
# Normalize spaces.
|
||||||
|
@ -226,7 +226,7 @@ this.AppsUtils = {
|
|||||||
deferred.resolve(file);
|
deferred.resolve(file);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
aRequestChannel.asyncOpen(listener, null);
|
aRequestChannel.asyncOpen2(listener);
|
||||||
|
|
||||||
return deferred.promise;
|
return deferred.promise;
|
||||||
},
|
},
|
||||||
|
@ -3490,21 +3490,15 @@ this.DOMApplicationRegistry = {
|
|||||||
let requestChannel;
|
let requestChannel;
|
||||||
|
|
||||||
let appURI = NetUtil.newURI(aNewApp.origin, null, null);
|
let appURI = NetUtil.newURI(aNewApp.origin, null, null);
|
||||||
let principal =
|
|
||||||
Services.scriptSecurityManager.createCodebasePrincipal(appURI,
|
|
||||||
{appId: aNewApp.localId});
|
|
||||||
|
|
||||||
if (aIsLocalFileInstall) {
|
if (aIsLocalFileInstall) {
|
||||||
requestChannel = NetUtil.newChannel({
|
requestChannel = NetUtil.newChannel({
|
||||||
uri: aFullPackagePath,
|
uri: aFullPackagePath,
|
||||||
loadingPrincipal: principal,
|
loadUsingSystemPrincipal: true}
|
||||||
contentPolicyType: Ci.nsIContentPolicy.TYPE_OTHER}
|
|
||||||
).QueryInterface(Ci.nsIFileChannel);
|
).QueryInterface(Ci.nsIFileChannel);
|
||||||
} else {
|
} else {
|
||||||
requestChannel = NetUtil.newChannel({
|
requestChannel = NetUtil.newChannel({
|
||||||
uri: aFullPackagePath,
|
uri: aFullPackagePath,
|
||||||
loadingPrincipal: principal,
|
loadUsingSystemPrincipal: true}
|
||||||
contentPolicyType: Ci.nsIContentPolicy.TYPE_OTHER}
|
|
||||||
).QueryInterface(Ci.nsIHttpChannel);
|
).QueryInterface(Ci.nsIHttpChannel);
|
||||||
requestChannel.loadFlags |= Ci.nsIRequest.INHIBIT_CACHING;
|
requestChannel.loadFlags |= Ci.nsIRequest.INHIBIT_CACHING;
|
||||||
}
|
}
|
||||||
|
@ -219,7 +219,7 @@ ShadowRoot::RemoveFromIdTable(Element* aElement, nsIAtom* aId)
|
|||||||
if (entry) {
|
if (entry) {
|
||||||
entry->RemoveIdElement(aElement);
|
entry->RemoveIdElement(aElement);
|
||||||
if (entry->IsEmpty()) {
|
if (entry->IsEmpty()) {
|
||||||
mIdentifierMap.RawRemoveEntry(entry);
|
mIdentifierMap.RemoveEntry(entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7270,13 +7270,13 @@ nsContentUtils::GetInnerWindowID(nsIRequest* aRequest)
|
|||||||
return inner ? inner->WindowID() : 0;
|
return inner ? inner->WindowID() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
nsresult
|
||||||
nsContentUtils::GetHostOrIPv6WithBrackets(nsIURI* aURI, nsCString& aHost)
|
nsContentUtils::GetHostOrIPv6WithBrackets(nsIURI* aURI, nsCString& aHost)
|
||||||
{
|
{
|
||||||
aHost.Truncate();
|
aHost.Truncate();
|
||||||
nsresult rv = aURI->GetHost(aHost);
|
nsresult rv = aURI->GetHost(aHost);
|
||||||
if (NS_FAILED(rv)) { // Some URIs do not have a host
|
if (NS_FAILED(rv)) { // Some URIs do not have a host
|
||||||
return;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aHost.FindChar(':') != -1) { // Escape IPv6 address
|
if (aHost.FindChar(':') != -1) { // Escape IPv6 address
|
||||||
@ -7285,14 +7285,20 @@ nsContentUtils::GetHostOrIPv6WithBrackets(nsIURI* aURI, nsCString& aHost)
|
|||||||
aHost.Insert('[', 0);
|
aHost.Insert('[', 0);
|
||||||
aHost.Append(']');
|
aHost.Append(']');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
nsresult
|
||||||
nsContentUtils::GetHostOrIPv6WithBrackets(nsIURI* aURI, nsAString& aHost)
|
nsContentUtils::GetHostOrIPv6WithBrackets(nsIURI* aURI, nsAString& aHost)
|
||||||
{
|
{
|
||||||
nsAutoCString hostname;
|
nsAutoCString hostname;
|
||||||
GetHostOrIPv6WithBrackets(aURI, hostname);
|
nsresult rv = GetHostOrIPv6WithBrackets(aURI, hostname);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
CopyUTF8toUTF16(hostname, aHost);
|
CopyUTF8toUTF16(hostname, aHost);
|
||||||
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -2402,8 +2402,8 @@ public:
|
|||||||
* If the hostname for aURI is an IPv6 it encloses it in brackets,
|
* If the hostname for aURI is an IPv6 it encloses it in brackets,
|
||||||
* otherwise it just outputs the hostname in aHost.
|
* otherwise it just outputs the hostname in aHost.
|
||||||
*/
|
*/
|
||||||
static void GetHostOrIPv6WithBrackets(nsIURI* aURI, nsAString& aHost);
|
static nsresult GetHostOrIPv6WithBrackets(nsIURI* aURI, nsAString& aHost);
|
||||||
static void GetHostOrIPv6WithBrackets(nsIURI* aURI, nsCString& aHost);
|
static nsresult GetHostOrIPv6WithBrackets(nsIURI* aURI, nsCString& aHost);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Call the given callback on all remote children of the given top-level
|
* Call the given callback on all remote children of the given top-level
|
||||||
|
@ -3003,7 +3003,7 @@ nsDocument::RemoveFromIdTable(Element *aElement, nsIAtom* aId)
|
|||||||
++mExpandoAndGeneration.generation;
|
++mExpandoAndGeneration.generation;
|
||||||
}
|
}
|
||||||
if (entry->IsEmpty()) {
|
if (entry->IsEmpty()) {
|
||||||
mIdentifierMap.RawRemoveEntry(entry);
|
mIdentifierMap.RemoveEntry(entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1438,7 +1438,7 @@ nsHTMLCopyEncoder::SetSelection(nsISelection* aSelection)
|
|||||||
mIsTextWidget = true;
|
mIsTextWidget = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#ifdef MOZ_THUNDERBIRD
|
#if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
|
||||||
else if (selContent->IsHTMLElement(nsGkAtoms::body)) {
|
else if (selContent->IsHTMLElement(nsGkAtoms::body)) {
|
||||||
// Currently, setting mIsTextWidget to 'true' will result in the selection
|
// Currently, setting mIsTextWidget to 'true' will result in the selection
|
||||||
// being encoded/copied as pre-formatted plain text.
|
// being encoded/copied as pre-formatted plain text.
|
||||||
|
@ -104,7 +104,6 @@ GK_ATOM(applet, "applet")
|
|||||||
GK_ATOM(applyImports, "apply-imports")
|
GK_ATOM(applyImports, "apply-imports")
|
||||||
GK_ATOM(applyTemplates, "apply-templates")
|
GK_ATOM(applyTemplates, "apply-templates")
|
||||||
GK_ATOM(mozapptype, "mozapptype")
|
GK_ATOM(mozapptype, "mozapptype")
|
||||||
GK_ATOM(apz, "apz")
|
|
||||||
GK_ATOM(archive, "archive")
|
GK_ATOM(archive, "archive")
|
||||||
GK_ATOM(area, "area")
|
GK_ATOM(area, "area")
|
||||||
GK_ATOM(arrow, "arrow")
|
GK_ATOM(arrow, "arrow")
|
||||||
@ -2270,13 +2269,20 @@ GK_ATOM(SendMail, "SendMail")
|
|||||||
GK_ATOM(ForwardMail, "ForwardMail")
|
GK_ATOM(ForwardMail, "ForwardMail")
|
||||||
GK_ATOM(ReplyToMail, "ReplyToMail")
|
GK_ATOM(ReplyToMail, "ReplyToMail")
|
||||||
|
|
||||||
// Smooth scroll events origins
|
// Scroll origins (these are used in various scrolling functions in
|
||||||
|
// nsIScrollableFrame and ScrollFrameHelper). These are divided into two lists
|
||||||
|
// - origins in the first one have smooth-scrolling prefs associated with them,
|
||||||
|
// under the "general.smoothScroll.<origin>.*" pref branch. Origins in the
|
||||||
|
// second one do not.
|
||||||
GK_ATOM(mouseWheel, "mouseWheel") // For discrete wheel events (e.g. not OSX magic mouse)
|
GK_ATOM(mouseWheel, "mouseWheel") // For discrete wheel events (e.g. not OSX magic mouse)
|
||||||
GK_ATOM(pixels, "pixels")
|
GK_ATOM(pixels, "pixels")
|
||||||
GK_ATOM(lines, "lines")
|
GK_ATOM(lines, "lines")
|
||||||
GK_ATOM(pages, "pages")
|
GK_ATOM(pages, "pages")
|
||||||
GK_ATOM(scrollbars, "scrollbars")
|
GK_ATOM(scrollbars, "scrollbars")
|
||||||
GK_ATOM(other, "other")
|
GK_ATOM(other, "other")
|
||||||
|
// Scroll origins without smooth-scrolling prefs
|
||||||
|
GK_ATOM(apz, "apz")
|
||||||
|
GK_ATOM(restore, "restore")
|
||||||
|
|
||||||
#ifdef ACCESSIBILITY
|
#ifdef ACCESSIBILITY
|
||||||
GK_ATOM(alert, "alert")
|
GK_ATOM(alert, "alert")
|
||||||
|
@ -40,7 +40,7 @@ protected:
|
|||||||
JS::MutableHandle<JS::Value> aVal);
|
JS::MutableHandle<JS::Value> aVal);
|
||||||
|
|
||||||
bool StringifyToJSON(JSContext* aCx,
|
bool StringifyToJSON(JSContext* aCx,
|
||||||
JS::MutableHandle<JS::Value> aValue,
|
JS::Handle<JSObject*> aObj,
|
||||||
nsAString& aJSON) const;
|
nsAString& aJSON) const;
|
||||||
|
|
||||||
// Struct used as a way to force a dictionary constructor to not init the
|
// Struct used as a way to force a dictionary constructor to not init the
|
||||||
|
@ -45,8 +45,9 @@
|
|||||||
#include "mozilla/dom/HTMLAppletElementBinding.h"
|
#include "mozilla/dom/HTMLAppletElementBinding.h"
|
||||||
#include "mozilla/dom/Promise.h"
|
#include "mozilla/dom/Promise.h"
|
||||||
#include "mozilla/dom/ResolveSystemBinding.h"
|
#include "mozilla/dom/ResolveSystemBinding.h"
|
||||||
|
#include "mozilla/dom/WorkerPrivate.h"
|
||||||
|
#include "mozilla/dom/WorkerScope.h"
|
||||||
#include "mozilla/jsipc/CrossProcessObjectWrappers.h"
|
#include "mozilla/jsipc/CrossProcessObjectWrappers.h"
|
||||||
#include "WorkerPrivate.h"
|
|
||||||
#include "nsDOMClassInfo.h"
|
#include "nsDOMClassInfo.h"
|
||||||
#include "ipc/ErrorIPCUtils.h"
|
#include "ipc/ErrorIPCUtils.h"
|
||||||
#include "mozilla/UseCounter.h"
|
#include "mozilla/UseCounter.h"
|
||||||
@ -1867,11 +1868,10 @@ DictionaryBase::ParseJSON(JSContext* aCx,
|
|||||||
|
|
||||||
bool
|
bool
|
||||||
DictionaryBase::StringifyToJSON(JSContext* aCx,
|
DictionaryBase::StringifyToJSON(JSContext* aCx,
|
||||||
JS::MutableHandle<JS::Value> aValue,
|
JS::Handle<JSObject*> aObj,
|
||||||
nsAString& aJSON) const
|
nsAString& aJSON) const
|
||||||
{
|
{
|
||||||
return JS_Stringify(aCx, aValue, nullptr, JS::NullHandleValue,
|
return JS::ToJSONMaybeSafely(aCx, aObj, AppendJSONToString, &aJSON);
|
||||||
AppendJSONToString, &aJSON);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
@ -3239,5 +3239,18 @@ DeprecationWarning(JSContext* aCx, JSObject* aObject,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace binding_detail {
|
||||||
|
JSObject*
|
||||||
|
UnprivilegedJunkScopeOrWorkerGlobal()
|
||||||
|
{
|
||||||
|
if (NS_IsMainThread()) {
|
||||||
|
return xpc::UnprivilegedJunkScope();
|
||||||
|
}
|
||||||
|
|
||||||
|
return workers::GetCurrentThreadWorkerPrivate()->
|
||||||
|
GlobalScope()->GetGlobalJSObject();
|
||||||
|
}
|
||||||
|
} // namespace binding_detail
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
@ -3327,6 +3327,26 @@ DeprecationWarning(JSContext* aCx, JSObject* aObject,
|
|||||||
JSString*
|
JSString*
|
||||||
InterfaceObjectToString(JSContext* aCx, JS::Handle<JSObject*> aObject,
|
InterfaceObjectToString(JSContext* aCx, JS::Handle<JSObject*> aObject,
|
||||||
unsigned /* indent */);
|
unsigned /* indent */);
|
||||||
|
|
||||||
|
namespace binding_detail {
|
||||||
|
// Get a JS global object that can be used for some temporary allocations. The
|
||||||
|
// idea is that this should be used for situations when you need to operate in
|
||||||
|
// _some_ compartment but don't care which one. A typical example is when you
|
||||||
|
// have non-JS input, non-JS output, but have to go through some sort of JS
|
||||||
|
// representation in the middle, so need a compartment to allocate things in.
|
||||||
|
//
|
||||||
|
// It's VERY important that any consumers of this function only do things that
|
||||||
|
// are guaranteed to be side-effect-free, even in the face of a script
|
||||||
|
// environment controlled by a hostile adversary. This is because in the worker
|
||||||
|
// case the global is in fact the worker global, so it and its standard objects
|
||||||
|
// are controlled by the worker script. This is why this function is in the
|
||||||
|
// binding_detail namespace. Any use of this function MUST be very carefully
|
||||||
|
// reviewed by someone who is sufficiently devious and has a very good
|
||||||
|
// understanding of all the code that will run while we're using the return
|
||||||
|
// value, including the SpiderMonkey parts.
|
||||||
|
JSObject* UnprivilegedJunkScopeOrWorkerGlobal();
|
||||||
|
} // namespace binding_detail
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
||||||
|
@ -12257,13 +12257,21 @@ class CGDictionary(CGThing):
|
|||||||
"ToJSON", "bool",
|
"ToJSON", "bool",
|
||||||
[Argument('nsAString&', 'aJSON')],
|
[Argument('nsAString&', 'aJSON')],
|
||||||
body=dedent("""
|
body=dedent("""
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
AutoJSAPI jsapi;
|
AutoJSAPI jsapi;
|
||||||
jsapi.Init();
|
jsapi.Init();
|
||||||
JSContext *cx = jsapi.cx();
|
JSContext *cx = jsapi.cx();
|
||||||
JSAutoCompartment ac(cx, xpc::UnprivilegedJunkScope()); // Usage approved by bholley
|
// It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
|
||||||
JS::Rooted<JS::Value> obj(cx);
|
// because we'll only be creating objects, in ways that have no
|
||||||
return ToObjectInternal(cx, &obj) && StringifyToJSON(cx, &obj, aJSON);
|
// side-effects, followed by a call to JS::ToJSONMaybeSafely,
|
||||||
|
// which likewise guarantees no side-effects for the sorts of
|
||||||
|
// things we will pass it.
|
||||||
|
JSAutoCompartment ac(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
|
||||||
|
JS::Rooted<JS::Value> val(cx);
|
||||||
|
if (!ToObjectInternal(cx, &val)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
JS::Rooted<JSObject*> obj(cx, &val.toObject());
|
||||||
|
return StringifyToJSON(cx, obj, aJSON);
|
||||||
"""), const=True)
|
"""), const=True)
|
||||||
|
|
||||||
def toObjectInternalMethod(self):
|
def toObjectInternalMethod(self):
|
||||||
@ -12403,7 +12411,8 @@ class CGDictionary(CGThing):
|
|||||||
methods.append(self.initFromJSONMethod())
|
methods.append(self.initFromJSONMethod())
|
||||||
try:
|
try:
|
||||||
methods.append(self.toObjectInternalMethod())
|
methods.append(self.toObjectInternalMethod())
|
||||||
methods.append(self.toJSONMethod())
|
if self.dictionarySafeToJSONify(self.dictionary):
|
||||||
|
methods.append(self.toJSONMethod())
|
||||||
except MethodNotNewObjectError:
|
except MethodNotNewObjectError:
|
||||||
# If we can't have a ToObjectInternal() because one of our members
|
# If we can't have a ToObjectInternal() because one of our members
|
||||||
# can only be returned from [NewObject] methods, then just skip
|
# can only be returned from [NewObject] methods, then just skip
|
||||||
@ -12710,6 +12719,52 @@ class CGDictionary(CGThing):
|
|||||||
return False
|
return False
|
||||||
return all(isTypeCopyConstructible(m.type) for m in dictionary.members)
|
return all(isTypeCopyConstructible(m.type) for m in dictionary.members)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def typeSafeToJSONify(type):
|
||||||
|
"""
|
||||||
|
Determine whether the given type is safe to convert to JSON. The
|
||||||
|
restriction is that this needs to be safe while in a global controlled
|
||||||
|
by an adversary, and "safe" means no side-effects when the JS
|
||||||
|
representation of this type is converted to JSON. That means that we
|
||||||
|
have to be pretty restrictive about what things we can allow. For
|
||||||
|
example, "object" is out, because it may have accessor properties on it.
|
||||||
|
"""
|
||||||
|
if type.nullable():
|
||||||
|
# Converting null to JSON is always OK.
|
||||||
|
return CGDictionary.typeSafeToJSONify(type.inner)
|
||||||
|
|
||||||
|
if type.isSequence():
|
||||||
|
# Sequences are arrays we create ourselves, with no holes. They
|
||||||
|
# should be safe if their contents are safe, as long as we suppress
|
||||||
|
# invocation of .toJSON on objects.
|
||||||
|
return CGDictionary.typeSafeToJSONify(type.inner)
|
||||||
|
|
||||||
|
if type.isUnion():
|
||||||
|
# OK if everything in it is ok.
|
||||||
|
return all(CGDictionary.typeSafeToJSONify(t)
|
||||||
|
for t in type.flatMemberTypes)
|
||||||
|
|
||||||
|
if type.isDictionary():
|
||||||
|
# OK if the dictionary is OK
|
||||||
|
return CGDictionary.dictionarySafeToJSONify(type.inner)
|
||||||
|
|
||||||
|
if type.isString() or type.isEnum():
|
||||||
|
# Strings are always OK.
|
||||||
|
return True
|
||||||
|
|
||||||
|
if type.isPrimitive():
|
||||||
|
# Primitives (numbers and booleans) are ok, as long as
|
||||||
|
# they're not unrestricted float/double.
|
||||||
|
return not type.isFloat() or not type.isUnrestricted()
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def dictionarySafeToJSONify(dictionary):
|
||||||
|
# The dictionary itself is OK, so we're good if all our types are.
|
||||||
|
return all(CGDictionary.typeSafeToJSONify(m.type)
|
||||||
|
for m in dictionary.members)
|
||||||
|
|
||||||
|
|
||||||
class CGRegisterWorkerBindings(CGAbstractMethod):
|
class CGRegisterWorkerBindings(CGAbstractMethod):
|
||||||
def __init__(self, config):
|
def __init__(self, config):
|
||||||
@ -13191,7 +13246,6 @@ class CGBindingRoot(CGThing):
|
|||||||
bindingHeaders["WrapperFactory.h"] = descriptors
|
bindingHeaders["WrapperFactory.h"] = descriptors
|
||||||
bindingHeaders["mozilla/dom/DOMJSClass.h"] = descriptors
|
bindingHeaders["mozilla/dom/DOMJSClass.h"] = descriptors
|
||||||
bindingHeaders["mozilla/dom/ScriptSettings.h"] = dictionaries # AutoJSAPI
|
bindingHeaders["mozilla/dom/ScriptSettings.h"] = dictionaries # AutoJSAPI
|
||||||
bindingHeaders["xpcpublic.h"] = dictionaries # xpc::UnprivilegedJunkScope
|
|
||||||
# Ensure we see our enums in the generated .cpp file, for the ToJSValue
|
# Ensure we see our enums in the generated .cpp file, for the ToJSValue
|
||||||
# method body. Also ensure that we see jsapi.h.
|
# method body. Also ensure that we see jsapi.h.
|
||||||
if enums:
|
if enums:
|
||||||
@ -15637,7 +15691,10 @@ class CGMaplikeOrSetlikeHelperFunctionGenerator(CallbackMember):
|
|||||||
jsapi.Init();
|
jsapi.Init();
|
||||||
jsapi.TakeOwnershipOfErrorReporting();
|
jsapi.TakeOwnershipOfErrorReporting();
|
||||||
JSContext* cx = jsapi.cx();
|
JSContext* cx = jsapi.cx();
|
||||||
JSAutoCompartment tempCompartment(cx, xpc::UnprivilegedJunkScope());
|
// It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here because
|
||||||
|
// all we want is to wrap into _some_ scope and then unwrap to find
|
||||||
|
// the reflector, and wrapping has no side-effects.
|
||||||
|
JSAutoCompartment tempCompartment(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
|
||||||
JS::Rooted<JS::Value> v(cx);
|
JS::Rooted<JS::Value> v(cx);
|
||||||
if(!ToJSValue(cx, self, &v)) {
|
if(!ToJSValue(cx, self, &v)) {
|
||||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||||
|
@ -15,6 +15,7 @@ var Cr = Components.results;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Cu.import("resource://gre/modules/Services.jsm");
|
Cu.import("resource://gre/modules/Services.jsm");
|
||||||
|
Cu.import("resource://gre/modules/NetUtil.jsm");
|
||||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
Cu.import("resource://gre/modules/BrowserElementPromptService.jsm");
|
Cu.import("resource://gre/modules/BrowserElementPromptService.jsm");
|
||||||
|
|
||||||
@ -1001,36 +1002,17 @@ BrowserElementParent.prototype = {
|
|||||||
Ci.nsIRequestObserver])
|
Ci.nsIRequestObserver])
|
||||||
};
|
};
|
||||||
|
|
||||||
// If we have a URI we'll use it to get the triggering principal to use,
|
let referrer = Services.io.newURI(_options.referrer, null, null);
|
||||||
// if not available a null principal is acceptable.
|
let principal =
|
||||||
let referrer = null;
|
Services.scriptSecurityManager.createCodebasePrincipal(
|
||||||
let principal = null;
|
referrer, this._frameLoader.loadContext.originAttributes);
|
||||||
if (_options.referrer) {
|
|
||||||
// newURI can throw on malformed URIs.
|
|
||||||
try {
|
|
||||||
referrer = Services.io.newURI(_options.referrer, null, null);
|
|
||||||
}
|
|
||||||
catch(e) {
|
|
||||||
debug('Malformed referrer -- ' + e);
|
|
||||||
}
|
|
||||||
|
|
||||||
// This simply returns null if there is no principal available
|
let channel = NetUtil.newChannel({
|
||||||
// for the requested uri. This is an acceptable fallback when
|
uri: url,
|
||||||
// calling newChannelFromURI2.
|
loadingPrincipal: principal,
|
||||||
principal =
|
securityFlags: SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS,
|
||||||
Services.scriptSecurityManager.createCodebasePrincipal(
|
contentPolicyType: Ci.nsIContentPolicy.TYPE_OTHER
|
||||||
referrer, this._frameLoader.loadContext.originAttributes);
|
});
|
||||||
}
|
|
||||||
|
|
||||||
debug('Using principal? ' + !!principal);
|
|
||||||
|
|
||||||
let channel =
|
|
||||||
Services.io.newChannelFromURI2(url,
|
|
||||||
null, // No document.
|
|
||||||
principal, // Loading principal
|
|
||||||
principal, // Triggering principal
|
|
||||||
Ci.nsILoadInfo.SEC_NORMAL,
|
|
||||||
Ci.nsIContentPolicy.TYPE_OTHER);
|
|
||||||
|
|
||||||
// XXX We would set private browsing information prior to calling this.
|
// XXX We would set private browsing information prior to calling this.
|
||||||
channel.notificationCallbacks = interfaceRequestor;
|
channel.notificationCallbacks = interfaceRequestor;
|
||||||
@ -1055,7 +1037,7 @@ BrowserElementParent.prototype = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set-up complete, let's get things started.
|
// Set-up complete, let's get things started.
|
||||||
channel.asyncOpen(new DownloadListener(), null);
|
channel.asyncOpen2(new DownloadListener());
|
||||||
|
|
||||||
return req;
|
return req;
|
||||||
},
|
},
|
||||||
|
@ -48,6 +48,7 @@
|
|||||||
#include "nsPIDOMWindow.h"
|
#include "nsPIDOMWindow.h"
|
||||||
#include "nsSandboxFlags.h"
|
#include "nsSandboxFlags.h"
|
||||||
#include "xpcpublic.h"
|
#include "xpcpublic.h"
|
||||||
|
#include "nsIFrame.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
@ -416,10 +417,7 @@ EventListenerManager::AddEventListenerInternal(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (IsApzAwareEvent(aTypeAtom)) {
|
if (IsApzAwareEvent(aTypeAtom)) {
|
||||||
nsCOMPtr<nsINode> node = do_QueryInterface(mTarget);
|
ProcessApzAwareEventListenerAdd();
|
||||||
if (node) {
|
|
||||||
node->SetMayHaveApzAwareListeners();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aTypeAtom && mTarget) {
|
if (aTypeAtom && mTarget) {
|
||||||
@ -432,6 +430,44 @@ EventListenerManager::AddEventListenerInternal(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
EventListenerManager::ProcessApzAwareEventListenerAdd()
|
||||||
|
{
|
||||||
|
// Mark the node as having apz aware listeners
|
||||||
|
nsCOMPtr<nsINode> node = do_QueryInterface(mTarget);
|
||||||
|
if (node) {
|
||||||
|
node->SetMayHaveApzAwareListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Schedule a paint so event regions on the layer tree gets updated
|
||||||
|
nsIDocument* doc = nullptr;
|
||||||
|
if (node) {
|
||||||
|
doc = node->OwnerDoc();
|
||||||
|
}
|
||||||
|
if (!doc) {
|
||||||
|
if (nsCOMPtr<nsPIDOMWindowInner> window = GetTargetAsInnerWindow()) {
|
||||||
|
doc = window->GetExtantDoc();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!doc) {
|
||||||
|
if (nsCOMPtr<DOMEventTargetHelper> helper = do_QueryInterface(mTarget)) {
|
||||||
|
if (nsPIDOMWindowInner* window = helper->GetOwner()) {
|
||||||
|
doc = window->GetExtantDoc();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doc) {
|
||||||
|
nsIPresShell* ps = doc->GetShell();
|
||||||
|
if (ps) {
|
||||||
|
nsIFrame* f = ps->GetRootFrame();
|
||||||
|
if (f) {
|
||||||
|
f->SchedulePaint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
EventListenerManager::IsDeviceType(EventMessage aEventMessage)
|
EventListenerManager::IsDeviceType(EventMessage aEventMessage)
|
||||||
{
|
{
|
||||||
|
@ -467,6 +467,8 @@ protected:
|
|||||||
|
|
||||||
nsIDocShell* GetDocShellForTarget();
|
nsIDocShell* GetDocShellForTarget();
|
||||||
|
|
||||||
|
void ProcessApzAwareEventListenerAdd();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compile the "inline" event listener for aListener. The
|
* Compile the "inline" event listener for aListener. The
|
||||||
* body of the listener can be provided in aBody; if this is null we
|
* body of the listener can be provided in aBody; if this is null we
|
||||||
|
@ -187,7 +187,7 @@ function mpTestModernBeatsLegacy(eventInfo) {
|
|||||||
// Test that an event which bubbles may fire listeners of different flavors
|
// Test that an event which bubbles may fire listeners of different flavors
|
||||||
// (modern vs. legacy) at each bubbling level, depending on what's registered
|
// (modern vs. legacy) at each bubbling level, depending on what's registered
|
||||||
// at that level.
|
// at that level.
|
||||||
function mpTestAncestorsWithDiffListeners(eventInfo) {
|
function mpTestDiffListenersEventBubbling(eventInfo) {
|
||||||
return new Promise(
|
return new Promise(
|
||||||
function(resolve, reject) {
|
function(resolve, reject) {
|
||||||
var grandparent = createChildDiv();
|
var grandparent = createChildDiv();
|
||||||
@ -198,35 +198,81 @@ function mpTestAncestorsWithDiffListeners(eventInfo) {
|
|||||||
var eventSentToTarget;
|
var eventSentToTarget;
|
||||||
|
|
||||||
target.addEventListener(eventInfo.modern_name,
|
target.addEventListener(eventInfo.modern_name,
|
||||||
createHandlerWithTypeCheck(eventInfo.modern_name,
|
createHandlerWithTypeCheck(eventInfo.modern_name, function(e) {
|
||||||
function(e) {
|
ok(e.bubbles, "Expecting event to bubble");
|
||||||
ok(e.bubbles, "Expecting event to bubble");
|
eventSentToTarget = e;
|
||||||
eventSentToTarget = e;
|
didEventFireOnTarget = true;
|
||||||
didEventFireOnTarget = true;
|
}));
|
||||||
}));
|
|
||||||
|
|
||||||
parent.addEventListener(eventInfo.legacy_name,
|
parent.addEventListener(eventInfo.legacy_name,
|
||||||
createHandlerWithTypeCheck(eventInfo.legacy_name,
|
createHandlerWithTypeCheck(eventInfo.legacy_name, function(e) {
|
||||||
function(e) {
|
is(e, eventSentToTarget,
|
||||||
is(e, eventSentToTarget,
|
"Same event object should bubble, despite difference in type");
|
||||||
"Same event object should bubble, " +
|
didEventFireOnParent = true;
|
||||||
"despite difference in type");
|
}));
|
||||||
didEventFireOnParent = true;
|
|
||||||
}));
|
|
||||||
|
|
||||||
grandparent.addEventListener(eventInfo.modern_name,
|
grandparent.addEventListener(eventInfo.modern_name,
|
||||||
createHandlerWithTypeCheck(eventInfo.modern_name,
|
createHandlerWithTypeCheck(eventInfo.modern_name, function(e) {
|
||||||
function(e) {
|
ok(didEventFireOnTarget,
|
||||||
ok(didEventFireOnTarget,
|
"Event should have fired on child");
|
||||||
"Event should have fired on child");
|
ok(didEventFireOnParent,
|
||||||
ok(didEventFireOnParent,
|
"Event should have fired on parent");
|
||||||
"Event should have fired on parent");
|
is(e, eventSentToTarget,
|
||||||
is(e, eventSentToTarget,
|
"Same event object should bubble, despite difference in type");
|
||||||
"Same event object should bubble, " +
|
// Clean up.
|
||||||
"despite difference in type");
|
grandparent.parentNode.removeChild(grandparent);
|
||||||
parent.removeChild(target);
|
resolve();
|
||||||
resolve();
|
}));
|
||||||
}));
|
|
||||||
|
eventInfo.trigger_event(target);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that an event in the capture phase may fire listeners of different
|
||||||
|
// flavors (modern vs. legacy) at each level, depending on what's registered
|
||||||
|
// at that level.
|
||||||
|
function mpTestDiffListenersEventCapturing(eventInfo) {
|
||||||
|
return new Promise(
|
||||||
|
function(resolve, reject) {
|
||||||
|
var grandparent = createChildDiv();
|
||||||
|
var parent = createChildDiv(grandparent);
|
||||||
|
var target = createChildDiv(parent);
|
||||||
|
var didEventFireOnTarget = false;
|
||||||
|
var didEventFireOnParent = false;
|
||||||
|
var didEventFireOnGrandparent = false;
|
||||||
|
var eventSentToGrandparent;
|
||||||
|
|
||||||
|
grandparent.addEventListener(eventInfo.modern_name,
|
||||||
|
createHandlerWithTypeCheck(eventInfo.modern_name, function(e) {
|
||||||
|
eventSentToGrandparent = e;
|
||||||
|
didEventFireOnGrandparent = true;
|
||||||
|
}), true);
|
||||||
|
|
||||||
|
parent.addEventListener(eventInfo.legacy_name,
|
||||||
|
createHandlerWithTypeCheck(eventInfo.legacy_name, function(e) {
|
||||||
|
is(e.eventPhase, Event.CAPTURING_PHASE,
|
||||||
|
"event should be in capturing phase");
|
||||||
|
is(e, eventSentToGrandparent,
|
||||||
|
"Same event object should capture, despite difference in type");
|
||||||
|
ok(didEventFireOnGrandparent,
|
||||||
|
"Event should have fired on grandparent");
|
||||||
|
didEventFireOnParent = true;
|
||||||
|
}), true);
|
||||||
|
|
||||||
|
target.addEventListener(eventInfo.modern_name,
|
||||||
|
createHandlerWithTypeCheck(eventInfo.modern_name, function(e) {
|
||||||
|
is(e.eventPhase, Event.AT_TARGET,
|
||||||
|
"event should be at target phase");
|
||||||
|
is(e, eventSentToGrandparent,
|
||||||
|
"Same event object should capture, despite difference in type");
|
||||||
|
ok(didEventFireOnParent,
|
||||||
|
"Event should have fired on parent");
|
||||||
|
// Clean up.
|
||||||
|
grandparent.parentNode.removeChild(grandparent);
|
||||||
|
resolve();
|
||||||
|
}), true);
|
||||||
|
|
||||||
eventInfo.trigger_event(target);
|
eventInfo.trigger_event(target);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -239,7 +285,9 @@ function main() {
|
|||||||
}).then(function() {
|
}).then(function() {
|
||||||
return Promise.all(gLegacyEventInfo.map(mpTestModernBeatsLegacy));
|
return Promise.all(gLegacyEventInfo.map(mpTestModernBeatsLegacy));
|
||||||
}).then(function() {
|
}).then(function() {
|
||||||
return Promise.all(gLegacyEventInfo.map(mpTestAncestorsWithDiffListeners));
|
return Promise.all(gLegacyEventInfo.map(mpTestDiffListenersEventCapturing));
|
||||||
|
}).then(function() {
|
||||||
|
return Promise.all(gLegacyEventInfo.map(mpTestDiffListenersEventBubbling));
|
||||||
}).then(function() {
|
}).then(function() {
|
||||||
SimpleTest.finish();
|
SimpleTest.finish();
|
||||||
}).catch(function(reason) {
|
}).catch(function(reason) {
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
<title>Test for MozMousePixelScroll events</title>
|
<title>Test for MozMousePixelScroll events</title>
|
||||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||||
|
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
|
||||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
<style>
|
<style>
|
||||||
.scrollable {
|
.scrollable {
|
||||||
@ -63,6 +64,8 @@ function* prepareScrollUnits()
|
|||||||
}
|
}
|
||||||
window.addEventListener("MozMousePixelScroll", handler, true);
|
window.addEventListener("MozMousePixelScroll", handler, true);
|
||||||
|
|
||||||
|
yield waitForAllPaints(function () { setTimeout(runTest, 0); });
|
||||||
|
|
||||||
yield synthesizeWheel(gScrollable128, 10, 10,
|
yield synthesizeWheel(gScrollable128, 10, 10,
|
||||||
{ deltaMode: WheelEvent.DOM_DELTA_LINE,
|
{ deltaMode: WheelEvent.DOM_DELTA_LINE,
|
||||||
deltaY: 1.0, lineOrPageDeltaY: 1 });
|
deltaY: 1.0, lineOrPageDeltaY: 1 });
|
||||||
|
@ -24,7 +24,7 @@ NS_NewHTMLDetailsElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
|
|||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace dom {
|
namespace dom {
|
||||||
|
|
||||||
bool
|
/* static */ bool
|
||||||
HTMLDetailsElement::IsDetailsEnabled()
|
HTMLDetailsElement::IsDetailsEnabled()
|
||||||
{
|
{
|
||||||
static bool isDetailsEnabled = false;
|
static bool isDetailsEnabled = false;
|
||||||
|
@ -891,8 +891,8 @@ nsHTMLDocument::GetDomain(nsAString& aDomain)
|
|||||||
}
|
}
|
||||||
|
|
||||||
nsAutoCString hostName;
|
nsAutoCString hostName;
|
||||||
|
nsresult rv = nsContentUtils::GetHostOrIPv6WithBrackets(uri, hostName);
|
||||||
if (NS_SUCCEEDED(uri->GetHost(hostName))) {
|
if (NS_SUCCEEDED(rv)) {
|
||||||
CopyUTF8toUTF16(hostName, aDomain);
|
CopyUTF8toUTF16(hostName, aDomain);
|
||||||
} else {
|
} else {
|
||||||
// If we can't get the host from the URI (e.g. about:, javascript:,
|
// If we can't get the host from the URI (e.g. about:, javascript:,
|
||||||
|
@ -8566,6 +8566,16 @@ private:
|
|||||||
NS_DECL_NSIRUNNABLE
|
NS_DECL_NSIRUNNABLE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class FlushPendingFileDeletionsRunnable final
|
||||||
|
: public nsRunnable
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
~FlushPendingFileDeletionsRunnable()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
NS_DECL_NSIRUNNABLE
|
||||||
|
};
|
||||||
|
|
||||||
class PermissionRequestHelper final
|
class PermissionRequestHelper final
|
||||||
: public PermissionRequestBase
|
: public PermissionRequestBase
|
||||||
, public PIndexedDBPermissionRequestParent
|
, public PIndexedDBPermissionRequestParent
|
||||||
@ -9568,6 +9578,19 @@ DeallocPBackgroundIndexedDBUtilsParent(PBackgroundIndexedDBUtilsParent* aActor)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
RecvFlushPendingFileDeletions()
|
||||||
|
{
|
||||||
|
AssertIsOnBackgroundThread();
|
||||||
|
|
||||||
|
RefPtr<FlushPendingFileDeletionsRunnable> runnable =
|
||||||
|
new FlushPendingFileDeletionsRunnable();
|
||||||
|
|
||||||
|
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(runnable)));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
PIndexedDBPermissionRequestParent*
|
PIndexedDBPermissionRequestParent*
|
||||||
AllocPIndexedDBPermissionRequestParent(Element* aOwnerElement,
|
AllocPIndexedDBPermissionRequestParent(Element* aOwnerElement,
|
||||||
nsIPrincipal* aPrincipal)
|
nsIPrincipal* aPrincipal)
|
||||||
@ -27062,6 +27085,24 @@ GetFileReferencesHelper::Run()
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
FlushPendingFileDeletionsRunnable::Run()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
|
RefPtr<IndexedDatabaseManager> mgr = IndexedDatabaseManager::Get();
|
||||||
|
if (NS_WARN_IF(!mgr)) {
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult rv = mgr->FlushPendingFileDeletions();
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
PermissionRequestHelper::OnPromptComplete(PermissionValue aPermissionValue)
|
PermissionRequestHelper::OnPromptComplete(PermissionValue aPermissionValue)
|
||||||
{
|
{
|
||||||
|
@ -45,6 +45,9 @@ AllocPBackgroundIndexedDBUtilsParent();
|
|||||||
bool
|
bool
|
||||||
DeallocPBackgroundIndexedDBUtilsParent(PBackgroundIndexedDBUtilsParent* aActor);
|
DeallocPBackgroundIndexedDBUtilsParent(PBackgroundIndexedDBUtilsParent* aActor);
|
||||||
|
|
||||||
|
bool
|
||||||
|
RecvFlushPendingFileDeletions();
|
||||||
|
|
||||||
PIndexedDBPermissionRequestParent*
|
PIndexedDBPermissionRequestParent*
|
||||||
AllocPIndexedDBPermissionRequestParent(Element* aOwnerElement,
|
AllocPIndexedDBPermissionRequestParent(Element* aOwnerElement,
|
||||||
nsIPrincipal* aPrincipal);
|
nsIPrincipal* aPrincipal);
|
||||||
|
@ -22,7 +22,6 @@
|
|||||||
#include "mozilla/EventDispatcher.h"
|
#include "mozilla/EventDispatcher.h"
|
||||||
#include "mozilla/Preferences.h"
|
#include "mozilla/Preferences.h"
|
||||||
#include "mozilla/Services.h"
|
#include "mozilla/Services.h"
|
||||||
#include "mozilla/dom/ContentChild.h"
|
|
||||||
#include "mozilla/dom/DOMError.h"
|
#include "mozilla/dom/DOMError.h"
|
||||||
#include "mozilla/dom/ErrorEvent.h"
|
#include "mozilla/dom/ErrorEvent.h"
|
||||||
#include "mozilla/dom/ErrorEventBinding.h"
|
#include "mozilla/dom/ErrorEventBinding.h"
|
||||||
@ -934,12 +933,12 @@ IndexedDatabaseManager::FlushPendingFileDeletions()
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ContentChild* contentChild = ContentChild::GetSingleton();
|
PBackgroundChild* bgActor = BackgroundChild::GetForCurrentThread();
|
||||||
if (NS_WARN_IF(!contentChild)) {
|
if (NS_WARN_IF(!bgActor)) {
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!contentChild->SendFlushPendingFileDeletions()) {
|
if (!bgActor->SendFlushPendingFileDeletions()) {
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -182,7 +182,7 @@ skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
|
|||||||
[test_file_delete.html]
|
[test_file_delete.html]
|
||||||
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
|
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
|
||||||
[test_file_os_delete.html]
|
[test_file_os_delete.html]
|
||||||
skip-if = e10s || (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116, Bug 1183959 for e10s
|
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
|
||||||
[test_file_put_get_object.html]
|
[test_file_put_get_object.html]
|
||||||
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
|
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
|
||||||
[test_file_put_get_values.html]
|
[test_file_put_get_values.html]
|
||||||
|
@ -64,7 +64,6 @@
|
|||||||
#include "mozilla/dom/cellbroadcast/CellBroadcastParent.h"
|
#include "mozilla/dom/cellbroadcast/CellBroadcastParent.h"
|
||||||
#include "mozilla/dom/devicestorage/DeviceStorageRequestParent.h"
|
#include "mozilla/dom/devicestorage/DeviceStorageRequestParent.h"
|
||||||
#include "mozilla/dom/icc/IccParent.h"
|
#include "mozilla/dom/icc/IccParent.h"
|
||||||
#include "mozilla/dom/indexedDB/IndexedDatabaseManager.h"
|
|
||||||
#include "mozilla/dom/mobileconnection/MobileConnectionParent.h"
|
#include "mozilla/dom/mobileconnection/MobileConnectionParent.h"
|
||||||
#include "mozilla/dom/mobilemessage/SmsParent.h"
|
#include "mozilla/dom/mobilemessage/SmsParent.h"
|
||||||
#include "mozilla/dom/power/PowerManagerService.h"
|
#include "mozilla/dom/power/PowerManagerService.h"
|
||||||
@ -291,7 +290,6 @@ using namespace mozilla::dom::bluetooth;
|
|||||||
using namespace mozilla::dom::cellbroadcast;
|
using namespace mozilla::dom::cellbroadcast;
|
||||||
using namespace mozilla::dom::devicestorage;
|
using namespace mozilla::dom::devicestorage;
|
||||||
using namespace mozilla::dom::icc;
|
using namespace mozilla::dom::icc;
|
||||||
using namespace mozilla::dom::indexedDB;
|
|
||||||
using namespace mozilla::dom::power;
|
using namespace mozilla::dom::power;
|
||||||
using namespace mozilla::dom::mobileconnection;
|
using namespace mozilla::dom::mobileconnection;
|
||||||
using namespace mozilla::dom::mobilemessage;
|
using namespace mozilla::dom::mobilemessage;
|
||||||
@ -5109,26 +5107,6 @@ ContentParent::DeallocPFileDescriptorSetParent(PFileDescriptorSetParent* aActor)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
ContentParent::RecvFlushPendingFileDeletions()
|
|
||||||
{
|
|
||||||
RefPtr<IndexedDatabaseManager> mgr = IndexedDatabaseManager::Get();
|
|
||||||
if (NS_WARN_IF(!mgr)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NS_WARN_IF(!mgr->IsMainProcess())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult rv = mgr->FlushPendingFileDeletions();
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ContentParent::IgnoreIPCPrincipal()
|
ContentParent::IgnoreIPCPrincipal()
|
||||||
{
|
{
|
||||||
|
@ -1045,9 +1045,6 @@ private:
|
|||||||
virtual bool
|
virtual bool
|
||||||
DeallocPFileDescriptorSetParent(PFileDescriptorSetParent*) override;
|
DeallocPFileDescriptorSetParent(PFileDescriptorSetParent*) override;
|
||||||
|
|
||||||
virtual bool
|
|
||||||
RecvFlushPendingFileDeletions() override;
|
|
||||||
|
|
||||||
virtual PWebrtcGlobalParent* AllocPWebrtcGlobalParent() override;
|
virtual PWebrtcGlobalParent* AllocPWebrtcGlobalParent() override;
|
||||||
virtual bool DeallocPWebrtcGlobalParent(PWebrtcGlobalParent *aActor) override;
|
virtual bool DeallocPWebrtcGlobalParent(PWebrtcGlobalParent *aActor) override;
|
||||||
|
|
||||||
|
@ -1055,9 +1055,6 @@ parent:
|
|||||||
sync KeygenProvideContent()
|
sync KeygenProvideContent()
|
||||||
returns (nsString aAttribute, nsString[] aContent);
|
returns (nsString aAttribute, nsString[] aContent);
|
||||||
|
|
||||||
// Use only for testing!
|
|
||||||
async FlushPendingFileDeletions();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tell the chrome process there is an creation of PBrowser.
|
* Tell the chrome process there is an creation of PBrowser.
|
||||||
* return a system-wise unique Id.
|
* return a system-wise unique Id.
|
||||||
|
@ -2631,6 +2631,9 @@ MediaManager::Shutdown()
|
|||||||
GetActiveWindows()->Clear();
|
GetActiveWindows()->Clear();
|
||||||
mActiveCallbacks.Clear();
|
mActiveCallbacks.Clear();
|
||||||
mCallIds.Clear();
|
mCallIds.Clear();
|
||||||
|
#ifdef MOZ_WEBRTC
|
||||||
|
StopWebRtcLog();
|
||||||
|
#endif
|
||||||
|
|
||||||
// Because mMediaThread is not an nsThread, we must dispatch to it so it can
|
// Because mMediaThread is not an nsThread, we must dispatch to it so it can
|
||||||
// clean up BackgroundChild. Continue stopping thread once this is done.
|
// clean up BackgroundChild. Continue stopping thread once this is done.
|
||||||
|
@ -53,8 +53,8 @@ function range(start, end) {
|
|||||||
|
|
||||||
function once(target, name, cb) {
|
function once(target, name, cb) {
|
||||||
var p = new Promise(function(resolve, reject) {
|
var p = new Promise(function(resolve, reject) {
|
||||||
target.addEventListener(name, function() {
|
target.addEventListener(name, function onceEvent() {
|
||||||
target.removeEventListener(name, arguments.callee);
|
target.removeEventListener(name, onceEvent);
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -740,7 +740,7 @@ MediaCodecDataDecoder::Shutdown()
|
|||||||
{
|
{
|
||||||
MonitorAutoLock lock(mMonitor);
|
MonitorAutoLock lock(mMonitor);
|
||||||
|
|
||||||
if (!mThread || State() == kStopping) {
|
if (State() == kStopping) {
|
||||||
// Already shutdown or in the process of doing so
|
// Already shutdown or in the process of doing so
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
@ -748,15 +748,20 @@ MediaCodecDataDecoder::Shutdown()
|
|||||||
State(kStopping);
|
State(kStopping);
|
||||||
lock.Notify();
|
lock.Notify();
|
||||||
|
|
||||||
while (State() == kStopping) {
|
while (mThread && State() == kStopping) {
|
||||||
lock.Wait();
|
lock.Wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
mThread->Shutdown();
|
if (mThread) {
|
||||||
mThread = nullptr;
|
mThread->Shutdown();
|
||||||
|
mThread = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
mDecoder->Stop();
|
if (mDecoder) {
|
||||||
mDecoder->Release();
|
mDecoder->Stop();
|
||||||
|
mDecoder->Release();
|
||||||
|
mDecoder = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
@ -40,8 +40,8 @@ FFmpegLibWrapper::Link()
|
|||||||
uint32_t version = avcodec_version();
|
uint32_t version = avcodec_version();
|
||||||
mVersion = (version >> 16) & 0xff;
|
mVersion = (version >> 16) & 0xff;
|
||||||
uint32_t micro = version & 0xff;
|
uint32_t micro = version & 0xff;
|
||||||
if (mVersion == 57 && micro != 100) {
|
if (mVersion == 57 && micro < 100) {
|
||||||
// a micro version of 100 indicates that it's FFmpeg (as opposed to LibAV).
|
// a micro version >= 100 indicates that it's FFmpeg (as opposed to LibAV).
|
||||||
// Due to current AVCodecContext binary incompatibility we can only
|
// Due to current AVCodecContext binary incompatibility we can only
|
||||||
// support FFmpeg 57 at this stage.
|
// support FFmpeg 57 at this stage.
|
||||||
Unlink();
|
Unlink();
|
||||||
|
73
dom/media/test/external/mach_commands.py
vendored
Normal file
73
dom/media/test/external/mach_commands.py
vendored
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
# 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/.
|
||||||
|
|
||||||
|
from __future__ import absolute_import, unicode_literals
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from mozbuild.base import (
|
||||||
|
MachCommandBase,
|
||||||
|
MachCommandConditions as conditions,
|
||||||
|
)
|
||||||
|
|
||||||
|
from mach.decorators import (
|
||||||
|
CommandProvider,
|
||||||
|
Command,
|
||||||
|
)
|
||||||
|
|
||||||
|
def setup_argument_parser():
|
||||||
|
from external_media_harness.runtests import MediaTestArguments
|
||||||
|
return MediaTestArguments()
|
||||||
|
|
||||||
|
|
||||||
|
def run_external_media_test(tests, testtype=None, topsrcdir=None, **kwargs):
|
||||||
|
from external_media_harness.runtests import (
|
||||||
|
FirefoxMediaHarness,
|
||||||
|
MediaTestArguments,
|
||||||
|
MediaTestRunner,
|
||||||
|
mn_cli,
|
||||||
|
)
|
||||||
|
|
||||||
|
from mozlog.structured import commandline
|
||||||
|
|
||||||
|
parser = MediaTestArguments()
|
||||||
|
commandline.add_logging_group(parser)
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
if not tests:
|
||||||
|
tests = [os.path.join(topsrcdir,
|
||||||
|
'dom/media/test/external/external_media_tests/manifest.ini')]
|
||||||
|
args.tests = tests
|
||||||
|
|
||||||
|
if not args.binary:
|
||||||
|
args.binary = kwargs['binary']
|
||||||
|
|
||||||
|
for k, v in kwargs.iteritems():
|
||||||
|
setattr(args, k, v)
|
||||||
|
|
||||||
|
parser.verify_usage(args)
|
||||||
|
|
||||||
|
args.logger = commandline.setup_logging("Firefox External Media Tests",
|
||||||
|
args,
|
||||||
|
{"mach": sys.stdout})
|
||||||
|
failed = mn_cli(MediaTestRunner, MediaTestArguments, FirefoxMediaHarness,
|
||||||
|
args=args)
|
||||||
|
|
||||||
|
if failed > 0:
|
||||||
|
return 1
|
||||||
|
else:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
@CommandProvider
|
||||||
|
class MachCommands(MachCommandBase):
|
||||||
|
@Command('external-media-tests', category='testing',
|
||||||
|
description='Run Firefox external media tests.',
|
||||||
|
conditions=[conditions.is_firefox],
|
||||||
|
parser=setup_argument_parser,
|
||||||
|
)
|
||||||
|
def run_external_media_test(self, tests, **kwargs):
|
||||||
|
kwargs['binary'] = self.get_binary_path('app')
|
||||||
|
return run_external_media_test(tests, topsrcdir=self.topsrcdir, **kwargs)
|
6
dom/media/test/external/requirements.txt
vendored
6
dom/media/test/external/requirements.txt
vendored
@ -15,9 +15,9 @@ mozrunner==6.11
|
|||||||
moztest==0.7
|
moztest==0.7
|
||||||
mozversion==1.4
|
mozversion==1.4
|
||||||
wptserve==1.3.0
|
wptserve==1.3.0
|
||||||
marionette-client==2.1.0
|
marionette-client == 2.2.0
|
||||||
marionette-driver==1.2.0
|
marionette-driver == 1.3.0
|
||||||
firefox-puppeteer==3.1.0
|
firefox-puppeteer==3.2.0
|
||||||
|
|
||||||
# Install the firefox media tests package
|
# Install the firefox media tests package
|
||||||
./
|
./
|
||||||
|
6
dom/media/test/external/setup.py
vendored
6
dom/media/test/external/setup.py
vendored
@ -7,11 +7,11 @@ from setuptools import setup, find_packages
|
|||||||
PACKAGE_VERSION = '1.0'
|
PACKAGE_VERSION = '1.0'
|
||||||
|
|
||||||
deps = [
|
deps = [
|
||||||
'marionette-client == 2.1.0',
|
'marionette-client == 2.2.0',
|
||||||
'marionette-driver == 1.2.0',
|
'marionette-driver == 1.3.0',
|
||||||
'mozlog == 3.1',
|
'mozlog == 3.1',
|
||||||
'manifestparser == 1.1',
|
'manifestparser == 1.1',
|
||||||
'firefox-puppeteer >= 3.1.0, <4.0.0',
|
'firefox-puppeteer >= 3.2.0, <4.0.0',
|
||||||
]
|
]
|
||||||
|
|
||||||
setup(name='external-media-tests',
|
setup(name='external-media-tests',
|
||||||
|
@ -1357,8 +1357,8 @@ function removeNodeAndSource(n) {
|
|||||||
|
|
||||||
function once(target, name, cb) {
|
function once(target, name, cb) {
|
||||||
var p = new Promise(function(resolve, reject) {
|
var p = new Promise(function(resolve, reject) {
|
||||||
target.addEventListener(name, function() {
|
target.addEventListener(name, function onceEvent() {
|
||||||
target.removeEventListener(name, cb);
|
target.removeEventListener(name, onceEvent);
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
32
dom/media/webspeech/synth/crashtests/1230428.html
Normal file
32
dom/media/webspeech/synth/crashtests/1230428.html
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-wait">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<script type="application/javascript">
|
||||||
|
function f()
|
||||||
|
{
|
||||||
|
if (speechSynthesis.getVoices().length == 0) {
|
||||||
|
// No synthesis backend to test this
|
||||||
|
document.documentElement.removeAttribute('class');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var s = new SpeechSynthesisUtterance("hello world");
|
||||||
|
s.onerror = () => {
|
||||||
|
// No synthesis backend to test this
|
||||||
|
document.documentElement.removeAttribute('class');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
s.onend = () => {
|
||||||
|
document.documentElement.removeAttribute('class');
|
||||||
|
};
|
||||||
|
speechSynthesis.speak(s);
|
||||||
|
speechSynthesis.cancel();
|
||||||
|
speechSynthesis.pause();
|
||||||
|
speechSynthesis.resume();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body onload="f();">
|
||||||
|
</body>
|
||||||
|
</html>
|
1
dom/media/webspeech/synth/crashtests/crashtests.list
Normal file
1
dom/media/webspeech/synth/crashtests/crashtests.list
Normal file
@ -0,0 +1 @@
|
|||||||
|
skip-if(!cocoaWidget) pref(media.webspeech.synth.enabled,true) load 1230428.html # bug 1230428
|
@ -58,9 +58,16 @@ public:
|
|||||||
switch (event) {
|
switch (event) {
|
||||||
case EVENT_FINISHED:
|
case EVENT_FINISHED:
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIRunnable> runnable =
|
if (!mStarted) {
|
||||||
|
mStarted = true;
|
||||||
|
nsCOMPtr<nsIRunnable> startRunnable =
|
||||||
|
NS_NewRunnableMethod(this, &SynthStreamListener::DoNotifyStarted);
|
||||||
|
aGraph->DispatchToMainThreadAfterStreamStateUpdate(startRunnable.forget());
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIRunnable> endRunnable =
|
||||||
NS_NewRunnableMethod(this, &SynthStreamListener::DoNotifyFinished);
|
NS_NewRunnableMethod(this, &SynthStreamListener::DoNotifyFinished);
|
||||||
aGraph->DispatchToMainThreadAfterStreamStateUpdate(runnable.forget());
|
aGraph->DispatchToMainThreadAfterStreamStateUpdate(endRunnable.forget());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case EVENT_REMOVED:
|
case EVENT_REMOVED:
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#include "mozilla/X11Util.h"
|
#include "mozilla/X11Util.h"
|
||||||
|
|
||||||
|
static void plug_added_cb(GtkWidget *widget, gpointer data);
|
||||||
static gboolean plug_removed_cb (GtkWidget *widget, gpointer data);
|
static gboolean plug_removed_cb (GtkWidget *widget, gpointer data);
|
||||||
static void socket_unrealize_cb (GtkWidget *widget, gpointer data);
|
static void socket_unrealize_cb (GtkWidget *widget, gpointer data);
|
||||||
|
|
||||||
@ -163,6 +164,9 @@ nsresult nsPluginNativeWindowGtk::CreateXEmbedWindow(bool aEnableXtFocus) {
|
|||||||
// see plugin_window_filter_func() for details
|
// see plugin_window_filter_func() for details
|
||||||
g_object_set_data(G_OBJECT(mSocketWidget), "enable-xt-focus", (void *)aEnableXtFocus);
|
g_object_set_data(G_OBJECT(mSocketWidget), "enable-xt-focus", (void *)aEnableXtFocus);
|
||||||
|
|
||||||
|
g_signal_connect(mSocketWidget, "plug_added",
|
||||||
|
G_CALLBACK(plug_added_cb), nullptr);
|
||||||
|
|
||||||
// Make sure to handle the plug_removed signal. If we don't the
|
// Make sure to handle the plug_removed signal. If we don't the
|
||||||
// socket will automatically be destroyed when the plug is
|
// socket will automatically be destroyed when the plug is
|
||||||
// removed, which means we're destroying it more than once.
|
// removed, which means we're destroying it more than once.
|
||||||
@ -278,6 +282,32 @@ nsresult nsPluginNativeWindowGtk::CreateXtWindow() {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static void
|
||||||
|
plug_window_finalize_cb(gpointer socket, GObject* plug_window)
|
||||||
|
{
|
||||||
|
g_object_unref(socket);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
plug_added_cb(GtkWidget *socket, gpointer data)
|
||||||
|
{
|
||||||
|
// The plug window has been embedded, and gtk_socket_add_window() has added
|
||||||
|
// a filter to the socket's plug_window, passing the socket as data for the
|
||||||
|
// filter, so the socket must live as long as events may be received on the
|
||||||
|
// plug window.
|
||||||
|
//
|
||||||
|
// https://git.gnome.org/browse/gtk+/tree/gtk/gtksocket.c?h=3.18.7#n1124
|
||||||
|
g_object_ref(socket);
|
||||||
|
// When the socket is unrealized, perhaps during gtk_widget_destroy() from
|
||||||
|
// ~nsPluginNativeWindowGtk, the plug is removed. The plug in the child
|
||||||
|
// process then destroys its widget and window. When the browser process
|
||||||
|
// receives the DestroyNotify event for the plug window, GDK releases its
|
||||||
|
// reference to plugWindow. This is typically the last reference and so the
|
||||||
|
// weak ref callback triggers release of the socket.
|
||||||
|
GdkWindow* plugWindow = gtk_socket_get_plug_window(GTK_SOCKET(socket));
|
||||||
|
g_object_weak_ref(G_OBJECT(plugWindow), plug_window_finalize_cb, socket);
|
||||||
|
}
|
||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
gboolean
|
gboolean
|
||||||
plug_removed_cb (GtkWidget *widget, gpointer data)
|
plug_removed_cb (GtkWidget *widget, gpointer data)
|
||||||
|
@ -1974,12 +1974,6 @@ RuntimeService::Shutdown()
|
|||||||
// That's it, no more workers.
|
// That's it, no more workers.
|
||||||
mShuttingDown = true;
|
mShuttingDown = true;
|
||||||
|
|
||||||
// Remove all listeners from the worker debugger manager to ensure that it
|
|
||||||
// gets properly destroyed.
|
|
||||||
if (NS_FAILED(ClearWorkerDebuggerManagerListeners())) {
|
|
||||||
NS_WARNING("Failed to clear worker debugger manager listeners!");
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
||||||
NS_WARN_IF_FALSE(obs, "Failed to get observer service?!");
|
NS_WARN_IF_FALSE(obs, "Failed to get observer service?!");
|
||||||
|
|
||||||
|
@ -8,22 +8,23 @@
|
|||||||
|
|
||||||
#include "nsISimpleEnumerator.h"
|
#include "nsISimpleEnumerator.h"
|
||||||
|
|
||||||
|
#include "mozilla/ClearOnShutdown.h"
|
||||||
|
|
||||||
#include "WorkerPrivate.h"
|
#include "WorkerPrivate.h"
|
||||||
|
|
||||||
USING_WORKERS_NAMESPACE
|
USING_WORKERS_NAMESPACE
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
class RegisterDebuggerMainThreadRunnable final : public nsRunnable
|
class RegisterDebuggerMainThreadRunnable final : public nsRunnable
|
||||||
{
|
{
|
||||||
RefPtr<WorkerDebuggerManager> mManager;
|
|
||||||
WorkerPrivate* mWorkerPrivate;
|
WorkerPrivate* mWorkerPrivate;
|
||||||
bool mNotifyListeners;
|
bool mNotifyListeners;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RegisterDebuggerMainThreadRunnable(WorkerDebuggerManager* aManager,
|
RegisterDebuggerMainThreadRunnable(WorkerPrivate* aWorkerPrivate,
|
||||||
WorkerPrivate* aWorkerPrivate,
|
|
||||||
bool aNotifyListeners)
|
bool aNotifyListeners)
|
||||||
: mManager(aManager),
|
: mWorkerPrivate(aWorkerPrivate),
|
||||||
mWorkerPrivate(aWorkerPrivate),
|
|
||||||
mNotifyListeners(aNotifyListeners)
|
mNotifyListeners(aNotifyListeners)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
@ -34,21 +35,21 @@ private:
|
|||||||
NS_IMETHOD
|
NS_IMETHOD
|
||||||
Run() override
|
Run() override
|
||||||
{
|
{
|
||||||
mManager->RegisterDebuggerMainThread(mWorkerPrivate, mNotifyListeners);
|
WorkerDebuggerManager* manager = WorkerDebuggerManager::Get();
|
||||||
|
MOZ_ASSERT(manager);
|
||||||
|
|
||||||
|
manager->RegisterDebuggerMainThread(mWorkerPrivate, mNotifyListeners);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class UnregisterDebuggerMainThreadRunnable final : public nsRunnable
|
class UnregisterDebuggerMainThreadRunnable final : public nsRunnable
|
||||||
{
|
{
|
||||||
RefPtr<WorkerDebuggerManager> mManager;
|
|
||||||
WorkerPrivate* mWorkerPrivate;
|
WorkerPrivate* mWorkerPrivate;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
UnregisterDebuggerMainThreadRunnable(WorkerDebuggerManager* aManager,
|
explicit UnregisterDebuggerMainThreadRunnable(WorkerPrivate* aWorkerPrivate)
|
||||||
WorkerPrivate* aWorkerPrivate)
|
: mWorkerPrivate(aWorkerPrivate)
|
||||||
: mManager(aManager), mWorkerPrivate(aWorkerPrivate)
|
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -58,12 +59,19 @@ private:
|
|||||||
NS_IMETHOD
|
NS_IMETHOD
|
||||||
Run() override
|
Run() override
|
||||||
{
|
{
|
||||||
mManager->UnregisterDebuggerMainThread(mWorkerPrivate);
|
WorkerDebuggerManager* manager = WorkerDebuggerManager::Get();
|
||||||
|
MOZ_ASSERT(manager);
|
||||||
|
|
||||||
|
manager->UnregisterDebuggerMainThread(mWorkerPrivate);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Does not hold an owning reference.
|
||||||
|
static WorkerDebuggerManager* gWorkerDebuggerManager;
|
||||||
|
|
||||||
|
} /* anonymous namespace */
|
||||||
|
|
||||||
BEGIN_WORKERS_NAMESPACE
|
BEGIN_WORKERS_NAMESPACE
|
||||||
|
|
||||||
class WorkerDebuggerEnumerator final : public nsISimpleEnumerator
|
class WorkerDebuggerEnumerator final : public nsISimpleEnumerator
|
||||||
@ -116,7 +124,54 @@ WorkerDebuggerManager::~WorkerDebuggerManager()
|
|||||||
AssertIsOnMainThread();
|
AssertIsOnMainThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS(WorkerDebuggerManager, nsIWorkerDebuggerManager);
|
// static
|
||||||
|
already_AddRefed<WorkerDebuggerManager>
|
||||||
|
WorkerDebuggerManager::GetInstance()
|
||||||
|
{
|
||||||
|
RefPtr<WorkerDebuggerManager> manager = WorkerDebuggerManager::GetOrCreate();
|
||||||
|
return manager.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
WorkerDebuggerManager*
|
||||||
|
WorkerDebuggerManager::GetOrCreate()
|
||||||
|
{
|
||||||
|
AssertIsOnMainThread();
|
||||||
|
|
||||||
|
if (!gWorkerDebuggerManager) {
|
||||||
|
// The observer service now owns us until shutdown.
|
||||||
|
gWorkerDebuggerManager = new WorkerDebuggerManager();
|
||||||
|
if (NS_FAILED(gWorkerDebuggerManager->Init())) {
|
||||||
|
NS_WARNING("Failed to initialize worker debugger manager!");
|
||||||
|
gWorkerDebuggerManager = nullptr;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return gWorkerDebuggerManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
WorkerDebuggerManager*
|
||||||
|
WorkerDebuggerManager::Get()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(gWorkerDebuggerManager);
|
||||||
|
return gWorkerDebuggerManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMPL_ISUPPORTS(WorkerDebuggerManager, nsIObserver, nsIWorkerDebuggerManager);
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
WorkerDebuggerManager::Observe(nsISupports* aSubject, const char* aTopic,
|
||||||
|
const char16_t* aData)
|
||||||
|
{
|
||||||
|
if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
|
||||||
|
Shutdown();
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_NOTREACHED("Unknown observer topic!");
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
WorkerDebuggerManager::GetWorkerDebuggerEnumerator(
|
WorkerDebuggerManager::GetWorkerDebuggerEnumerator(
|
||||||
@ -161,8 +216,20 @@ WorkerDebuggerManager::RemoveListener(
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
WorkerDebuggerManager::Init()
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
||||||
|
NS_ENSURE_TRUE(obs, NS_ERROR_FAILURE);
|
||||||
|
|
||||||
|
nsresult rv = obs->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
WorkerDebuggerManager::ClearListeners()
|
WorkerDebuggerManager::Shutdown()
|
||||||
{
|
{
|
||||||
AssertIsOnMainThread();
|
AssertIsOnMainThread();
|
||||||
|
|
||||||
@ -205,8 +272,7 @@ WorkerDebuggerManager::RegisterDebugger(WorkerPrivate* aWorkerPrivate)
|
|||||||
}
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsIRunnable> runnable =
|
nsCOMPtr<nsIRunnable> runnable =
|
||||||
new RegisterDebuggerMainThreadRunnable(this, aWorkerPrivate,
|
new RegisterDebuggerMainThreadRunnable(aWorkerPrivate, hasListeners);
|
||||||
hasListeners);
|
|
||||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(
|
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(
|
||||||
NS_DispatchToMainThread(runnable, NS_DISPATCH_NORMAL)));
|
NS_DispatchToMainThread(runnable, NS_DISPATCH_NORMAL)));
|
||||||
|
|
||||||
@ -225,7 +291,7 @@ WorkerDebuggerManager::UnregisterDebugger(WorkerPrivate* aWorkerPrivate)
|
|||||||
UnregisterDebuggerMainThread(aWorkerPrivate);
|
UnregisterDebuggerMainThread(aWorkerPrivate);
|
||||||
} else {
|
} else {
|
||||||
nsCOMPtr<nsIRunnable> runnable =
|
nsCOMPtr<nsIRunnable> runnable =
|
||||||
new UnregisterDebuggerMainThreadRunnable(this, aWorkerPrivate);
|
new UnregisterDebuggerMainThreadRunnable(aWorkerPrivate);
|
||||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(
|
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(
|
||||||
NS_DispatchToMainThread(runnable, NS_DISPATCH_NORMAL)));
|
NS_DispatchToMainThread(runnable, NS_DISPATCH_NORMAL)));
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include "Workers.h"
|
#include "Workers.h"
|
||||||
|
|
||||||
|
#include "nsIObserver.h"
|
||||||
#include "nsIWorkerDebuggerManager.h"
|
#include "nsIWorkerDebuggerManager.h"
|
||||||
|
|
||||||
#include "nsServiceManagerUtils.h"
|
#include "nsServiceManagerUtils.h"
|
||||||
@ -24,7 +25,8 @@ BEGIN_WORKERS_NAMESPACE
|
|||||||
|
|
||||||
class WorkerDebugger;
|
class WorkerDebugger;
|
||||||
|
|
||||||
class WorkerDebuggerManager final : public nsIWorkerDebuggerManager
|
class WorkerDebuggerManager final : public nsIObserver,
|
||||||
|
public nsIWorkerDebuggerManager
|
||||||
{
|
{
|
||||||
Mutex mMutex;
|
Mutex mMutex;
|
||||||
|
|
||||||
@ -35,54 +37,58 @@ class WorkerDebuggerManager final : public nsIWorkerDebuggerManager
|
|||||||
nsTArray<RefPtr<WorkerDebugger>> mDebuggers;
|
nsTArray<RefPtr<WorkerDebugger>> mDebuggers;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
static already_AddRefed<WorkerDebuggerManager>
|
||||||
|
GetInstance();
|
||||||
|
|
||||||
static WorkerDebuggerManager*
|
static WorkerDebuggerManager*
|
||||||
GetOrCreateService()
|
GetOrCreate();
|
||||||
{
|
|
||||||
nsCOMPtr<nsIWorkerDebuggerManager> manager =
|
static WorkerDebuggerManager*
|
||||||
do_GetService(WORKERDEBUGGERMANAGER_CONTRACTID);
|
Get();
|
||||||
return static_cast<WorkerDebuggerManager*>(manager.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
WorkerDebuggerManager();
|
WorkerDebuggerManager();
|
||||||
|
|
||||||
NS_DECL_THREADSAFE_ISUPPORTS
|
NS_DECL_ISUPPORTS
|
||||||
|
NS_DECL_NSIOBSERVER
|
||||||
NS_DECL_NSIWORKERDEBUGGERMANAGER
|
NS_DECL_NSIWORKERDEBUGGERMANAGER
|
||||||
|
|
||||||
void ClearListeners();
|
nsresult
|
||||||
|
Init();
|
||||||
|
|
||||||
void RegisterDebugger(WorkerPrivate* aWorkerPrivate);
|
void
|
||||||
|
Shutdown();
|
||||||
|
|
||||||
void UnregisterDebugger(WorkerPrivate* aWorkerPrivate);
|
void
|
||||||
|
RegisterDebugger(WorkerPrivate* aWorkerPrivate);
|
||||||
|
|
||||||
void RegisterDebuggerMainThread(WorkerPrivate* aWorkerPrivate,
|
void
|
||||||
bool aNotifyListeners);
|
RegisterDebuggerMainThread(WorkerPrivate* aWorkerPrivate,
|
||||||
|
bool aNotifyListeners);
|
||||||
|
|
||||||
void UnregisterDebuggerMainThread(WorkerPrivate* aWorkerPrivate);
|
void
|
||||||
|
UnregisterDebugger(WorkerPrivate* aWorkerPrivate);
|
||||||
|
|
||||||
|
void
|
||||||
|
UnregisterDebuggerMainThread(WorkerPrivate* aWorkerPrivate);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual ~WorkerDebuggerManager();
|
virtual ~WorkerDebuggerManager();
|
||||||
};
|
};
|
||||||
|
|
||||||
inline nsresult
|
|
||||||
ClearWorkerDebuggerManagerListeners()
|
|
||||||
{
|
|
||||||
RefPtr<WorkerDebuggerManager> manager =
|
|
||||||
WorkerDebuggerManager::GetOrCreateService();
|
|
||||||
if (!manager) {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
manager->ClearListeners();
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline nsresult
|
inline nsresult
|
||||||
RegisterWorkerDebugger(WorkerPrivate* aWorkerPrivate)
|
RegisterWorkerDebugger(WorkerPrivate* aWorkerPrivate)
|
||||||
{
|
{
|
||||||
RefPtr<WorkerDebuggerManager> manager =
|
WorkerDebuggerManager* manager;
|
||||||
WorkerDebuggerManager::GetOrCreateService();
|
|
||||||
if (!manager) {
|
if (NS_IsMainThread()) {
|
||||||
return NS_ERROR_FAILURE;
|
manager = WorkerDebuggerManager::GetOrCreate();
|
||||||
|
if (!manager) {
|
||||||
|
NS_WARNING("Failed to create worker debugger manager!");
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
manager = WorkerDebuggerManager::Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
manager->RegisterDebugger(aWorkerPrivate);
|
manager->RegisterDebugger(aWorkerPrivate);
|
||||||
@ -92,10 +98,17 @@ RegisterWorkerDebugger(WorkerPrivate* aWorkerPrivate)
|
|||||||
inline nsresult
|
inline nsresult
|
||||||
UnregisterWorkerDebugger(WorkerPrivate* aWorkerPrivate)
|
UnregisterWorkerDebugger(WorkerPrivate* aWorkerPrivate)
|
||||||
{
|
{
|
||||||
RefPtr<WorkerDebuggerManager> manager =
|
WorkerDebuggerManager* manager;
|
||||||
WorkerDebuggerManager::GetOrCreateService();
|
|
||||||
if (!manager) {
|
if (NS_IsMainThread()) {
|
||||||
return NS_ERROR_FAILURE;
|
manager = WorkerDebuggerManager::GetOrCreate();
|
||||||
|
if (!manager) {
|
||||||
|
NS_WARNING("Failed to create worker debugger manager!");
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
manager = WorkerDebuggerManager::Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
manager->UnregisterDebugger(aWorkerPrivate);
|
manager->UnregisterDebugger(aWorkerPrivate);
|
||||||
|
@ -1832,7 +1832,7 @@ XULDocument::RemoveElementFromRefMap(Element* aElement)
|
|||||||
if (!entry)
|
if (!entry)
|
||||||
return;
|
return;
|
||||||
if (entry->RemoveElement(aElement)) {
|
if (entry->RemoveElement(aElement)) {
|
||||||
mRefMap.RawRemoveEntry(entry);
|
mRefMap.RemoveEntry(entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1571,7 +1571,7 @@ nsPermissionManager::AddInternal(nsIPrincipal* aPrincipal,
|
|||||||
PermissionHashKey* entry = mPermissionTable.PutEntry(key);
|
PermissionHashKey* entry = mPermissionTable.PutEntry(key);
|
||||||
if (!entry) return NS_ERROR_FAILURE;
|
if (!entry) return NS_ERROR_FAILURE;
|
||||||
if (!entry->GetKey()) {
|
if (!entry->GetKey()) {
|
||||||
mPermissionTable.RawRemoveEntry(entry);
|
mPermissionTable.RemoveEntry(entry);
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1694,7 +1694,7 @@ nsPermissionManager::AddInternal(nsIPrincipal* aPrincipal,
|
|||||||
|
|
||||||
// If there are no more permissions stored for that entry, clear it.
|
// If there are no more permissions stored for that entry, clear it.
|
||||||
if (entry->GetPermissions().IsEmpty()) {
|
if (entry->GetPermissions().IsEmpty()) {
|
||||||
mPermissionTable.RawRemoveEntry(entry);
|
mPermissionTable.RemoveEntry(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -238,7 +238,7 @@ uint16 Face::getGlyphMetric(uint16 gid, uint8 metric) const
|
|||||||
case kgmetAscent : return m_ascent;
|
case kgmetAscent : return m_ascent;
|
||||||
case kgmetDescent : return m_descent;
|
case kgmetDescent : return m_descent;
|
||||||
default:
|
default:
|
||||||
if (gid > glyphs().numGlyphs()) return 0;
|
if (gid >= glyphs().numGlyphs()) return 0;
|
||||||
return glyphs().glyph(gid)->getMetric(metric);
|
return glyphs().glyph(gid)->getMetric(metric);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,8 +60,12 @@ FileFace::FileFace(const char *filename)
|
|||||||
if (!TtfUtil::GetTableDirInfo(_header_tbl, tbl_offset, tbl_len)) return;
|
if (!TtfUtil::GetTableDirInfo(_header_tbl, tbl_offset, tbl_len)) return;
|
||||||
_table_dir = (TtfUtil::Sfnt::OffsetSubTable::Entry*)gralloc<char>(tbl_len);
|
_table_dir = (TtfUtil::Sfnt::OffsetSubTable::Entry*)gralloc<char>(tbl_len);
|
||||||
if (fseek(_file, tbl_offset, SEEK_SET)) return;
|
if (fseek(_file, tbl_offset, SEEK_SET)) return;
|
||||||
if (_table_dir)
|
if (_table_dir && fread(_table_dir, 1, tbl_len, _file) != tbl_len)
|
||||||
if (fread(_table_dir, 1, tbl_len, _file) != tbl_len) return;
|
{
|
||||||
|
free(_table_dir);
|
||||||
|
_table_dir = NULL;
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
FileFace::~FileFace()
|
FileFace::~FileFace()
|
||||||
|
@ -100,7 +100,9 @@ bool Pass::readPass(const byte * const pass_start, size_t pass_length, size_t su
|
|||||||
if (e.test(pass_length < 40, E_BADPASSLENGTH)) return face.error(e);
|
if (e.test(pass_length < 40, E_BADPASSLENGTH)) return face.error(e);
|
||||||
// Read in basic values
|
// Read in basic values
|
||||||
const byte flags = be::read<byte>(p);
|
const byte flags = be::read<byte>(p);
|
||||||
if (e.test((flags & 0x1f) && pt < PASS_TYPE_POSITIONING, E_BADCOLLISIONPASS))
|
if (e.test((flags & 0x1f) &&
|
||||||
|
(pt < PASS_TYPE_POSITIONING || !m_silf->aCollision() || !face.glyphs().hasBoxes()),
|
||||||
|
E_BADCOLLISIONPASS))
|
||||||
return face.error(e);
|
return face.error(e);
|
||||||
m_numCollRuns = flags & 0x7;
|
m_numCollRuns = flags & 0x7;
|
||||||
m_kernColls = (flags >> 3) & 0x3;
|
m_kernColls = (flags >> 3) & 0x3;
|
||||||
|
@ -112,6 +112,7 @@ public:
|
|||||||
const SlantBox & getSubBoundingSlantBox(unsigned short glyphid, uint8 subindex) const;
|
const SlantBox & getSubBoundingSlantBox(unsigned short glyphid, uint8 subindex) const;
|
||||||
const BBox & getSubBoundingBBox(unsigned short glyphid, uint8 subindex) const;
|
const BBox & getSubBoundingBBox(unsigned short glyphid, uint8 subindex) const;
|
||||||
bool check(unsigned short glyphid) const;
|
bool check(unsigned short glyphid) const;
|
||||||
|
bool hasBoxes() const { return _boxes != 0; }
|
||||||
|
|
||||||
CLASS_NEW_DELETE;
|
CLASS_NEW_DELETE;
|
||||||
|
|
||||||
|
@ -31,3 +31,4 @@ skip-if = (os == 'android') || (os == 'b2g') || (buildapp == 'mulet') # wheel ev
|
|||||||
skip-if = (os == 'android') || (os == 'b2g') || (buildapp == 'mulet') # wheel events not supported on mobile; see bug 1164274 for mulet
|
skip-if = (os == 'android') || (os == 'b2g') || (buildapp == 'mulet') # wheel events not supported on mobile; see bug 1164274 for mulet
|
||||||
[test_scroll_subframe_scrollbar.html]
|
[test_scroll_subframe_scrollbar.html]
|
||||||
skip-if = (os == 'android') || (os == 'b2g') || (buildapp == 'mulet') # wheel events not supported on mobile; see bug 1164274 for mulet
|
skip-if = (os == 'android') || (os == 'b2g') || (buildapp == 'mulet') # wheel events not supported on mobile; see bug 1164274 for mulet
|
||||||
|
[test_frame_reconstruction.html]
|
||||||
|
231
gfx/layers/apz/test/mochitest/test_frame_reconstruction.html
Normal file
231
gfx/layers/apz/test/mochitest/test_frame_reconstruction.html
Normal file
@ -0,0 +1,231 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<!--
|
||||||
|
https://bugzilla.mozilla.org/show_bug.cgi?id=1235899
|
||||||
|
-->
|
||||||
|
<head>
|
||||||
|
<title>Test for bug 1235899</title>
|
||||||
|
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||||
|
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
|
||||||
|
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||||
|
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
|
<style>
|
||||||
|
.outer {
|
||||||
|
height: 400px;
|
||||||
|
width: 415px;
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.inner {
|
||||||
|
height: 100%;
|
||||||
|
outline: none;
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: scroll;
|
||||||
|
position: relative;
|
||||||
|
scroll-behavior: smooth;
|
||||||
|
}
|
||||||
|
.outer.contentBefore::before {
|
||||||
|
top: 0;
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
height: 2px;
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
z-index: 99;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1235899">Mozilla Bug 1235899</a>
|
||||||
|
<p id="display"></p>
|
||||||
|
<div id="content">
|
||||||
|
<p>You should be able to fling this list without it stopping abruptly</p>
|
||||||
|
<div class="outer">
|
||||||
|
<div class="inner">
|
||||||
|
<ol>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
<li>Some text</li>
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<pre id="test">
|
||||||
|
<script type="application/javascript;version=1.7">
|
||||||
|
function* runTest() {
|
||||||
|
var elm = document.getElementsByClassName('inner')[0];
|
||||||
|
elm.scrollTop = 0;
|
||||||
|
yield flushApzRepaints(driveTest);
|
||||||
|
|
||||||
|
// Take over control of the refresh driver and compositor
|
||||||
|
var utils = SpecialPowers.DOMWindowUtils;
|
||||||
|
utils.advanceTimeAndRefresh(0);
|
||||||
|
|
||||||
|
// Kick off an APZ smooth-scroll to 0,200
|
||||||
|
elm.scrollTo(0, 200);
|
||||||
|
yield waitForAllPaints(function() { setTimeout(driveTest, 0); });
|
||||||
|
|
||||||
|
// Let's do a couple of frames of the animation, and make sure it's going
|
||||||
|
utils.advanceTimeAndRefresh(16);
|
||||||
|
utils.advanceTimeAndRefresh(16);
|
||||||
|
yield flushApzRepaints(driveTest);
|
||||||
|
ok(elm.scrollTop > 0, "APZ animation in progress", "scrollTop is now " + elm.scrollTop);
|
||||||
|
ok(elm.scrollTop < 200, "APZ animation not yet completed", "scrollTop is now " + elm.scrollTop);
|
||||||
|
|
||||||
|
var frameReconstructionTriggered = 0;
|
||||||
|
// Register the listener that triggers the frame reconstruction
|
||||||
|
elm.onscroll = function() {
|
||||||
|
// Do the reconstruction
|
||||||
|
elm.parentNode.classList.add('contentBefore');
|
||||||
|
frameReconstructionTriggered++;
|
||||||
|
// schedule a thing to undo the changes above
|
||||||
|
setTimeout(function() {
|
||||||
|
elm.parentNode.classList.remove('contentBefore');
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// and do a few more frames of the animation, this should trigger the listener
|
||||||
|
// and the frame reconstruction
|
||||||
|
utils.advanceTimeAndRefresh(16);
|
||||||
|
utils.advanceTimeAndRefresh(16);
|
||||||
|
yield flushApzRepaints(driveTest);
|
||||||
|
ok(elm.scrollTop < 200, "APZ animation not yet completed", "scrollTop is now " + elm.scrollTop);
|
||||||
|
ok(frameReconstructionTriggered > 0, "Frame reconstruction triggered", "reconstruction triggered " + frameReconstructionTriggered + " times");
|
||||||
|
|
||||||
|
// and now run to completion
|
||||||
|
for (var i = 0; i < 100; i++) {
|
||||||
|
utils.advanceTimeAndRefresh(16);
|
||||||
|
}
|
||||||
|
utils.restoreNormalRefresh();
|
||||||
|
yield waitForAllPaints(function() { setTimeout(driveTest, 0); });
|
||||||
|
yield flushApzRepaints(driveTest);
|
||||||
|
|
||||||
|
is(elm.scrollTop, 200, "Element should have scrolled by 200px");
|
||||||
|
}
|
||||||
|
|
||||||
|
var gTestContinuation = null;
|
||||||
|
function driveTest() {
|
||||||
|
if (!gTestContinuation) {
|
||||||
|
gTestContinuation = runTest();
|
||||||
|
}
|
||||||
|
var ret = gTestContinuation.next();
|
||||||
|
if (ret.done) {
|
||||||
|
SimpleTest.finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
var apzEnabled = SpecialPowers.getDOMWindowUtils(window).asyncPanZoomEnabled;
|
||||||
|
if (!apzEnabled) {
|
||||||
|
ok(true, "APZ not enabled, skipping test");
|
||||||
|
SimpleTest.finish();
|
||||||
|
} else {
|
||||||
|
SimpleTest.expectAssertions(0, 1); // this test triggers an assertion, see bug 1247050
|
||||||
|
SimpleTest.waitForFocus(driveTest, window);
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -61,12 +61,6 @@
|
|||||||
SimpleTest.finish();
|
SimpleTest.finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
var hwVsyncEnabled = SpecialPowers.getBoolPref("gfx.vsync.hw-vsync.enabled");
|
|
||||||
if (!hwVsyncEnabled) {
|
|
||||||
SimpleTest.ok(true, "Hardware vsync not enabled, skipping test");
|
|
||||||
SimpleTest.finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
SpecialPowers.pushPrefEnv({
|
SpecialPowers.pushPrefEnv({
|
||||||
"set" : [
|
"set" : [
|
||||||
[testPref, true]
|
[testPref, true]
|
||||||
|
@ -92,11 +92,11 @@ ScrollFrameTo(nsIScrollableFrame* aFrame, const CSSPoint& aPoint, bool& aSuccess
|
|||||||
|
|
||||||
// If the scrollable frame is currently in the middle of an async or smooth
|
// If the scrollable frame is currently in the middle of an async or smooth
|
||||||
// scroll then we don't want to interrupt it (see bug 961280).
|
// scroll then we don't want to interrupt it (see bug 961280).
|
||||||
// Also if the scrollable frame got a scroll request from something other than us
|
// Also if the scrollable frame got a scroll request from a higher priority origin
|
||||||
// since the last layers update, then we don't want to push our scroll request
|
// since the last layers update, then we don't want to push our scroll request
|
||||||
// because we'll clobber that one, which is bad.
|
// because we'll clobber that one, which is bad.
|
||||||
bool scrollInProgress = aFrame->IsProcessingAsyncScroll()
|
bool scrollInProgress = aFrame->IsProcessingAsyncScroll()
|
||||||
|| (aFrame->LastScrollOrigin() && aFrame->LastScrollOrigin() != nsGkAtoms::apz)
|
|| nsLayoutUtils::CanScrollOriginClobberApz(aFrame->LastScrollOrigin())
|
||||||
|| aFrame->LastSmoothScrollOrigin();
|
|| aFrame->LastSmoothScrollOrigin();
|
||||||
if (!scrollInProgress) {
|
if (!scrollInProgress) {
|
||||||
aFrame->ScrollToCSSPixelsApproximate(targetScrollPosition, nsGkAtoms::apz);
|
aFrame->ScrollToCSSPixelsApproximate(targetScrollPosition, nsGkAtoms::apz);
|
||||||
|
@ -564,8 +564,8 @@ RenderLayers(ContainerT* aContainer,
|
|||||||
|
|
||||||
if (layerToRender->HasLayerBeenComposited()) {
|
if (layerToRender->HasLayerBeenComposited()) {
|
||||||
// Composer2D will compose this layer so skip GPU composition
|
// Composer2D will compose this layer so skip GPU composition
|
||||||
// this time & reset composition flag for next composition phase
|
// this time. The flag will be reset for the next composition phase
|
||||||
layerToRender->SetLayerComposited(false);
|
// at the beginning of LayerManagerComposite::Rener().
|
||||||
gfx::IntRect clearRect = layerToRender->GetClearRect();
|
gfx::IntRect clearRect = layerToRender->GetClearRect();
|
||||||
if (!clearRect.IsEmpty()) {
|
if (!clearRect.IsEmpty()) {
|
||||||
// Clear layer's visible rect on FrameBuffer with transparent pixels
|
// Clear layer's visible rect on FrameBuffer with transparent pixels
|
||||||
|
@ -762,6 +762,21 @@ LayerManagerComposite::PopGroupForLayerEffects(RefPtr<CompositingRenderTarget> a
|
|||||||
Matrix4x4());
|
Matrix4x4());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Used to clear the 'mLayerComposited' flag at the beginning of each Render().
|
||||||
|
static void
|
||||||
|
ClearLayerFlags(Layer* aLayer) {
|
||||||
|
if (!aLayer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (aLayer->AsLayerComposite()) {
|
||||||
|
aLayer->AsLayerComposite()->SetLayerComposited(false);
|
||||||
|
}
|
||||||
|
for (Layer* child = aLayer->GetFirstChild(); child;
|
||||||
|
child = child->GetNextSibling()) {
|
||||||
|
ClearLayerFlags(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
LayerManagerComposite::Render(const nsIntRegion& aInvalidRegion)
|
LayerManagerComposite::Render(const nsIntRegion& aInvalidRegion)
|
||||||
{
|
{
|
||||||
@ -773,6 +788,8 @@ LayerManagerComposite::Render(const nsIntRegion& aInvalidRegion)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ClearLayerFlags(mRoot);
|
||||||
|
|
||||||
// At this time, it doesn't really matter if these preferences change
|
// At this time, it doesn't really matter if these preferences change
|
||||||
// during the execution of the function; we should be safe in all
|
// during the execution of the function; we should be safe in all
|
||||||
// permutations. However, may as well just get the values onces and
|
// permutations. However, may as well just get the values onces and
|
||||||
|
@ -58,6 +58,37 @@ using namespace mozilla::media;
|
|||||||
typedef std::vector<CompositableOperation> OpVector;
|
typedef std::vector<CompositableOperation> OpVector;
|
||||||
typedef nsTArray<OpDestroy> OpDestroyVector;
|
typedef nsTArray<OpDestroy> OpDestroyVector;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
class ImageBridgeThread : public Thread {
|
||||||
|
public:
|
||||||
|
|
||||||
|
ImageBridgeThread() : Thread("ImageBridgeChild") {
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
void Init() {
|
||||||
|
#ifdef MOZ_ENABLE_PROFILER_SPS
|
||||||
|
mPseudoStackHack = mozilla_get_pseudo_stack();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void CleanUp() {
|
||||||
|
#ifdef MOZ_ENABLE_PROFILER_SPS
|
||||||
|
mPseudoStackHack = nullptr;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
#ifdef MOZ_ENABLE_PROFILER_SPS
|
||||||
|
// This is needed to avoid a spurious leak report. There's no other
|
||||||
|
// use for it. See bug 1239504 and bug 1215265.
|
||||||
|
PseudoStack* mPseudoStackHack;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
struct CompositableTransaction
|
struct CompositableTransaction
|
||||||
{
|
{
|
||||||
CompositableTransaction()
|
CompositableTransaction()
|
||||||
@ -376,7 +407,7 @@ bool ImageBridgeChild::IsCreated()
|
|||||||
void ImageBridgeChild::StartUp()
|
void ImageBridgeChild::StartUp()
|
||||||
{
|
{
|
||||||
NS_ASSERTION(NS_IsMainThread(), "Should be on the main Thread!");
|
NS_ASSERTION(NS_IsMainThread(), "Should be on the main Thread!");
|
||||||
ImageBridgeChild::StartUpOnThread(new Thread("ImageBridgeChild"));
|
ImageBridgeChild::StartUpOnThread(new ImageBridgeThread());
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MOZ_NUWA_PROCESS
|
#ifdef MOZ_NUWA_PROCESS
|
||||||
@ -709,7 +740,7 @@ ImageBridgeChild::StartUpInChildProcess(Transport* aTransport,
|
|||||||
|
|
||||||
gfxPlatform::GetPlatform();
|
gfxPlatform::GetPlatform();
|
||||||
|
|
||||||
sImageBridgeChildThread = new Thread("ImageBridgeChild");
|
sImageBridgeChildThread = new ImageBridgeThread();
|
||||||
if (!sImageBridgeChildThread->Start()) {
|
if (!sImageBridgeChildThread->Start()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -590,11 +590,12 @@ ShareTableAndGetBlob(nsTArray<uint8_t>&& aTable,
|
|||||||
Clear();
|
Clear();
|
||||||
// adopts elements of aTable
|
// adopts elements of aTable
|
||||||
mSharedBlobData = new FontTableBlobData(Move(aTable));
|
mSharedBlobData = new FontTableBlobData(Move(aTable));
|
||||||
|
|
||||||
mBlob = hb_blob_create(mSharedBlobData->GetTable(),
|
mBlob = hb_blob_create(mSharedBlobData->GetTable(),
|
||||||
mSharedBlobData->GetTableLength(),
|
mSharedBlobData->GetTableLength(),
|
||||||
HB_MEMORY_MODE_READONLY,
|
HB_MEMORY_MODE_READONLY,
|
||||||
mSharedBlobData, DeleteFontTableBlobData);
|
mSharedBlobData, DeleteFontTableBlobData);
|
||||||
if (!mSharedBlobData) {
|
if (mBlob == hb_blob_get_empty() ) {
|
||||||
// The FontTableBlobData was destroyed during hb_blob_create().
|
// The FontTableBlobData was destroyed during hb_blob_create().
|
||||||
// The (empty) blob is still be held in the hashtable with a strong
|
// The (empty) blob is still be held in the hashtable with a strong
|
||||||
// reference.
|
// reference.
|
||||||
|
@ -617,13 +617,13 @@ gfxFontconfigUtils::UpdateFontListInternal(bool aForce)
|
|||||||
bool added = entry->AddFont(font);
|
bool added = entry->AddFont(font);
|
||||||
|
|
||||||
if (!entry->mKey) {
|
if (!entry->mKey) {
|
||||||
// The reference to the font pattern keeps the pointer to
|
// The reference to the font pattern keeps the pointer
|
||||||
// string for the key valid. If adding the font failed
|
// to string for the key valid. If adding the font
|
||||||
// then the entry must be removed.
|
// failed then the entry must be removed.
|
||||||
if (added) {
|
if (added) {
|
||||||
entry->mKey = family;
|
entry->mKey = family;
|
||||||
} else {
|
} else {
|
||||||
mFontsByFamily.RawRemoveEntry(entry);
|
mFontsByFamily.RemoveEntry(entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -217,6 +217,15 @@ BackgroundParentImpl::DeallocPBackgroundIndexedDBUtilsParent(
|
|||||||
mozilla::dom::indexedDB::DeallocPBackgroundIndexedDBUtilsParent(aActor);
|
mozilla::dom::indexedDB::DeallocPBackgroundIndexedDBUtilsParent(aActor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
BackgroundParentImpl::RecvFlushPendingFileDeletions()
|
||||||
|
{
|
||||||
|
AssertIsInMainProcess();
|
||||||
|
AssertIsOnBackgroundThread();
|
||||||
|
|
||||||
|
return mozilla::dom::indexedDB::RecvFlushPendingFileDeletions();
|
||||||
|
}
|
||||||
|
|
||||||
auto
|
auto
|
||||||
BackgroundParentImpl::AllocPBlobParent(const BlobConstructorParams& aParams)
|
BackgroundParentImpl::AllocPBlobParent(const BlobConstructorParams& aParams)
|
||||||
-> PBlobParent*
|
-> PBlobParent*
|
||||||
|
@ -58,6 +58,9 @@ protected:
|
|||||||
PBackgroundIndexedDBUtilsParent* aActor)
|
PBackgroundIndexedDBUtilsParent* aActor)
|
||||||
override;
|
override;
|
||||||
|
|
||||||
|
virtual bool
|
||||||
|
RecvFlushPendingFileDeletions() override;
|
||||||
|
|
||||||
virtual PBlobParent*
|
virtual PBlobParent*
|
||||||
AllocPBlobParent(const BlobConstructorParams& aParams) override;
|
AllocPBlobParent(const BlobConstructorParams& aParams) override;
|
||||||
|
|
||||||
|
@ -157,6 +157,7 @@ public:
|
|||||||
MOZ_RELEASE_ASSERT(aOther.mMessageName);
|
MOZ_RELEASE_ASSERT(aOther.mMessageName);
|
||||||
mMessageName = aOther.mMessageName;
|
mMessageName = aOther.mMessageName;
|
||||||
aOther.mMessageName = nullptr;
|
aOther.mMessageName = nullptr;
|
||||||
|
mMoved = aOther.mMoved;
|
||||||
aOther.mMoved = true;
|
aOther.mMoved = true;
|
||||||
|
|
||||||
mMessageRoutingId = aOther.mMessageRoutingId;
|
mMessageRoutingId = aOther.mMessageRoutingId;
|
||||||
|
@ -66,6 +66,9 @@ parent:
|
|||||||
|
|
||||||
async PBackgroundIndexedDBUtils();
|
async PBackgroundIndexedDBUtils();
|
||||||
|
|
||||||
|
// Use only for testing!
|
||||||
|
async FlushPendingFileDeletions();
|
||||||
|
|
||||||
async PVsync();
|
async PVsync();
|
||||||
|
|
||||||
async PCameras();
|
async PCameras();
|
||||||
|
@ -468,7 +468,6 @@ struct RuntimeSizes
|
|||||||
macro(_, MallocHeap, object) \
|
macro(_, MallocHeap, object) \
|
||||||
macro(_, MallocHeap, atomsTable) \
|
macro(_, MallocHeap, atomsTable) \
|
||||||
macro(_, MallocHeap, contexts) \
|
macro(_, MallocHeap, contexts) \
|
||||||
macro(_, MallocHeap, dtoa) \
|
|
||||||
macro(_, MallocHeap, temporary) \
|
macro(_, MallocHeap, temporary) \
|
||||||
macro(_, MallocHeap, interpreterStack) \
|
macro(_, MallocHeap, interpreterStack) \
|
||||||
macro(_, MallocHeap, mathCache) \
|
macro(_, MallocHeap, mathCache) \
|
||||||
|
@ -934,7 +934,7 @@ MutableHandle<T>::MutableHandle(PersistentRooted<T>* root)
|
|||||||
* These roots can be used in heap-allocated data structures, so they are not
|
* These roots can be used in heap-allocated data structures, so they are not
|
||||||
* associated with any particular JSContext or stack. They are registered with
|
* associated with any particular JSContext or stack. They are registered with
|
||||||
* the JSRuntime itself, without locking, so they require a full JSContext to be
|
* the JSRuntime itself, without locking, so they require a full JSContext to be
|
||||||
* initialized, not one of its more restricted superclasses. Initialization may
|
* initialized, not one of its more restricted superclasses. Initialization may
|
||||||
* take place on construction, or in two phases if the no-argument constructor
|
* take place on construction, or in two phases if the no-argument constructor
|
||||||
* is called followed by init().
|
* is called followed by init().
|
||||||
*
|
*
|
||||||
@ -1048,9 +1048,10 @@ class PersistentRooted : public js::PersistentRootedBase<T>,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void set(T value) {
|
template <typename U>
|
||||||
|
void set(U&& value) {
|
||||||
MOZ_ASSERT(initialized());
|
MOZ_ASSERT(initialized());
|
||||||
ptr = value;
|
ptr = mozilla::Forward<U>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// See the comment above Rooted::ptr.
|
// See the comment above Rooted::ptr.
|
||||||
|
@ -30,6 +30,8 @@
|
|||||||
using namespace js;
|
using namespace js;
|
||||||
using namespace js::wasm;
|
using namespace js::wasm;
|
||||||
|
|
||||||
|
using mozilla::IsNaN;
|
||||||
|
|
||||||
typedef Handle<WasmModuleObject*> HandleWasmModule;
|
typedef Handle<WasmModuleObject*> HandleWasmModule;
|
||||||
typedef MutableHandle<WasmModuleObject*> MutableHandleWasmModule;
|
typedef MutableHandle<WasmModuleObject*> MutableHandleWasmModule;
|
||||||
|
|
||||||
@ -952,6 +954,9 @@ DecodeDataSection(JSContext* cx, Decoder& d, Handle<ArrayBufferObject*> heap)
|
|||||||
if (!d.readCStringIf(DataSection))
|
if (!d.readCStringIf(DataSection))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
if (!heap)
|
||||||
|
return Fail(cx, d, "data section requires a memory section");
|
||||||
|
|
||||||
uint32_t sectionStart;
|
uint32_t sectionStart;
|
||||||
if (!d.startSection(§ionStart))
|
if (!d.startSection(§ionStart))
|
||||||
return Fail(cx, d, "expected data section byte size");
|
return Fail(cx, d, "expected data section byte size");
|
||||||
|
@ -96,6 +96,7 @@ FrameIterator::settle()
|
|||||||
case CodeRange::ImportJitExit:
|
case CodeRange::ImportJitExit:
|
||||||
case CodeRange::ImportInterpExit:
|
case CodeRange::ImportInterpExit:
|
||||||
case CodeRange::Inline:
|
case CodeRange::Inline:
|
||||||
|
case CodeRange::CallThunk:
|
||||||
MOZ_CRASH("Should not encounter an exit during iteration");
|
MOZ_CRASH("Should not encounter an exit during iteration");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -491,6 +492,7 @@ ProfilingFrameIterator::initFromFP(const WasmActivation& activation)
|
|||||||
case CodeRange::ImportJitExit:
|
case CodeRange::ImportJitExit:
|
||||||
case CodeRange::ImportInterpExit:
|
case CodeRange::ImportInterpExit:
|
||||||
case CodeRange::Inline:
|
case CodeRange::Inline:
|
||||||
|
case CodeRange::CallThunk:
|
||||||
MOZ_CRASH("Unexpected CodeRange kind");
|
MOZ_CRASH("Unexpected CodeRange kind");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -541,6 +543,7 @@ ProfilingFrameIterator::ProfilingFrameIterator(const WasmActivation& activation,
|
|||||||
const CodeRange* codeRange = module_->lookupCodeRange(state.pc);
|
const CodeRange* codeRange = module_->lookupCodeRange(state.pc);
|
||||||
switch (codeRange->kind()) {
|
switch (codeRange->kind()) {
|
||||||
case CodeRange::Function:
|
case CodeRange::Function:
|
||||||
|
case CodeRange::CallThunk:
|
||||||
case CodeRange::ImportJitExit:
|
case CodeRange::ImportJitExit:
|
||||||
case CodeRange::ImportInterpExit: {
|
case CodeRange::ImportInterpExit: {
|
||||||
// When the pc is inside the prologue/epilogue, the innermost
|
// When the pc is inside the prologue/epilogue, the innermost
|
||||||
@ -557,7 +560,7 @@ ProfilingFrameIterator::ProfilingFrameIterator(const WasmActivation& activation,
|
|||||||
uint32_t offsetInCodeRange = offsetInModule - codeRange->begin();
|
uint32_t offsetInCodeRange = offsetInModule - codeRange->begin();
|
||||||
void** sp = (void**)state.sp;
|
void** sp = (void**)state.sp;
|
||||||
#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
|
#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
|
||||||
if (offsetInCodeRange < PushedRetAddr) {
|
if (offsetInCodeRange < PushedRetAddr || codeRange->kind() == CodeRange::CallThunk) {
|
||||||
// First instruction of the ARM/MIPS function; the return address is
|
// First instruction of the ARM/MIPS function; the return address is
|
||||||
// still in lr and fp still holds the caller's fp.
|
// still in lr and fp still holds the caller's fp.
|
||||||
callerPC_ = state.lr;
|
callerPC_ = state.lr;
|
||||||
@ -571,7 +574,9 @@ ProfilingFrameIterator::ProfilingFrameIterator(const WasmActivation& activation,
|
|||||||
AssertMatchesCallSite(*module_, callerPC_, callerFP_, sp);
|
AssertMatchesCallSite(*module_, callerPC_, callerFP_, sp);
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
if (offsetInCodeRange < PushedFP || offsetInModule == codeRange->profilingReturn()) {
|
if (offsetInCodeRange < PushedFP || offsetInModule == codeRange->profilingReturn() ||
|
||||||
|
codeRange->kind() == CodeRange::CallThunk)
|
||||||
|
{
|
||||||
// The return address has been pushed on the stack but not fp; fp
|
// The return address has been pushed on the stack but not fp; fp
|
||||||
// still points to the caller's fp.
|
// still points to the caller's fp.
|
||||||
callerPC_ = *sp;
|
callerPC_ = *sp;
|
||||||
@ -655,6 +660,7 @@ ProfilingFrameIterator::operator++()
|
|||||||
case CodeRange::ImportJitExit:
|
case CodeRange::ImportJitExit:
|
||||||
case CodeRange::ImportInterpExit:
|
case CodeRange::ImportInterpExit:
|
||||||
case CodeRange::Inline:
|
case CodeRange::Inline:
|
||||||
|
case CodeRange::CallThunk:
|
||||||
stackAddress_ = callerFP_;
|
stackAddress_ = callerFP_;
|
||||||
callerPC_ = ReturnAddressFromFP(callerFP_);
|
callerPC_ = ReturnAddressFromFP(callerFP_);
|
||||||
AssertMatchesCallSite(*module_, callerPC_, CallerFPFromFP(callerFP_), callerFP_);
|
AssertMatchesCallSite(*module_, callerPC_, CallerFPFromFP(callerFP_), callerFP_);
|
||||||
@ -696,6 +702,7 @@ ProfilingFrameIterator::label() const
|
|||||||
case CodeRange::ImportJitExit: return importJitDescription;
|
case CodeRange::ImportJitExit: return importJitDescription;
|
||||||
case CodeRange::ImportInterpExit: return importInterpDescription;
|
case CodeRange::ImportInterpExit: return importInterpDescription;
|
||||||
case CodeRange::Inline: return "inline stub (in asm.js)";
|
case CodeRange::Inline: return "inline stub (in asm.js)";
|
||||||
|
case CodeRange::CallThunk: return "call thunk (in asm.js)";
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_CRASH("bad code range kind");
|
MOZ_CRASH("bad code range kind");
|
||||||
@ -771,6 +778,14 @@ wasm::EnableProfilingPrologue(const Module& module, const CallSite& callSite, bo
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
wasm::EnableProfilingThunk(const Module& module, const CallThunk& callThunk, bool enabled)
|
||||||
|
{
|
||||||
|
const CodeRange& cr = module.codeRanges()[callThunk.u.codeRangeIndex];
|
||||||
|
uint32_t calleeOffset = enabled ? cr.funcProfilingEntry() : cr.funcNonProfilingEntry();
|
||||||
|
MacroAssembler::repatchThunk(module.code(), callThunk.offset, calleeOffset);
|
||||||
|
}
|
||||||
|
|
||||||
// Replace all the nops in all the epilogues of asm.js functions with jumps
|
// Replace all the nops in all the epilogues of asm.js functions with jumps
|
||||||
// to the profiling epilogues.
|
// to the profiling epilogues.
|
||||||
void
|
void
|
||||||
|
@ -33,6 +33,7 @@ namespace wasm {
|
|||||||
class CallSite;
|
class CallSite;
|
||||||
class CodeRange;
|
class CodeRange;
|
||||||
class Module;
|
class Module;
|
||||||
|
struct CallThunk;
|
||||||
struct FuncOffsets;
|
struct FuncOffsets;
|
||||||
struct ProfilingOffsets;
|
struct ProfilingOffsets;
|
||||||
|
|
||||||
@ -112,6 +113,9 @@ GenerateFunctionEpilogue(jit::MacroAssembler& masm, unsigned framePushed, FuncOf
|
|||||||
void
|
void
|
||||||
EnableProfilingPrologue(const Module& module, const CallSite& callSite, bool enabled);
|
EnableProfilingPrologue(const Module& module, const CallSite& callSite, bool enabled);
|
||||||
|
|
||||||
|
void
|
||||||
|
EnableProfilingThunk(const Module& module, const CallThunk& callThunk, bool enabled);
|
||||||
|
|
||||||
void
|
void
|
||||||
EnableProfilingEpilogue(const Module& module, const CodeRange& codeRange, bool enabled);
|
EnableProfilingEpilogue(const Module& module, const CodeRange& codeRange, bool enabled);
|
||||||
|
|
||||||
|
@ -18,6 +18,8 @@
|
|||||||
|
|
||||||
#include "asmjs/WasmGenerator.h"
|
#include "asmjs/WasmGenerator.h"
|
||||||
|
|
||||||
|
#include "mozilla/EnumeratedRange.h"
|
||||||
|
|
||||||
#include "asmjs/WasmStubs.h"
|
#include "asmjs/WasmStubs.h"
|
||||||
|
|
||||||
#include "jit/MacroAssembler-inl.h"
|
#include "jit/MacroAssembler-inl.h"
|
||||||
@ -26,6 +28,8 @@ using namespace js;
|
|||||||
using namespace js::jit;
|
using namespace js::jit;
|
||||||
using namespace js::wasm;
|
using namespace js::wasm;
|
||||||
|
|
||||||
|
using mozilla::MakeEnumeratedRange;
|
||||||
|
|
||||||
// ****************************************************************************
|
// ****************************************************************************
|
||||||
// ModuleGenerator
|
// ModuleGenerator
|
||||||
|
|
||||||
@ -41,6 +45,8 @@ ModuleGenerator::ModuleGenerator(ExclusiveContext* cx)
|
|||||||
alloc_(&lifo_),
|
alloc_(&lifo_),
|
||||||
masm_(MacroAssembler::AsmJSToken(), alloc_),
|
masm_(MacroAssembler::AsmJSToken(), alloc_),
|
||||||
funcIndexToExport_(cx),
|
funcIndexToExport_(cx),
|
||||||
|
lastPatchedCallsite_(0),
|
||||||
|
startOfUnpatchedBranches_(0),
|
||||||
parallel_(false),
|
parallel_(false),
|
||||||
outstanding_(0),
|
outstanding_(0),
|
||||||
tasks_(cx),
|
tasks_(cx),
|
||||||
@ -173,13 +179,111 @@ ModuleGenerator::finishOutstandingTask()
|
|||||||
return finishTask(task);
|
return finishTask(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const uint32_t BadEntry = UINT32_MAX;
|
static const uint32_t BadCodeRange = UINT32_MAX;
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ModuleGenerator::funcIsDefined(uint32_t funcIndex) const
|
ModuleGenerator::funcIsDefined(uint32_t funcIndex) const
|
||||||
{
|
{
|
||||||
return funcIndex < funcEntryOffsets_.length() &&
|
return funcIndex < funcIndexToCodeRange_.length() &&
|
||||||
funcEntryOffsets_[funcIndex] != BadEntry;
|
funcIndexToCodeRange_[funcIndex] != BadCodeRange;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
ModuleGenerator::funcEntry(uint32_t funcIndex) const
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(funcIsDefined(funcIndex));
|
||||||
|
return module_->codeRanges[funcIndexToCodeRange_[funcIndex]].funcNonProfilingEntry();
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t
|
||||||
|
JumpRange()
|
||||||
|
{
|
||||||
|
return Min(JitOptions.jumpThreshold, JumpImmediateRange);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef HashMap<uint32_t, uint32_t> OffsetMap;
|
||||||
|
|
||||||
|
bool
|
||||||
|
ModuleGenerator::convertOutOfRangeBranchesToThunks()
|
||||||
|
{
|
||||||
|
masm_.haltingAlign(CodeAlignment);
|
||||||
|
|
||||||
|
// Create thunks for callsites that have gone out of range. Use a map to
|
||||||
|
// create one thunk for each callee since there is often high reuse.
|
||||||
|
|
||||||
|
OffsetMap alreadyThunked(cx_);
|
||||||
|
if (!alreadyThunked.init())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (; lastPatchedCallsite_ < masm_.callSites().length(); lastPatchedCallsite_++) {
|
||||||
|
const CallSiteAndTarget& cs = masm_.callSites()[lastPatchedCallsite_];
|
||||||
|
if (!cs.isInternal())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
uint32_t callerOffset = cs.returnAddressOffset();
|
||||||
|
MOZ_RELEASE_ASSERT(callerOffset < INT32_MAX);
|
||||||
|
|
||||||
|
if (funcIsDefined(cs.targetIndex())) {
|
||||||
|
uint32_t calleeOffset = funcEntry(cs.targetIndex());
|
||||||
|
MOZ_RELEASE_ASSERT(calleeOffset < INT32_MAX);
|
||||||
|
|
||||||
|
if (uint32_t(abs(int32_t(calleeOffset) - int32_t(callerOffset))) < JumpRange()) {
|
||||||
|
masm_.patchCall(callerOffset, calleeOffset);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OffsetMap::AddPtr p = alreadyThunked.lookupForAdd(cs.targetIndex());
|
||||||
|
if (!p) {
|
||||||
|
Offsets offsets;
|
||||||
|
offsets.begin = masm_.currentOffset();
|
||||||
|
uint32_t thunkOffset = masm_.thunkWithPatch().offset();
|
||||||
|
if (masm_.oom())
|
||||||
|
return false;
|
||||||
|
offsets.end = masm_.currentOffset();
|
||||||
|
|
||||||
|
if (!module_->codeRanges.emplaceBack(CodeRange::CallThunk, offsets))
|
||||||
|
return false;
|
||||||
|
if (!module_->callThunks.emplaceBack(thunkOffset, cs.targetIndex()))
|
||||||
|
return false;
|
||||||
|
if (!alreadyThunked.add(p, cs.targetIndex(), offsets.begin))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
masm_.patchCall(callerOffset, p->value());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create thunks for jumps to stubs. Stubs are always generated at the end
|
||||||
|
// so unconditionally thunk all existing jump sites.
|
||||||
|
|
||||||
|
for (JumpTarget target : MakeEnumeratedRange(JumpTarget::Limit)) {
|
||||||
|
if (masm_.jumpSites()[target].empty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (uint32_t jumpSite : masm_.jumpSites()[target]) {
|
||||||
|
RepatchLabel label;
|
||||||
|
label.use(jumpSite);
|
||||||
|
masm_.bind(&label);
|
||||||
|
}
|
||||||
|
|
||||||
|
Offsets offsets;
|
||||||
|
offsets.begin = masm_.currentOffset();
|
||||||
|
uint32_t thunkOffset = masm_.thunkWithPatch().offset();
|
||||||
|
if (masm_.oom())
|
||||||
|
return false;
|
||||||
|
offsets.end = masm_.currentOffset();
|
||||||
|
|
||||||
|
if (!module_->codeRanges.emplaceBack(CodeRange::Inline, offsets))
|
||||||
|
return false;
|
||||||
|
if (!jumpThunks_[target].append(thunkOffset))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unlike callsites, which need to be persisted in the Module, we can simply
|
||||||
|
// flush jump sites after each patching pass.
|
||||||
|
masm_.clearJumpSites();
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -188,19 +292,33 @@ ModuleGenerator::finishTask(IonCompileTask* task)
|
|||||||
const FuncBytecode& func = task->func();
|
const FuncBytecode& func = task->func();
|
||||||
FuncCompileResults& results = task->results();
|
FuncCompileResults& results = task->results();
|
||||||
|
|
||||||
|
// Before merging in the new function's code, if jumps/calls in a previous
|
||||||
|
// function's body might go out of range, patch these to thunks which have
|
||||||
|
// full range.
|
||||||
|
if ((masm_.size() - startOfUnpatchedBranches_) + results.masm().size() > JumpRange()) {
|
||||||
|
startOfUnpatchedBranches_ = masm_.size();
|
||||||
|
if (!convertOutOfRangeBranchesToThunks())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Offset the recorded FuncOffsets by the offset of the function in the
|
// Offset the recorded FuncOffsets by the offset of the function in the
|
||||||
// whole module's code segment.
|
// whole module's code segment.
|
||||||
uint32_t offsetInWhole = masm_.size();
|
uint32_t offsetInWhole = masm_.size();
|
||||||
results.offsets().offsetBy(offsetInWhole);
|
results.offsets().offsetBy(offsetInWhole);
|
||||||
|
|
||||||
// Record the non-profiling entry for whole-module linking later.
|
// Add the CodeRange for this function.
|
||||||
// Cannot simply append because funcIndex order is nonlinear.
|
uint32_t funcCodeRangeIndex = module_->codeRanges.length();
|
||||||
if (func.index() >= funcEntryOffsets_.length()) {
|
if (!module_->codeRanges.emplaceBack(func.index(), func.lineOrBytecode(), results.offsets()))
|
||||||
if (!funcEntryOffsets_.appendN(BadEntry, func.index() - funcEntryOffsets_.length() + 1))
|
return false;
|
||||||
|
|
||||||
|
// Maintain a mapping from function index to CodeRange index.
|
||||||
|
if (func.index() >= funcIndexToCodeRange_.length()) {
|
||||||
|
uint32_t n = func.index() - funcIndexToCodeRange_.length() + 1;
|
||||||
|
if (!funcIndexToCodeRange_.appendN(BadCodeRange, n))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
MOZ_ASSERT(!funcIsDefined(func.index()));
|
MOZ_ASSERT(!funcIsDefined(func.index()));
|
||||||
funcEntryOffsets_[func.index()] = results.offsets().nonProfilingEntry;
|
funcIndexToCodeRange_[func.index()] = funcCodeRangeIndex;
|
||||||
|
|
||||||
// Merge the compiled results into the whole-module masm.
|
// Merge the compiled results into the whole-module masm.
|
||||||
DebugOnly<size_t> sizeBefore = masm_.size();
|
DebugOnly<size_t> sizeBefore = masm_.size();
|
||||||
@ -208,10 +326,6 @@ ModuleGenerator::finishTask(IonCompileTask* task)
|
|||||||
return false;
|
return false;
|
||||||
MOZ_ASSERT(masm_.size() == offsetInWhole + results.masm().size());
|
MOZ_ASSERT(masm_.size() == offsetInWhole + results.masm().size());
|
||||||
|
|
||||||
// Add the CodeRange for this function.
|
|
||||||
if (!module_->codeRanges.emplaceBack(func.index(), func.lineOrBytecode(), results.offsets()))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Keep a record of slow functions for printing in the final console message.
|
// Keep a record of slow functions for printing in the final console message.
|
||||||
unsigned totalTime = func.generateTime() + results.compileTime();
|
unsigned totalTime = func.generateTime() + results.compileTime();
|
||||||
if (totalTime >= SlowFunction::msThreshold) {
|
if (totalTime >= SlowFunction::msThreshold) {
|
||||||
@ -223,6 +337,113 @@ ModuleGenerator::finishTask(IonCompileTask* task)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ModuleGenerator::finishCodegen()
|
||||||
|
{
|
||||||
|
uint32_t offsetInWhole = masm_.size();
|
||||||
|
|
||||||
|
// Generate stubs in a separate MacroAssembler since, otherwise, for modules
|
||||||
|
// larger than the JumpImmediateRange, even local uses of Label will fail
|
||||||
|
// due to the large absolute offsets temporarily stored by Label::bind().
|
||||||
|
|
||||||
|
Vector<Offsets> entries(cx_);
|
||||||
|
Vector<ProfilingOffsets> interpExits(cx_);
|
||||||
|
Vector<ProfilingOffsets> jitExits(cx_);
|
||||||
|
EnumeratedArray<JumpTarget, JumpTarget::Limit, Offsets> jumpTargets;
|
||||||
|
Offsets interruptExit;
|
||||||
|
|
||||||
|
{
|
||||||
|
TempAllocator alloc(&lifo_);
|
||||||
|
MacroAssembler masm(MacroAssembler::AsmJSToken(), alloc);
|
||||||
|
|
||||||
|
if (!entries.resize(numExports()))
|
||||||
|
return false;
|
||||||
|
for (uint32_t i = 0; i < numExports(); i++) {
|
||||||
|
uint32_t target = exportMap_->exportFuncIndices[i];
|
||||||
|
const Sig& sig = module_->exports[i].sig();
|
||||||
|
entries[i] = GenerateEntry(masm, target, sig, usesHeap());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!interpExits.resize(numImports()))
|
||||||
|
return false;
|
||||||
|
if (!jitExits.resize(numImports()))
|
||||||
|
return false;
|
||||||
|
for (uint32_t i = 0; i < numImports(); i++) {
|
||||||
|
interpExits[i] = GenerateInterpExit(masm, module_->imports[i], i);
|
||||||
|
jitExits[i] = GenerateJitExit(masm, module_->imports[i], usesHeap());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (JumpTarget target : MakeEnumeratedRange(JumpTarget::Limit))
|
||||||
|
jumpTargets[target] = GenerateJumpTarget(masm, target);
|
||||||
|
|
||||||
|
interruptExit = GenerateInterruptStub(masm);
|
||||||
|
|
||||||
|
if (masm.oom() || !masm_.asmMergeWith(masm))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adjust each of the resulting Offsets (to account for being merged into
|
||||||
|
// masm_) and then create code ranges for all the stubs.
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < numExports(); i++) {
|
||||||
|
entries[i].offsetBy(offsetInWhole);
|
||||||
|
module_->exports[i].initStubOffset(entries[i].begin);
|
||||||
|
if (!module_->codeRanges.emplaceBack(CodeRange::Entry, entries[i]))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < numImports(); i++) {
|
||||||
|
interpExits[i].offsetBy(offsetInWhole);
|
||||||
|
module_->imports[i].initInterpExitOffset(interpExits[i].begin);
|
||||||
|
if (!module_->codeRanges.emplaceBack(CodeRange::ImportInterpExit, interpExits[i]))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
jitExits[i].offsetBy(offsetInWhole);
|
||||||
|
module_->imports[i].initJitExitOffset(jitExits[i].begin);
|
||||||
|
if (!module_->codeRanges.emplaceBack(CodeRange::ImportJitExit, jitExits[i]))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (JumpTarget target : MakeEnumeratedRange(JumpTarget::Limit)) {
|
||||||
|
jumpTargets[target].offsetBy(offsetInWhole);
|
||||||
|
if (!module_->codeRanges.emplaceBack(CodeRange::Inline, jumpTargets[target]))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
interruptExit.offsetBy(offsetInWhole);
|
||||||
|
if (!module_->codeRanges.emplaceBack(CodeRange::Inline, interruptExit))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// The signal handler redirects PC to the out-of-bounds and interrupt stubs.
|
||||||
|
|
||||||
|
link_->pod.outOfBoundsOffset = jumpTargets[JumpTarget::OutOfBounds].begin;
|
||||||
|
link_->pod.interruptOffset = interruptExit.begin;
|
||||||
|
|
||||||
|
// Only call convertOutOfRangeBranchesToThunks after all other codegen that may
|
||||||
|
// emit new jumps to JumpTargets has finished.
|
||||||
|
|
||||||
|
if (!convertOutOfRangeBranchesToThunks())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Now that all thunks have been generated, patch all the thunks.
|
||||||
|
|
||||||
|
for (CallThunk& callThunk : module_->callThunks) {
|
||||||
|
uint32_t funcIndex = callThunk.u.funcIndex;
|
||||||
|
callThunk.u.codeRangeIndex = funcIndexToCodeRange_[funcIndex];
|
||||||
|
masm_.patchThunk(callThunk.offset, funcEntry(funcIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (JumpTarget target : MakeEnumeratedRange(JumpTarget::Limit)) {
|
||||||
|
for (uint32_t thunkOffset : jumpThunks_[target])
|
||||||
|
masm_.patchThunk(thunkOffset, jumpTargets[target].begin);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Code-generation is complete!
|
||||||
|
|
||||||
|
masm_.finish();
|
||||||
|
return !masm_.oom();
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ModuleGenerator::addImport(const Sig& sig, uint32_t globalDataOffset)
|
ModuleGenerator::addImport(const Sig& sig, uint32_t globalDataOffset)
|
||||||
{
|
{
|
||||||
@ -335,11 +556,12 @@ ModuleGenerator::funcSig(uint32_t funcIndex) const
|
|||||||
bool
|
bool
|
||||||
ModuleGenerator::initImport(uint32_t importIndex, uint32_t sigIndex)
|
ModuleGenerator::initImport(uint32_t importIndex, uint32_t sigIndex)
|
||||||
{
|
{
|
||||||
|
MOZ_ASSERT(isAsmJS());
|
||||||
|
|
||||||
uint32_t globalDataOffset;
|
uint32_t globalDataOffset;
|
||||||
if (!allocateGlobalBytes(Module::SizeOfImportExit, sizeof(void*), &globalDataOffset))
|
if (!allocateGlobalBytes(Module::SizeOfImportExit, sizeof(void*), &globalDataOffset))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
MOZ_ASSERT(isAsmJS());
|
|
||||||
MOZ_ASSERT(importIndex == module_->imports.length());
|
MOZ_ASSERT(importIndex == module_->imports.length());
|
||||||
if (!addImport(sig(sigIndex), globalDataOffset))
|
if (!addImport(sig(sigIndex), globalDataOffset))
|
||||||
return false;
|
return false;
|
||||||
@ -364,16 +586,6 @@ ModuleGenerator::import(uint32_t index) const
|
|||||||
return shared_->imports[index];
|
return shared_->imports[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
ModuleGenerator::defineImport(uint32_t index, ProfilingOffsets interpExit, ProfilingOffsets jitExit)
|
|
||||||
{
|
|
||||||
Import& import = module_->imports[index];
|
|
||||||
import.initInterpExitOffset(interpExit.begin);
|
|
||||||
import.initJitExitOffset(jitExit.begin);
|
|
||||||
return module_->codeRanges.emplaceBack(CodeRange::ImportInterpExit, interpExit) &&
|
|
||||||
module_->codeRanges.emplaceBack(CodeRange::ImportJitExit, jitExit);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ModuleGenerator::declareExport(UniqueChars fieldName, uint32_t funcIndex, uint32_t* exportIndex)
|
ModuleGenerator::declareExport(UniqueChars fieldName, uint32_t funcIndex, uint32_t* exportIndex)
|
||||||
{
|
{
|
||||||
@ -403,39 +615,12 @@ ModuleGenerator::declareExport(UniqueChars fieldName, uint32_t funcIndex, uint32
|
|||||||
exportMap_->exportFuncIndices.append(funcIndex);
|
exportMap_->exportFuncIndices.append(funcIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t
|
|
||||||
ModuleGenerator::exportFuncIndex(uint32_t index) const
|
|
||||||
{
|
|
||||||
return exportMap_->exportFuncIndices[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t
|
|
||||||
ModuleGenerator::exportEntryOffset(uint32_t index) const
|
|
||||||
{
|
|
||||||
uint32_t funcIndex = exportMap_->exportFuncIndices[index];
|
|
||||||
MOZ_ASSERT(funcIsDefined(funcIndex));
|
|
||||||
return funcEntryOffsets_[funcIndex];
|
|
||||||
}
|
|
||||||
|
|
||||||
const Sig&
|
|
||||||
ModuleGenerator::exportSig(uint32_t index) const
|
|
||||||
{
|
|
||||||
return module_->exports[index].sig();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
ModuleGenerator::numExports() const
|
ModuleGenerator::numExports() const
|
||||||
{
|
{
|
||||||
return module_->exports.length();
|
return module_->exports.length();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
ModuleGenerator::defineExport(uint32_t index, Offsets offsets)
|
|
||||||
{
|
|
||||||
module_->exports[index].initStubOffset(offsets.begin);
|
|
||||||
return module_->codeRanges.emplaceBack(CodeRange::Entry, offsets);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ModuleGenerator::addMemoryExport(UniqueChars fieldName)
|
ModuleGenerator::addMemoryExport(UniqueChars fieldName)
|
||||||
{
|
{
|
||||||
@ -561,24 +746,9 @@ ModuleGenerator::finishFuncDefs()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint32_t funcIndex = 0; funcIndex < funcEntryOffsets_.length(); funcIndex++)
|
for (uint32_t funcIndex = 0; funcIndex < funcIndexToCodeRange_.length(); funcIndex++)
|
||||||
MOZ_ASSERT(funcIsDefined(funcIndex));
|
MOZ_ASSERT(funcIsDefined(funcIndex));
|
||||||
|
|
||||||
// During codegen, all wasm->wasm (internal) calls use AsmJSInternalCallee
|
|
||||||
// as the call target, which contains the function-index of the target.
|
|
||||||
// These get recorded in a CallSiteAndTargetVector in the MacroAssembler
|
|
||||||
// so that we can patch them now that all the function entry offsets are
|
|
||||||
// known.
|
|
||||||
|
|
||||||
for (CallSiteAndTarget& cs : masm_.callSites()) {
|
|
||||||
if (!cs.isInternal())
|
|
||||||
continue;
|
|
||||||
MOZ_ASSERT(cs.kind() == CallSiteDesc::Relative);
|
|
||||||
uint32_t callerOffset = cs.returnAddressOffset();
|
|
||||||
uint32_t calleeOffset = funcEntryOffsets_[cs.targetIndex()];
|
|
||||||
masm_.patchCall(callerOffset, calleeOffset);
|
|
||||||
}
|
|
||||||
|
|
||||||
module_->functionBytes = masm_.size();
|
module_->functionBytes = masm_.size();
|
||||||
finishedFuncs_ = true;
|
finishedFuncs_ = true;
|
||||||
return true;
|
return true;
|
||||||
@ -628,31 +798,10 @@ ModuleGenerator::defineFuncPtrTable(uint32_t index, const Vector<uint32_t>& elem
|
|||||||
for (size_t i = 0; i < elemFuncIndices.length(); i++) {
|
for (size_t i = 0; i < elemFuncIndices.length(); i++) {
|
||||||
uint32_t funcIndex = elemFuncIndices[i];
|
uint32_t funcIndex = elemFuncIndices[i];
|
||||||
MOZ_ASSERT(funcIsDefined(funcIndex));
|
MOZ_ASSERT(funcIsDefined(funcIndex));
|
||||||
table.elemOffsets[i] = funcEntryOffsets_[funcIndex];
|
table.elemOffsets[i] = funcEntry(funcIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
ModuleGenerator::defineInlineStub(Offsets offsets)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(finishedFuncs_);
|
|
||||||
return module_->codeRanges.emplaceBack(CodeRange::Inline, offsets);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ModuleGenerator::defineInterruptExit(uint32_t offset)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(finishedFuncs_);
|
|
||||||
link_->pod.interruptOffset = offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ModuleGenerator::defineOutOfBoundsExit(uint32_t offset)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(finishedFuncs_);
|
|
||||||
link_->pod.outOfBoundsOffset = offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ModuleGenerator::finish(CacheableCharsVector&& prettyFuncNames,
|
ModuleGenerator::finish(CacheableCharsVector&& prettyFuncNames,
|
||||||
UniqueModuleData* module,
|
UniqueModuleData* module,
|
||||||
@ -663,15 +812,11 @@ ModuleGenerator::finish(CacheableCharsVector&& prettyFuncNames,
|
|||||||
MOZ_ASSERT(!activeFunc_);
|
MOZ_ASSERT(!activeFunc_);
|
||||||
MOZ_ASSERT(finishedFuncs_);
|
MOZ_ASSERT(finishedFuncs_);
|
||||||
|
|
||||||
|
if (!finishCodegen())
|
||||||
|
return false;
|
||||||
|
|
||||||
module_->prettyFuncNames = Move(prettyFuncNames);
|
module_->prettyFuncNames = Move(prettyFuncNames);
|
||||||
|
|
||||||
if (!GenerateStubs(*this))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
masm_.finish();
|
|
||||||
if (masm_.oom())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Start global data on a new page so JIT code may be given independent
|
// Start global data on a new page so JIT code may be given independent
|
||||||
// protection flags. Note assumption that global data starts right after
|
// protection flags. Note assumption that global data starts right after
|
||||||
// code below.
|
// code below.
|
||||||
|
@ -142,8 +142,11 @@ class MOZ_STACK_CLASS ModuleGenerator
|
|||||||
LifoAlloc lifo_;
|
LifoAlloc lifo_;
|
||||||
jit::TempAllocator alloc_;
|
jit::TempAllocator alloc_;
|
||||||
jit::MacroAssembler masm_;
|
jit::MacroAssembler masm_;
|
||||||
Uint32Vector funcEntryOffsets_;
|
Uint32Vector funcIndexToCodeRange_;
|
||||||
FuncIndexMap funcIndexToExport_;
|
FuncIndexMap funcIndexToExport_;
|
||||||
|
uint32_t lastPatchedCallsite_;
|
||||||
|
uint32_t startOfUnpatchedBranches_;
|
||||||
|
JumpSiteArray jumpThunks_;
|
||||||
|
|
||||||
// Parallel compilation
|
// Parallel compilation
|
||||||
bool parallel_;
|
bool parallel_;
|
||||||
@ -158,7 +161,10 @@ class MOZ_STACK_CLASS ModuleGenerator
|
|||||||
|
|
||||||
bool finishOutstandingTask();
|
bool finishOutstandingTask();
|
||||||
bool funcIsDefined(uint32_t funcIndex) const;
|
bool funcIsDefined(uint32_t funcIndex) const;
|
||||||
|
uint32_t funcEntry(uint32_t funcIndex) const;
|
||||||
|
bool convertOutOfRangeBranchesToThunks();
|
||||||
bool finishTask(IonCompileTask* task);
|
bool finishTask(IonCompileTask* task);
|
||||||
|
bool finishCodegen();
|
||||||
bool addImport(const Sig& sig, uint32_t globalDataOffset);
|
bool addImport(const Sig& sig, uint32_t globalDataOffset);
|
||||||
bool startedFuncDefs() const { return !!threadView_; }
|
bool startedFuncDefs() const { return !!threadView_; }
|
||||||
bool allocateGlobalBytes(uint32_t bytes, uint32_t align, uint32_t* globalDataOffset);
|
bool allocateGlobalBytes(uint32_t bytes, uint32_t align, uint32_t* globalDataOffset);
|
||||||
@ -195,15 +201,10 @@ class MOZ_STACK_CLASS ModuleGenerator
|
|||||||
bool initImport(uint32_t importIndex, uint32_t sigIndex);
|
bool initImport(uint32_t importIndex, uint32_t sigIndex);
|
||||||
uint32_t numImports() const;
|
uint32_t numImports() const;
|
||||||
const ModuleImportGeneratorData& import(uint32_t index) const;
|
const ModuleImportGeneratorData& import(uint32_t index) const;
|
||||||
bool defineImport(uint32_t index, ProfilingOffsets interpExit, ProfilingOffsets jitExit);
|
|
||||||
|
|
||||||
// Exports:
|
// Exports:
|
||||||
bool declareExport(UniqueChars fieldName, uint32_t funcIndex, uint32_t* exportIndex = nullptr);
|
bool declareExport(UniqueChars fieldName, uint32_t funcIndex, uint32_t* exportIndex = nullptr);
|
||||||
uint32_t numExports() const;
|
uint32_t numExports() const;
|
||||||
uint32_t exportFuncIndex(uint32_t index) const;
|
|
||||||
uint32_t exportEntryOffset(uint32_t index) const;
|
|
||||||
const Sig& exportSig(uint32_t index) const;
|
|
||||||
bool defineExport(uint32_t index, Offsets offsets);
|
|
||||||
bool addMemoryExport(UniqueChars fieldName);
|
bool addMemoryExport(UniqueChars fieldName);
|
||||||
|
|
||||||
// Function definitions:
|
// Function definitions:
|
||||||
@ -217,11 +218,6 @@ class MOZ_STACK_CLASS ModuleGenerator
|
|||||||
uint32_t funcPtrTableGlobalDataOffset(uint32_t index) const;
|
uint32_t funcPtrTableGlobalDataOffset(uint32_t index) const;
|
||||||
void defineFuncPtrTable(uint32_t index, const Vector<uint32_t>& elemFuncIndices);
|
void defineFuncPtrTable(uint32_t index, const Vector<uint32_t>& elemFuncIndices);
|
||||||
|
|
||||||
// Stubs:
|
|
||||||
bool defineInlineStub(Offsets offsets);
|
|
||||||
void defineInterruptExit(uint32_t offset);
|
|
||||||
void defineOutOfBoundsExit(uint32_t offset);
|
|
||||||
|
|
||||||
// Return a ModuleData object which may be used to construct a Module, the
|
// Return a ModuleData object which may be used to construct a Module, the
|
||||||
// StaticLinkData required to call Module::staticallyLink, and the list of
|
// StaticLinkData required to call Module::staticallyLink, and the list of
|
||||||
// functions that took a long time to compile.
|
// functions that took a long time to compile.
|
||||||
|
@ -360,7 +360,7 @@ CodeRange::CodeRange(Kind kind, Offsets offsets)
|
|||||||
u.kind_ = kind;
|
u.kind_ = kind;
|
||||||
|
|
||||||
MOZ_ASSERT(begin_ <= end_);
|
MOZ_ASSERT(begin_ <= end_);
|
||||||
MOZ_ASSERT(u.kind_ == Entry || u.kind_ == Inline);
|
MOZ_ASSERT(u.kind_ == Entry || u.kind_ == Inline || u.kind_ == CallThunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
CodeRange::CodeRange(Kind kind, ProfilingOffsets offsets)
|
CodeRange::CodeRange(Kind kind, ProfilingOffsets offsets)
|
||||||
@ -508,6 +508,7 @@ ModuleData::serializedSize() const
|
|||||||
SerializedPodVectorSize(heapAccesses) +
|
SerializedPodVectorSize(heapAccesses) +
|
||||||
SerializedPodVectorSize(codeRanges) +
|
SerializedPodVectorSize(codeRanges) +
|
||||||
SerializedPodVectorSize(callSites) +
|
SerializedPodVectorSize(callSites) +
|
||||||
|
SerializedPodVectorSize(callThunks) +
|
||||||
SerializedVectorSize(prettyFuncNames) +
|
SerializedVectorSize(prettyFuncNames) +
|
||||||
filename.serializedSize();
|
filename.serializedSize();
|
||||||
}
|
}
|
||||||
@ -522,6 +523,7 @@ ModuleData::serialize(uint8_t* cursor) const
|
|||||||
cursor = SerializePodVector(cursor, heapAccesses);
|
cursor = SerializePodVector(cursor, heapAccesses);
|
||||||
cursor = SerializePodVector(cursor, codeRanges);
|
cursor = SerializePodVector(cursor, codeRanges);
|
||||||
cursor = SerializePodVector(cursor, callSites);
|
cursor = SerializePodVector(cursor, callSites);
|
||||||
|
cursor = SerializePodVector(cursor, callThunks);
|
||||||
cursor = SerializeVector(cursor, prettyFuncNames);
|
cursor = SerializeVector(cursor, prettyFuncNames);
|
||||||
cursor = filename.serialize(cursor);
|
cursor = filename.serialize(cursor);
|
||||||
return cursor;
|
return cursor;
|
||||||
@ -542,6 +544,7 @@ ModuleData::deserialize(ExclusiveContext* cx, const uint8_t* cursor)
|
|||||||
(cursor = DeserializePodVector(cx, cursor, &heapAccesses)) &&
|
(cursor = DeserializePodVector(cx, cursor, &heapAccesses)) &&
|
||||||
(cursor = DeserializePodVector(cx, cursor, &codeRanges)) &&
|
(cursor = DeserializePodVector(cx, cursor, &codeRanges)) &&
|
||||||
(cursor = DeserializePodVector(cx, cursor, &callSites)) &&
|
(cursor = DeserializePodVector(cx, cursor, &callSites)) &&
|
||||||
|
(cursor = DeserializePodVector(cx, cursor, &callThunks)) &&
|
||||||
(cursor = DeserializeVector(cx, cursor, &prettyFuncNames)) &&
|
(cursor = DeserializeVector(cx, cursor, &prettyFuncNames)) &&
|
||||||
(cursor = filename.deserialize(cx, cursor));
|
(cursor = filename.deserialize(cx, cursor));
|
||||||
return cursor;
|
return cursor;
|
||||||
@ -562,6 +565,7 @@ ModuleData::clone(JSContext* cx, ModuleData* out) const
|
|||||||
ClonePodVector(cx, heapAccesses, &out->heapAccesses) &&
|
ClonePodVector(cx, heapAccesses, &out->heapAccesses) &&
|
||||||
ClonePodVector(cx, codeRanges, &out->codeRanges) &&
|
ClonePodVector(cx, codeRanges, &out->codeRanges) &&
|
||||||
ClonePodVector(cx, callSites, &out->callSites) &&
|
ClonePodVector(cx, callSites, &out->callSites) &&
|
||||||
|
ClonePodVector(cx, callThunks, &out->callThunks) &&
|
||||||
CloneVector(cx, prettyFuncNames, &out->prettyFuncNames) &&
|
CloneVector(cx, prettyFuncNames, &out->prettyFuncNames) &&
|
||||||
filename.clone(cx, &out->filename);
|
filename.clone(cx, &out->filename);
|
||||||
}
|
}
|
||||||
@ -575,6 +579,7 @@ ModuleData::sizeOfExcludingThis(MallocSizeOf mallocSizeOf) const
|
|||||||
heapAccesses.sizeOfExcludingThis(mallocSizeOf) +
|
heapAccesses.sizeOfExcludingThis(mallocSizeOf) +
|
||||||
codeRanges.sizeOfExcludingThis(mallocSizeOf) +
|
codeRanges.sizeOfExcludingThis(mallocSizeOf) +
|
||||||
callSites.sizeOfExcludingThis(mallocSizeOf) +
|
callSites.sizeOfExcludingThis(mallocSizeOf) +
|
||||||
|
callThunks.sizeOfExcludingThis(mallocSizeOf) +
|
||||||
prettyFuncNames.sizeOfExcludingThis(mallocSizeOf) +
|
prettyFuncNames.sizeOfExcludingThis(mallocSizeOf) +
|
||||||
filename.sizeOfExcludingThis(mallocSizeOf);
|
filename.sizeOfExcludingThis(mallocSizeOf);
|
||||||
}
|
}
|
||||||
@ -792,6 +797,9 @@ Module::setProfilingEnabled(JSContext* cx, bool enabled)
|
|||||||
for (const CallSite& callSite : module_->callSites)
|
for (const CallSite& callSite : module_->callSites)
|
||||||
EnableProfilingPrologue(*this, callSite, enabled);
|
EnableProfilingPrologue(*this, callSite, enabled);
|
||||||
|
|
||||||
|
for (const CallThunk& callThunk : module_->callThunks)
|
||||||
|
EnableProfilingThunk(*this, callThunk, enabled);
|
||||||
|
|
||||||
for (const CodeRange& codeRange : module_->codeRanges)
|
for (const CodeRange& codeRange : module_->codeRanges)
|
||||||
EnableProfilingEpilogue(*this, codeRange, enabled);
|
EnableProfilingEpilogue(*this, codeRange, enabled);
|
||||||
}
|
}
|
||||||
|
@ -67,9 +67,7 @@ struct StaticLinkData
|
|||||||
typedef Vector<InternalLink, 0, SystemAllocPolicy> InternalLinkVector;
|
typedef Vector<InternalLink, 0, SystemAllocPolicy> InternalLinkVector;
|
||||||
|
|
||||||
typedef Vector<uint32_t, 0, SystemAllocPolicy> OffsetVector;
|
typedef Vector<uint32_t, 0, SystemAllocPolicy> OffsetVector;
|
||||||
struct SymbolicLinkArray : mozilla::EnumeratedArray<SymbolicAddress,
|
struct SymbolicLinkArray : EnumeratedArray<SymbolicAddress, SymbolicAddress::Limit, OffsetVector> {
|
||||||
SymbolicAddress::Limit,
|
|
||||||
OffsetVector> {
|
|
||||||
WASM_DECLARE_SERIALIZABLE(SymbolicLinkArray)
|
WASM_DECLARE_SERIALIZABLE(SymbolicLinkArray)
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -213,7 +211,7 @@ class CodeRange
|
|||||||
void assertValid();
|
void assertValid();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum Kind { Function, Entry, ImportJitExit, ImportInterpExit, Inline };
|
enum Kind { Function, Entry, ImportJitExit, ImportInterpExit, Inline, CallThunk };
|
||||||
|
|
||||||
CodeRange() = default;
|
CodeRange() = default;
|
||||||
CodeRange(Kind kind, Offsets offsets);
|
CodeRange(Kind kind, Offsets offsets);
|
||||||
@ -237,7 +235,7 @@ class CodeRange
|
|||||||
// which is used for asynchronous profiling to determine the frame pointer.
|
// which is used for asynchronous profiling to determine the frame pointer.
|
||||||
|
|
||||||
uint32_t profilingReturn() const {
|
uint32_t profilingReturn() const {
|
||||||
MOZ_ASSERT(kind() != Entry && kind() != Inline);
|
MOZ_ASSERT(isFunction() || isImportExit());
|
||||||
return profilingReturn_;
|
return profilingReturn_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -247,6 +245,9 @@ class CodeRange
|
|||||||
bool isFunction() const {
|
bool isFunction() const {
|
||||||
return kind() == Function;
|
return kind() == Function;
|
||||||
}
|
}
|
||||||
|
bool isImportExit() const {
|
||||||
|
return kind() == ImportJitExit || kind() == ImportInterpExit;
|
||||||
|
}
|
||||||
uint32_t funcProfilingEntry() const {
|
uint32_t funcProfilingEntry() const {
|
||||||
MOZ_ASSERT(isFunction());
|
MOZ_ASSERT(isFunction());
|
||||||
return begin();
|
return begin();
|
||||||
@ -288,6 +289,25 @@ class CodeRange
|
|||||||
|
|
||||||
typedef Vector<CodeRange, 0, SystemAllocPolicy> CodeRangeVector;
|
typedef Vector<CodeRange, 0, SystemAllocPolicy> CodeRangeVector;
|
||||||
|
|
||||||
|
// A CallThunk describes the offset and target of thunks so that they may be
|
||||||
|
// patched at runtime when profiling is toggled. Thunks are emitted to connect
|
||||||
|
// callsites that are too far away from callees to fit in a single call
|
||||||
|
// instruction's relative offset.
|
||||||
|
|
||||||
|
struct CallThunk
|
||||||
|
{
|
||||||
|
uint32_t offset;
|
||||||
|
union {
|
||||||
|
uint32_t funcIndex;
|
||||||
|
uint32_t codeRangeIndex;
|
||||||
|
} u;
|
||||||
|
|
||||||
|
CallThunk(uint32_t offset, uint32_t funcIndex) : offset(offset) { u.funcIndex = funcIndex; }
|
||||||
|
CallThunk() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef Vector<CallThunk, 0, SystemAllocPolicy> CallThunkVector;
|
||||||
|
|
||||||
// CacheableChars is used to cacheably store UniqueChars.
|
// CacheableChars is used to cacheably store UniqueChars.
|
||||||
|
|
||||||
struct CacheableChars : UniqueChars
|
struct CacheableChars : UniqueChars
|
||||||
@ -389,6 +409,7 @@ struct ModuleData : ModuleCacheablePod
|
|||||||
HeapAccessVector heapAccesses;
|
HeapAccessVector heapAccesses;
|
||||||
CodeRangeVector codeRanges;
|
CodeRangeVector codeRanges;
|
||||||
CallSiteVector callSites;
|
CallSiteVector callSites;
|
||||||
|
CallThunkVector callThunks;
|
||||||
CacheableCharsVector prettyFuncNames;
|
CacheableCharsVector prettyFuncNames;
|
||||||
CacheableChars filename;
|
CacheableChars filename;
|
||||||
bool loadedFromCache;
|
bool loadedFromCache;
|
||||||
@ -496,6 +517,7 @@ class Module
|
|||||||
CompileArgs compileArgs() const { return module_->compileArgs; }
|
CompileArgs compileArgs() const { return module_->compileArgs; }
|
||||||
const ImportVector& imports() const { return module_->imports; }
|
const ImportVector& imports() const { return module_->imports; }
|
||||||
const ExportVector& exports() const { return module_->exports; }
|
const ExportVector& exports() const { return module_->exports; }
|
||||||
|
const CodeRangeVector& codeRanges() const { return module_->codeRanges; }
|
||||||
const char* filename() const { return module_->filename.get(); }
|
const char* filename() const { return module_->filename.get(); }
|
||||||
bool loadedFromCache() const { return module_->loadedFromCache; }
|
bool loadedFromCache() const { return module_->loadedFromCache; }
|
||||||
bool staticallyLinked() const { return staticallyLinked_; }
|
bool staticallyLinked() const { return staticallyLinked_; }
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
#include "asmjs/WasmStubs.h"
|
#include "asmjs/WasmStubs.h"
|
||||||
|
|
||||||
#include "mozilla/ArrayUtils.h"
|
#include "mozilla/ArrayUtils.h"
|
||||||
#include "mozilla/EnumeratedRange.h"
|
|
||||||
|
|
||||||
#include "jit/MacroAssembler-inl.h"
|
#include "jit/MacroAssembler-inl.h"
|
||||||
|
|
||||||
@ -28,7 +27,6 @@ using namespace js::jit;
|
|||||||
using namespace js::wasm;
|
using namespace js::wasm;
|
||||||
|
|
||||||
using mozilla::ArrayLength;
|
using mozilla::ArrayLength;
|
||||||
using mozilla::MakeEnumeratedRange;
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
AssertStackAlignment(MacroAssembler& masm, uint32_t alignment, uint32_t addBeforeAssert = 0)
|
AssertStackAlignment(MacroAssembler& masm, uint32_t alignment, uint32_t addBeforeAssert = 0)
|
||||||
@ -94,12 +92,9 @@ static const unsigned FramePushedForEntrySP = FramePushedAfterSave + sizeof(void
|
|||||||
// The signature of the entry point is Module::CodePtr. The exported wasm
|
// The signature of the entry point is Module::CodePtr. The exported wasm
|
||||||
// function has an ABI derived from its specific signature, so this function
|
// function has an ABI derived from its specific signature, so this function
|
||||||
// must map from the ABI of CodePtr to the export's signature's ABI.
|
// must map from the ABI of CodePtr to the export's signature's ABI.
|
||||||
static bool
|
Offsets
|
||||||
GenerateEntry(ModuleGenerator& mg, unsigned exportIndex)
|
wasm::GenerateEntry(MacroAssembler& masm, unsigned target, const Sig& sig, bool usesHeap)
|
||||||
{
|
{
|
||||||
MacroAssembler& masm = mg.masm();
|
|
||||||
const Sig& sig = mg.exportSig(exportIndex);
|
|
||||||
|
|
||||||
masm.haltingAlign(CodeAlignment);
|
masm.haltingAlign(CodeAlignment);
|
||||||
|
|
||||||
Offsets offsets;
|
Offsets offsets;
|
||||||
@ -131,7 +126,7 @@ GenerateEntry(ModuleGenerator& mg, unsigned exportIndex)
|
|||||||
// ARM, MIPS/MIPS64 and x64 have a globally-pinned HeapReg (x86 uses immediates in
|
// ARM, MIPS/MIPS64 and x64 have a globally-pinned HeapReg (x86 uses immediates in
|
||||||
// effective addresses). Loading the heap register depends on the global
|
// effective addresses). Loading the heap register depends on the global
|
||||||
// register already having been loaded.
|
// register already having been loaded.
|
||||||
if (mg.usesHeap())
|
if (usesHeap)
|
||||||
masm.loadAsmJSHeapRegisterFromGlobalData();
|
masm.loadAsmJSHeapRegisterFromGlobalData();
|
||||||
|
|
||||||
// Put the 'argv' argument into a non-argument/return register so that we
|
// Put the 'argv' argument into a non-argument/return register so that we
|
||||||
@ -235,9 +230,7 @@ GenerateEntry(ModuleGenerator& mg, unsigned exportIndex)
|
|||||||
|
|
||||||
// Call into the real function.
|
// Call into the real function.
|
||||||
masm.assertStackAlignment(AsmJSStackAlignment);
|
masm.assertStackAlignment(AsmJSStackAlignment);
|
||||||
Label target;
|
masm.call(CallSiteDesc(CallSiteDesc::Relative), AsmJSInternalCallee(target));
|
||||||
target.bind(mg.exportEntryOffset(exportIndex));
|
|
||||||
masm.call(CallSiteDesc(CallSiteDesc::Relative), &target);
|
|
||||||
|
|
||||||
// Recover the stack pointer value before dynamic alignment.
|
// Recover the stack pointer value before dynamic alignment.
|
||||||
masm.loadWasmActivation(scratch);
|
masm.loadWasmActivation(scratch);
|
||||||
@ -283,11 +276,8 @@ GenerateEntry(ModuleGenerator& mg, unsigned exportIndex)
|
|||||||
masm.move32(Imm32(true), ReturnReg);
|
masm.move32(Imm32(true), ReturnReg);
|
||||||
masm.ret();
|
masm.ret();
|
||||||
|
|
||||||
if (masm.oom())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
offsets.end = masm.currentOffset();
|
offsets.end = masm.currentOffset();
|
||||||
return mg.defineExport(exportIndex, offsets);
|
return offsets;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -333,11 +323,10 @@ FillArgumentArray(MacroAssembler& masm, const ValTypeVector& args, unsigned argO
|
|||||||
// Generate a stub that is called via the internal ABI derived from the
|
// Generate a stub that is called via the internal ABI derived from the
|
||||||
// signature of the import and calls into an appropriate InvokeImport C++
|
// signature of the import and calls into an appropriate InvokeImport C++
|
||||||
// function, having boxed all the ABI arguments into a homogeneous Value array.
|
// function, having boxed all the ABI arguments into a homogeneous Value array.
|
||||||
static bool
|
ProfilingOffsets
|
||||||
GenerateInterpExitStub(ModuleGenerator& mg, unsigned importIndex, ProfilingOffsets* offsets)
|
wasm::GenerateInterpExit(MacroAssembler& masm, const Import& import, uint32_t importIndex)
|
||||||
{
|
{
|
||||||
MacroAssembler& masm = mg.masm();
|
const Sig& sig = import.sig();
|
||||||
const Sig& sig = *mg.import(importIndex).sig;
|
|
||||||
|
|
||||||
masm.setFramePushed(0);
|
masm.setFramePushed(0);
|
||||||
|
|
||||||
@ -356,7 +345,8 @@ GenerateInterpExitStub(ModuleGenerator& mg, unsigned importIndex, ProfilingOffse
|
|||||||
unsigned argBytes = Max<size_t>(1, sig.args().length()) * sizeof(Value);
|
unsigned argBytes = Max<size_t>(1, sig.args().length()) * sizeof(Value);
|
||||||
unsigned framePushed = StackDecrementForCall(masm, ABIStackAlignment, argOffset + argBytes);
|
unsigned framePushed = StackDecrementForCall(masm, ABIStackAlignment, argOffset + argBytes);
|
||||||
|
|
||||||
GenerateExitPrologue(masm, framePushed, ExitReason::ImportInterp, offsets);
|
ProfilingOffsets offsets;
|
||||||
|
GenerateExitPrologue(masm, framePushed, ExitReason::ImportInterp, &offsets);
|
||||||
|
|
||||||
// Fill the argument array.
|
// Fill the argument array.
|
||||||
unsigned offsetToCallerStackArgs = sizeof(AsmJSFrame) + masm.framePushed();
|
unsigned offsetToCallerStackArgs = sizeof(AsmJSFrame) + masm.framePushed();
|
||||||
@ -407,7 +397,6 @@ GenerateInterpExitStub(ModuleGenerator& mg, unsigned importIndex, ProfilingOffse
|
|||||||
case ExprType::I64:
|
case ExprType::I64:
|
||||||
MOZ_CRASH("no int64 in asm.js");
|
MOZ_CRASH("no int64 in asm.js");
|
||||||
case ExprType::F32:
|
case ExprType::F32:
|
||||||
MOZ_ASSERT(!mg.isAsmJS(), "import can't return float32 in asm.js");
|
|
||||||
masm.call(SymbolicAddress::InvokeImport_F64);
|
masm.call(SymbolicAddress::InvokeImport_F64);
|
||||||
masm.branchTest32(Assembler::Zero, ReturnReg, ReturnReg, JumpTarget::Throw);
|
masm.branchTest32(Assembler::Zero, ReturnReg, ReturnReg, JumpTarget::Throw);
|
||||||
masm.loadDouble(argv, ReturnDoubleReg);
|
masm.loadDouble(argv, ReturnDoubleReg);
|
||||||
@ -426,13 +415,10 @@ GenerateInterpExitStub(ModuleGenerator& mg, unsigned importIndex, ProfilingOffse
|
|||||||
MOZ_CRASH("Limit");
|
MOZ_CRASH("Limit");
|
||||||
}
|
}
|
||||||
|
|
||||||
GenerateExitEpilogue(masm, framePushed, ExitReason::ImportInterp, offsets);
|
GenerateExitEpilogue(masm, framePushed, ExitReason::ImportInterp, &offsets);
|
||||||
|
|
||||||
if (masm.oom())
|
offsets.end = masm.currentOffset();
|
||||||
return false;
|
return offsets;
|
||||||
|
|
||||||
offsets->end = masm.currentOffset();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
|
#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
|
||||||
@ -444,11 +430,10 @@ static const unsigned MaybeSavedGlobalReg = 0;
|
|||||||
// Generate a stub that is called via the internal ABI derived from the
|
// Generate a stub that is called via the internal ABI derived from the
|
||||||
// signature of the import and calls into a compatible JIT function,
|
// signature of the import and calls into a compatible JIT function,
|
||||||
// having boxed all the ABI arguments into the JIT stack frame layout.
|
// having boxed all the ABI arguments into the JIT stack frame layout.
|
||||||
static bool
|
ProfilingOffsets
|
||||||
GenerateJitExitStub(ModuleGenerator& mg, unsigned importIndex, ProfilingOffsets* offsets)
|
wasm::GenerateJitExit(MacroAssembler& masm, const Import& import, bool usesHeap)
|
||||||
{
|
{
|
||||||
MacroAssembler& masm = mg.masm();
|
const Sig& sig = import.sig();
|
||||||
const Sig& sig = *mg.import(importIndex).sig;
|
|
||||||
|
|
||||||
masm.setFramePushed(0);
|
masm.setFramePushed(0);
|
||||||
|
|
||||||
@ -465,7 +450,8 @@ GenerateJitExitStub(ModuleGenerator& mg, unsigned importIndex, ProfilingOffsets*
|
|||||||
unsigned jitFramePushed = StackDecrementForCall(masm, JitStackAlignment, totalJitFrameBytes) -
|
unsigned jitFramePushed = StackDecrementForCall(masm, JitStackAlignment, totalJitFrameBytes) -
|
||||||
sizeOfRetAddr;
|
sizeOfRetAddr;
|
||||||
|
|
||||||
GenerateExitPrologue(masm, jitFramePushed, ExitReason::ImportJit, offsets);
|
ProfilingOffsets offsets;
|
||||||
|
GenerateExitPrologue(masm, jitFramePushed, ExitReason::ImportJit, &offsets);
|
||||||
|
|
||||||
// 1. Descriptor
|
// 1. Descriptor
|
||||||
size_t argOffset = 0;
|
size_t argOffset = 0;
|
||||||
@ -479,7 +465,7 @@ GenerateJitExitStub(ModuleGenerator& mg, unsigned importIndex, ProfilingOffsets*
|
|||||||
Register scratch = ABIArgGenerator::NonArgReturnReg1; // repeatedly clobbered
|
Register scratch = ABIArgGenerator::NonArgReturnReg1; // repeatedly clobbered
|
||||||
|
|
||||||
// 2.1. Get ExitDatum
|
// 2.1. Get ExitDatum
|
||||||
unsigned globalDataOffset = mg.import(importIndex).globalDataOffset;
|
uint32_t globalDataOffset = import.exitGlobalDataOffset();
|
||||||
#if defined(JS_CODEGEN_X64)
|
#if defined(JS_CODEGEN_X64)
|
||||||
masm.append(AsmJSGlobalAccess(masm.leaRipRelative(callee), globalDataOffset));
|
masm.append(AsmJSGlobalAccess(masm.leaRipRelative(callee), globalDataOffset));
|
||||||
#elif defined(JS_CODEGEN_X86)
|
#elif defined(JS_CODEGEN_X86)
|
||||||
@ -663,7 +649,6 @@ GenerateJitExitStub(ModuleGenerator& mg, unsigned importIndex, ProfilingOffsets*
|
|||||||
case ExprType::I64:
|
case ExprType::I64:
|
||||||
MOZ_CRASH("no int64 in asm.js");
|
MOZ_CRASH("no int64 in asm.js");
|
||||||
case ExprType::F32:
|
case ExprType::F32:
|
||||||
MOZ_ASSERT(!mg.isAsmJS(), "import can't return float32 in asm.js");
|
|
||||||
masm.convertValueToFloat(JSReturnOperand, ReturnFloat32Reg, &oolConvert);
|
masm.convertValueToFloat(JSReturnOperand, ReturnFloat32Reg, &oolConvert);
|
||||||
break;
|
break;
|
||||||
case ExprType::F64:
|
case ExprType::F64:
|
||||||
@ -682,10 +667,10 @@ GenerateJitExitStub(ModuleGenerator& mg, unsigned importIndex, ProfilingOffsets*
|
|||||||
|
|
||||||
// Ion code does not respect system callee-saved register conventions so
|
// Ion code does not respect system callee-saved register conventions so
|
||||||
// reload the heap register.
|
// reload the heap register.
|
||||||
if (mg.usesHeap())
|
if (usesHeap)
|
||||||
masm.loadAsmJSHeapRegisterFromGlobalData();
|
masm.loadAsmJSHeapRegisterFromGlobalData();
|
||||||
|
|
||||||
GenerateExitEpilogue(masm, masm.framePushed(), ExitReason::ImportJit, offsets);
|
GenerateExitEpilogue(masm, masm.framePushed(), ExitReason::ImportJit, &offsets);
|
||||||
|
|
||||||
if (oolConvert.used()) {
|
if (oolConvert.used()) {
|
||||||
masm.bind(&oolConvert);
|
masm.bind(&oolConvert);
|
||||||
@ -728,7 +713,6 @@ GenerateJitExitStub(ModuleGenerator& mg, unsigned importIndex, ProfilingOffsets*
|
|||||||
masm.loadDouble(Address(masm.getStackPointer(), offsetToCoerceArgv), ReturnDoubleReg);
|
masm.loadDouble(Address(masm.getStackPointer(), offsetToCoerceArgv), ReturnDoubleReg);
|
||||||
break;
|
break;
|
||||||
case ExprType::F32:
|
case ExprType::F32:
|
||||||
MOZ_ASSERT(!mg.isAsmJS(), "import can't return float32 in asm.js");
|
|
||||||
masm.call(SymbolicAddress::CoerceInPlace_ToNumber);
|
masm.call(SymbolicAddress::CoerceInPlace_ToNumber);
|
||||||
masm.branchTest32(Assembler::Zero, ReturnReg, ReturnReg, JumpTarget::Throw);
|
masm.branchTest32(Assembler::Zero, ReturnReg, ReturnReg, JumpTarget::Throw);
|
||||||
masm.loadDouble(Address(masm.getStackPointer(), offsetToCoerceArgv), ReturnDoubleReg);
|
masm.loadDouble(Address(masm.getStackPointer(), offsetToCoerceArgv), ReturnDoubleReg);
|
||||||
@ -744,37 +728,18 @@ GenerateJitExitStub(ModuleGenerator& mg, unsigned importIndex, ProfilingOffsets*
|
|||||||
|
|
||||||
MOZ_ASSERT(masm.framePushed() == 0);
|
MOZ_ASSERT(masm.framePushed() == 0);
|
||||||
|
|
||||||
if (masm.oom())
|
offsets.end = masm.currentOffset();
|
||||||
return false;
|
return offsets;
|
||||||
|
|
||||||
offsets->end = masm.currentOffset();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
BindJumps(MacroAssembler& masm, JumpTarget target)
|
|
||||||
{
|
|
||||||
for (uint32_t offset : masm.jumpSites()[target]) {
|
|
||||||
RepatchLabel label;
|
|
||||||
label.use(offset);
|
|
||||||
masm.bind(&label);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate a stub that is called immediately after the prologue when there is a
|
// Generate a stub that is called immediately after the prologue when there is a
|
||||||
// stack overflow. This stub calls a C++ function to report the error and then
|
// stack overflow. This stub calls a C++ function to report the error and then
|
||||||
// jumps to the throw stub to pop the activation.
|
// jumps to the throw stub to pop the activation.
|
||||||
static bool
|
static Offsets
|
||||||
GenerateStackOverflowStub(ModuleGenerator& mg)
|
GenerateStackOverflow(MacroAssembler& masm)
|
||||||
{
|
{
|
||||||
MacroAssembler& masm = mg.masm();
|
|
||||||
masm.haltingAlign(CodeAlignment);
|
masm.haltingAlign(CodeAlignment);
|
||||||
|
|
||||||
if (masm.jumpSites()[JumpTarget::StackOverflow].empty())
|
|
||||||
return true;
|
|
||||||
|
|
||||||
BindJumps(masm, JumpTarget::StackOverflow);
|
|
||||||
|
|
||||||
Offsets offsets;
|
Offsets offsets;
|
||||||
offsets.begin = masm.currentOffset();
|
offsets.begin = masm.currentOffset();
|
||||||
|
|
||||||
@ -797,27 +762,18 @@ GenerateStackOverflowStub(ModuleGenerator& mg)
|
|||||||
masm.call(SymbolicAddress::ReportOverRecursed);
|
masm.call(SymbolicAddress::ReportOverRecursed);
|
||||||
masm.jump(JumpTarget::Throw);
|
masm.jump(JumpTarget::Throw);
|
||||||
|
|
||||||
if (masm.oom())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
offsets.end = masm.currentOffset();
|
offsets.end = masm.currentOffset();
|
||||||
return mg.defineInlineStub(offsets);
|
return offsets;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate a stub that is jumped to from an out-of-bounds heap access when
|
// Generate a stub that is jumped to from an out-of-bounds heap access when
|
||||||
// there are throwing semantics. This stub calls a C++ function to report an
|
// there are throwing semantics. This stub calls a C++ function to report an
|
||||||
// error and then jumps to the throw stub to pop the activation.
|
// error and then jumps to the throw stub to pop the activation.
|
||||||
static bool
|
static Offsets
|
||||||
GenerateConversionErrorStub(ModuleGenerator& mg)
|
GenerateConversionError(MacroAssembler& masm)
|
||||||
{
|
{
|
||||||
MacroAssembler& masm = mg.masm();
|
|
||||||
masm.haltingAlign(CodeAlignment);
|
masm.haltingAlign(CodeAlignment);
|
||||||
|
|
||||||
if (masm.jumpSites()[JumpTarget::ConversionError].empty())
|
|
||||||
return true;
|
|
||||||
|
|
||||||
BindJumps(masm, JumpTarget::ConversionError);
|
|
||||||
|
|
||||||
Offsets offsets;
|
Offsets offsets;
|
||||||
offsets.begin = masm.currentOffset();
|
offsets.begin = masm.currentOffset();
|
||||||
|
|
||||||
@ -830,28 +786,18 @@ GenerateConversionErrorStub(ModuleGenerator& mg)
|
|||||||
masm.call(SymbolicAddress::OnImpreciseConversion);
|
masm.call(SymbolicAddress::OnImpreciseConversion);
|
||||||
masm.jump(JumpTarget::Throw);
|
masm.jump(JumpTarget::Throw);
|
||||||
|
|
||||||
if (masm.oom())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
offsets.end = masm.currentOffset();
|
offsets.end = masm.currentOffset();
|
||||||
return mg.defineInlineStub(offsets);
|
return offsets;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate a stub that is jumped to from an out-of-bounds heap access when
|
// Generate a stub that is jumped to from an out-of-bounds heap access when
|
||||||
// there are throwing semantics. This stub calls a C++ function to report an
|
// there are throwing semantics. This stub calls a C++ function to report an
|
||||||
// error and then jumps to the throw stub to pop the activation.
|
// error and then jumps to the throw stub to pop the activation.
|
||||||
static bool
|
static Offsets
|
||||||
GenerateOutOfBoundsStub(ModuleGenerator& mg)
|
GenerateOutOfBounds(MacroAssembler& masm)
|
||||||
{
|
{
|
||||||
MacroAssembler& masm = mg.masm();
|
|
||||||
masm.haltingAlign(CodeAlignment);
|
masm.haltingAlign(CodeAlignment);
|
||||||
|
|
||||||
// Generate the out-of-bounds stub unconditionally since it may always be
|
|
||||||
// used by the signal handler.
|
|
||||||
mg.defineOutOfBoundsExit(masm.currentOffset());
|
|
||||||
|
|
||||||
BindJumps(masm, JumpTarget::OutOfBounds);
|
|
||||||
|
|
||||||
Offsets offsets;
|
Offsets offsets;
|
||||||
offsets.begin = masm.currentOffset();
|
offsets.begin = masm.currentOffset();
|
||||||
|
|
||||||
@ -864,11 +810,54 @@ GenerateOutOfBoundsStub(ModuleGenerator& mg)
|
|||||||
masm.call(SymbolicAddress::OnOutOfBounds);
|
masm.call(SymbolicAddress::OnOutOfBounds);
|
||||||
masm.jump(JumpTarget::Throw);
|
masm.jump(JumpTarget::Throw);
|
||||||
|
|
||||||
if (masm.oom())
|
offsets.end = masm.currentOffset();
|
||||||
return false;
|
return offsets;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If an exception is thrown, simply pop all frames (since asm.js does not
|
||||||
|
// contain try/catch). To do this:
|
||||||
|
// 1. Restore 'sp' to it's value right after the PushRegsInMask in GenerateEntry.
|
||||||
|
// 2. PopRegsInMask to restore the caller's non-volatile registers.
|
||||||
|
// 3. Return (to CallAsmJS).
|
||||||
|
static Offsets
|
||||||
|
GenerateThrow(MacroAssembler& masm)
|
||||||
|
{
|
||||||
|
masm.haltingAlign(CodeAlignment);
|
||||||
|
|
||||||
|
Offsets offsets;
|
||||||
|
offsets.begin = masm.currentOffset();
|
||||||
|
|
||||||
|
// We are about to pop all frames in this WasmActivation. Set fp to null to
|
||||||
|
// maintain the invariant that fp is either null or pointing to a valid
|
||||||
|
// frame.
|
||||||
|
Register scratch = ABIArgGenerator::NonArgReturnReg0;
|
||||||
|
masm.loadWasmActivation(scratch);
|
||||||
|
masm.storePtr(ImmWord(0), Address(scratch, WasmActivation::offsetOfFP()));
|
||||||
|
|
||||||
|
masm.setFramePushed(FramePushedForEntrySP);
|
||||||
|
masm.loadStackPtr(Address(scratch, WasmActivation::offsetOfEntrySP()));
|
||||||
|
masm.Pop(scratch);
|
||||||
|
masm.PopRegsInMask(NonVolatileRegs);
|
||||||
|
MOZ_ASSERT(masm.framePushed() == 0);
|
||||||
|
|
||||||
|
masm.mov(ImmWord(0), ReturnReg);
|
||||||
|
masm.ret();
|
||||||
|
|
||||||
offsets.end = masm.currentOffset();
|
offsets.end = masm.currentOffset();
|
||||||
return mg.defineInlineStub(offsets);
|
return offsets;
|
||||||
|
}
|
||||||
|
|
||||||
|
Offsets
|
||||||
|
wasm::GenerateJumpTarget(MacroAssembler& masm, JumpTarget target)
|
||||||
|
{
|
||||||
|
switch (target) {
|
||||||
|
case JumpTarget::StackOverflow: return GenerateStackOverflow(masm);
|
||||||
|
case JumpTarget::ConversionError: return GenerateConversionError(masm);
|
||||||
|
case JumpTarget::OutOfBounds: return GenerateOutOfBounds(masm);
|
||||||
|
case JumpTarget::Throw: return GenerateThrow(masm);
|
||||||
|
case JumpTarget::Limit: break;
|
||||||
|
}
|
||||||
|
MOZ_CRASH("bad JumpTarget");
|
||||||
}
|
}
|
||||||
|
|
||||||
static const LiveRegisterSet AllRegsExceptSP(
|
static const LiveRegisterSet AllRegsExceptSP(
|
||||||
@ -884,16 +873,11 @@ static const LiveRegisterSet AllRegsExceptSP(
|
|||||||
// Unfortunately, loading this requires a scratch register which we don't have
|
// Unfortunately, loading this requires a scratch register which we don't have
|
||||||
// after restoring all registers. To hack around this, push the resumePC on the
|
// after restoring all registers. To hack around this, push the resumePC on the
|
||||||
// stack so that it can be popped directly into PC.
|
// stack so that it can be popped directly into PC.
|
||||||
static bool
|
Offsets
|
||||||
GenerateInterruptStub(ModuleGenerator& mg)
|
wasm::GenerateInterruptStub(MacroAssembler& masm)
|
||||||
{
|
{
|
||||||
MacroAssembler& masm = mg.masm();
|
|
||||||
masm.haltingAlign(CodeAlignment);
|
masm.haltingAlign(CodeAlignment);
|
||||||
|
|
||||||
// Generate the interrupt stub unconditionally since it may always be used
|
|
||||||
// by the signal handler.
|
|
||||||
mg.defineInterruptExit(masm.currentOffset());
|
|
||||||
|
|
||||||
Offsets offsets;
|
Offsets offsets;
|
||||||
offsets.begin = masm.currentOffset();
|
offsets.begin = masm.currentOffset();
|
||||||
|
|
||||||
@ -1040,89 +1024,6 @@ GenerateInterruptStub(ModuleGenerator& mg)
|
|||||||
# error "Unknown architecture!"
|
# error "Unknown architecture!"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (masm.oom())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
offsets.end = masm.currentOffset();
|
offsets.end = masm.currentOffset();
|
||||||
return mg.defineInlineStub(offsets);
|
return offsets;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If an exception is thrown, simply pop all frames (since asm.js does not
|
|
||||||
// contain try/catch). To do this:
|
|
||||||
// 1. Restore 'sp' to it's value right after the PushRegsInMask in GenerateEntry.
|
|
||||||
// 2. PopRegsInMask to restore the caller's non-volatile registers.
|
|
||||||
// 3. Return (to CallAsmJS).
|
|
||||||
static bool
|
|
||||||
GenerateThrowStub(ModuleGenerator& mg)
|
|
||||||
{
|
|
||||||
MacroAssembler& masm = mg.masm();
|
|
||||||
masm.haltingAlign(CodeAlignment);
|
|
||||||
|
|
||||||
if (masm.jumpSites()[JumpTarget::Throw].empty())
|
|
||||||
return true;
|
|
||||||
|
|
||||||
BindJumps(masm, JumpTarget::Throw);
|
|
||||||
|
|
||||||
Offsets offsets;
|
|
||||||
offsets.begin = masm.currentOffset();
|
|
||||||
|
|
||||||
// We are about to pop all frames in this WasmActivation. Set fp to null to
|
|
||||||
// maintain the invariant that fp is either null or pointing to a valid
|
|
||||||
// frame.
|
|
||||||
Register scratch = ABIArgGenerator::NonArgReturnReg0;
|
|
||||||
masm.loadWasmActivation(scratch);
|
|
||||||
masm.storePtr(ImmWord(0), Address(scratch, WasmActivation::offsetOfFP()));
|
|
||||||
|
|
||||||
masm.setFramePushed(FramePushedForEntrySP);
|
|
||||||
masm.loadStackPtr(Address(scratch, WasmActivation::offsetOfEntrySP()));
|
|
||||||
masm.Pop(scratch);
|
|
||||||
masm.PopRegsInMask(NonVolatileRegs);
|
|
||||||
MOZ_ASSERT(masm.framePushed() == 0);
|
|
||||||
|
|
||||||
masm.mov(ImmWord(0), ReturnReg);
|
|
||||||
masm.ret();
|
|
||||||
|
|
||||||
if (masm.oom())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
offsets.end = masm.currentOffset();
|
|
||||||
return mg.defineInlineStub(offsets);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
wasm::GenerateStubs(ModuleGenerator& mg)
|
|
||||||
{
|
|
||||||
for (unsigned i = 0; i < mg.numExports(); i++) {
|
|
||||||
if (!GenerateEntry(mg, i))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < mg.numImports(); i++) {
|
|
||||||
ProfilingOffsets interp;
|
|
||||||
if (!GenerateInterpExitStub(mg, i, &interp))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
ProfilingOffsets jit;
|
|
||||||
if (!GenerateJitExitStub(mg, i, &jit))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!mg.defineImport(i, interp, jit))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!GenerateStackOverflowStub(mg))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!GenerateConversionErrorStub(mg))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!GenerateOutOfBoundsStub(mg))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!GenerateInterruptStub(mg))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// The throw stub must go last since the other stubs use it.
|
|
||||||
return GenerateThrowStub(mg);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -24,8 +24,20 @@
|
|||||||
namespace js {
|
namespace js {
|
||||||
namespace wasm {
|
namespace wasm {
|
||||||
|
|
||||||
bool
|
extern Offsets
|
||||||
GenerateStubs(ModuleGenerator& mg);
|
GenerateEntry(jit::MacroAssembler& masm, uint32_t target, const Sig& sig, bool usesHeap);
|
||||||
|
|
||||||
|
extern ProfilingOffsets
|
||||||
|
GenerateInterpExit(jit::MacroAssembler& masm, const Import& import, uint32_t importIndex);
|
||||||
|
|
||||||
|
extern ProfilingOffsets
|
||||||
|
GenerateJitExit(jit::MacroAssembler& masm, const Import& import, bool usesHeap);
|
||||||
|
|
||||||
|
extern Offsets
|
||||||
|
GenerateJumpTarget(jit::MacroAssembler& masm, JumpTarget target);
|
||||||
|
|
||||||
|
extern Offsets
|
||||||
|
GenerateInterruptStub(jit::MacroAssembler& masm);
|
||||||
|
|
||||||
} // namespace wasm
|
} // namespace wasm
|
||||||
} // namespace js
|
} // namespace js
|
||||||
|
@ -38,6 +38,7 @@ class PropertyName;
|
|||||||
|
|
||||||
namespace wasm {
|
namespace wasm {
|
||||||
|
|
||||||
|
using mozilla::EnumeratedArray;
|
||||||
using mozilla::Move;
|
using mozilla::Move;
|
||||||
using mozilla::DebugOnly;
|
using mozilla::DebugOnly;
|
||||||
using mozilla::MallocSizeOf;
|
using mozilla::MallocSizeOf;
|
||||||
@ -266,7 +267,7 @@ typedef Vector<const DeclaredSig*, 0, SystemAllocPolicy> DeclaredSigPtrVector;
|
|||||||
|
|
||||||
struct Offsets
|
struct Offsets
|
||||||
{
|
{
|
||||||
MOZ_IMPLICIT Offsets(uint32_t begin = 0, uint32_t end = 0)
|
explicit Offsets(uint32_t begin = 0, uint32_t end = 0)
|
||||||
: begin(begin), end(end)
|
: begin(begin), end(end)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@ -571,7 +572,7 @@ enum class JumpTarget
|
|||||||
Limit
|
Limit
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef mozilla::EnumeratedArray<JumpTarget, JumpTarget::Limit, Uint32Vector> JumpSiteArray;
|
typedef EnumeratedArray<JumpTarget, JumpTarget::Limit, Uint32Vector> JumpSiteArray;
|
||||||
|
|
||||||
// The CompileArgs struct captures global parameters that affect all wasm code
|
// The CompileArgs struct captures global parameters that affect all wasm code
|
||||||
// generation. It also currently is the single source of truth for whether or
|
// generation. It also currently is the single source of truth for whether or
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user