Merge inbound to central, a=merge

--HG--
extra : commitid : Diy1mnutqUS
This commit is contained in:
Wes Kocher 2016-02-23 16:56:58 -08:00
commit c3e2aac340
131 changed files with 2148 additions and 1440 deletions

View File

@ -254,8 +254,26 @@ def bootstrap(topsrcdir, mozilla_dir=None):
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
data.setdefault('system', {}).update(dict(
architecture=list(platform.architecture()),
machine=platform.machine(),
python_version=platform.python_version(),
release=platform.release(),
system=platform.system(),
version=platform.version(),
))
if platform.system() == 'Linux':
dist = list(platform.linux_distribution())
data['system']['linux_distribution'] = dist
elif platform.system() == 'Windows':
win32_ver=list((platform.win32_ver())),
data['system']['win32_ver'] = win32_ver
elif platform.system() == 'Darwin':
# mac version is a special Cupertino snowflake
r, v, m = platform.mac_ver()
data['system']['mac_ver'] = [r, list(v), m]
with open(os.path.join(outgoing_dir, str(uuid.uuid4()) + '.json'),
'w') as f:

View File

@ -0,0 +1,24 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"argv": {"type": "array"},
"system": {
"type": "object",
"properties": {
"architecture": {"type": "array"},
"linux_distribution": {"type": "array"},
"mac_ver": {"type": "array"},
"machine": {"type": "string"},
"python_version": {"type": "string"},
"release": {"type": "string"},
"system": {"type": "string"},
"version": {"type": "string"},
"win_ver": {"type": "array"}
},
"required": ["architecture", "machine", "python_version",
"release", "system", "version"]
}
},
"required": ["argv", "system"]
}

View File

@ -3851,18 +3851,6 @@ MOZ_ARG_WITH_STRING(gcm-senderid-keyfile,
MOZ_ANDROID_GCM_SENDERID=`cat $withval`)
AC_SUBST(MOZ_ANDROID_GCM_SENDERID)
# Whether to include optional-but-large font files in the final APK.
# We want this in mobile/android/confvars.sh, so it goes early.
MOZ_ARG_DISABLE_BOOL(android-include-fonts,
[ --disable-android-include-fonts
Disable the inclusion of fonts into the final APK],
MOZ_ANDROID_EXCLUDE_FONTS=1)
if test -n "$MOZ_ANDROID_EXCLUDE_FONTS"; then
AC_DEFINE(MOZ_ANDROID_EXCLUDE_FONTS)
fi
AC_SUBST(MOZ_ANDROID_EXCLUDE_FONTS)
# Whether this APK is destined for resource constrained devices.
# We want this in mobile/android/confvars.sh, so it goes early.
MOZ_ARG_ENABLE_BOOL(android-resource-constrained,
@ -4775,6 +4763,13 @@ if test -n "$MOZ_ANDROID_MLS_STUMBLER"; then
AC_DEFINE(MOZ_ANDROID_MLS_STUMBLER)
fi
dnl =========================================================
dnl = Whether to exclude font files in the build
dnl =========================================================
if test -n "$MOZ_ANDROID_EXCLUDE_FONTS"; then
AC_DEFINE(MOZ_ANDROID_EXCLUDE_FONTS)
fi
dnl =========================================================
dnl = Whether to exclude hyphenations files in the build
dnl =========================================================
@ -8457,6 +8452,7 @@ AC_SUBST(MOZ_ANDROID_APPLICATION_CLASS)
AC_SUBST(MOZ_ANDROID_BROWSER_INTENT_CLASS)
AC_SUBST(MOZ_ANDROID_SEARCH_INTENT_CLASS)
AC_SUBST(MOZ_ANDROID_DOWNLOAD_CONTENT_SERVICE)
AC_SUBST(MOZ_ANDROID_EXCLUDE_FONTS)
AC_SUBST(MOZ_EXCLUDE_HYPHENATION_DICTIONARIES)
AC_SUBST(MOZ_INSTALL_TRACKING)
AC_SUBST(MOZ_SWITCHBOARD)

View File

@ -1,8 +1,8 @@
load 1239889-1.html
load 1244595-1.html
load 1216842-1.html
load 1216842-2.html
load 1216842-3.html
load 1216842-4.html
load 1216842-5.html
load 1216842-6.html
pref(dom.animations-api.core.enabled,true) load 1239889-1.html
pref(dom.animations-api.core.enabled,true) load 1244595-1.html
pref(dom.animations-api.core.enabled,true) load 1216842-1.html
pref(dom.animations-api.core.enabled,true) load 1216842-2.html
pref(dom.animations-api.core.enabled,true) load 1216842-3.html
pref(dom.animations-api.core.enabled,true) load 1216842-4.html
pref(dom.animations-api.core.enabled,true) load 1216842-5.html
pref(dom.animations-api.core.enabled,true) load 1216842-6.html

View File

@ -486,7 +486,7 @@ skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' # b2g
[test_iframe_sandbox_popups.html]
skip-if = buildapp == 'b2g' # b2g(multiple concurrent window.open()s fail on B2G) b2g-debug(multiple concurrent window.open()s fail on B2G) b2g-desktop(Bug 931116, b2g desktop specific, initial triage)
[test_iframe_sandbox_popups_inheritance.html]
skip-if = buildapp == 'b2g' || e10s || toolkit == 'android' # b2g(multiple concurrent window.open()s fail on B2G) b2g-debug(multiple concurrent window.open()s fail on B2G) b2g-desktop(Bug 931116, b2g desktop specific, initial triage) android(bug 939642)
skip-if = buildapp == 'b2g' || toolkit == 'android' # b2g(multiple concurrent window.open()s fail on B2G) b2g-debug(multiple concurrent window.open()s fail on B2G) b2g-desktop(Bug 931116, b2g desktop specific, initial triage) android(bug 939642)
[test_iframe_sandbox_redirect.html]
[test_iframe_sandbox_refresh.html]
[test_iframe_sandbox_same_origin.html]
@ -582,7 +582,7 @@ skip-if = toolkit == 'android'
[test_bug677495.html]
[test_bug677495-1.html]
[test_bug741266.html]
skip-if = buildapp == "mulet" || buildapp == "b2g" || toolkit == "android" || toolkit == "windows" || e10s # b2g(needs control of popup window size) b2g-debug(needs control of popup window size) b2g-desktop(needs control of popup window size) windows(bug 1234520)
skip-if = buildapp == "mulet" || buildapp == "b2g" || toolkit == "android" || toolkit == "windows" # b2g(needs control of popup window size) b2g-debug(needs control of popup window size) b2g-desktop(needs control of popup window size) windows(bug 1234520)
[test_non-ascii-cookie.html]
skip-if = buildapp == 'b2g'
support-files = file_cookiemanager.js

View File

@ -2052,6 +2052,17 @@ MediaManager::GetUserMedia(nsPIDOMWindowInner* aWindow,
RemoveFromWindowList(windowID, listener);
return NS_OK;
}
} else if (loop) {
// Record that we gave Loop permission to use camera access.
nsCOMPtr<nsIPermissionManager> permManager =
do_GetService(NS_PERMISSIONMANAGER_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = permManager->Add(docURI, "camera",
nsIPermissionManager::ALLOW_ACTION,
nsIPermissionManager::EXPIRE_SESSION,
0);
NS_ENSURE_SUCCESS(rv, rv);
}
#if defined(MOZ_B2G_CAMERA) && defined(MOZ_WIDGET_GONK)

View File

@ -0,0 +1,26 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Test for B2G PresentationReceiver on a non-receiver inner iframe of the receiver page at receiver side (OOP)</title>
</head>
<body onload="testConnectionAvailable()">
<div id="content"></div>
<script type="application/javascript;version=1.7">
"use strict";
function ok(a, msg) {
alert((a ? 'OK ' : 'KO ') + msg);
}
function testConnectionAvailable() {
return new Promise(function(aResolve, aReject) {
ok(!navigator.presentation, "navigator.presentation shouldn't be available in inner iframes with different origins from receiving OOP pages.");
aResolve();
});
}
</script>
</body>
</html>

View File

@ -0,0 +1,26 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Test for B2G PresentationReceiver in an inner iframe of the receiver page at receiver side (OOP)</title>
</head>
<body onload="testConnectionAvailable()">
<div id="content"></div>
<script type="application/javascript;version=1.7">
"use strict";
function ok(a, msg) {
alert((a ? 'OK ' : 'KO ') + msg);
}
function testConnectionAvailable() {
return new Promise(function(aResolve, aReject) {
ok(navigator.presentation, "navigator.presentation should be available in same-origin inner iframes of receiving OOP pages.");
aResolve();
});
}
</script>
</body>
</html>

View File

@ -54,7 +54,7 @@ function testConnectionAvailable() {
});
}
function testConnectionAvailableInnerIframe() {
function testConnectionAvailableSameOriginInnerIframe() {
return new Promise(function(aResolve, aReject) {
var iframe = document.createElement('iframe');
iframe.setAttribute('src', './file_presentation_receiver_inner_iframe_oop.html');
@ -64,6 +64,16 @@ function testConnectionAvailableInnerIframe() {
});
}
function testConnectionUnavailableDiffOriginInnerIframe() {
return new Promise(function(aResolve, aReject) {
var iframe = document.createElement('iframe');
iframe.setAttribute('src', 'http://example.com/tests/dom/presentation/tests/mochitest/file_presentation_non_receiver_inner_iframe_oop.html');
document.body.appendChild(iframe);
aResolve();
});
}
function testConnectionReady() {
return new Promise(function(aResolve, aReject) {
connection.onstatechange = function() {
@ -104,7 +114,11 @@ function testTerminateConnection() {
}
testConnectionAvailable().
then(testConnectionAvailableInnerIframe).
// TODO Bug 1234128 - Fix the timing issue for navigator.presentation.receiver.
// This test fails intermittently under some edge cases. Disable it for now until
// the issue gets fixed.
// then(testConnectionAvailableSameOriginInnerIframe).
then(testConnectionUnavailableDiffOriginInnerIframe).
then(testConnectionReady).
then(testIncomingMessage).
then(testTerminateConnection).

View File

@ -6,6 +6,8 @@ support-files =
file_presentation_receiver_oop.html
file_presentation_non_receiver_oop.html
file_presentation_receiver_establish_connection_error.html
file_presentation_receiver_inner_iframe_oop.html
file_presentation_non_receiver_inner_iframe_oop.html
[test_presentation_device_info.html]
[test_presentation_device_info_permission.html]

View File

@ -40,6 +40,7 @@ namespace {
static const char* gSupportedRegistrarVersions[] = {
SERVICEWORKERREGISTRAR_VERSION,
"3",
"2"
};
@ -330,6 +331,7 @@ ServiceWorkerRegistrar::ReadData()
nsTArray<ServiceWorkerRegistrationData> tmpData;
bool overwrite = false;
bool dedupe = false;
while (hasMoreLines) {
ServiceWorkerRegistrationData* entry = tmpData.AppendElement();
@ -343,6 +345,7 @@ ServiceWorkerRegistrar::ReadData()
}
nsAutoCString line;
nsAutoCString unused;
if (version.EqualsLiteral(SERVICEWORKERREGISTRAR_VERSION)) {
nsAutoCString suffix;
GET_LINE(suffix);
@ -352,18 +355,19 @@ ServiceWorkerRegistrar::ReadData()
return NS_ERROR_INVALID_ARG;
}
GET_LINE(line);
entry->principal() =
mozilla::ipc::ContentPrincipalInfo(attrs, line);
GET_LINE(entry->scope());
entry->principal() =
mozilla::ipc::ContentPrincipalInfo(attrs, entry->scope());
GET_LINE(entry->currentWorkerURL());
nsAutoCString cacheName;
GET_LINE(cacheName);
CopyUTF8toUTF16(cacheName, entry->cacheName());
} else if (version.EqualsLiteral("2")) {
} else if (version.EqualsLiteral("3")) {
overwrite = true;
dedupe = true;
nsAutoCString suffix;
GET_LINE(suffix);
@ -373,14 +377,40 @@ ServiceWorkerRegistrar::ReadData()
return NS_ERROR_INVALID_ARG;
}
GET_LINE(line);
entry->principal() =
mozilla::ipc::ContentPrincipalInfo(attrs, line);
// principal spec is no longer used; we use scope directly instead
GET_LINE(unused);
GET_LINE(entry->scope());
entry->principal() =
mozilla::ipc::ContentPrincipalInfo(attrs, entry->scope());
GET_LINE(entry->currentWorkerURL());
nsAutoCString cacheName;
GET_LINE(cacheName);
CopyUTF8toUTF16(cacheName, entry->cacheName());
} else if (version.EqualsLiteral("2")) {
overwrite = true;
dedupe = true;
nsAutoCString suffix;
GET_LINE(suffix);
PrincipalOriginAttributes attrs;
if (!attrs.PopulateFromSuffix(suffix)) {
return NS_ERROR_INVALID_ARG;
}
// principal spec is no longer used; we use scope directly instead
GET_LINE(unused);
GET_LINE(entry->scope());
entry->principal() =
mozilla::ipc::ContentPrincipalInfo(attrs, entry->scope());
// scriptSpec is no more used in latest version.
nsAutoCString unused;
GET_LINE(unused);
GET_LINE(entry->currentWorkerURL());
@ -409,22 +439,32 @@ ServiceWorkerRegistrar::ReadData()
stream->Close();
// Dedupe data in file. Old profiles had many duplicates. In theory
// we can remove this in the future. (Bug 1248449)
// Copy data over to mData.
for (uint32_t i = 0; i < tmpData.Length(); ++i) {
bool match = false;
for (uint32_t j = 0; j < mData.Length(); ++j) {
// Use same comparison as RegisterServiceWorker. Scope contains
// basic origin information. Combine with any principal attributes.
if (Equivalent(tmpData[i], mData[j])) {
// Last match wins, just like legacy loading used to do in
// the ServiceWorkerManager.
mData[j] = tmpData[i];
// Dupe found, so overwrite file with reduced list.
overwrite = true;
match = true;
break;
if (dedupe) {
MOZ_ASSERT(overwrite);
// If this is an old profile, then we might need to deduplicate. In
// theory this can be removed in the future (Bug 1248449)
for (uint32_t j = 0; j < mData.Length(); ++j) {
// Use same comparison as RegisterServiceWorker. Scope contains
// basic origin information. Combine with any principal attributes.
if (Equivalent(tmpData[i], mData[j])) {
// Last match wins, just like legacy loading used to do in
// the ServiceWorkerManager.
mData[j] = tmpData[i];
// Dupe found, so overwrite file with reduced list.
match = true;
break;
}
}
} else {
#ifdef DEBUG
// Otherwise assert no duplications in debug builds.
for (uint32_t j = 0; j < mData.Length(); ++j) {
MOZ_ASSERT(!Equivalent(tmpData[i], mData[j]));
}
#endif
}
if (!match) {
mData.AppendElement(tmpData[i]);
@ -647,9 +687,6 @@ ServiceWorkerRegistrar::WriteData()
buffer.Append(suffix.get());
buffer.Append('\n');
buffer.Append(cInfo.spec());
buffer.Append('\n');
buffer.Append(data[i].scope());
buffer.Append('\n');

View File

@ -16,7 +16,7 @@
#include "nsTArray.h"
#define SERVICEWORKERREGISTRAR_FILE "serviceworker.txt"
#define SERVICEWORKERREGISTRAR_VERSION "3"
#define SERVICEWORKERREGISTRAR_VERSION "4"
#define SERVICEWORKERREGISTRAR_TERMINATOR "#"
#define SERVICEWORKERREGISTRAR_TRUE "true"
#define SERVICEWORKERREGISTRAR_FALSE "false"

View File

@ -142,11 +142,11 @@ TEST(ServiceWorkerRegistrar, TestReadData)
nsAutoCString buffer(SERVICEWORKERREGISTRAR_VERSION "\n");
buffer.Append("^appId=123&inBrowser=1\n");
buffer.Append("spec 0\nscope 0\ncurrentWorkerURL 0\ncacheName 0\n");
buffer.Append("scope 0\ncurrentWorkerURL 0\ncacheName 0\n");
buffer.Append(SERVICEWORKERREGISTRAR_TERMINATOR "\n");
buffer.Append("\n");
buffer.Append("spec 1\nscope 1\ncurrentWorkerURL 1\ncacheName 1\n");
buffer.Append("scope 1\ncurrentWorkerURL 1\ncacheName 1\n");
buffer.Append(SERVICEWORKERREGISTRAR_TERMINATOR "\n");
ASSERT_TRUE(CreateFile(buffer)) << "CreateFile should not fail";
@ -167,7 +167,7 @@ TEST(ServiceWorkerRegistrar, TestReadData)
cInfo0.attrs().CreateSuffix(suffix0);
ASSERT_STREQ("^appId=123&inBrowser=1", suffix0.get());
ASSERT_STREQ("spec 0", cInfo0.spec().get());
ASSERT_STREQ("scope 0", cInfo0.spec().get());
ASSERT_STREQ("scope 0", data[0].scope().get());
ASSERT_STREQ("currentWorkerURL 0", data[0].currentWorkerURL().get());
ASSERT_STREQ("cacheName 0", NS_ConvertUTF16toUTF8(data[0].cacheName()).get());
@ -180,7 +180,7 @@ TEST(ServiceWorkerRegistrar, TestReadData)
cInfo1.attrs().CreateSuffix(suffix1);
ASSERT_STREQ("", suffix1.get());
ASSERT_STREQ("spec 1", cInfo1.spec().get());
ASSERT_STREQ("scope 1", cInfo1.spec().get());
ASSERT_STREQ("scope 1", data[1].scope().get());
ASSERT_STREQ("currentWorkerURL 1", data[1].currentWorkerURL().get());
ASSERT_STREQ("cacheName 1", NS_ConvertUTF16toUTF8(data[1].cacheName()).get());
@ -246,7 +246,7 @@ TEST(ServiceWorkerRegistrar, TestWriteData)
ASSERT_STREQ(expectSuffix.get(), suffix.get());
test.AppendPrintf("spec write %d", i);
test.AppendPrintf("scope write %d", i);
ASSERT_STREQ(test.get(), cInfo.spec().get());
test.Truncate();
@ -283,7 +283,7 @@ TEST(ServiceWorkerRegistrar, TestVersion2Migration)
ASSERT_EQ(NS_OK, rv) << "ReadData() should not fail";
const nsTArray<ServiceWorkerRegistrationData>& data = swr->TestGetData();
ASSERT_EQ((uint32_t)2, data.Length()) << "4 entries should be found";
ASSERT_EQ((uint32_t)2, data.Length()) << "2 entries should be found";
const mozilla::ipc::PrincipalInfo& info0 = data[0].principal();
ASSERT_EQ(info0.type(), mozilla::ipc::PrincipalInfo::TContentPrincipalInfo) << "First principal must be content";
@ -293,7 +293,7 @@ TEST(ServiceWorkerRegistrar, TestVersion2Migration)
cInfo0.attrs().CreateSuffix(suffix0);
ASSERT_STREQ("^appId=123&inBrowser=1", suffix0.get());
ASSERT_STREQ("spec 0", cInfo0.spec().get());
ASSERT_STREQ("scope 0", cInfo0.spec().get());
ASSERT_STREQ("scope 0", data[0].scope().get());
ASSERT_STREQ("currentWorkerURL 0", data[0].currentWorkerURL().get());
ASSERT_STREQ("activeCache 0", NS_ConvertUTF16toUTF8(data[0].cacheName()).get());
@ -306,15 +306,64 @@ TEST(ServiceWorkerRegistrar, TestVersion2Migration)
cInfo1.attrs().CreateSuffix(suffix1);
ASSERT_STREQ("", suffix1.get());
ASSERT_STREQ("spec 1", cInfo1.spec().get());
ASSERT_STREQ("scope 1", cInfo1.spec().get());
ASSERT_STREQ("scope 1", data[1].scope().get());
ASSERT_STREQ("currentWorkerURL 1", data[1].currentWorkerURL().get());
ASSERT_STREQ("activeCache 1", NS_ConvertUTF16toUTF8(data[1].cacheName()).get());
}
TEST(ServiceWorkerRegistrar, TestVersion3Migration)
{
nsAutoCString buffer("3" "\n");
buffer.Append("^appId=123&inBrowser=1\n");
buffer.Append("spec 0\nscope 0\ncurrentWorkerURL 0\ncacheName 0\n");
buffer.Append(SERVICEWORKERREGISTRAR_TERMINATOR "\n");
buffer.Append("\n");
buffer.Append("spec 1\nscope 1\ncurrentWorkerURL 1\ncacheName 1\n");
buffer.Append(SERVICEWORKERREGISTRAR_TERMINATOR "\n");
ASSERT_TRUE(CreateFile(buffer)) << "CreateFile should not fail";
RefPtr<ServiceWorkerRegistrarTest> swr = new ServiceWorkerRegistrarTest;
nsresult rv = swr->TestReadData();
ASSERT_EQ(NS_OK, rv) << "ReadData() should not fail";
const nsTArray<ServiceWorkerRegistrationData>& data = swr->TestGetData();
ASSERT_EQ((uint32_t)2, data.Length()) << "2 entries should be found";
const mozilla::ipc::PrincipalInfo& info0 = data[0].principal();
ASSERT_EQ(info0.type(), mozilla::ipc::PrincipalInfo::TContentPrincipalInfo) << "First principal must be content";
const mozilla::ipc::ContentPrincipalInfo& cInfo0 = data[0].principal();
nsAutoCString suffix0;
cInfo0.attrs().CreateSuffix(suffix0);
ASSERT_STREQ("^appId=123&inBrowser=1", suffix0.get());
ASSERT_STREQ("scope 0", cInfo0.spec().get());
ASSERT_STREQ("scope 0", data[0].scope().get());
ASSERT_STREQ("currentWorkerURL 0", data[0].currentWorkerURL().get());
ASSERT_STREQ("cacheName 0", NS_ConvertUTF16toUTF8(data[0].cacheName()).get());
const mozilla::ipc::PrincipalInfo& info1 = data[1].principal();
ASSERT_EQ(info1.type(), mozilla::ipc::PrincipalInfo::TContentPrincipalInfo) << "First principal must be content";
const mozilla::ipc::ContentPrincipalInfo& cInfo1 = data[1].principal();
nsAutoCString suffix1;
cInfo1.attrs().CreateSuffix(suffix1);
ASSERT_STREQ("", suffix1.get());
ASSERT_STREQ("scope 1", cInfo1.spec().get());
ASSERT_STREQ("scope 1", data[1].scope().get());
ASSERT_STREQ("currentWorkerURL 1", data[1].currentWorkerURL().get());
ASSERT_STREQ("cacheName 1", NS_ConvertUTF16toUTF8(data[1].cacheName()).get());
}
TEST(ServiceWorkerRegistrar, TestDedupe)
{
nsAutoCString buffer(SERVICEWORKERREGISTRAR_VERSION "\n");
nsAutoCString buffer("3" "\n");
// unique entries
buffer.Append("^appId=123&inBrowser=1\n");
@ -356,7 +405,7 @@ TEST(ServiceWorkerRegistrar, TestDedupe)
cInfo0.attrs().CreateSuffix(suffix0);
ASSERT_STREQ("^appId=123&inBrowser=1", suffix0.get());
ASSERT_STREQ("spec 2", cInfo0.spec().get());
ASSERT_STREQ("scope 0", cInfo0.spec().get());
ASSERT_STREQ("scope 0", data[0].scope().get());
ASSERT_STREQ("currentWorkerURL 0", data[0].currentWorkerURL().get());
ASSERT_STREQ("cacheName 0", NS_ConvertUTF16toUTF8(data[0].cacheName()).get());
@ -369,7 +418,7 @@ TEST(ServiceWorkerRegistrar, TestDedupe)
cInfo1.attrs().CreateSuffix(suffix1);
ASSERT_STREQ("", suffix1.get());
ASSERT_STREQ("spec 3", cInfo1.spec().get());
ASSERT_STREQ("scope 1", cInfo1.spec().get());
ASSERT_STREQ("scope 1", data[1].scope().get());
ASSERT_STREQ("currentWorkerURL 1", data[1].currentWorkerURL().get());
ASSERT_STREQ("cacheName 1", NS_ConvertUTF16toUTF8(data[1].cacheName()).get());

View File

@ -170,3 +170,10 @@ function synthesizeNativeDrag(aElement, aX, aY, aDeltaX, aDeltaY, aObserver = nu
synthesizeNativeTouch(aElement, aX + aDeltaX, aY + aDeltaY, SpecialPowers.DOMWindowUtils.TOUCH_CONTACT, null, aTouchId);
return synthesizeNativeTouch(aElement, aX + aDeltaX, aY + aDeltaY, SpecialPowers.DOMWindowUtils.TOUCH_REMOVE, aObserver, aTouchId);
}
function synthesizeNativeTap(aElement, aX, aY, aObserver = null) {
var pt = coordinatesRelativeToWindow(aX, aY, aElement);
var utils = SpecialPowers.getDOMWindowUtils(aElement.ownerDocument.defaultView);
utils.sendNativeTouchTap(pt.x, pt.y, false, aObserver);
return true;
}

View File

@ -0,0 +1,42 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width; initial-scale=1.0">
<title>Sanity touch-tapping test</title>
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
<script type="application/javascript" src="apz_test_utils.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
<script type="application/javascript">
function clickButton() {
if (!window.TouchEvent) {
window.opener.ok(true, "Touch events are not supported on this platform, sorry!\n");
window.opener.testDone();
return;
}
document.addEventListener('click', clicked, false);
synthesizeNativeTap(document.getElementById('b'), 5, 5, function() {
dump("Finished synthesizing tap, waiting for button to be clicked...\n");
});
}
function clicked(e) {
window.opener.is(e.target, document.getElementById('b'), "Clicked on button, yay! (at " + e.clientX + "," + e.clientY + ")");
window.opener.testDone();
}
window.onload = function() {
waitForAllPaints(function() {
flushApzRepaints(clickButton);
});
}
</script>
</head>
<body>
<button id="b" style="width: 10px; height: 10px"></button>
</body>
</html>

View File

@ -10,6 +10,7 @@ support-files =
helper_basic_pan.html
helper_div_pan.html
helper_iframe_pan.html
helper_tap.html
tags = apz
[test_bug982141.html]
skip-if = toolkit != 'gonk' # bug 991198
@ -32,3 +33,7 @@ skip-if = (os == 'android') || (os == 'b2g') || (buildapp == 'mulet') # wheel ev
[test_scroll_subframe_scrollbar.html]
skip-if = (os == 'android') || (os == 'b2g') || (buildapp == 'mulet') # wheel events not supported on mobile; see bug 1164274 for mulet
[test_frame_reconstruction.html]
[test_tap.html]
# Windows touch injection doesn't work in automation, but this test can be run locally on a windows touch device.
# On OS X we don't support touch events at all.
skip-if = (toolkit == 'windows') || (toolkit == 'cocoa')

View File

@ -0,0 +1,46 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Sanity panning test</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript">
SimpleTest.waitForExplicitFinish();
// this page just serially loads each one of the following test helper pages in
// a new window and waits for it to call testDone()
var tests = [
'helper_tap.html',
];
var testIndex = -1;
var w = null;
function testDone() {
if (w) {
w.close();
}
testIndex++;
if (testIndex < tests.length) {
w = window.open(tests[testIndex], "_blank");
} else {
SimpleTest.finish();
}
}
window.onload = function() {
if (!SpecialPowers.getDOMWindowUtils(window).asyncPanZoomEnabled) {
ok(true, "APZ is not enabled, this test is not relevant, sorry!\n");
SimpleTest.finish();
return;
}
testDone();
};
</script>
</head>
<body>
</body>
</html>

View File

@ -434,7 +434,7 @@ BasicCompositor::DrawQuad(const gfx::Rect& aRect,
MOZ_ASSERT(effectMask->mMaskTransform.Is2D(), "How did we end up with a 3D transform here?!");
MOZ_ASSERT(!effectMask->mIs3D);
maskTransform = effectMask->mMaskTransform.As2D();
maskTransform.PreTranslate(-offset.x, -offset.y);
maskTransform.PostTranslate(-offset.x, -offset.y);
}
CompositionOp blendMode = CompositionOp::OP_OVER;

View File

@ -820,7 +820,8 @@ TextureClient::CreateForRawBufferAccess(ISurfaceAllocator* aAllocator,
TextureFlags aTextureFlags,
TextureAllocationFlags aAllocFlags)
{
MOZ_ASSERT(aAllocator->IPCOpen());
// also test the validity of aAllocator
MOZ_ASSERT(aAllocator && aAllocator->IPCOpen());
if (!aAllocator || !aAllocator->IPCOpen()) {
return nullptr;
}

View File

@ -112,7 +112,7 @@ struct JS_PUBLIC_API(ShortestPaths)
BackEdge* back, bool first)
{
MOZ_ASSERT(back);
MOZ_ASSERT(traversal.visited.has(origin));
MOZ_ASSERT(origin == shortestPaths.root_ || traversal.visited.has(origin));
MOZ_ASSERT(totalPathsRecorded < totalMaxPathsToRecord);
if (first && !back->init(origin, edge))
@ -128,9 +128,7 @@ struct JS_PUBLIC_API(ShortestPaths)
// `back->clone()` in the first branch, and the `init` call in the
// second branch.
auto ptr = shortestPaths.paths_.lookupForAdd(edge.referent);
if (first) {
MOZ_ASSERT(!ptr);
BackEdgeVector paths;
if (!paths.reserve(shortestPaths.maxNumPaths_))
return false;
@ -138,16 +136,23 @@ struct JS_PUBLIC_API(ShortestPaths)
if (!cloned)
return false;
paths.infallibleAppend(mozilla::Move(cloned));
if (!shortestPaths.paths_.add(ptr, edge.referent, mozilla::Move(paths)))
if (!shortestPaths.paths_.putNew(edge.referent, mozilla::Move(paths)))
return false;
totalPathsRecorded++;
} else if (ptr->value().length() < shortestPaths.maxNumPaths_) {
MOZ_ASSERT(ptr);
BackEdge::Ptr thisBackEdge(js_new<BackEdge>());
if (!thisBackEdge || !thisBackEdge->init(origin, edge))
return false;
ptr->value().infallibleAppend(mozilla::Move(thisBackEdge));
totalPathsRecorded++;
} else {
auto ptr = shortestPaths.paths_.lookup(edge.referent);
MOZ_ASSERT(ptr,
"This isn't the first time we have seen the target node `edge.referent`. "
"We should have inserted it into shortestPaths.paths_ the first time we "
"saw it.");
if (ptr->value().length() < shortestPaths.maxNumPaths_) {
BackEdge::Ptr thisBackEdge(js_new<BackEdge>());
if (!thisBackEdge || !thisBackEdge->init(origin, edge))
return false;
ptr->value().infallibleAppend(mozilla::Move(thisBackEdge));
totalPathsRecorded++;
}
}
MOZ_ASSERT(totalPathsRecorded <= totalMaxPathsToRecord);
@ -251,7 +256,7 @@ struct JS_PUBLIC_API(ShortestPaths)
Handler handler(paths);
Traversal traversal(rt, handler, noGC);
traversal.wantNames = true;
if (!traversal.init() || !traversal.addStartVisited(root) || !traversal.traverse())
if (!traversal.init() || !traversal.addStart(root) || !traversal.traverse())
return mozilla::Nothing();
// Take ownership of the back edges we created while traversing the

View File

@ -653,30 +653,6 @@ ComparisonRight(ParseNode* pn)
return BinaryOpRight(pn);
}
static inline ParseNode*
AndOrLeft(ParseNode* pn)
{
return BinaryOpLeft(pn);
}
static inline ParseNode*
AndOrRight(ParseNode* pn)
{
return BinaryOpRight(pn);
}
static inline ParseNode*
RelationalLeft(ParseNode* pn)
{
return BinaryOpLeft(pn);
}
static inline ParseNode*
RelationalRight(ParseNode* pn)
{
return BinaryOpRight(pn);
}
static inline bool
IsExpressionStatement(ParseNode* pn)
{

View File

@ -200,7 +200,6 @@ namespace {
#define DEFINE_DEFN_(TypeName) \
class TypeName##Defn { \
public: \
static const SimdType type = SimdType::TypeName; \
static const JSFunctionSpec Methods[]; \
};

View File

@ -933,7 +933,10 @@ Statistics::endGC()
int64_t markRootsTotal = SumPhase(PHASE_MARK_ROOTS, phaseTimes);
runtime->addTelemetry(JS_TELEMETRY_GC_MARK_MS, t(markTotal));
runtime->addTelemetry(JS_TELEMETRY_GC_SWEEP_MS, t(phaseTimes[PHASE_DAG_NONE][PHASE_SWEEP]));
runtime->addTelemetry(JS_TELEMETRY_GC_COMPACT_MS, t(phaseTimes[PHASE_DAG_NONE][PHASE_COMPACT]));
if (runtime->gc.isCompactingGc()) {
runtime->addTelemetry(JS_TELEMETRY_GC_COMPACT_MS,
t(phaseTimes[PHASE_DAG_NONE][PHASE_COMPACT]));
}
runtime->addTelemetry(JS_TELEMETRY_GC_MARK_ROOTS_MS, t(markRootsTotal));
runtime->addTelemetry(JS_TELEMETRY_GC_MARK_GRAY_MS, t(phaseTimes[PHASE_DAG_NONE][PHASE_SWEEP_MARK_GRAY]));
runtime->addTelemetry(JS_TELEMETRY_GC_NON_INCREMENTAL, !!nonincrementalReason_);

View File

@ -0,0 +1 @@
shortestPaths(this, [this], 5)

View File

@ -3306,7 +3306,7 @@ IonBuilder::inlineConstructSimdObject(CallInfo& callInfo, SimdTypeDescr* descr)
defVal = constant(DoubleNaNValue());
} else {
MOZ_ASSERT(laneType == MIRType_Float32);
defVal = MConstant::NewFloat32(alloc(), GenericNaN());
defVal = MConstant::NewFloat32(alloc(), JS::GenericNaN());
current->add(defVal);
}
}

View File

@ -619,6 +619,21 @@ MacroAssembler::assertStackAlignment(uint32_t alignment, int32_t offset /* = 0 *
#endif
}
void
MacroAssembler::storeCallResultValue(AnyRegister dest)
{
unboxValue(JSReturnOperand, dest);
}
void
MacroAssembler::storeCallResultValue(TypedOrValueRegister dest)
{
if (dest.hasValue())
storeCallResultValue(dest.valueReg());
else
storeCallResultValue(dest.typedReg());
}
} // namespace jit
} // namespace js

View File

@ -824,6 +824,15 @@ class MacroAssembler : public MacroAssemblerSpecific
inline void branchPtr(Condition cond, wasm::SymbolicAddress lhs, Register rhs, Label* label)
DEFINED_ON(arm, arm64, mips_shared, x86, x64);
template <typename T>
inline CodeOffsetJump branchPtrWithPatch(Condition cond, Register lhs, T rhs, RepatchLabel* label) PER_SHARED_ARCH;
template <typename T>
inline CodeOffsetJump branchPtrWithPatch(Condition cond, Address lhs, T rhs, RepatchLabel* label) PER_SHARED_ARCH;
void branchPtrInNurseryRange(Condition cond, Register ptr, Register temp, Label* label)
DEFINED_ON(arm, arm64, mips_shared, x86, x64);
void branchValueIsNurseryObject(Condition cond, ValueOperand value, Register temp, Label* label) PER_ARCH;
// This function compares a Value (lhs) which is having a private pointer
// boxed inside a js::Value, with a raw pointer (rhs).
inline void branchPrivatePtr(Condition cond, const Address& lhs, Register rhs, Label* label) PER_ARCH;
@ -838,6 +847,13 @@ class MacroAssembler : public MacroAssemblerSpecific
inline void branchTruncateDouble(FloatRegister src, Register dest, Label* fail)
DEFINED_ON(arm, arm64, mips_shared, x86, x64);
template <typename T>
inline void branchAdd32(Condition cond, T src, Register dest, Label* label) PER_SHARED_ARCH;
template <typename T>
inline void branchSub32(Condition cond, T src, Register dest, Label* label) PER_SHARED_ARCH;
inline void decBranchPtr(Condition cond, Register lhs, Imm32 rhs, Label* label) PER_SHARED_ARCH;
template <class L>
inline void branchTest32(Condition cond, Register lhs, Register rhs, L label) PER_SHARED_ARCH;
template <class L>
@ -902,6 +918,17 @@ class MacroAssembler : public MacroAssemblerSpecific
inline void branchTestNeedsIncrementalBarrier(Condition cond, Label* label);
inline void branchTestInt32(Condition cond, Register tag, Label* label)
DEFINED_ON(arm, arm64, mips_shared, x86, x64);
inline void branchTestInt32(Condition cond, const Address& address, Label* label)
DEFINED_ON(arm, arm64, mips_shared, x86, x64);
inline void branchTestInt32(Condition cond, const BaseIndex& address, Label* label)
DEFINED_ON(arm, arm64, mips_shared, x86, x64);
inline void branchTestInt32(Condition cond, const ValueOperand& src, Label* label) PER_ARCH;
inline void branchTestInt32Truthy(bool truthy, const ValueOperand& operand, Label* label)
DEFINED_ON(arm, arm64, mips32, mips64, x86_shared);
//}}} check_macroassembler_style
public:
@ -1012,15 +1039,7 @@ class MacroAssembler : public MacroAssemblerSpecific
moveDouble(ReturnDoubleReg, reg);
}
void storeCallResultValue(AnyRegister dest) {
#if defined(JS_NUNBOX32)
unboxValue(ValueOperand(JSReturnReg_Type, JSReturnReg_Data), dest);
#elif defined(JS_PUNBOX64)
unboxValue(ValueOperand(JSReturnReg), dest);
#else
#error "Bad architecture"
#endif
}
inline void storeCallResultValue(AnyRegister dest);
void storeCallResultValue(ValueOperand dest) {
#if defined(JS_NUNBOX32)
@ -1051,12 +1070,7 @@ class MacroAssembler : public MacroAssemblerSpecific
#endif
}
void storeCallResultValue(TypedOrValueRegister dest) {
if (dest.hasValue())
storeCallResultValue(dest.valueReg());
else
storeCallResultValue(dest.typedReg());
}
inline void storeCallResultValue(TypedOrValueRegister dest);
template <typename T>
Register extractString(const T& source, Register scratch) {

View File

@ -585,6 +585,24 @@ MacroAssembler::branchPtr(Condition cond, wasm::SymbolicAddress lhs, Register rh
branchPtr(cond, scratch, rhs, label);
}
template <typename T>
CodeOffsetJump
MacroAssembler::branchPtrWithPatch(Condition cond, Register lhs, T rhs, RepatchLabel* label)
{
ma_cmp(lhs, rhs);
return jumpWithPatch(label, cond);
}
template <typename T>
CodeOffsetJump
MacroAssembler::branchPtrWithPatch(Condition cond, Address lhs, T rhs, RepatchLabel* label)
{
AutoRegisterScope scratch2(*this, secondScratchReg_);
ma_ldr(lhs, scratch2);
ma_cmp(scratch2, rhs);
return jumpWithPatch(label, cond);
}
void
MacroAssembler::branchPrivatePtr(Condition cond, const Address& lhs, Register rhs, Label* label)
{
@ -671,6 +689,29 @@ MacroAssembler::branchTruncateDouble(FloatRegister src, Register dest, Label* fa
ma_b(fail, Assembler::Equal);
}
template <typename T>
void
MacroAssembler::branchAdd32(Condition cond, T src, Register dest, Label* label)
{
add32(src, dest);
j(cond, label);
}
template <typename T>
void
MacroAssembler::branchSub32(Condition cond, T src, Register dest, Label* label)
{
ma_sub(src, dest, SetCC);
j(cond, label);
}
void
MacroAssembler::decBranchPtr(Condition cond, Register lhs, Imm32 rhs, Label* label)
{
ma_sub(rhs, lhs, SetCC);
as_b(label, cond);
}
template <class L>
void
MacroAssembler::branchTest32(Condition cond, Register lhs, Register rhs, L label)
@ -744,17 +785,40 @@ MacroAssembler::branchTest64(Condition cond, Register64 lhs, Register64 rhs, Reg
}
}
void
MacroAssembler::branchTestInt32(Condition cond, Register tag, Label* label)
{
branchTestInt32Impl(cond, tag, label);
}
void
MacroAssembler::branchTestInt32(Condition cond, const Address& address, Label* label)
{
branchTestInt32Impl(cond, address, label);
}
void
MacroAssembler::branchTestInt32(Condition cond, const BaseIndex& address, Label* label)
{
branchTestInt32Impl(cond, address, label);
}
void
MacroAssembler::branchTestInt32(Condition cond, const ValueOperand& src, Label* label)
{
branchTestInt32Impl(cond, src, label);
}
void
MacroAssembler::branchTestInt32Truthy(bool truthy, const ValueOperand& operand, Label* label)
{
Condition c = testInt32Truthy(truthy, operand);
ma_b(label, c);
}
//}}} check_macroassembler_style
// ===============================================================
template <typename T>
void
MacroAssemblerARMCompat::branchAdd32(Condition cond, T src, Register dest, Label* label)
{
asMasm().add32(src, dest);
j(cond, label);
}
void
MacroAssemblerARMCompat::incrementInt32Value(const Address& addr)
{

View File

@ -2942,7 +2942,7 @@ MacroAssemblerARMCompat::unboxValue(const ValueOperand& src, AnyRegister dest)
{
if (dest.isFloat()) {
Label notInt32, end;
branchTestInt32(Assembler::NotEqual, src, &notInt32);
asMasm().branchTestInt32(Assembler::NotEqual, src, &notInt32);
convertInt32ToDouble(src.payloadReg(), dest.fpu());
ma_b(&end);
bind(&notInt32);
@ -3031,7 +3031,7 @@ MacroAssemblerARMCompat::loadInt32OrDouble(const Address& src, FloatRegister des
ScratchRegisterScope scratch(asMasm());
ma_ldr(ToType(src), scratch);
branchTestInt32(Assembler::NotEqual, scratch, &notInt32);
asMasm().branchTestInt32(Assembler::NotEqual, scratch, &notInt32);
ma_ldr(ToPayload(src), scratch);
convertInt32ToDouble(scratch, dest);
ma_b(&end);
@ -3059,7 +3059,7 @@ MacroAssemblerARMCompat::loadInt32OrDouble(Register base, Register index,
// Since we only have one scratch register, we need to stomp over it with
// the tag.
ma_ldr(Address(scratch, NUNBOX32_TYPE_OFFSET), scratch);
branchTestInt32(Assembler::NotEqual, scratch, &notInt32);
asMasm().branchTestInt32(Assembler::NotEqual, scratch, &notInt32);
// Implicitly requires NUNBOX32_PAYLOAD_OFFSET == 0: no offset provided
ma_ldr(DTRAddr(base, DtrRegImmShift(index, LSL, shift)), scratch);
@ -3449,7 +3449,7 @@ MacroAssemblerARMCompat::ensureDouble(const ValueOperand& source, FloatRegister
{
Label isDouble, done;
branchTestDouble(Assembler::Equal, source.typeReg(), &isDouble);
branchTestInt32(Assembler::NotEqual, source.typeReg(), failure);
asMasm().branchTestInt32(Assembler::NotEqual, source.typeReg(), failure);
convertInt32ToDouble(source.payloadReg(), dest);
jump(&done);
@ -4011,39 +4011,6 @@ MacroAssemblerARMCompat::jumpWithPatch(RepatchLabel* label, Condition cond, Labe
return ret;
}
void
MacroAssemblerARMCompat::branchPtrInNurseryRange(Condition cond, Register ptr, Register temp,
Label* label)
{
AutoRegisterScope scratch2(asMasm(), secondScratchReg_);
MOZ_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
MOZ_ASSERT(ptr != temp);
MOZ_ASSERT(ptr != scratch2);
const Nursery& nursery = GetJitContext()->runtime->gcNursery();
uintptr_t startChunk = nursery.start() >> Nursery::ChunkShift;
ma_mov(Imm32(startChunk), scratch2);
as_rsb(scratch2, scratch2, lsr(ptr, Nursery::ChunkShift));
asMasm().branch32(cond == Assembler::Equal ? Assembler::Below : Assembler::AboveOrEqual,
scratch2, Imm32(nursery.numChunks()), label);
}
void
MacroAssemblerARMCompat::branchValueIsNurseryObject(Condition cond, ValueOperand value,
Register temp, Label* label)
{
MOZ_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
Label done;
branchTestObject(Assembler::NotEqual, value, cond == Assembler::Equal ? &done : label);
branchPtrInNurseryRange(cond, value.payloadReg(), temp, label);
bind(&done);
}
namespace js {
namespace jit {
@ -5065,4 +5032,40 @@ MacroAssembler::pushFakeReturnAddress(Register scratch)
return pseudoReturnOffset;
}
// ===============================================================
// Branch functions
void
MacroAssembler::branchPtrInNurseryRange(Condition cond, Register ptr, Register temp,
Label* label)
{
AutoRegisterScope scratch2(*this, secondScratchReg_);
MOZ_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
MOZ_ASSERT(ptr != temp);
MOZ_ASSERT(ptr != scratch2);
const Nursery& nursery = GetJitContext()->runtime->gcNursery();
uintptr_t startChunk = nursery.start() >> Nursery::ChunkShift;
ma_mov(Imm32(startChunk), scratch2);
as_rsb(scratch2, scratch2, lsr(ptr, Nursery::ChunkShift));
branch32(cond == Assembler::Equal ? Assembler::Below : Assembler::AboveOrEqual,
scratch2, Imm32(nursery.numChunks()), label);
}
void
MacroAssembler::branchValueIsNurseryObject(Condition cond, ValueOperand value,
Register temp, Label* label)
{
MOZ_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
Label done;
branchTestObject(Assembler::NotEqual, value, cond == Assembler::Equal ? &done : label);
branchPtrInNurseryRange(cond, value.payloadReg(), temp, label);
bind(&done);
}
//}}} check_macroassembler_style

View File

@ -763,7 +763,7 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM
void loadConstantFloat32(float f, FloatRegister dest);
template<typename T>
void branchTestInt32(Condition cond, const T & t, Label* label) {
void branchTestInt32Impl(Condition cond, const T & t, Label* label) {
Condition c = testInt32(cond, t);
ma_b(label, c);
}
@ -818,10 +818,6 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM
MOZ_ASSERT(cond == Equal || cond == NotEqual);
branchTestValue(cond, val, MagicValue(why), label);
}
void branchTestInt32Truthy(bool truthy, const ValueOperand& operand, Label* label) {
Condition c = testInt32Truthy(truthy, operand);
ma_b(label, c);
}
void branchTestBooleanTruthy(bool truthy, const ValueOperand& operand, Label* label) {
Condition c = testBooleanTruthy(truthy, operand);
ma_b(label, c);
@ -834,10 +830,6 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM
Condition c = testStringTruthy(truthy, value);
ma_b(label, c);
}
void decBranchPtr(Condition cond, Register lhs, Imm32 imm, Label* label) {
ma_sub(imm, lhs, SetCC);
as_b(label, cond);
}
void moveValue(const Value& val, Register type, Register data);
CodeOffsetJump jumpWithPatch(RepatchLabel* label, Condition cond = Always,
@ -845,18 +837,6 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM
CodeOffsetJump backedgeJump(RepatchLabel* label, Label* documentation) {
return jumpWithPatch(label, Always, documentation);
}
template <typename T>
CodeOffsetJump branchPtrWithPatch(Condition cond, Register reg, T ptr, RepatchLabel* label) {
ma_cmp(reg, ptr);
return jumpWithPatch(label, cond);
}
template <typename T>
CodeOffsetJump branchPtrWithPatch(Condition cond, Address addr, T ptr, RepatchLabel* label) {
AutoRegisterScope scratch2(asMasm(), secondScratchReg_);
ma_ldr(addr, scratch2);
ma_cmp(scratch2, ptr);
return jumpWithPatch(label, cond);
}
void loadUnboxedValue(Address address, MIRType type, AnyRegister dest) {
if (dest.isFloat())
@ -985,13 +965,6 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM
// Common interface.
/////////////////////////////////////////////////////////////////
public:
template <typename T> inline void branchAdd32(Condition cond, T src, Register dest, Label* label);
template <typename T>
void branchSub32(Condition cond, T src, Register dest, Label* label) {
ma_sub(src, dest, SetCC);
j(cond, label);
}
void not32(Register reg);
void move32(Imm32 imm, Register dest);
@ -1548,9 +1521,6 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM
as_vmov(VFPRegister(dest).singleOverlay(), VFPRegister(src).singleOverlay());
}
void branchPtrInNurseryRange(Condition cond, Register ptr, Register temp, Label* label);
void branchValueIsNurseryObject(Condition cond, ValueOperand value, Register temp, Label* label);
void loadWasmActivation(Register dest) {
loadPtr(Address(GlobalReg, wasm::ActivationGlobalDataOffset - AsmJSGlobalRegBias), dest);
}

View File

@ -654,6 +654,29 @@ MacroAssembler::branchPtr(Condition cond, wasm::SymbolicAddress lhs, Register rh
branchPtr(cond, scratch, rhs, label);
}
template <typename T>
CodeOffsetJump
MacroAssembler::branchPtrWithPatch(Condition cond, Register lhs, T rhs, RepatchLabel* label)
{
cmpPtr(lhs, rhs);
return jumpWithPatch(label, cond);
}
template <typename T>
CodeOffsetJump
MacroAssembler::branchPtrWithPatch(Condition cond, Address lhs, T rhs, RepatchLabel* label)
{
// The scratch register is unused after the condition codes are set.
{
vixl::UseScratchRegisterScope temps(this);
const Register scratch = temps.AcquireX().asUnsized();
MOZ_ASSERT(scratch != lhs.base);
loadPtr(lhs, scratch);
cmpPtr(scratch, rhs);
}
return jumpWithPatch(label, cond);
}
void
MacroAssembler::branchPrivatePtr(Condition cond, const Address& lhs, Register rhs, Label* label)
{
@ -749,6 +772,29 @@ MacroAssembler::branchTruncateDouble(FloatRegister src, Register dest, Label* fa
And(dest64, dest64, Operand(0xffffffff));
}
template <typename T>
void
MacroAssembler::branchAdd32(Condition cond, T src, Register dest, Label* label)
{
adds32(src, dest);
branch(cond, label);
}
template <typename T>
void
MacroAssembler::branchSub32(Condition cond, T src, Register dest, Label* label)
{
subs32(src, dest);
branch(cond, label);
}
void
MacroAssembler::decBranchPtr(Condition cond, Register lhs, Imm32 rhs, Label* label)
{
Subs(ARMRegister(lhs, 64), ARMRegister(lhs, 64), Operand(rhs.value));
B(cond, label);
}
template <class L>
void
MacroAssembler::branchTest32(Condition cond, Register lhs, Register rhs, L label)
@ -822,6 +868,37 @@ MacroAssembler::branchTest64(Condition cond, Register64 lhs, Register64 rhs, Reg
branchTestPtr(cond, lhs.reg, rhs.reg, label);
}
void
MacroAssembler::branchTestInt32(Condition cond, Register tag, Label* label)
{
branchTestInt32Impl(cond, tag, label);
}
void
MacroAssembler::branchTestInt32(Condition cond, const Address& address, Label* label)
{
branchTestInt32Impl(cond, address, label);
}
void
MacroAssembler::branchTestInt32(Condition cond, const BaseIndex& address, Label* label)
{
branchTestInt32Impl(cond, address, label);
}
void
MacroAssembler::branchTestInt32(Condition cond, const ValueOperand& src, Label* label)
{
branchTestInt32Impl(cond, src, label);
}
void
MacroAssembler::branchTestInt32Truthy(bool truthy, const ValueOperand& operand, Label* label)
{
Condition c = testInt32Truthy(truthy, operand);
B(label, c);
}
//}}} check_macroassembler_style
// ===============================================================
@ -889,6 +966,49 @@ MacroAssemblerCompat::branchTestStackPtr(Condition cond, T t, Label* label)
asMasm().branchTestPtr(cond, getStackPointer(), t, label);
}
// If source is a double, load into dest.
// If source is int32, convert to double and store in dest.
// Else, branch to failure.
void
MacroAssemblerCompat::ensureDouble(const ValueOperand& source, FloatRegister dest, Label* failure)
{
Label isDouble, done;
// TODO: splitTagForTest really should not leak a scratch register.
Register tag = splitTagForTest(source);
{
vixl::UseScratchRegisterScope temps(this);
temps.Exclude(ARMRegister(tag, 64));
branchTestDouble(Assembler::Equal, tag, &isDouble);
asMasm().branchTestInt32(Assembler::NotEqual, tag, failure);
}
convertInt32ToDouble(source.valueReg(), dest);
jump(&done);
bind(&isDouble);
unboxDouble(source, dest);
bind(&done);
}
void
MacroAssemblerCompat::unboxValue(const ValueOperand& src, AnyRegister dest)
{
if (dest.isFloat()) {
Label notInt32, end;
asMasm().branchTestInt32(Assembler::NotEqual, src, &notInt32);
convertInt32ToDouble(src.valueReg(), dest.fpu());
jump(&end);
bind(&notInt32);
unboxDouble(src, dest.fpu());
bind(&end);
} else {
unboxNonDouble(src, dest.gpr());
}
}
} // namespace jit
} // namespace js

View File

@ -217,44 +217,6 @@ MacroAssemblerCompat::handleFailureWithHandlerTail(void* handler)
Br(x1);
}
void
MacroAssemblerCompat::branchPtrInNurseryRange(Condition cond, Register ptr, Register temp,
Label* label)
{
MOZ_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
MOZ_ASSERT(ptr != temp);
MOZ_ASSERT(ptr != ScratchReg && ptr != ScratchReg2); // Both may be used internally.
MOZ_ASSERT(temp != ScratchReg && temp != ScratchReg2);
const Nursery& nursery = GetJitContext()->runtime->gcNursery();
movePtr(ImmWord(-ptrdiff_t(nursery.start())), temp);
asMasm().addPtr(ptr, temp);
asMasm().branchPtr(cond == Assembler::Equal ? Assembler::Below : Assembler::AboveOrEqual,
temp, ImmWord(nursery.nurserySize()), label);
}
void
MacroAssemblerCompat::branchValueIsNurseryObject(Condition cond, ValueOperand value, Register temp,
Label* label)
{
MOZ_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
MOZ_ASSERT(temp != ScratchReg && temp != ScratchReg2); // Both may be used internally.
const Nursery& nursery = GetJitContext()->runtime->gcNursery();
// Avoid creating a bogus ObjectValue below.
if (!nursery.exists())
return;
// 'Value' representing the start of the nursery tagged as a JSObject
Value start = ObjectValue(*reinterpret_cast<JSObject*>(nursery.start()));
movePtr(ImmWord(-ptrdiff_t(start.asRawBits())), temp);
asMasm().addPtr(value.valueReg(), temp);
asMasm().branchPtr(cond == Assembler::Equal ? Assembler::Below : Assembler::AboveOrEqual,
temp, ImmWord(nursery.nurserySize()), label);
}
void
MacroAssemblerCompat::breakpoint()
{
@ -720,6 +682,47 @@ MacroAssembler::pushFakeReturnAddress(Register scratch)
return pseudoReturnOffset;
}
// ===============================================================
// Branch functions
void
MacroAssembler::branchPtrInNurseryRange(Condition cond, Register ptr, Register temp,
Label* label)
{
MOZ_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
MOZ_ASSERT(ptr != temp);
MOZ_ASSERT(ptr != ScratchReg && ptr != ScratchReg2); // Both may be used internally.
MOZ_ASSERT(temp != ScratchReg && temp != ScratchReg2);
const Nursery& nursery = GetJitContext()->runtime->gcNursery();
movePtr(ImmWord(-ptrdiff_t(nursery.start())), temp);
addPtr(ptr, temp);
branchPtr(cond == Assembler::Equal ? Assembler::Below : Assembler::AboveOrEqual,
temp, ImmWord(nursery.nurserySize()), label);
}
void
MacroAssembler::branchValueIsNurseryObject(Condition cond, ValueOperand value, Register temp,
Label* label)
{
MOZ_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
MOZ_ASSERT(temp != ScratchReg && temp != ScratchReg2); // Both may be used internally.
const Nursery& nursery = GetJitContext()->runtime->gcNursery();
// Avoid creating a bogus ObjectValue below.
if (!nursery.exists())
return;
// 'Value' representing the start of the nursery tagged as a JSObject
Value start = ObjectValue(*reinterpret_cast<JSObject*>(nursery.start()));
movePtr(ImmWord(-ptrdiff_t(start.asRawBits())), temp);
addPtr(value.valueReg(), temp);
branchPtr(cond == Assembler::Equal ? Assembler::Below : Assembler::AboveOrEqual,
temp, ImmWord(nursery.nurserySize()), label);
}
//}}} check_macroassembler_style
} // namespace jit

View File

@ -439,30 +439,7 @@ class MacroAssemblerCompat : public vixl::MacroAssembler
return scratch;
}
// If source is a double, load into dest.
// If source is int32, convert to double and store in dest.
// Else, branch to failure.
void ensureDouble(const ValueOperand& source, FloatRegister dest, Label* failure) {
Label isDouble, done;
// TODO: splitTagForTest really should not leak a scratch register.
Register tag = splitTagForTest(source);
{
vixl::UseScratchRegisterScope temps(this);
temps.Exclude(ARMRegister(tag, 64));
branchTestDouble(Assembler::Equal, tag, &isDouble);
branchTestInt32(Assembler::NotEqual, tag, failure);
}
convertInt32ToDouble(source.valueReg(), dest);
jump(&done);
bind(&isDouble);
unboxDouble(source, dest);
bind(&done);
}
inline void ensureDouble(const ValueOperand& source, FloatRegister dest, Label* failure);
void emitSet(Condition cond, Register dest) {
Cset(ARMRegister(dest, 64), cond);
@ -1350,35 +1327,15 @@ class MacroAssemblerCompat : public vixl::MacroAssembler
CodeOffsetJump backedgeJump(RepatchLabel* label, Label* documentation = nullptr) {
return jumpWithPatch(label, Always, documentation);
}
template <typename T>
CodeOffsetJump branchPtrWithPatch(Condition cond, Register reg, T ptr, RepatchLabel* label) {
cmpPtr(reg, ptr);
return jumpWithPatch(label, cond);
}
template <typename T>
CodeOffsetJump branchPtrWithPatch(Condition cond, Address addr, T ptr, RepatchLabel* label) {
// The scratch register is unused after the condition codes are set.
{
vixl::UseScratchRegisterScope temps(this);
const Register scratch = temps.AcquireX().asUnsized();
MOZ_ASSERT(scratch != addr.base);
loadPtr(addr, scratch);
cmpPtr(scratch, ptr);
}
return jumpWithPatch(label, cond);
}
void decBranchPtr(Condition cond, Register lhs, Imm32 imm, Label* label) {
Subs(ARMRegister(lhs, 64), ARMRegister(lhs, 64), Operand(imm.value));
B(cond, label);
}
void branchTestUndefined(Condition cond, Register tag, Label* label) {
Condition c = testUndefined(cond, tag);
B(label, c);
}
void branchTestInt32(Condition cond, Register tag, Label* label) {
Condition c = testInt32(cond, tag);
template<typename T>
void branchTestInt32Impl(Condition cond, T& t, Label* label) {
Condition c = testInt32(cond, t);
B(label, c);
}
void branchTestDouble(Condition cond, Register tag, Label* label) {
@ -1414,10 +1371,6 @@ class MacroAssemblerCompat : public vixl::MacroAssembler
Condition c = testUndefined(cond, address);
B(label, c);
}
void branchTestInt32(Condition cond, const Address& address, Label* label) {
Condition c = testInt32(cond, address);
B(label, c);
}
void branchTestDouble(Condition cond, const Address& address, Label* label) {
Condition c = testDouble(cond, address);
B(label, c);
@ -1453,10 +1406,6 @@ class MacroAssemblerCompat : public vixl::MacroAssembler
Condition c = testUndefined(cond, src);
B(label, c);
}
void branchTestInt32(Condition cond, const ValueOperand& src, Label* label) {
Condition c = testInt32(cond, src);
B(label, c);
}
void branchTestBoolean(Condition cond, const ValueOperand& src, Label* label) {
Condition c = testBoolean(cond, src);
B(label, c);
@ -1492,10 +1441,6 @@ class MacroAssemblerCompat : public vixl::MacroAssembler
Condition c = testUndefined(cond, address);
B(label, c);
}
void branchTestInt32(Condition cond, const BaseIndex& address, Label* label) {
Condition c = testInt32(cond, address);
B(label, c);
}
void branchTestBoolean(Condition cond, const BaseIndex& address, Label* label) {
Condition c = testBoolean(cond, address);
B(label, c);
@ -1649,20 +1594,8 @@ class MacroAssemblerCompat : public vixl::MacroAssembler
unboxNonDouble(dest, dest);
}
void unboxValue(const ValueOperand& src, AnyRegister dest) {
if (dest.isFloat()) {
Label notInt32, end;
branchTestInt32(Assembler::NotEqual, src, &notInt32);
convertInt32ToDouble(src.valueReg(), dest.fpu());
jump(&end);
bind(&notInt32);
unboxDouble(src, dest.fpu());
bind(&end);
} else {
unboxNonDouble(src, dest.gpr());
}
inline void unboxValue(const ValueOperand& src, AnyRegister dest);
}
void unboxString(const ValueOperand& operand, Register dest) {
unboxNonDouble(operand, dest);
}
@ -2036,10 +1969,6 @@ class MacroAssemblerCompat : public vixl::MacroAssembler
Tst(payload32, payload32);
return truthy ? NonZero : Zero;
}
void branchTestInt32Truthy(bool truthy, const ValueOperand& operand, Label* label) {
Condition c = testInt32Truthy(truthy, operand);
B(label, c);
}
void branchTestDoubleTruthy(bool truthy, FloatRegister reg, Label* label) {
Fcmp(ARMFPRegister(reg, 64), 0.0);
@ -2193,9 +2122,6 @@ class MacroAssemblerCompat : public vixl::MacroAssembler
storeValue(JSVAL_TYPE_INT32, scratch, dest);
}
void branchPtrInNurseryRange(Condition cond, Register ptr, Register temp, Label* label);
void branchValueIsNurseryObject(Condition cond, ValueOperand value, Register temp, Label* label);
void profilerEnterFrame(Register framePtr, Register scratch) {
AbsoluteAddress activation(GetJitContext()->runtime->addressOfProfilingActivation());
loadPtr(activation, scratch);
@ -2558,17 +2484,6 @@ class MacroAssemblerCompat : public vixl::MacroAssembler
Ucvtf(ARMFPRegister(dest, 64), ARMRegister(src.reg, 64));
}
template <typename T>
void branchAdd32(Condition cond, T src, Register dest, Label* label) {
adds32(src, dest);
branch(cond, label);
}
template <typename T>
void branchSub32(Condition cond, T src, Register dest, Label* label) {
subs32(src, dest);
branch(cond, label);
}
void clampCheck(Register r, Label* handleNotAnInt) {
MOZ_CRASH("clampCheck");
}

View File

@ -346,6 +346,31 @@ MacroAssembler::branchPtr(Condition cond, wasm::SymbolicAddress lhs, Register rh
branchPtr(cond, SecondScratchReg, rhs, label);
}
template <typename T>
CodeOffsetJump
MacroAssembler::branchPtrWithPatch(Condition cond, Register lhs, T rhs, RepatchLabel* label)
{
movePtr(rhs, ScratchRegister);
Label skipJump;
ma_b(lhs, ScratchRegister, &skipJump, InvertCondition(cond), ShortJump);
CodeOffsetJump off = jumpWithPatch(label);
bind(&skipJump);
return off;
}
template <typename T>
CodeOffsetJump
MacroAssembler::branchPtrWithPatch(Condition cond, Address lhs, T rhs, RepatchLabel* label)
{
loadPtr(lhs, SecondScratchReg);
movePtr(rhs, ScratchRegister);
Label skipJump;
ma_b(SecondScratchReg, ScratchRegister, &skipJump, InvertCondition(cond), ShortJump);
CodeOffsetJump off = jumpWithPatch(label);
bind(&skipJump);
return off;
}
void
MacroAssembler::branchFloat(DoubleCondition cond, FloatRegister lhs, FloatRegister rhs,
Label* label)
@ -385,6 +410,44 @@ MacroAssembler::branchTruncateDouble(FloatRegister src, Register dest, Label* fa
ma_b(dest, Imm32(INT32_MIN), fail, Assembler::Equal);
}
template <typename T>
void
MacroAssembler::branchAdd32(Condition cond, T src, Register dest, Label* overflow)
{
switch (cond) {
case Overflow:
ma_addTestOverflow(dest, dest, src, overflow);
break;
default:
MOZ_CRASH("NYI");
}
}
template <typename T>
void
MacroAssembler::branchSub32(Condition cond, T src, Register dest, Label* overflow)
{
switch (cond) {
case Overflow:
ma_subTestOverflow(dest, dest, src, overflow);
break;
case NonZero:
case Zero:
ma_subu(dest, src);
ma_b(dest, dest, overflow, cond);
break;
default:
MOZ_CRASH("NYI");
}
}
void
MacroAssembler::decBranchPtr(Condition cond, Register lhs, Imm32 rhs, Label* label)
{
subPtr(rhs, lhs);
branchPtr(cond, lhs, Imm32(0), label);
}
template <class L>
void
MacroAssembler::branchTest32(Condition cond, Register lhs, Register rhs, L label)
@ -446,6 +509,29 @@ MacroAssembler::branchTestPtr(Condition cond, const Address& lhs, Imm32 rhs, Lab
branchTestPtr(cond, SecondScratchReg, rhs, label);
}
void
MacroAssembler::branchTestInt32(Condition cond, Register tag, Label* label)
{
MOZ_ASSERT(cond == Equal || cond == NotEqual);
ma_b(tag, ImmTag(JSVAL_TAG_INT32), label, cond);
}
void
MacroAssembler::branchTestInt32(Condition cond, const Address& address, Label* label)
{
MOZ_ASSERT(cond == Equal || cond == NotEqual);
extractTag(address, SecondScratchReg);
ma_b(SecondScratchReg, ImmTag(JSVAL_TAG_INT32), label, cond);
}
void
MacroAssembler::branchTestInt32(Condition cond, const BaseIndex& address, Label* label)
{
MOZ_ASSERT(cond == Equal || cond == NotEqual);
extractTag(address, SecondScratchReg);
ma_b(SecondScratchReg, ImmTag(JSVAL_TAG_INT32), label, cond);
}
//}}} check_macroassembler_style
// ===============================================================

View File

@ -1276,4 +1276,19 @@ MacroAssembler::pushFakeReturnAddress(Register scratch)
return retAddr;
}
void
MacroAssembler::branchPtrInNurseryRange(Condition cond, Register ptr, Register temp,
Label* label)
{
MOZ_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
MOZ_ASSERT(ptr != temp);
MOZ_ASSERT(ptr != SecondScratchReg);
const Nursery& nursery = GetJitContext()->runtime->gcNursery();
movePtr(ImmWord(-ptrdiff_t(nursery.start())), SecondScratchReg);
addPtr(ptr, SecondScratchReg);
branchPtr(cond == Assembler::Equal ? Assembler::Below : Assembler::AboveOrEqual,
SecondScratchReg, Imm32(nursery.nurserySize()), label);
}
//}}} check_macroassembler_style

View File

@ -274,6 +274,21 @@ MacroAssembler::branchTest64(Condition cond, Register64 lhs, Register64 rhs, Reg
}
}
void
MacroAssembler::branchTestInt32(Condition cond, const ValueOperand& value, Label* label)
{
MOZ_ASSERT(cond == Equal || cond == NotEqual);
ma_b(value.typeReg(), ImmType(JSVAL_TYPE_INT32), label, cond);
}
void
MacroAssembler::branchTestInt32Truthy(bool b, const ValueOperand& value, Label* label)
{
as_and(ScratchRegister, value.payloadReg(), value.payloadReg());
ma_b(ScratchRegister, ScratchRegister, label, b ? NonZero : Zero);
}
//}}} check_macroassembler_style
// ===============================================================
@ -300,13 +315,6 @@ MacroAssemblerMIPSCompat::retn(Imm32 n) {
as_nop();
}
void
MacroAssemblerMIPSCompat::decBranchPtr(Condition cond, Register lhs, Imm32 imm, Label* label)
{
asMasm().subPtr(imm, lhs);
asMasm().branchPtr(cond, lhs, Imm32(0), label);
}
} // namespace jit
} // namespace js

View File

@ -1126,36 +1126,6 @@ MacroAssemblerMIPSCompat::branchTestPrimitive(Condition cond, Register tag, Labe
(cond == Equal) ? Below : AboveOrEqual);
}
void
MacroAssemblerMIPSCompat::branchTestInt32(Condition cond, const ValueOperand& value, Label* label)
{
MOZ_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
ma_b(value.typeReg(), ImmType(JSVAL_TYPE_INT32), label, cond);
}
void
MacroAssemblerMIPSCompat::branchTestInt32(Condition cond, Register tag, Label* label)
{
MOZ_ASSERT(cond == Equal || cond == NotEqual);
ma_b(tag, ImmTag(JSVAL_TAG_INT32), label, cond);
}
void
MacroAssemblerMIPSCompat::branchTestInt32(Condition cond, const Address& address, Label* label)
{
MOZ_ASSERT(cond == Equal || cond == NotEqual);
extractTag(address, SecondScratchReg);
ma_b(SecondScratchReg, ImmTag(JSVAL_TAG_INT32), label, cond);
}
void
MacroAssemblerMIPSCompat::branchTestInt32(Condition cond, const BaseIndex& src, Label* label)
{
MOZ_ASSERT(cond == Equal || cond == NotEqual);
extractTag(src, SecondScratchReg);
ma_b(SecondScratchReg, ImmTag(JSVAL_TAG_INT32), label, cond);
}
void
MacroAssemblerMIPSCompat:: branchTestBoolean(Condition cond, const ValueOperand& value,
Label* label)
@ -1549,7 +1519,7 @@ MacroAssemblerMIPSCompat::unboxValue(const ValueOperand& src, AnyRegister dest)
{
if (dest.isFloat()) {
Label notInt32, end;
branchTestInt32(Assembler::NotEqual, src, &notInt32);
asMasm().branchTestInt32(Assembler::NotEqual, src, &notInt32);
convertInt32ToDouble(src.payloadReg(), dest.fpu());
ma_b(&end, ShortJump);
bind(&notInt32);
@ -1624,7 +1594,7 @@ MacroAssemblerMIPSCompat::loadInt32OrDouble(const Address& src, FloatRegister de
Label notInt32, end;
// If it's an int, convert it to double.
ma_lw(SecondScratchReg, Address(src.base, src.offset + TAG_OFFSET));
branchTestInt32(Assembler::NotEqual, SecondScratchReg, &notInt32);
asMasm().branchTestInt32(Assembler::NotEqual, SecondScratchReg, &notInt32);
ma_lw(SecondScratchReg, Address(src.base, src.offset + PAYLOAD_OFFSET));
convertInt32ToDouble(SecondScratchReg, dest);
ma_b(&end, ShortJump);
@ -1646,7 +1616,7 @@ MacroAssemblerMIPSCompat::loadInt32OrDouble(Register base, Register index,
computeScaledAddress(BaseIndex(base, index, ShiftToScale(shift)), SecondScratchReg);
// Since we only have one scratch, we need to stomp over it with the tag.
load32(Address(SecondScratchReg, TAG_OFFSET), SecondScratchReg);
branchTestInt32(Assembler::NotEqual, SecondScratchReg, &notInt32);
asMasm().branchTestInt32(Assembler::NotEqual, SecondScratchReg, &notInt32);
computeScaledAddress(BaseIndex(base, index, ShiftToScale(shift)), SecondScratchReg);
load32(Address(SecondScratchReg, PAYLOAD_OFFSET), SecondScratchReg);
@ -1668,13 +1638,6 @@ MacroAssemblerMIPSCompat::loadConstantDouble(double dp, FloatRegister dest)
ma_lid(dest, dp);
}
void
MacroAssemblerMIPSCompat::branchTestInt32Truthy(bool b, const ValueOperand& value, Label* label)
{
as_and(ScratchRegister, value.payloadReg(), value.payloadReg());
ma_b(ScratchRegister, ScratchRegister, label, b ? NonZero : Zero);
}
void
MacroAssemblerMIPSCompat::branchTestStringTruthy(bool b, const ValueOperand& value, Label* label)
{
@ -2052,7 +2015,7 @@ MacroAssemblerMIPSCompat::ensureDouble(const ValueOperand& source, FloatRegister
{
Label isDouble, done;
branchTestDouble(Assembler::Equal, source.typeReg(), &isDouble);
branchTestInt32(Assembler::NotEqual, source.typeReg(), failure);
asMasm().branchTestInt32(Assembler::NotEqual, source.typeReg(), failure);
convertInt32ToDouble(source.payloadReg(), dest);
jump(&done);
@ -2327,35 +2290,6 @@ MacroAssemblerMIPSCompat::toggledCall(JitCode* target, bool enabled)
return offset;
}
void
MacroAssemblerMIPSCompat::branchPtrInNurseryRange(Condition cond, Register ptr, Register temp,
Label* label)
{
MOZ_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
MOZ_ASSERT(ptr != temp);
MOZ_ASSERT(ptr != SecondScratchReg);
const Nursery& nursery = GetJitContext()->runtime->gcNursery();
movePtr(ImmWord(-ptrdiff_t(nursery.start())), SecondScratchReg);
asMasm().addPtr(ptr, SecondScratchReg);
asMasm().branchPtr(cond == Assembler::Equal ? Assembler::Below : Assembler::AboveOrEqual,
SecondScratchReg, Imm32(nursery.nurserySize()), label);
}
void
MacroAssemblerMIPSCompat::branchValueIsNurseryObject(Condition cond, ValueOperand value,
Register temp, Label* label)
{
MOZ_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
Label done;
branchTestObject(Assembler::NotEqual, value, cond == Assembler::Equal ? &done : label);
branchPtrInNurseryRange(cond, value.payloadReg(), temp, label);
bind(&done);
}
void
MacroAssemblerMIPSCompat::profilerEnterFrame(Register framePtr, Register scratch)
{
@ -2541,4 +2475,21 @@ MacroAssembler::callWithABINoProfiler(const Address& fun, MoveOp::Type result)
callWithABIPost(stackAdjust, result);
}
// ===============================================================
// Branch functions
void
MacroAssembler::branchValueIsNurseryObject(Condition cond, ValueOperand value,
Register temp, Label* label)
{
MOZ_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
Label done;
branchTestObject(Assembler::NotEqual, value, cond == Assembler::Equal ? &done : label);
branchPtrInNurseryRange(cond, value.payloadReg(), temp, label);
bind(&done);
}
//}}} check_macroassembler_style

View File

@ -375,11 +375,6 @@ class MacroAssemblerMIPSCompat : public MacroAssemblerMIPS
void int32ValueToFloat32(const ValueOperand& operand, FloatRegister dest);
void loadConstantFloat32(float f, FloatRegister dest);
void branchTestInt32(Condition cond, const ValueOperand& value, Label* label);
void branchTestInt32(Condition cond, Register tag, Label* label);
void branchTestInt32(Condition cond, const Address& address, Label* label);
void branchTestInt32(Condition cond, const BaseIndex& src, Label* label);
void branchTestBoolean(Condition cond, const ValueOperand& value, Label* label);
void branchTestBoolean(Condition cond, Register tag, Label* label);
void branchTestBoolean(Condition cond, const Address& address, Label* label);
@ -432,16 +427,12 @@ class MacroAssemblerMIPSCompat : public MacroAssemblerMIPS
branchTestValue(cond, val, MagicValue(why), label);
}
void branchTestInt32Truthy(bool b, const ValueOperand& value, Label* label);
void branchTestStringTruthy(bool b, const ValueOperand& value, Label* label);
void branchTestDoubleTruthy(bool b, FloatRegister value, Label* label);
void branchTestBooleanTruthy(bool b, const ValueOperand& operand, Label* label);
inline void decBranchPtr(Condition cond, Register lhs, Imm32 imm, Label* label);
// higher level tag testing code
Operand ToPayload(Operand base);
Address ToPayload(Address base) {
@ -462,27 +453,6 @@ class MacroAssemblerMIPSCompat : public MacroAssemblerMIPS
CodeOffsetJump backedgeJump(RepatchLabel* label, Label* documentation = nullptr);
CodeOffsetJump jumpWithPatch(RepatchLabel* label, Label* documentation = nullptr);
template <typename T>
CodeOffsetJump branchPtrWithPatch(Condition cond, Register reg, T ptr, RepatchLabel* label) {
movePtr(ptr, ScratchRegister);
Label skipJump;
ma_b(reg, ScratchRegister, &skipJump, InvertCondition(cond), ShortJump);
CodeOffsetJump off = jumpWithPatch(label);
bind(&skipJump);
return off;
}
template <typename T>
CodeOffsetJump branchPtrWithPatch(Condition cond, Address addr, T ptr, RepatchLabel* label) {
loadPtr(addr, SecondScratchReg);
movePtr(ptr, ScratchRegister);
Label skipJump;
ma_b(SecondScratchReg, ScratchRegister, &skipJump, InvertCondition(cond), ShortJump);
CodeOffsetJump off = jumpWithPatch(label);
bind(&skipJump);
return off;
}
void loadUnboxedValue(Address address, MIRType type, AnyRegister dest) {
if (dest.isFloat())
loadInt32OrDouble(address, dest.fpu());
@ -908,32 +878,6 @@ class MacroAssemblerMIPSCompat : public MacroAssemblerMIPS
inline void incrementInt32Value(const Address& addr);
template <typename T>
void branchAdd32(Condition cond, T src, Register dest, Label* overflow) {
switch (cond) {
case Overflow:
ma_addTestOverflow(dest, dest, src, overflow);
break;
default:
MOZ_CRASH("NYI");
}
}
template <typename T>
void branchSub32(Condition cond, T src, Register dest, Label* overflow) {
switch (cond) {
case Overflow:
ma_subTestOverflow(dest, dest, src, overflow);
break;
case NonZero:
case Zero:
ma_subu(dest, src);
ma_b(dest, dest, overflow, cond);
break;
default:
MOZ_CRASH("NYI");
}
}
void move32(Imm32 imm, Register dest);
void move32(Register src, Register dest);
@ -1132,10 +1076,6 @@ class MacroAssemblerMIPSCompat : public MacroAssemblerMIPS
as_movs(dest, src);
}
void branchPtrInNurseryRange(Condition cond, Register ptr, Register temp, Label* label);
void branchValueIsNurseryObject(Condition cond, ValueOperand value, Register temp,
Label* label);
void loadWasmActivation(Register dest) {
loadPtr(Address(GlobalReg, wasm::ActivationGlobalDataOffset - AsmJSGlobalRegBias), dest);
}

View File

@ -210,6 +210,21 @@ MacroAssembler::branchTest64(Condition cond, Register64 lhs, Register64 rhs, Reg
branchTestPtr(cond, lhs.reg, rhs.reg, label);
}
void
MacroAssembler::branchTestInt32(Condition cond, const ValueOperand& value, Label* label)
{
MOZ_ASSERT(cond == Equal || cond == NotEqual);
splitTag(value, SecondScratchReg);
ma_b(SecondScratchReg, ImmTag(JSVAL_TAG_INT32), label, cond);
}
void
MacroAssembler::branchTestInt32Truthy(bool b, const ValueOperand& value, Label* label)
{
ma_dext(ScratchRegister, value.valueReg(), Imm32(0), Imm32(32));
ma_b(ScratchRegister, ScratchRegister, label, b ? NonZero : Zero);
}
//}}} check_macroassembler_style
// ===============================================================
@ -237,13 +252,6 @@ MacroAssemblerMIPS64Compat::retn(Imm32 n)
as_nop();
}
void
MacroAssemblerMIPS64Compat::decBranchPtr(Condition cond, Register lhs, Imm32 imm, Label* label)
{
asMasm().subPtr(imm, lhs);
asMasm().branchPtr(cond, lhs, Imm32(0), label);
}
} // namespace jit
} // namespace js

View File

@ -1254,37 +1254,6 @@ MacroAssemblerMIPS64Compat::branchTestPrimitive(Condition cond, Register tag, La
(cond == Equal) ? Below : AboveOrEqual);
}
void
MacroAssemblerMIPS64Compat::branchTestInt32(Condition cond, const ValueOperand& value, Label* label)
{
MOZ_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
splitTag(value, SecondScratchReg);
ma_b(SecondScratchReg, ImmTag(JSVAL_TAG_INT32), label, cond);
}
void
MacroAssemblerMIPS64Compat::branchTestInt32(Condition cond, Register tag, Label* label)
{
MOZ_ASSERT(cond == Equal || cond == NotEqual);
ma_b(tag, ImmTag(JSVAL_TAG_INT32), label, cond);
}
void
MacroAssemblerMIPS64Compat::branchTestInt32(Condition cond, const Address& address, Label* label)
{
MOZ_ASSERT(cond == Equal || cond == NotEqual);
extractTag(address, SecondScratchReg);
ma_b(SecondScratchReg, ImmTag(JSVAL_TAG_INT32), label, cond);
}
void
MacroAssemblerMIPS64Compat::branchTestInt32(Condition cond, const BaseIndex& src, Label* label)
{
MOZ_ASSERT(cond == Equal || cond == NotEqual);
extractTag(src, SecondScratchReg);
ma_b(SecondScratchReg, ImmTag(JSVAL_TAG_INT32), label, cond);
}
void
MacroAssemblerMIPS64Compat:: branchTestBoolean(Condition cond, const ValueOperand& value,
Label* label)
@ -1775,7 +1744,7 @@ MacroAssemblerMIPS64Compat::unboxValue(const ValueOperand& src, AnyRegister dest
{
if (dest.isFloat()) {
Label notInt32, end;
branchTestInt32(Assembler::NotEqual, src, &notInt32);
asMasm().branchTestInt32(Assembler::NotEqual, src, &notInt32);
convertInt32ToDouble(src.valueReg(), dest.fpu());
ma_b(&end, ShortJump);
bind(&notInt32);
@ -1849,7 +1818,7 @@ MacroAssemblerMIPS64Compat::loadInt32OrDouble(const Address& src, FloatRegister
// If it's an int, convert it to double.
loadPtr(Address(src.base, src.offset), ScratchRegister);
ma_dsrl(SecondScratchReg, ScratchRegister, Imm32(JSVAL_TAG_SHIFT));
branchTestInt32(Assembler::NotEqual, SecondScratchReg, &notInt32);
asMasm().branchTestInt32(Assembler::NotEqual, SecondScratchReg, &notInt32);
loadPtr(Address(src.base, src.offset), SecondScratchReg);
convertInt32ToDouble(SecondScratchReg, dest);
ma_b(&end, ShortJump);
@ -1870,7 +1839,7 @@ MacroAssemblerMIPS64Compat::loadInt32OrDouble(const BaseIndex& addr, FloatRegist
// Since we only have one scratch, we need to stomp over it with the tag.
loadPtr(Address(SecondScratchReg, 0), ScratchRegister);
ma_dsrl(SecondScratchReg, ScratchRegister, Imm32(JSVAL_TAG_SHIFT));
branchTestInt32(Assembler::NotEqual, SecondScratchReg, &notInt32);
asMasm().branchTestInt32(Assembler::NotEqual, SecondScratchReg, &notInt32);
computeScaledAddress(addr, SecondScratchReg);
loadPtr(Address(SecondScratchReg, 0), SecondScratchReg);
@ -1892,13 +1861,6 @@ MacroAssemblerMIPS64Compat::loadConstantDouble(double dp, FloatRegister dest)
ma_lid(dest, dp);
}
void
MacroAssemblerMIPS64Compat::branchTestInt32Truthy(bool b, const ValueOperand& value, Label* label)
{
ma_dext(ScratchRegister, value.valueReg(), Imm32(0), Imm32(32));
ma_b(ScratchRegister, ScratchRegister, label, b ? NonZero : Zero);
}
void
MacroAssemblerMIPS64Compat::branchTestStringTruthy(bool b, const ValueOperand& value, Label* label)
{
@ -2213,7 +2175,7 @@ MacroAssemblerMIPS64Compat::ensureDouble(const ValueOperand& source, FloatRegist
Label isDouble, done;
Register tag = splitTagForTest(source);
branchTestDouble(Assembler::Equal, tag, &isDouble);
branchTestInt32(Assembler::NotEqual, tag, failure);
asMasm().branchTestInt32(Assembler::NotEqual, tag, failure);
unboxInt32(source, ScratchRegister);
convertInt32ToDouble(ScratchRegister, dest);
@ -2499,37 +2461,6 @@ MacroAssemblerMIPS64Compat::toggledCall(JitCode* target, bool enabled)
return offset;
}
void
MacroAssemblerMIPS64Compat::branchPtrInNurseryRange(Condition cond, Register ptr, Register temp,
Label* label)
{
MOZ_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
MOZ_ASSERT(ptr != temp);
MOZ_ASSERT(ptr != SecondScratchReg);
const Nursery& nursery = GetJitContext()->runtime->gcNursery();
movePtr(ImmWord(-ptrdiff_t(nursery.start())), SecondScratchReg);
asMasm().addPtr(ptr, SecondScratchReg);
asMasm().branchPtr(cond == Assembler::Equal ? Assembler::Below : Assembler::AboveOrEqual,
SecondScratchReg, Imm32(nursery.nurserySize()), label);
}
void
MacroAssemblerMIPS64Compat::branchValueIsNurseryObject(Condition cond, ValueOperand value,
Register temp, Label* label)
{
MOZ_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
// 'Value' representing the start of the nursery tagged as a JSObject
const Nursery& nursery = GetJitContext()->runtime->gcNursery();
Value start = ObjectValue(*reinterpret_cast<JSObject *>(nursery.start()));
movePtr(ImmWord(-ptrdiff_t(start.asRawBits())), SecondScratchReg);
asMasm().addPtr(value.valueReg(), SecondScratchReg);
asMasm().branchPtr(cond == Assembler::Equal ? Assembler::Below : Assembler::AboveOrEqual,
SecondScratchReg, Imm32(nursery.nurserySize()), label);
}
void
MacroAssemblerMIPS64Compat::profilerEnterFrame(Register framePtr, Register scratch)
{
@ -2698,4 +2629,23 @@ MacroAssembler::callWithABINoProfiler(const Address& fun, MoveOp::Type result)
callWithABIPost(stackAdjust, result);
}
// ===============================================================
// Branch functions
void
MacroAssembler::branchValueIsNurseryObject(Condition cond, ValueOperand value,
Register temp, Label* label)
{
MOZ_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
// 'Value' representing the start of the nursery tagged as a JSObject
const Nursery& nursery = GetJitContext()->runtime->gcNursery();
Value start = ObjectValue(*reinterpret_cast<JSObject *>(nursery.start()));
movePtr(ImmWord(-ptrdiff_t(start.asRawBits())), SecondScratchReg);
addPtr(value.valueReg(), SecondScratchReg);
branchPtr(cond == Assembler::Equal ? Assembler::Below : Assembler::AboveOrEqual,
SecondScratchReg, Imm32(nursery.nurserySize()), label);
}
//}}} check_macroassembler_style

View File

@ -416,11 +416,6 @@ class MacroAssemblerMIPS64Compat : public MacroAssemblerMIPS64
void int32ValueToFloat32(const ValueOperand& operand, FloatRegister dest);
void loadConstantFloat32(float f, FloatRegister dest);
void branchTestInt32(Condition cond, const ValueOperand& value, Label* label);
void branchTestInt32(Condition cond, Register tag, Label* label);
void branchTestInt32(Condition cond, const Address& address, Label* label);
void branchTestInt32(Condition cond, const BaseIndex& src, Label* label);
void branchTestBoolean(Condition cond, const ValueOperand& value, Label* label);
void branchTestBoolean(Condition cond, Register tag, Label* label);
void branchTestBoolean(Condition cond, const Address& address, Label* label);
@ -473,16 +468,12 @@ class MacroAssemblerMIPS64Compat : public MacroAssemblerMIPS64
branchTestValue(cond, val, MagicValue(why), label);
}
void branchTestInt32Truthy(bool b, const ValueOperand& value, Label* label);
void branchTestStringTruthy(bool b, const ValueOperand& value, Label* label);
void branchTestDoubleTruthy(bool b, FloatRegister value, Label* label);
void branchTestBooleanTruthy(bool b, const ValueOperand& operand, Label* label);
inline void decBranchPtr(Condition cond, Register lhs, Imm32 imm, Label* label);
// higher level tag testing code
Address ToPayload(Address value) {
return value;
@ -493,27 +484,6 @@ class MacroAssemblerMIPS64Compat : public MacroAssemblerMIPS64
CodeOffsetJump backedgeJump(RepatchLabel* label, Label* documentation = nullptr);
CodeOffsetJump jumpWithPatch(RepatchLabel* label, Label* documentation = nullptr);
template <typename T>
CodeOffsetJump branchPtrWithPatch(Condition cond, Register reg, T ptr, RepatchLabel* label) {
movePtr(ptr, ScratchRegister);
Label skipJump;
ma_b(reg, ScratchRegister, &skipJump, InvertCondition(cond), ShortJump);
CodeOffsetJump off = jumpWithPatch(label);
bind(&skipJump);
return off;
}
template <typename T>
CodeOffsetJump branchPtrWithPatch(Condition cond, Address addr, T ptr, RepatchLabel* label) {
loadPtr(addr, SecondScratchReg);
movePtr(ptr, ScratchRegister);
Label skipJump;
ma_b(SecondScratchReg, ScratchRegister, &skipJump, InvertCondition(cond), ShortJump);
CodeOffsetJump off = jumpWithPatch(label);
bind(&skipJump);
return off;
}
template <typename T>
void loadUnboxedValue(const T& address, MIRType type, AnyRegister dest) {
if (dest.isFloat())
@ -922,32 +892,6 @@ class MacroAssemblerMIPS64Compat : public MacroAssemblerMIPS64
inline void incrementInt32Value(const Address& addr);
template <typename T>
void branchAdd32(Condition cond, T src, Register dest, Label* overflow) {
switch (cond) {
case Overflow:
ma_addTestOverflow(dest, dest, src, overflow);
break;
default:
MOZ_CRASH("NYI");
}
}
template <typename T>
void branchSub32(Condition cond, T src, Register dest, Label* overflow) {
switch (cond) {
case Overflow:
ma_subTestOverflow(dest, dest, src, overflow);
break;
case NonZero:
case Zero:
ma_subu(dest, src);
ma_b(dest, dest, overflow, cond);
break;
default:
MOZ_CRASH("NYI");
}
}
void move32(Imm32 imm, Register dest);
void move32(Register src, Register dest);
@ -1140,10 +1084,6 @@ class MacroAssemblerMIPS64Compat : public MacroAssemblerMIPS64
as_movs(dest, src);
}
void branchPtrInNurseryRange(Condition cond, Register ptr, Register temp, Label* label);
void branchValueIsNurseryObject(Condition cond, ValueOperand value, Register temp,
Label* label);
void loadWasmActivation(Register dest) {
loadPtr(Address(GlobalReg, wasm::ActivationGlobalDataOffset - AsmJSGlobalRegBias), dest);
}

View File

@ -47,7 +47,7 @@
#define I64(v) static_cast<int64_t>(v)
#define U64(v) static_cast<uint64_t>(v)
#define I128(v) static_cast<__int128_t>(v)
#define U128(v) static_cast<unsigned __int128_t>(v)
#define U128(v) static_cast<__uint128_t>(v)
namespace js {
namespace jit {

View File

@ -233,8 +233,6 @@ class MacroAssemblerNone : public Assembler
CodeOffsetJump jumpWithPatch(RepatchLabel*, Label* doc = nullptr) { MOZ_CRASH(); }
CodeOffsetJump jumpWithPatch(RepatchLabel*, Condition, Label* doc = nullptr) { MOZ_CRASH(); }
CodeOffsetJump backedgeJump(RepatchLabel* label, Label* doc = nullptr) { MOZ_CRASH(); }
template <typename T, typename S>
CodeOffsetJump branchPtrWithPatch(Condition, T, S, RepatchLabel*) { MOZ_CRASH(); }
template <typename T, typename S> void branchTestValue(Condition, T, S, Label*) { MOZ_CRASH(); }
void testNullSet(Condition, ValueOperand, Register) { MOZ_CRASH(); }
@ -244,9 +242,6 @@ class MacroAssemblerNone : public Assembler
template <typename T, typename S> void cmpPtrSet(Condition, T, S, Register) { MOZ_CRASH(); }
template <typename T, typename S> void cmp32Set(Condition, T, S, Register) { MOZ_CRASH(); }
template <typename T, typename S> void branchAdd32(Condition, T, S, Label*) { MOZ_CRASH(); }
template <typename T, typename S> void branchSub32(Condition, T, S, Label*) { MOZ_CRASH(); }
template <typename T, typename S> void decBranchPtr(Condition, T, S, Label*) { MOZ_CRASH(); }
template <typename T, typename S> void mov(T, S) { MOZ_CRASH(); }
template <typename T, typename S> void movq(T, S) { MOZ_CRASH(); }
template <typename T, typename S> void movePtr(T, S) { MOZ_CRASH(); }
@ -351,7 +346,6 @@ class MacroAssemblerNone : public Assembler
Register splitTagForTest(ValueOperand) { MOZ_CRASH(); }
template <typename T> void branchTestUndefined(Condition, T, Label*) { MOZ_CRASH(); }
template <typename T> void branchTestInt32(Condition, T, Label*) { MOZ_CRASH(); }
template <typename T> void branchTestBoolean(Condition, T, Label*) { MOZ_CRASH(); }
template <typename T> void branchTestDouble(Condition, T, Label*) { MOZ_CRASH(); }
template <typename T> void branchTestNull(Condition, T, Label*) { MOZ_CRASH(); }
@ -400,7 +394,6 @@ class MacroAssemblerNone : public Assembler
void loadConstantFloat32(float, FloatRegister) { MOZ_CRASH(); }
Condition testInt32Truthy(bool, ValueOperand) { MOZ_CRASH(); }
Condition testStringTruthy(bool, ValueOperand) { MOZ_CRASH(); }
void branchTestInt32Truthy(bool, ValueOperand, Label*) { MOZ_CRASH(); }
void branchTestBooleanTruthy(bool, ValueOperand, Label*) { MOZ_CRASH(); }
void branchTestStringTruthy(bool, ValueOperand, Label*) { MOZ_CRASH(); }
void branchTestDoubleTruthy(bool, FloatRegister, Label*) { MOZ_CRASH(); }
@ -415,9 +408,6 @@ class MacroAssemblerNone : public Assembler
void ensureDouble(ValueOperand, FloatRegister, Label*) { MOZ_CRASH(); }
void handleFailureWithHandlerTail(void*) { MOZ_CRASH(); }
void branchPtrInNurseryRange(Condition, Register, Register, Label*) { MOZ_CRASH(); }
void branchValueIsNurseryObject(Condition, ValueOperand, Register, Label*) { MOZ_CRASH(); }
void buildFakeExitFrame(Register, uint32_t*) { MOZ_CRASH(); }
bool buildOOLFakeExitFrame(void*) { MOZ_CRASH(); }
void loadWasmActivation(Register) { MOZ_CRASH(); }

View File

@ -356,6 +356,36 @@ MacroAssembler::branchTest64(Condition cond, Register64 lhs, Register64 rhs, Reg
branchTestPtr(cond, lhs.reg, rhs.reg, label);
}
void
MacroAssembler::branchTestInt32(Condition cond, Register tag, Label* label)
{
cond = testInt32(cond, tag);
j(cond, label);
}
void
MacroAssembler::branchTestInt32(Condition cond, const Address& address, Label* label)
{
MOZ_ASSERT(cond == Equal || cond == NotEqual);
branchTestInt32Impl(cond, Operand(address), label);
}
void
MacroAssembler::branchTestInt32(Condition cond, const BaseIndex& address, Label* label)
{
ScratchRegisterScope scratch(*this);
splitTag(address, scratch);
branchTestInt32(cond, scratch, label);
}
void
MacroAssembler::branchTestInt32(Condition cond, const ValueOperand& src, Label* label)
{
ScratchRegisterScope scratch(*this);
splitTag(src, scratch);
branchTestInt32(cond, scratch, label);
}
//}}} check_macroassembler_style
// ===============================================================
@ -381,6 +411,55 @@ MacroAssemblerX64::branchPtrImpl(Condition cond, const T& lhs, const S& rhs, Lab
j(cond, label);
}
void
MacroAssemblerX64::unboxValue(const ValueOperand& src, AnyRegister dest)
{
if (dest.isFloat()) {
Label notInt32, end;
asMasm().branchTestInt32(Assembler::NotEqual, src, &notInt32);
convertInt32ToDouble(src.valueReg(), dest.fpu());
jump(&end);
bind(&notInt32);
unboxDouble(src, dest.fpu());
bind(&end);
} else {
unboxNonDouble(src, dest.gpr());
}
}
void
MacroAssemblerX64::loadInt32OrDouble(const Operand& operand, FloatRegister dest)
{
Label notInt32, end;
branchTestInt32Impl(Assembler::NotEqual, operand, &notInt32);
convertInt32ToDouble(operand, dest);
jump(&end);
bind(&notInt32);
loadDouble(operand, dest);
bind(&end);
}
// If source is a double, load it into dest. If source is int32,
// convert it to double. Else, branch to failure.
void
MacroAssemblerX64::ensureDouble(const ValueOperand& source, FloatRegister dest, Label* failure)
{
Label isDouble, done;
Register tag = splitTagForTest(source);
branchTestDouble(Assembler::Equal, tag, &isDouble);
asMasm().branchTestInt32(Assembler::NotEqual, tag, failure);
ScratchRegisterScope scratch(asMasm());
unboxInt32(source, scratch);
convertInt32ToDouble(scratch, dest);
jump(&done);
bind(&isDouble);
unboxDouble(source, dest);
bind(&done);
}
} // namespace jit
} // namespace js

View File

@ -264,44 +264,6 @@ template void
MacroAssemblerX64::storeUnboxedValue(ConstantOrRegister value, MIRType valueType, const BaseIndex& dest,
MIRType slotType);
void
MacroAssemblerX64::branchPtrInNurseryRange(Condition cond, Register ptr, Register temp, Label* label)
{
ScratchRegisterScope scratch(asMasm());
MOZ_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
MOZ_ASSERT(ptr != temp);
MOZ_ASSERT(ptr != scratch);
const Nursery& nursery = GetJitContext()->runtime->gcNursery();
movePtr(ImmWord(-ptrdiff_t(nursery.start())), scratch);
asMasm().addPtr(ptr, scratch);
asMasm().branchPtr(cond == Assembler::Equal ? Assembler::Below : Assembler::AboveOrEqual,
scratch, Imm32(nursery.nurserySize()), label);
}
void
MacroAssemblerX64::branchValueIsNurseryObject(Condition cond, ValueOperand value, Register temp,
Label* label)
{
MOZ_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
const Nursery& nursery = GetJitContext()->runtime->gcNursery();
// Avoid creating a bogus ObjectValue below.
if (!nursery.exists())
return;
// 'Value' representing the start of the nursery tagged as a JSObject
Value start = ObjectValue(*reinterpret_cast<JSObject*>(nursery.start()));
ScratchRegisterScope scratch(asMasm());
movePtr(ImmWord(-ptrdiff_t(start.asRawBits())), scratch);
asMasm().addPtr(value.valueReg(), scratch);
asMasm().branchPtr(cond == Assembler::Equal ? Assembler::Below : Assembler::AboveOrEqual,
scratch, Imm32(nursery.nurserySize()), label);
}
void
MacroAssemblerX64::profilerEnterFrame(Register framePtr, Register scratch)
{
@ -464,4 +426,45 @@ MacroAssembler::callWithABINoProfiler(const Address& fun, MoveOp::Type result)
callWithABIPost(stackAdjust, result);
}
// ===============================================================
// Branch functions
void
MacroAssembler::branchPtrInNurseryRange(Condition cond, Register ptr, Register temp, Label* label)
{
ScratchRegisterScope scratch(*this);
MOZ_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
MOZ_ASSERT(ptr != temp);
MOZ_ASSERT(ptr != scratch);
const Nursery& nursery = GetJitContext()->runtime->gcNursery();
movePtr(ImmWord(-ptrdiff_t(nursery.start())), scratch);
addPtr(ptr, scratch);
branchPtr(cond == Assembler::Equal ? Assembler::Below : Assembler::AboveOrEqual,
scratch, Imm32(nursery.nurserySize()), label);
}
void
MacroAssembler::branchValueIsNurseryObject(Condition cond, ValueOperand value, Register temp,
Label* label)
{
MOZ_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
const Nursery& nursery = GetJitContext()->runtime->gcNursery();
// Avoid creating a bogus ObjectValue below.
if (!nursery.exists())
return;
// 'Value' representing the start of the nursery tagged as a JSObject
Value start = ObjectValue(*reinterpret_cast<JSObject*>(nursery.start()));
ScratchRegisterScope scratch(*this);
movePtr(ImmWord(-ptrdiff_t(start.asRawBits())), scratch);
addPtr(value.valueReg(), scratch);
branchPtr(cond == Assembler::Equal ? Assembler::Below : Assembler::AboveOrEqual,
scratch, Imm32(nursery.nurserySize()), label);
}
//}}} check_macroassembler_style

View File

@ -545,16 +545,6 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
return jumpWithPatch(label);
}
template <typename S, typename T>
CodeOffsetJump branchPtrWithPatch(Condition cond, S lhs, T ptr, RepatchLabel* label) {
cmpPtr(lhs, ptr);
return jumpWithPatch(label, cond);
}
void decBranchPtr(Condition cond, Register lhs, Imm32 imm, Label* label) {
subq(imm, lhs);
j(cond, label);
}
void movePtr(Register src, Register dest) {
movq(src, dest);
}
@ -691,10 +681,6 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
cond = testUndefined(cond, tag);
j(cond, label);
}
void branchTestInt32(Condition cond, Register tag, Label* label) {
cond = testInt32(cond, tag);
j(cond, label);
}
void branchTestDouble(Condition cond, Register tag, Label* label) {
cond = testDouble(cond, tag);
j(cond, label);
@ -736,15 +722,11 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
MOZ_ASSERT(cond == Equal || cond == NotEqual);
branchTestUndefined(cond, Operand(address), label);
}
void branchTestInt32(Condition cond, const Operand& operand, Label* label) {
void branchTestInt32Impl(Condition cond, const Operand& operand, Label* label) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
cmp32(ToUpper32(operand), Imm32(Upper32Of(GetShiftedTag(JSVAL_TYPE_INT32))));
j(cond, label);
}
void branchTestInt32(Condition cond, const Address& address, Label* label) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
branchTestInt32(cond, Operand(address), label);
}
void branchTestDouble(Condition cond, const Operand& operand, Label* label) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
ScratchRegisterScope scratch(asMasm());
@ -786,11 +768,6 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
cond = testUndefined(cond, src);
j(cond, label);
}
void branchTestInt32(Condition cond, const ValueOperand& src, Label* label) {
ScratchRegisterScope scratch(asMasm());
splitTag(src, scratch);
branchTestInt32(cond, scratch, label);
}
void branchTestBoolean(Condition cond, const ValueOperand& src, Label* label) {
ScratchRegisterScope scratch(asMasm());
splitTag(src, scratch);
@ -827,11 +804,6 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
cond = testUndefined(cond, address);
j(cond, label);
}
void branchTestInt32(Condition cond, const BaseIndex& address, Label* label) {
ScratchRegisterScope scratch(asMasm());
splitTag(address, scratch);
branchTestInt32(cond, scratch, label);
}
void branchTestBoolean(Condition cond, const BaseIndex& address, Label* label) {
ScratchRegisterScope scratch(asMasm());
splitTag(address, scratch);
@ -1046,19 +1018,7 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
return scratch;
}
void unboxValue(const ValueOperand& src, AnyRegister dest) {
if (dest.isFloat()) {
Label notInt32, end;
branchTestInt32(Assembler::NotEqual, src, &notInt32);
convertInt32ToDouble(src.valueReg(), dest.fpu());
jump(&end);
bind(&notInt32);
unboxDouble(src, dest.fpu());
bind(&end);
} else {
unboxNonDouble(src, dest.gpr());
}
}
inline void unboxValue(const ValueOperand& src, AnyRegister dest);
// These two functions use the low 32-bits of the full value register.
void boolValueToDouble(const ValueOperand& operand, FloatRegister dest) {
@ -1084,10 +1044,6 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
test32(operand.valueReg(), operand.valueReg());
return truthy ? NonZero : Zero;
}
void branchTestInt32Truthy(bool truthy, const ValueOperand& operand, Label* label) {
Condition cond = testInt32Truthy(truthy, operand);
j(cond, label);
}
void branchTestBooleanTruthy(bool truthy, const ValueOperand& operand, Label* label) {
test32(operand.valueReg(), operand.valueReg());
j(truthy ? NonZero : Zero, label);
@ -1103,15 +1059,7 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
j(cond, label);
}
void loadInt32OrDouble(const Operand& operand, FloatRegister dest) {
Label notInt32, end;
branchTestInt32(Assembler::NotEqual, operand, &notInt32);
convertInt32ToDouble(operand, dest);
jump(&end);
bind(&notInt32);
loadDouble(operand, dest);
bind(&end);
}
inline void loadInt32OrDouble(const Operand& operand, FloatRegister dest);
template <typename T>
void loadUnboxedValue(const T& src, MIRType type, AnyRegister dest) {
@ -1163,24 +1111,7 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
inline void incrementInt32Value(const Address& addr);
// If source is a double, load it into dest. If source is int32,
// convert it to double. Else, branch to failure.
void ensureDouble(const ValueOperand& source, FloatRegister dest, Label* failure) {
Label isDouble, done;
Register tag = splitTagForTest(source);
branchTestDouble(Assembler::Equal, tag, &isDouble);
branchTestInt32(Assembler::NotEqual, tag, failure);
ScratchRegisterScope scratch(asMasm());
unboxInt32(source, scratch);
convertInt32ToDouble(scratch, dest);
jump(&done);
bind(&isDouble);
unboxDouble(source, dest);
bind(&done);
}
inline void ensureDouble(const ValueOperand& source, FloatRegister dest, Label* failure);
public:
void handleFailureWithHandlerTail(void* handler);
@ -1200,9 +1131,6 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
storeValue(JSVAL_TYPE_INT32, scratch, Dest);
}
void branchPtrInNurseryRange(Condition cond, Register ptr, Register temp, Label* label);
void branchValueIsNurseryObject(Condition cond, ValueOperand value, Register temp, Label* label);
// Instrumentation for entering and leaving the profiler.
void profilerEnterFrame(Register framePtr, Register scratch);
void profilerExitFrame();

View File

@ -295,6 +295,22 @@ MacroAssembler::branchPtr(Condition cond, const Address& lhs, ImmWord rhs, Label
branchPtrImpl(cond, lhs, rhs, label);
}
template <typename T>
CodeOffsetJump
MacroAssembler::branchPtrWithPatch(Condition cond, Register lhs, T rhs, RepatchLabel* label)
{
cmpPtr(lhs, rhs);
return jumpWithPatch(label, cond);
}
template <typename T>
CodeOffsetJump
MacroAssembler::branchPtrWithPatch(Condition cond, Address lhs, T rhs, RepatchLabel* label)
{
cmpPtr(lhs, rhs);
return jumpWithPatch(label, cond);
}
void
MacroAssembler::branchFloat(DoubleCondition cond, FloatRegister lhs, FloatRegister rhs,
Label* label)
@ -342,6 +358,29 @@ MacroAssembler::branchDouble(DoubleCondition cond, FloatRegister lhs, FloatRegis
j(ConditionFromDoubleCondition(cond), label);
}
template <typename T>
void
MacroAssembler::branchAdd32(Condition cond, T src, Register dest, Label* label)
{
addl(src, dest);
j(cond, label);
}
template <typename T>
void
MacroAssembler::branchSub32(Condition cond, T src, Register dest, Label* label)
{
subl(src, dest);
j(cond, label);
}
void
MacroAssembler::decBranchPtr(Condition cond, Register lhs, Imm32 rhs, Label* label)
{
subPtr(rhs, lhs);
j(cond, label);
}
template <class L>
void
MacroAssembler::branchTest32(Condition cond, Register lhs, Register rhs, L label)
@ -389,6 +428,13 @@ MacroAssembler::branchTestPtr(Condition cond, const Address& lhs, Imm32 rhs, Lab
j(cond, label);
}
void
MacroAssembler::branchTestInt32Truthy(bool truthy, const ValueOperand& operand, Label* label)
{
Condition cond = testInt32Truthy(truthy, operand);
j(cond, label);
}
//}}} check_macroassembler_style
// ===============================================================

View File

@ -165,16 +165,6 @@ class MacroAssemblerX86Shared : public Assembler
CodeOffset cmp32WithPatch(Register lhs, Imm32 rhs) {
return cmplWithPatch(rhs, lhs);
}
template <typename T>
void branchAdd32(Condition cond, T src, Register dest, Label* label) {
addl(src, dest);
j(cond, label);
}
template <typename T>
void branchSub32(Condition cond, T src, Register dest, Label* label) {
subl(src, dest);
j(cond, label);
}
void atomic_inc32(const Operand& addr) {
lock_incl(addr);
}

View File

@ -365,6 +365,30 @@ MacroAssembler::branchTest64(Condition cond, Register64 lhs, Register64 rhs, Reg
}
}
void
MacroAssembler::branchTestInt32(Condition cond, Register tag, Label* label)
{
branchTestInt32Impl(cond, tag, label);
}
void
MacroAssembler::branchTestInt32(Condition cond, const Address& address, Label* label)
{
branchTestInt32Impl(cond, address, label);
}
void
MacroAssembler::branchTestInt32(Condition cond, const BaseIndex& address, Label* label)
{
branchTestInt32Impl(cond, address, label);
}
void
MacroAssembler::branchTestInt32(Condition cond, const ValueOperand& src, Label* label)
{
branchTestInt32Impl(cond, src, label);
}
//}}} check_macroassembler_style
// ===============================================================
@ -416,6 +440,64 @@ MacroAssemblerX86::branchPtrImpl(Condition cond, const T& lhs, const S& rhs, Lab
j(cond, label);
}
void
MacroAssemblerX86::unboxValue(const ValueOperand& src, AnyRegister dest)
{
if (dest.isFloat()) {
Label notInt32, end;
asMasm().branchTestInt32(Assembler::NotEqual, src, &notInt32);
convertInt32ToDouble(src.payloadReg(), dest.fpu());
jump(&end);
bind(&notInt32);
unboxDouble(src, dest.fpu());
bind(&end);
} else {
if (src.payloadReg() != dest.gpr())
movl(src.payloadReg(), dest.gpr());
}
}
template <typename T>
void
MacroAssemblerX86::loadInt32OrDouble(const T& src, FloatRegister dest)
{
Label notInt32, end;
asMasm().branchTestInt32(Assembler::NotEqual, src, &notInt32);
convertInt32ToDouble(ToPayload(src), dest);
jump(&end);
bind(&notInt32);
loadDouble(src, dest);
bind(&end);
}
template <typename T>
void
MacroAssemblerX86::loadUnboxedValue(const T& src, MIRType type, AnyRegister dest)
{
if (dest.isFloat())
loadInt32OrDouble(src, dest.fpu());
else
movl(Operand(src), dest.gpr());
}
// If source is a double, load it into dest. If source is int32,
// convert it to double. Else, branch to failure.
void
MacroAssemblerX86::ensureDouble(const ValueOperand& source, FloatRegister dest, Label* failure)
{
Label isDouble, done;
branchTestDouble(Assembler::Equal, source.typeReg(), &isDouble);
asMasm().branchTestInt32(Assembler::NotEqual, source.typeReg(), failure);
convertInt32ToDouble(source.payloadReg(), dest);
jump(&done);
bind(&isDouble);
unboxDouble(source, dest);
bind(&done);
}
} // namespace jit
} // namespace js

View File

@ -328,35 +328,6 @@ template void
MacroAssemblerX86::storeUnboxedValue(ConstantOrRegister value, MIRType valueType, const BaseIndex& dest,
MIRType slotType);
void
MacroAssemblerX86::branchPtrInNurseryRange(Condition cond, Register ptr, Register temp,
Label* label)
{
MOZ_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
MOZ_ASSERT(ptr != temp);
MOZ_ASSERT(temp != InvalidReg); // A temp register is required for x86.
const Nursery& nursery = GetJitContext()->runtime->gcNursery();
movePtr(ImmWord(-ptrdiff_t(nursery.start())), temp);
asMasm().addPtr(ptr, temp);
asMasm().branchPtr(cond == Assembler::Equal ? Assembler::Below : Assembler::AboveOrEqual,
temp, Imm32(nursery.nurserySize()), label);
}
void
MacroAssemblerX86::branchValueIsNurseryObject(Condition cond, ValueOperand value, Register temp,
Label* label)
{
MOZ_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
Label done;
branchTestObject(Assembler::NotEqual, value, cond == Assembler::Equal ? &done : label);
branchPtrInNurseryRange(cond, value.payloadReg(), temp, label);
bind(&done);
}
void
MacroAssemblerX86::profilerEnterFrame(Register framePtr, Register scratch)
{
@ -498,4 +469,36 @@ MacroAssembler::callWithABINoProfiler(const Address& fun, MoveOp::Type result)
callWithABIPost(stackAdjust, result);
}
// ===============================================================
// Branch functions
void
MacroAssembler::branchPtrInNurseryRange(Condition cond, Register ptr, Register temp,
Label* label)
{
MOZ_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
MOZ_ASSERT(ptr != temp);
MOZ_ASSERT(temp != InvalidReg); // A temp register is required for x86.
const Nursery& nursery = GetJitContext()->runtime->gcNursery();
movePtr(ImmWord(-ptrdiff_t(nursery.start())), temp);
addPtr(ptr, temp);
branchPtr(cond == Assembler::Equal ? Assembler::Below : Assembler::AboveOrEqual,
temp, Imm32(nursery.nurserySize()), label);
}
void
MacroAssembler::branchValueIsNurseryObject(Condition cond, ValueOperand value, Register temp,
Label* label)
{
MOZ_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
Label done;
branchTestObject(Assembler::NotEqual, value, cond == Assembler::Equal ? &done : label);
branchPtrInNurseryRange(cond, value.payloadReg(), temp, label);
bind(&done);
}
//}}} check_macroassembler_style

View File

@ -72,6 +72,9 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
Address ToPayload(Address base) {
return base;
}
BaseIndex ToPayload(BaseIndex base) {
return base;
}
Operand ToType(Operand base) {
switch (base.kind()) {
case Operand::MEM_REG_DISP:
@ -575,19 +578,10 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
return jumpWithPatch(label);
}
template <typename S, typename T>
CodeOffsetJump branchPtrWithPatch(Condition cond, S lhs, T ptr, RepatchLabel* label) {
branchPtr(cond, lhs, ptr, label);
return CodeOffsetJump(size());
}
void branchPtr(Condition cond, Register lhs, Register rhs, RepatchLabel* label) {
cmpPtr(lhs, rhs);
j(cond, label);
}
void decBranchPtr(Condition cond, Register lhs, Imm32 imm, Label* label) {
subl(imm, lhs);
j(cond, label);
}
void movePtr(ImmWord imm, Register dest) {
movl(Imm32(imm.value), dest);
@ -667,7 +661,7 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
j(cond, label);
}
template <typename T>
void branchTestInt32(Condition cond, const T& t, Label* label) {
void branchTestInt32Impl(Condition cond, const T& t, Label* label) {
cond = testInt32(cond, t);
j(cond, label);
}
@ -796,20 +790,7 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
vunpcklps(ScratchDoubleReg, dest, dest);
}
}
void unboxValue(const ValueOperand& src, AnyRegister dest) {
if (dest.isFloat()) {
Label notInt32, end;
branchTestInt32(Assembler::NotEqual, src, &notInt32);
convertInt32ToDouble(src.payloadReg(), dest.fpu());
jump(&end);
bind(&notInt32);
unboxDouble(src, dest.fpu());
bind(&end);
} else {
if (src.payloadReg() != dest.gpr())
movl(src.payloadReg(), dest.gpr());
}
}
inline void unboxValue(const ValueOperand& src, AnyRegister dest);
void unboxPrivate(const ValueOperand& src, Register dest) {
if (src.payloadReg() != dest)
movl(src.payloadReg(), dest);
@ -865,10 +846,6 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
test32(operand.payloadReg(), operand.payloadReg());
return truthy ? NonZero : Zero;
}
void branchTestInt32Truthy(bool truthy, const ValueOperand& operand, Label* label) {
Condition cond = testInt32Truthy(truthy, operand);
j(cond, label);
}
void branchTestBooleanTruthy(bool truthy, const ValueOperand& operand, Label* label) {
test32(operand.payloadReg(), operand.payloadReg());
j(truthy ? NonZero : Zero, label);
@ -883,23 +860,11 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
j(cond, label);
}
void loadInt32OrDouble(const Operand& operand, FloatRegister dest) {
Label notInt32, end;
branchTestInt32(Assembler::NotEqual, operand, &notInt32);
convertInt32ToDouble(ToPayload(operand), dest);
jump(&end);
bind(&notInt32);
loadDouble(operand, dest);
bind(&end);
}
template <typename T>
inline void loadInt32OrDouble(const T& src, FloatRegister dest);
template <typename T>
void loadUnboxedValue(const T& src, MIRType type, AnyRegister dest) {
if (dest.isFloat())
loadInt32OrDouble(Operand(src), dest.fpu());
else
movl(Operand(src), dest.gpr());
}
inline void loadUnboxedValue(const T& src, MIRType type, AnyRegister dest);
template <typename T>
void storeUnboxedValue(ConstantOrRegister value, MIRType valueType, const T& dest,
@ -934,29 +899,12 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
addl(Imm32(1), payloadOf(addr));
}
// If source is a double, load it into dest. If source is int32,
// convert it to double. Else, branch to failure.
void ensureDouble(const ValueOperand& source, FloatRegister dest, Label* failure) {
Label isDouble, done;
branchTestDouble(Assembler::Equal, source.typeReg(), &isDouble);
branchTestInt32(Assembler::NotEqual, source.typeReg(), failure);
convertInt32ToDouble(source.payloadReg(), dest);
jump(&done);
bind(&isDouble);
unboxDouble(source, dest);
bind(&done);
}
inline void ensureDouble(const ValueOperand& source, FloatRegister dest, Label* failure);
public:
// Used from within an Exit frame to handle a pending exception.
void handleFailureWithHandlerTail(void* handler);
void branchPtrInNurseryRange(Condition cond, Register ptr, Register temp, Label* label);
void branchValueIsNurseryObject(Condition cond, ValueOperand value, Register temp, Label* label);
// Instrumentation for entering and leaving the profiler.
void profilerEnterFrame(Register framePtr, Register scratch);
void profilerExitFrame();

View File

@ -830,6 +830,7 @@ js::Disassemble1(JSContext* cx, HandleScript script, jsbytecode* pc,
Sprint(sp, "%4u", PCToLineNumber(script, pc));
Sprint(sp, " %s", CodeName[op]);
int i;
switch (JOF_TYPE(cs->format)) {
case JOF_BYTE:
// Scan the trynotes to find the associated catch block
@ -946,9 +947,6 @@ js::Disassemble1(JSContext* cx, HandleScript script, jsbytecode* pc,
Sprint(sp, " %u", GET_UINT32(pc));
break;
{
int i;
case JOF_UINT16:
i = (int)GET_UINT16(pc);
goto print_int;
@ -972,7 +970,6 @@ js::Disassemble1(JSContext* cx, HandleScript script, jsbytecode* pc,
print_int:
Sprint(sp, " %d", i);
break;
}
default: {
char numBuf[12];

View File

@ -128,17 +128,6 @@ GetDirectProxyHandlerObject(JSObject* proxy)
return proxy->as<ProxyObject>().extra(ScriptedDirectProxyHandler::HANDLER_EXTRA).toObjectOrNull();
}
static inline void
ReportInvalidTrapResult(JSContext* cx, JSObject* proxy, JSAtom* atom)
{
RootedValue v(cx, ObjectOrNullValue(proxy));
JSAutoByteString bytes;
if (!AtomToPrintableString(cx, atom, &bytes))
return;
ReportValueError2(cx, JSMSG_INVALID_TRAP_RESULT, JSDVG_IGNORE_STACK, v,
nullptr, bytes.ptr());
}
// ES6 implements both getPrototype and setPrototype traps. We don't have them yet (see bug
// 888969). For now, use these, to account for proxy revocation.
bool

View File

@ -75,6 +75,7 @@
#include "js/TrackedOptimizationInfo.h"
#include "perf/jsperf.h"
#include "shell/jsoptparse.h"
#include "shell/jsshell.h"
#include "shell/OSObject.h"
#include "vm/ArgumentsObject.h"
#include "vm/Compression.h"
@ -359,7 +360,7 @@ GetLine(FILE* file, const char * prompt)
return nullptr;
char* current = buffer;
while (true) {
do {
while (true) {
if (fgets(current, size - len, file))
break;
@ -387,11 +388,7 @@ GetLine(FILE* file, const char * prompt)
buffer = tmp;
}
current = buffer + len;
}
if (len && !ferror(file))
return buffer;
free(buffer);
} while (true);
return nullptr;
}
@ -4407,6 +4404,7 @@ SingleStepCallback(void* arg, jit::Simulator* sim, void* pc)
mozilla::DebugOnly<void*> lastStackAddress = nullptr;
StackChars stack;
uint32_t frameNo = 0;
AutoEnterOOMUnsafeRegion oomUnsafe;
for (JS::ProfilingFrameIterator i(rt, state); !i.done(); ++i) {
MOZ_ASSERT(i.stackAddress() != nullptr);
MOZ_ASSERT(lastStackAddress <= i.stackAddress());
@ -4414,9 +4412,12 @@ SingleStepCallback(void* arg, jit::Simulator* sim, void* pc)
JS::ProfilingFrameIterator::Frame frames[16];
uint32_t nframes = i.extractStack(frames, 0, 16);
for (uint32_t i = 0; i < nframes; i++) {
if (frameNo > 0)
stack.append(",", 1);
stack.append(frames[i].label, strlen(frames[i].label));
if (frameNo > 0) {
if (!stack.append(",", 1))
oomUnsafe.crash("stack.append");
}
if (!stack.append(frames[i].label, strlen(frames[i].label)))
oomUnsafe.crash("stack.append");
frameNo++;
}
}
@ -4426,7 +4427,8 @@ SingleStepCallback(void* arg, jit::Simulator* sim, void* pc)
stacks.back().length() != stack.length() ||
!PodEqual(stacks.back().begin(), stack.begin(), stack.length()))
{
stacks.append(Move(stack));
if (!stacks.append(Move(stack)))
oomUnsafe.crash("stacks.append");
}
}
#endif

View File

@ -23,7 +23,7 @@ enum JSShellErrNum {
const JSErrorFormatString*
my_GetErrorMessage(void* userRef, const unsigned errorNumber);
static void
void
my_ErrorReporter(JSContext* cx, const char* message, JSErrorReport* report);
JSString*

View File

@ -14,6 +14,7 @@
#include "jsobj.h"
#include "jsscript.h"
#include "gc/Heap.h"
#include "jit/BaselineJIT.h"
#include "jit/Ion.h"
#include "vm/ArrayObject.h"
@ -356,7 +357,7 @@ StatsArenaCallback(JSRuntime* rt, void* data, gc::Arena* arena,
// The admin space includes (a) the header and (b) the padding between the
// end of the header and the start of the first GC thing.
size_t allocationSpace = Arena::thingsSpan(arena->aheader.getAllocKind());
size_t allocationSpace = gc::Arena::thingsSpan(arena->aheader.getAllocKind());
rtStats->currZoneStats->gcHeapArenaAdmin += gc::ArenaSize - allocationSpace;
// We don't call the callback on unused things. So we compute the

View File

@ -605,6 +605,7 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
mCurrentReferenceFrame(aReferenceFrame),
mCurrentAGR(&mRootAGR),
mRootAGR(aReferenceFrame, nullptr),
mUsedAGRBudget(0),
mDirtyRect(-1,-1,-1,-1),
mGlassDisplayItem(nullptr),
mPendingScrollInfoItems(nullptr),
@ -1087,8 +1088,12 @@ nsDisplayListBuilder::IsAnimatedGeometryRoot(nsIFrame* aFrame, nsIFrame** aParen
if (nsLayoutUtils::IsPopup(aFrame))
return true;
if (ActiveLayerTracker::IsOffsetOrMarginStyleAnimated(aFrame))
return true;
if (ActiveLayerTracker::IsOffsetOrMarginStyleAnimated(aFrame)) {
const bool inBudget = AddToAGRBudget(aFrame);
if (inBudget) {
return true;
}
}
if (!aFrame->GetParent() &&
nsLayoutUtils::ViewportHasDisplayPort(aFrame->PresContext())) {
// Viewport frames in a display port need to be animated geometry roots
@ -1255,7 +1260,7 @@ nsDisplayListBuilder::GetWindowDraggingRegion() const
}
const uint32_t gWillChangeAreaMultiplier = 3;
static uint32_t GetWillChangeCost(const nsSize& aSize) {
static uint32_t GetLayerizationCost(const nsSize& aSize) {
// There's significant overhead for each layer created from Gecko
// (IPC+Shared Objects) and from the backend (like an OpenGL texture).
// Therefore we set a minimum cost threshold of a 64x64 area.
@ -1272,7 +1277,7 @@ static uint32_t GetWillChangeCost(const nsSize& aSize) {
bool
nsDisplayListBuilder::AddToWillChangeBudget(nsIFrame* aFrame,
const nsSize& aSize) {
if (mBudgetSet.Contains(aFrame)) {
if (mWillChangeBudgetSet.Contains(aFrame)) {
return true; // Already accounted
}
@ -1288,14 +1293,14 @@ nsDisplayListBuilder::AddToWillChangeBudget(nsIFrame* aFrame,
uint32_t budgetLimit = nsPresContext::AppUnitsToIntCSSPixels(area.width) *
nsPresContext::AppUnitsToIntCSSPixels(area.height);
uint32_t cost = GetWillChangeCost(aSize);
uint32_t cost = GetLayerizationCost(aSize);
bool onBudget = (budget.mBudget + cost) /
gWillChangeAreaMultiplier < budgetLimit;
if (onBudget) {
budget.mBudget += cost;
mWillChangeBudget.Put(key, budget);
mBudgetSet.PutEntry(aFrame);
mWillChangeBudgetSet.PutEntry(aFrame);
}
return onBudget;
@ -1308,7 +1313,7 @@ nsDisplayListBuilder::IsInWillChangeBudget(nsIFrame* aFrame,
if (!onBudget) {
nsString usageStr;
usageStr.AppendInt(GetWillChangeCost(aSize));
usageStr.AppendInt(GetLayerizationCost(aSize));
nsString multiplierStr;
multiplierStr.AppendInt(gWillChangeAreaMultiplier);
@ -1327,6 +1332,40 @@ nsDisplayListBuilder::IsInWillChangeBudget(nsIFrame* aFrame,
return onBudget;
}
#ifdef MOZ_GFX_OPTIMIZE_MOBILE
const float gAGRBudgetAreaMultiplier = 0.3;
#else
const float gAGRBudgetAreaMultiplier = 3.0;
#endif
bool
nsDisplayListBuilder::AddToAGRBudget(nsIFrame* aFrame)
{
if (mAGRBudgetSet.Contains(aFrame)) {
return true;
}
const nsPresContext* presContext = aFrame->PresContext()->GetRootPresContext();
if (!presContext) {
return false;
}
const nsRect area = presContext->GetVisibleArea();
const uint32_t budgetLimit = gAGRBudgetAreaMultiplier *
nsPresContext::AppUnitsToIntCSSPixels(area.width) *
nsPresContext::AppUnitsToIntCSSPixels(area.height);
const uint32_t cost = GetLayerizationCost(aFrame->GetSize());
const bool onBudget = mUsedAGRBudget + cost < budgetLimit;
if (onBudget) {
mUsedAGRBudget += cost;
mAGRBudgetSet.PutEntry(aFrame);
}
return onBudget;
}
nsDisplayList*
nsDisplayListBuilder::EnterScrollInfoItemHoisting(nsDisplayList* aScrollInfoItemStorage)
{

View File

@ -1164,6 +1164,13 @@ private:
nsDataHashtable<nsPtrHashKey<nsIFrame>, AnimatedGeometryRoot*> mFrameToAnimatedGeometryRootMap;
/**
* Add the current frame to the AGR budget if possible and remember
* the outcome. Subsequent calls will return the same value as
* returned here.
*/
bool AddToAGRBudget(nsIFrame* aFrame);
struct PresShellState {
nsIPresShell* mPresShell;
nsIFrame* mCaretFrame;
@ -1217,7 +1224,12 @@ private:
// Any frame listed in this set is already counted in the budget
// and thus is in-budget.
nsTHashtable<nsPtrHashKey<nsIFrame> > mBudgetSet;
nsTHashtable<nsPtrHashKey<nsIFrame> > mWillChangeBudgetSet;
// Area of animated geometry root budget already allocated
uint32_t mUsedAGRBudget;
// Set of frames already counted in budget
nsTHashtable<nsPtrHashKey<nsIFrame> > mAGRBudgetSet;
// rects are relative to the frame's reference frame
nsDataHashtable<nsPtrHashKey<nsIFrame>, nsRect> mDirtyRectForScrolledContents;

View File

@ -455,7 +455,7 @@ public:
* presenting the document. The returned value is in the standard
* nscoord units (as scaled by the device context).
*/
nsRect GetVisibleArea() { return mVisibleArea; }
nsRect GetVisibleArea() const { return mVisibleArea; }
/**
* Set the currently visible area. The units for r are standard

View File

@ -0,0 +1,21 @@
<html><head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Testcase for bug 1239564</title>
<style>
#circle {
border-radius: 300px;
height: 80px;
width: 80px;
background-color: red;
margin: auto;
position: absolute;
left: 0;
right: 0;
top:0;
bottom: 0;
transform: scale(3);
}
</style>
<body>
<div id="circle"></div>
</body></html>

View File

@ -0,0 +1,29 @@
<html class="reftest-wait"><head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Testcase for bug 1239564</title>
<style>
#circle {
border-radius: 300px;
height: 80px;
width: 80px;
background-color: red;
margin: auto;
position: absolute;
left: 0;
right: 0;
top:0;
bottom: 0;
will-change: transform;
}
</style>
<body>
<div id="circle"></div>
<script>
var c = document.getElementById('circle');
function doTest() {
c.style.transform = "translateZ(1px) scale(3)";
document.documentElement.removeAttribute('class');
}
document.addEventListener("MozReftestInvalidate", doTest, false);
</script>
</body></html>

View File

@ -1944,3 +1944,4 @@ fuzzy(1,74) fuzzy-if(gtkWidget,6,79) == 1174332-1.html 1174332-1-ref.html
== 1222226-1.html 1222226-1-ref.html
pref(layout.css.overflow-clip-box.enabled,true) == 1226278.html 1226278-ref.html
== 1230466.html about:blank
fuzzy(100,2000) == 1239564.html 1239564-ref.html

View File

@ -23,6 +23,8 @@ import android.graphics.RectF;
import android.os.SystemClock;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.InputDevice;
import android.view.MotionEvent;
import org.json.JSONObject;
import java.util.ArrayList;
@ -106,6 +108,8 @@ class GeckoLayerClient implements LayerView.Listener, PanZoomTarget
*/
private volatile boolean mContentDocumentIsDisplayed;
private SynthesizedEventState mPointerState;
public GeckoLayerClient(Context context, LayerView view, EventDispatcher eventDispatcher) {
// we can fill these in with dummy values because they are always written
// to before being read
@ -709,6 +713,141 @@ class GeckoLayerClient implements LayerView.Listener, PanZoomTarget
layersUpdated, paintSyncId);
}
class PointerInfo {
public int pointerId;
public int screenX;
public int screenY;
public double pressure;
public int orientation;
public MotionEvent.PointerCoords getCoords() {
MotionEvent.PointerCoords coords = new MotionEvent.PointerCoords();
coords.orientation = orientation;
coords.pressure = (float)pressure;
coords.x = screenX;
coords.y = screenY;
return coords;
}
}
class SynthesizedEventState {
public final ArrayList<PointerInfo> pointers;
public long downTime;
SynthesizedEventState() {
pointers = new ArrayList<PointerInfo>();
}
int getPointerIndex(int pointerId) {
for (int i = 0; i < pointers.size(); i++) {
if (pointers.get(i).pointerId == pointerId) {
return i;
}
}
return -1;
}
int addPointer(int pointerId) {
PointerInfo info = new PointerInfo();
info.pointerId = pointerId;
pointers.add(info);
return pointers.size() - 1;
}
int[] getPointerIds() {
int[] ids = new int[pointers.size()];
for (int i = 0; i < ids.length; i++) {
ids[i] = pointers.get(i).pointerId;
}
return ids;
}
MotionEvent.PointerCoords[] getPointerCoords() {
MotionEvent.PointerCoords[] coords = new MotionEvent.PointerCoords[pointers.size()];
for (int i = 0; i < coords.length; i++) {
coords[i] = pointers.get(i).getCoords();
}
return coords;
}
}
@WrapForJNI
public void synthesizeNativeTouchPoint(int pointerId, int eventType, int screenX,
int screenY, double pressure, int orientation)
{
if (mPointerState == null) {
mPointerState = new SynthesizedEventState();
}
// Find the pointer if it already exists
int pointerIndex = mPointerState.getPointerIndex(pointerId);
// Event-specific handling
switch (eventType) {
case MotionEvent.ACTION_POINTER_UP:
if (pointerIndex < 0) {
Log.d(LOGTAG, "Requested synthesis of a pointer-up for a pointer that doesn't exist!");
return;
}
if (mPointerState.pointers.size() == 1) {
// Last pointer is going up
eventType = MotionEvent.ACTION_UP;
}
break;
case MotionEvent.ACTION_CANCEL:
if (pointerIndex < 0) {
Log.d(LOGTAG, "Requested synthesis of a pointer-cancel for a pointer that doesn't exist!");
return;
}
break;
case MotionEvent.ACTION_POINTER_DOWN:
if (pointerIndex < 0) {
// Adding a new pointer
pointerIndex = mPointerState.addPointer(pointerId);
if (pointerIndex == 0) {
// first pointer
eventType = MotionEvent.ACTION_DOWN;
mPointerState.downTime = SystemClock.uptimeMillis();
}
} else {
// We're moving an existing pointer
eventType = MotionEvent.ACTION_MOVE;
}
break;
}
// Update the pointer with the new info
PointerInfo info = mPointerState.pointers.get(pointerIndex);
info.screenX = screenX;
info.screenY = screenY;
info.pressure = pressure;
info.orientation = orientation;
// Dispatch the event
int action = (pointerIndex << MotionEvent.ACTION_POINTER_INDEX_SHIFT);
action &= MotionEvent.ACTION_POINTER_INDEX_MASK;
action |= (eventType & MotionEvent.ACTION_MASK);
final MotionEvent event = MotionEvent.obtain(mPointerState.downTime,
SystemClock.uptimeMillis(), action, mPointerState.pointers.size(),
mPointerState.getPointerIds(), mPointerState.getPointerCoords(),
0, 0, 0, 0, 0, InputDevice.SOURCE_TOUCHSCREEN, 0);
mView.post(new Runnable() {
@Override
public void run() {
event.offsetLocation(0, mView.getSurfaceTranslation());
mView.dispatchTouchEvent(event);
}
});
// Forget about removed pointers
if (eventType == MotionEvent.ACTION_POINTER_UP ||
eventType == MotionEvent.ACTION_UP ||
eventType == MotionEvent.ACTION_CANCEL)
{
mPointerState.pointers.remove(pointerIndex);
}
}
@WrapForJNI(allowMultithread = true)
public LayerRenderer.Frame createFrame() {
// Create the shaders and textures if necessary.

View File

@ -1315,7 +1315,7 @@ static nsresult pref_InitInitialObjects()
// channel, telemetry is on by default, otherwise not. This is necessary
// so that beta users who are testing final release builds don't flipflop
// defaults.
if (Preferences::GetDefaultType(kTelemetryPref) == PREF_INVALID) {
if (Preferences::GetDefaultType(kTelemetryPref) == nsIPrefBranch::PREF_INVALID) {
bool prerelease = false;
#ifdef MOZ_TELEMETRY_ON_BY_DEFAULT
prerelease = true;

View File

@ -127,7 +127,21 @@ NS_IMETHODIMP nsPrefBranch::GetPrefType(const char *aPrefName, int32_t *_retval)
{
NS_ENSURE_ARG(aPrefName);
const char *pref = getPrefName(aPrefName);
*_retval = PREF_GetPrefType(pref);
switch (PREF_GetPrefType(pref)) {
case PrefType::String:
*_retval = PREF_STRING;
break;
case PrefType::Int:
*_retval = PREF_INT;
break;
case PrefType::Bool:
*_retval = PREF_BOOL;
break;
case PrefType::Invalid:
default:
*_retval = PREF_INVALID;
break;
}
return NS_OK;
}

View File

@ -40,7 +40,7 @@ static void
clearPrefEntry(PLDHashTable *table, PLDHashEntryHdr *entry)
{
PrefHashEntry *pref = static_cast<PrefHashEntry *>(entry);
if (pref->flags & PREF_STRING)
if (pref->prefFlags.IsTypeString())
{
if (pref->defaultPref.stringVal)
PL_strfree(pref->defaultPref.stringVal);
@ -117,13 +117,7 @@ static char *ArenaStrDup(const char* str, PLArenaPool* aArena)
/*---------------------------------------------------------------------------*/
#define PREF_IS_LOCKED(pref) ((pref)->flags & PREF_LOCKED)
#define PREF_HAS_DEFAULT_VALUE(pref) ((pref)->flags & PREF_HAS_DEFAULT)
#define PREF_HAS_USER_VALUE(pref) ((pref)->flags & PREF_USERSET)
#define PREF_TYPE(pref) (PrefType)((pref)->flags & PREF_VALUETYPE_MASK)
static bool pref_ValueChanged(PrefValue oldValue, PrefValue newValue, PrefType type);
/* -- Privates */
struct CallbackNode {
char* domain;
@ -249,7 +243,7 @@ PREF_SetCharPref(const char *pref_name, const char *value, bool set_default)
PrefValue pref;
pref.stringVal = (char*)value;
return pref_HashPref(pref_name, pref, PREF_STRING, set_default ? kPrefSetDefault : 0);
return pref_HashPref(pref_name, pref, PrefType::String, set_default ? kPrefSetDefault : 0);
}
nsresult
@ -258,7 +252,7 @@ PREF_SetIntPref(const char *pref_name, int32_t value, bool set_default)
PrefValue pref;
pref.intVal = value;
return pref_HashPref(pref_name, pref, PREF_INT, set_default ? kPrefSetDefault : 0);
return pref_HashPref(pref_name, pref, PrefType::Int, set_default ? kPrefSetDefault : 0);
}
nsresult
@ -267,7 +261,7 @@ PREF_SetBoolPref(const char *pref_name, bool value, bool set_default)
PrefValue pref;
pref.boolVal = value;
return pref_HashPref(pref_name, pref, PREF_BOOL, set_default ? kPrefSetDefault : 0);
return pref_HashPref(pref_name, pref, PrefType::Bool, set_default ? kPrefSetDefault : 0);
}
enum WhichValue { DEFAULT_VALUE, USER_VALUE };
@ -335,12 +329,12 @@ pref_savePrefs(PLDHashTable* aTable)
// where we're getting our pref from
PrefValue* sourcePref;
if (PREF_HAS_USER_VALUE(pref) &&
if (pref->prefFlags.HasUserValue() &&
(pref_ValueChanged(pref->defaultPref,
pref->userPref,
(PrefType) PREF_TYPE(pref)) ||
!(pref->flags & PREF_HAS_DEFAULT) ||
pref->flags & PREF_STICKY_DEFAULT)) {
pref->prefFlags.GetPrefType()) ||
!(pref->prefFlags.HasDefault()) ||
pref->prefFlags.HasStickyDefault())) {
sourcePref = &pref->userPref;
} else {
// do not save default prefs that haven't changed
@ -348,15 +342,15 @@ pref_savePrefs(PLDHashTable* aTable)
}
// strings are in quotes!
if (pref->flags & PREF_STRING) {
if (pref->prefFlags.IsTypeString()) {
prefValue = '\"';
str_escape(sourcePref->stringVal, prefValue);
prefValue += '\"';
} else if (pref->flags & PREF_INT) {
} else if (pref->prefFlags.IsTypeInt()) {
prefValue.AppendInt(sourcePref->intVal);
} else if (pref->flags & PREF_BOOL) {
} else if (pref->prefFlags.IsTypeBool()) {
prefValue = (sourcePref->boolVal) ? "true" : "false";
}
@ -389,14 +383,14 @@ GetPrefValueFromEntry(PrefHashEntry *aHashEntry, dom::PrefSetting* aPref,
settingValue = &aPref->defaultValue().get_PrefValue();
}
switch (aHashEntry->flags & PREF_VALUETYPE_MASK) {
case PREF_STRING:
switch (aHashEntry->prefFlags.GetPrefType()) {
case PrefType::String:
*settingValue = nsDependentCString(value->stringVal);
return;
case PREF_INT:
case PrefType::Int:
*settingValue = value->intVal;
return;
case PREF_BOOL:
case PrefType::Bool:
*settingValue = !!value->boolVal;
return;
default:
@ -408,12 +402,12 @@ void
pref_GetPrefFromEntry(PrefHashEntry *aHashEntry, dom::PrefSetting* aPref)
{
aPref->name() = aHashEntry->key;
if (PREF_HAS_DEFAULT_VALUE(aHashEntry)) {
if (aHashEntry->prefFlags.HasDefault()) {
GetPrefValueFromEntry(aHashEntry, aPref, DEFAULT_VALUE);
} else {
aPref->defaultValue() = null_t();
}
if (PREF_HAS_USER_VALUE(aHashEntry)) {
if (aHashEntry->prefFlags.HasUserValue()) {
GetPrefValueFromEntry(aHashEntry, aPref, USER_VALUE);
} else {
aPref->userValue() = null_t();
@ -451,11 +445,7 @@ bool PREF_HasUserPref(const char *pref_name)
return false;
PrefHashEntry *pref = pref_HashTableLookup(pref_name);
if (!pref) return false;
/* convert PREF_HAS_USER_VALUE to bool */
return (PREF_HAS_USER_VALUE(pref) != 0);
return pref && pref->prefFlags.HasUserValue();
}
nsresult
@ -468,12 +458,12 @@ PREF_CopyCharPref(const char *pref_name, char ** return_buffer, bool get_default
char* stringVal;
PrefHashEntry* pref = pref_HashTableLookup(pref_name);
if (pref && (pref->flags & PREF_STRING))
{
if (get_default || PREF_IS_LOCKED(pref) || !PREF_HAS_USER_VALUE(pref))
if (pref && (pref->prefFlags.IsTypeString())) {
if (get_default || pref->prefFlags.IsLocked() || !pref->prefFlags.HasUserValue()) {
stringVal = pref->defaultPref.stringVal;
else
} else {
stringVal = pref->userPref.stringVal;
}
if (stringVal) {
*return_buffer = NS_strdup(stringVal);
@ -490,18 +480,17 @@ nsresult PREF_GetIntPref(const char *pref_name,int32_t * return_int, bool get_de
nsresult rv = NS_ERROR_UNEXPECTED;
PrefHashEntry* pref = pref_HashTableLookup(pref_name);
if (pref && (pref->flags & PREF_INT))
{
if (get_default || PREF_IS_LOCKED(pref) || !PREF_HAS_USER_VALUE(pref))
{
if (pref && (pref->prefFlags.IsTypeInt())) {
if (get_default || pref->prefFlags.IsLocked() || !pref->prefFlags.HasUserValue()) {
int32_t tempInt = pref->defaultPref.intVal;
/* check to see if we even had a default */
if (!(pref->flags & PREF_HAS_DEFAULT))
if (!pref->prefFlags.HasDefault()) {
return NS_ERROR_UNEXPECTED;
}
*return_int = tempInt;
}
else
} else {
*return_int = pref->userPref.intVal;
}
rv = NS_OK;
}
return rv;
@ -515,18 +504,15 @@ nsresult PREF_GetBoolPref(const char *pref_name, bool * return_value, bool get_d
nsresult rv = NS_ERROR_UNEXPECTED;
PrefHashEntry* pref = pref_HashTableLookup(pref_name);
//NS_ASSERTION(pref, pref_name);
if (pref && (pref->flags & PREF_BOOL))
{
if (get_default || PREF_IS_LOCKED(pref) || !PREF_HAS_USER_VALUE(pref))
{
if (pref && (pref->prefFlags.IsTypeBool())) {
if (get_default || pref->prefFlags.IsLocked() || !pref->prefFlags.HasUserValue()) {
bool tempBool = pref->defaultPref.boolVal;
/* check to see if we even had a default */
if (pref->flags & PREF_HAS_DEFAULT) {
if (pref->prefFlags.HasDefault()) {
*return_value = tempBool;
rv = NS_OK;
}
}
else {
} else {
*return_value = pref->userPref.boolVal;
rv = NS_OK;
}
@ -584,11 +570,10 @@ PREF_ClearUserPref(const char *pref_name)
return NS_ERROR_NOT_INITIALIZED;
PrefHashEntry* pref = pref_HashTableLookup(pref_name);
if (pref && PREF_HAS_USER_VALUE(pref))
{
pref->flags &= ~PREF_USERSET;
if (pref && pref->prefFlags.HasUserValue()) {
pref->prefFlags.SetHasUserValue(false);
if (!(pref->flags & PREF_HAS_DEFAULT)) {
if (!pref->prefFlags.HasDefault()) {
gHashTable->RemoveEntry(pref);
}
@ -612,11 +597,11 @@ PREF_ClearAllUserPrefs()
for (auto iter = gHashTable->Iter(); !iter.Done(); iter.Next()) {
auto pref = static_cast<PrefHashEntry*>(iter.Get());
if (PREF_HAS_USER_VALUE(pref)) {
if (pref->prefFlags.HasUserValue()) {
prefStrings.push_back(std::string(pref->key));
pref->flags &= ~PREF_USERSET;
if (!(pref->flags & PREF_HAS_DEFAULT)) {
pref->prefFlags.SetHasUserValue(false);
if (!pref->prefFlags.HasDefault()) {
iter.Remove();
}
}
@ -640,18 +625,14 @@ nsresult PREF_LockPref(const char *key, bool lockit)
return NS_ERROR_UNEXPECTED;
if (lockit) {
if (!PREF_IS_LOCKED(pref))
{
pref->flags |= PREF_LOCKED;
if (!pref->prefFlags.IsLocked()) {
pref->prefFlags.SetLocked(true);
gIsAnyPrefLocked = true;
pref_DoCallback(key);
}
}
else
{
if (PREF_IS_LOCKED(pref))
{
pref->flags &= ~PREF_LOCKED;
} else {
if (pref->prefFlags.IsLocked()) {
pref->prefFlags.SetLocked(false);
pref_DoCallback(key);
}
}
@ -664,15 +645,23 @@ nsresult PREF_LockPref(const char *key, bool lockit)
static bool pref_ValueChanged(PrefValue oldValue, PrefValue newValue, PrefType type)
{
bool changed = true;
if (type & PREF_STRING)
{
if (oldValue.stringVal && newValue.stringVal)
switch(type) {
case PrefType::String:
if (oldValue.stringVal && newValue.stringVal) {
changed = (strcmp(oldValue.stringVal, newValue.stringVal) != 0);
}
else if (type & PREF_INT)
}
break;
case PrefType::Int:
changed = oldValue.intVal != newValue.intVal;
else if (type & PREF_BOOL)
break;
case PrefType::Bool:
changed = oldValue.boolVal != newValue.boolVal;
break;
case PrefType::Invalid:
default:
changed = false;
break;
}
return changed;
}
@ -681,20 +670,21 @@ static bool pref_ValueChanged(PrefValue oldValue, PrefValue newValue, PrefType t
* ensure that they are not changing the type of a preference that has
* a default value.
*/
static void pref_SetValue(PrefValue* existingValue, uint16_t *existingFlags,
PrefValue newValue, PrefType newType)
static PrefTypeFlags pref_SetValue(PrefValue* existingValue, PrefTypeFlags flags,
PrefValue newValue, PrefType newType)
{
if ((*existingFlags & PREF_STRING) && existingValue->stringVal) {
if (flags.IsTypeString() && existingValue->stringVal) {
PL_strfree(existingValue->stringVal);
}
*existingFlags = (*existingFlags & ~PREF_VALUETYPE_MASK) | newType;
if (newType & PREF_STRING) {
flags.SetPrefType(newType);
if (flags.IsTypeString()) {
PR_ASSERT(newValue.stringVal);
existingValue->stringVal = newValue.stringVal ? PL_strdup(newValue.stringVal) : nullptr;
}
else {
*existingValue = newValue;
}
return flags;
}
PrefHashEntry* pref_HashTableLookup(const char *key)
@ -723,63 +713,53 @@ nsresult pref_HashPref(const char *key, PrefValue value, PrefType type, uint32_t
if (!pref->key) {
// initialize the pref entry
pref->flags = type;
pref->prefFlags.Reset().SetPrefType(type);
pref->key = ArenaStrDup(key, &gPrefNameArena);
memset(&pref->defaultPref, 0, sizeof(pref->defaultPref));
memset(&pref->userPref, 0, sizeof(pref->userPref));
}
else if ((pref->flags & PREF_HAS_DEFAULT) && PREF_TYPE(pref) != type)
{
} else if (pref->prefFlags.HasDefault() && !pref->prefFlags.IsPrefType(type)) {
NS_WARNING(nsPrintfCString("Trying to overwrite value of default pref %s with the wrong type!", key).get());
return NS_ERROR_UNEXPECTED;
}
bool valueChanged = false;
if (flags & kPrefSetDefault)
{
if (!PREF_IS_LOCKED(pref))
{ /* ?? change of semantics? */
if (flags & kPrefSetDefault) {
if (!pref->prefFlags.IsLocked()) {
/* ?? change of semantics? */
if (pref_ValueChanged(pref->defaultPref, value, type) ||
!(pref->flags & PREF_HAS_DEFAULT))
{
pref_SetValue(&pref->defaultPref, &pref->flags, value, type);
pref->flags |= PREF_HAS_DEFAULT;
if (flags & kPrefStickyDefault)
pref->flags |= PREF_STICKY_DEFAULT;
if (!PREF_HAS_USER_VALUE(pref))
!pref->prefFlags.HasDefault()) {
pref->prefFlags = pref_SetValue(&pref->defaultPref, pref->prefFlags, value, type).SetHasDefault(true);
if (flags & kPrefStickyDefault) {
pref->prefFlags.SetHasStickyDefault(true);
}
if (!pref->prefFlags.HasUserValue()) {
valueChanged = true;
}
}
// What if we change the default to be the same as the user value?
// Should we clear the user value?
}
}
else
{
} else {
/* If new value is same as the default value and it's not a "sticky"
pref, then un-set the user value.
Otherwise, set the user value only if it has changed */
if ((pref->flags & PREF_HAS_DEFAULT) &&
!(pref->flags & PREF_STICKY_DEFAULT) &&
if ((pref->prefFlags.HasDefault()) &&
!(pref->prefFlags.HasStickyDefault()) &&
!pref_ValueChanged(pref->defaultPref, value, type) &&
!(flags & kPrefForceSet))
{
if (PREF_HAS_USER_VALUE(pref))
{
!(flags & kPrefForceSet)) {
if (pref->prefFlags.HasUserValue()) {
/* XXX should we free a user-set string value if there is one? */
pref->flags &= ~PREF_USERSET;
if (!PREF_IS_LOCKED(pref)) {
pref->prefFlags.SetHasUserValue(false);
if (!pref->prefFlags.IsLocked()) {
gDirty = true;
valueChanged = true;
}
}
}
else if (!PREF_HAS_USER_VALUE(pref) ||
PREF_TYPE(pref) != type ||
pref_ValueChanged(pref->userPref, value, type) )
{
pref_SetValue(&pref->userPref, &pref->flags, value, type);
pref->flags |= PREF_USERSET;
if (!PREF_IS_LOCKED(pref)) {
} else if (!pref->prefFlags.HasUserValue() ||
!pref->prefFlags.IsPrefType(type) ||
pref_ValueChanged(pref->userPref, value, type) ) {
pref->prefFlags = pref_SetValue(&pref->userPref, pref->prefFlags, value, type).SetHasUserValue(true);
if (!pref->prefFlags.IsLocked()) {
gDirty = true;
valueChanged = true;
}
@ -808,17 +788,11 @@ PREF_GetPrefType(const char *pref_name)
{
if (gHashTable) {
PrefHashEntry* pref = pref_HashTableLookup(pref_name);
if (pref)
{
if (pref->flags & PREF_STRING)
return PREF_STRING;
else if (pref->flags & PREF_INT)
return PREF_INT;
else if (pref->flags & PREF_BOOL)
return PREF_BOOL;
if (pref) {
return pref->prefFlags.GetPrefType();
}
}
return PREF_INVALID;
return PrefType::Invalid;
}
/* -- */
@ -829,8 +803,9 @@ PREF_PrefIsLocked(const char *pref_name)
bool result = false;
if (gIsAnyPrefLocked && gHashTable) {
PrefHashEntry* pref = pref_HashTableLookup(pref_name);
if (pref && PREF_IS_LOCKED(pref))
if (pref && pref->prefFlags.IsLocked()) {
result = true;
}
}
return result;
@ -973,10 +948,16 @@ void PREF_ReaderCallback(void *closure,
PrefType type,
bool isDefault,
bool isStickyDefault)
{
uint32_t flags = isDefault ? kPrefSetDefault : kPrefForceSet;
if (isDefault && isStickyDefault) {
flags |= kPrefStickyDefault;
uint32_t flags = 0;
if (isDefault) {
flags |= kPrefSetDefault;
if (isStickyDefault) {
flags |= kPrefStickyDefault;
}
} else {
flags |= kPrefForceSet;
}
pref_HashPref(pref, value, type, flags);
}

View File

@ -28,14 +28,6 @@ typedef union
bool boolVal;
} PrefValue;
struct PrefHashEntry : PLDHashEntryHdr
{
uint16_t flags; // This field goes first to minimize struct size on 64-bit.
const char *key;
PrefValue defaultPref;
PrefValue userPref;
};
/*
// <font color=blue>
// The Init function initializes the preference context and creates
@ -45,7 +37,7 @@ struct PrefHashEntry : PLDHashEntryHdr
void PREF_Init();
/*
// Cleanup should be called at program exit to free the
// Cleanup should be called at program exit to free the
// list of registered callbacks.
*/
void PREF_Cleanup();
@ -53,23 +45,88 @@ void PREF_CleanupPrefs();
/*
// <font color=blue>
// Preference flags, including the native type of the preference
// Preference flags, including the native type of the preference. Changing any of these
// values will require modifying the code inside of PrefTypeFlags class.
// </font>
*/
typedef enum { PREF_INVALID = 0,
PREF_LOCKED = 1, PREF_USERSET = 2, PREF_CONFIG = 4, PREF_REMOTE = 8,
PREF_LILOCAL = 16, PREF_STRING = 32, PREF_INT = 64, PREF_BOOL = 128,
PREF_HAS_DEFAULT = 256,
// pref is default pref with "sticky" semantics
PREF_STICKY_DEFAULT = 512,
PREF_VALUETYPE_MASK = (PREF_STRING | PREF_INT | PREF_BOOL)
} PrefType;
enum class PrefType {
Invalid = 0,
String = 1,
Int = 2,
Bool = 3,
};
// Keep the type of the preference, as well as the flags guiding its behaviour.
class PrefTypeFlags
{
public:
PrefTypeFlags() : mValue(AsInt(PrefType::Invalid)) {}
explicit PrefTypeFlags(PrefType aType) : mValue(AsInt(aType)) {}
PrefTypeFlags& Reset() { mValue = AsInt(PrefType::Invalid); return *this; }
bool IsTypeValid() const { return !IsPrefType(PrefType::Invalid); }
bool IsTypeString() const { return IsPrefType(PrefType::String); }
bool IsTypeInt() const { return IsPrefType(PrefType::Int); }
bool IsTypeBool() const { return IsPrefType(PrefType::Bool); }
bool IsPrefType(PrefType type) const { return GetPrefType() == type; }
PrefTypeFlags& SetPrefType(PrefType aType) {
mValue = mValue - AsInt(GetPrefType()) + AsInt(aType);
return *this;
}
PrefType GetPrefType() const {
return (PrefType)(mValue & (AsInt(PrefType::String) |
AsInt(PrefType::Int) |
AsInt(PrefType::Bool)));
}
bool HasDefault() const { return mValue & PREF_FLAG_HAS_DEFAULT; }
PrefTypeFlags& SetHasDefault(bool aSetOrUnset) { return SetFlag(PREF_FLAG_HAS_DEFAULT, aSetOrUnset); }
bool HasStickyDefault() const { return mValue & PREF_FLAG_STICKY_DEFAULT; }
PrefTypeFlags& SetHasStickyDefault(bool aSetOrUnset) { return SetFlag(PREF_FLAG_STICKY_DEFAULT, aSetOrUnset); }
bool IsLocked() const { return mValue & PREF_FLAG_LOCKED; }
PrefTypeFlags& SetLocked(bool aSetOrUnset) { return SetFlag(PREF_FLAG_LOCKED, aSetOrUnset); }
bool HasUserValue() const { return mValue & PREF_FLAG_USERSET; }
PrefTypeFlags& SetHasUserValue(bool aSetOrUnset) { return SetFlag(PREF_FLAG_USERSET, aSetOrUnset); }
private:
static uint16_t AsInt(PrefType aType) { return (uint16_t)aType; }
PrefTypeFlags& SetFlag(uint16_t aFlag, bool aSetOrUnset) {
mValue = aSetOrUnset ? mValue | aFlag : mValue & ~aFlag;
return *this;
}
// Pack both the value of type (PrefType) and flags into the same int. This is why
// the flag enum starts at 4, as PrefType occupies the bottom two bits.
enum {
PREF_FLAG_LOCKED = 4,
PREF_FLAG_USERSET = 8,
PREF_FLAG_CONFIG = 16,
PREF_FLAG_REMOTE = 32,
PREF_FLAG_LILOCAL = 64,
PREF_FLAG_HAS_DEFAULT = 128,
PREF_FLAG_STICKY_DEFAULT = 256,
};
uint16_t mValue;
};
struct PrefHashEntry : PLDHashEntryHdr
{
PrefTypeFlags prefFlags; // This field goes first to minimize struct size on 64-bit.
const char *key;
PrefValue defaultPref;
PrefValue userPref;
};
/*
// <font color=blue>
// Set the various types of preferences. These functions take a dotted
// notation of the preference name (e.g. "browser.startup.homepage").
// notation of the preference name (e.g. "browser.startup.homepage").
// Note that this will cause the preference to be saved to the file if
// it is different from the default. In other words, these are used
// to set the _user_ preferences.
@ -103,8 +160,8 @@ bool PREF_HasUserPref(const char* pref_name);
// </font>
*/
nsresult PREF_GetIntPref(const char *pref,
int32_t * return_int, bool get_default);
nsresult PREF_GetBoolPref(const char *pref, bool * return_val, bool get_default);
int32_t * return_int, bool get_default);
nsresult PREF_GetBoolPref(const char *pref, bool * return_val, bool get_default);
/*
// <font color=blue>
// These functions are similar to the above "Get" version with the significant
@ -173,10 +230,10 @@ typedef void (*PrefChangedFunc) (const char *, void *);
// matched all the parameters; otherwise it returns PREF_ERROR.
// </font>
*/
void PREF_RegisterCallback( const char* domain,
PrefChangedFunc callback, void* instance_data );
nsresult PREF_UnregisterCallback( const char* domain,
PrefChangedFunc callback, void* instance_data );
void PREF_RegisterCallback(const char* domain,
PrefChangedFunc callback, void* instance_data );
nsresult PREF_UnregisterCallback(const char* domain,
PrefChangedFunc callback, void* instance_data );
/*
* Used by nsPrefService as the callback function of the 'pref' parser

View File

@ -114,17 +114,17 @@ pref_DoCallback(PrefParseState *ps)
PrefValue value;
switch (ps->vtype) {
case PREF_STRING:
case PrefType::String:
value.stringVal = ps->vb;
break;
case PREF_INT:
case PrefType::Int:
if ((ps->vb[0] == '-' || ps->vb[0] == '+') && ps->vb[1] == '\0') {
NS_WARNING("malformed integer value");
return false;
}
value.intVal = atoi(ps->vb);
break;
case PREF_BOOL:
case PrefType::Bool:
value.boolVal = (ps->vb == kTrue);
break;
default:
@ -154,7 +154,7 @@ PREF_FinalizeParseState(PrefParseState *ps)
* Pseudo-BNF
* ----------
* function = LJUNK function-name JUNK function-args
* function-name = "user_pref" | "pref"
* function-name = "user_pref" | "pref" | "sticky_pref"
* function-args = "(" JUNK pref-name JUNK "," JUNK pref-value JUNK ")" JUNK ";"
* pref-name = quoted-string
* pref-value = quoted-string | "true" | "false" | integer-value
@ -188,7 +188,7 @@ PREF_ParseBuf(PrefParseState *ps, const char *buf, int bufLen)
if (ps->lbcur != ps->lb) { /* reset state */
ps->lbcur = ps->lb;
ps->vb = nullptr;
ps->vtype = PREF_INVALID;
ps->vtype = PrefType::Invalid;
ps->fdefault = false;
ps->fstickydefault = false;
}
@ -200,10 +200,15 @@ PREF_ParseBuf(PrefParseState *ps, const char *buf, int bufLen)
state = PREF_PARSE_UNTIL_EOL;
break;
case 'u': /* indicating user_pref */
case 'p': /* indicating pref */
case 's': /* indicating sticky_pref */
ps->smatch = (c == 'u' ? kUserPref :
(c == 's' ? kPrefSticky : kPref));
case 'p': /* indicating pref */
if (c == 'u') {
ps->smatch = kUserPref;
} else if (c == 's') {
ps->smatch = kPrefSticky;
} else {
ps->smatch = kPref;
}
ps->sindex = 1;
ps->nextstate = PREF_PARSE_UNTIL_OPEN_PAREN;
state = PREF_PARSE_MATCH_STRING;
@ -248,6 +253,8 @@ PREF_ParseBuf(PrefParseState *ps, const char *buf, int bufLen)
case PREF_PARSE_UNTIL_NAME:
if (c == '\"' || c == '\'') {
ps->fdefault = (ps->smatch == kPref || ps->smatch == kPrefSticky);
ps->fdefault = (ps->smatch == kPref ||
ps->smatch == kPrefSticky);
ps->fstickydefault = (ps->smatch == kPrefSticky);
ps->quotechar = c;
ps->nextstate = PREF_PARSE_UNTIL_COMMA; /* return here when done */
@ -284,21 +291,21 @@ PREF_ParseBuf(PrefParseState *ps, const char *buf, int bufLen)
/* the pref value type is unknown. so, we scan for the first
* character of the value, and determine the type from that. */
if (c == '\"' || c == '\'') {
ps->vtype = PREF_STRING;
ps->vtype = PrefType::String;
ps->quotechar = c;
ps->nextstate = PREF_PARSE_UNTIL_CLOSE_PAREN;
state = PREF_PARSE_QUOTED_STRING;
}
else if (c == 't' || c == 'f') {
ps->vb = (char *) (c == 't' ? kTrue : kFalse);
ps->vtype = PREF_BOOL;
ps->vtype = PrefType::Bool;
ps->smatch = ps->vb;
ps->sindex = 1;
ps->nextstate = PREF_PARSE_UNTIL_CLOSE_PAREN;
state = PREF_PARSE_MATCH_STRING;
}
else if (isdigit(c) || (c == '-') || (c == '+')) {
ps->vtype = PREF_INT;
ps->vtype = PrefType::Int;
/* write c to line buffer... */
if (ps->lbcur == ps->lbend && !pref_GrowBuf(ps))
return false; /* out of memory */
@ -511,13 +518,12 @@ PREF_ParseBuf(PrefParseState *ps, const char *buf, int bufLen)
break;
case PREF_PARSE_UNTIL_CLOSE_PAREN:
/* tolerate only whitespace and embedded comments */
if (c == ')')
if (c == ')') {
state = PREF_PARSE_UNTIL_SEMICOLON;
else if (c == '/') {
} else if (c == '/') {
ps->nextstate = state; /* return here when done with comment */
state = PREF_PARSE_COMMENT_MAYBE_START;
}
else if (!isspace(c)) {
} else if (!isspace(c)) {
NS_WARNING("malformed pref file");
return false;
}

View File

@ -54,7 +54,7 @@ typedef struct PrefParseState {
char *lbend; /* line buffer end */
char *vb; /* value buffer (ptr into lb) */
PrefType vtype; /* PREF_STRING,INT,BOOL */
bool fdefault; /* true if (default) pref */
bool fdefault; /* true if (default) pref */
bool fstickydefault; /* true if (sticky) pref */
} PrefParseState;

View File

@ -37,7 +37,7 @@ inline size_t Store16(uint8_t* dst, size_t offset, int x) {
*reinterpret_cast<uint16_t*>(dst + offset) =
((x & 0xFF) << 8) | ((x & 0xFF00) >> 8);
#elif (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
*reinterpret_cast<uint16_t*>(dst + offset) = reinterpret_cast<uint16_t>(x);
*reinterpret_cast<uint16_t*>(dst + offset) = static_cast<uint16_t>(x);
#else
dst[offset] = x >> 8;
dst[offset + 1] = x;
@ -59,7 +59,7 @@ inline void Store16(int val, size_t* offset, uint8_t* dst) {
*offset += 2;
#elif (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
*reinterpret_cast<uint16_t*>(dst + *offset) =
reinterpret_cast<uint16_t>(val);
static_cast<uint16_t>(val);
*offset += 2;
#else
dst[(*offset)++] = val >> 8;

View File

@ -545,7 +545,6 @@ already_AddRefed<CacheEntryHandle> CacheEntry::ReopenTruncated(bool aMemoryOnly,
mUseDisk && !aMemoryOnly,
mSkipSizeCheck,
mPinned,
true, // always create
true, // truncate existing (this one)
getter_AddRefs(handle));
@ -1072,13 +1071,12 @@ NS_IMETHODIMP CacheEntry::GetIsForcedValid(bool *aIsForcedValid)
}
nsAutoCString key;
nsresult rv = HashingKeyWithStorage(key);
nsresult rv = HashingKey(key);
if (NS_FAILED(rv)) {
return rv;
}
*aIsForcedValid = CacheStorageService::Self()->IsForcedValidEntry(key);
*aIsForcedValid = CacheStorageService::Self()->IsForcedValidEntry(mStorageID, key);
LOG(("CacheEntry::GetIsForcedValid [this=%p, IsForcedValid=%d]", this, *aIsForcedValid));
return NS_OK;
@ -1089,12 +1087,12 @@ NS_IMETHODIMP CacheEntry::ForceValidFor(uint32_t aSecondsToTheFuture)
LOG(("CacheEntry::ForceValidFor [this=%p, aSecondsToTheFuture=%d]", this, aSecondsToTheFuture));
nsAutoCString key;
nsresult rv = HashingKeyWithStorage(key);
nsresult rv = HashingKey(key);
if (NS_FAILED(rv)) {
return rv;
}
CacheStorageService::Self()->ForceEntryValidFor(key, aSecondsToTheFuture);
CacheStorageService::Self()->ForceEntryValidFor(mStorageID, key, aSecondsToTheFuture);
return NS_OK;
}
@ -1325,6 +1323,8 @@ NS_IMETHODIMP CacheEntry::AsyncDoom(nsICacheEntryDoomCallback *aCallback)
if (mIsDoomed || mDoomCallback)
return NS_ERROR_IN_PROGRESS; // to aggregate have DOOMING state
RemoveForcedValidity();
mIsDoomed = true;
mDoomCallback = aCallback;
}
@ -1623,6 +1623,8 @@ void CacheEntry::DoomAlreadyRemoved()
mozilla::MutexAutoLock lock(mLock);
RemoveForcedValidity();
mIsDoomed = true;
// Pretend pinning is know. This entry is now doomed for good, so don't
@ -1666,6 +1668,25 @@ void CacheEntry::DoomFile()
OnFileDoomed(rv);
}
void CacheEntry::RemoveForcedValidity()
{
mLock.AssertCurrentThreadOwns();
nsresult rv;
if (mIsDoomed) {
return;
}
nsAutoCString entryKey;
rv = HashingKey(entryKey);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
CacheStorageService::Self()->RemoveEntryForceValid(mStorageID, entryKey);
}
void CacheEntry::BackgroundOp(uint32_t aOperations, bool aForceAsync)
{
mLock.AssertCurrentThreadOwns();

View File

@ -266,6 +266,9 @@ private:
// Called only from DoomAlreadyRemoved()
void DoomFile();
// When this entry is doomed the first time, this method removes
// any force-valid timing info for this entry.
void RemoveForcedValidity();
already_AddRefed<CacheEntryHandle> ReopenTruncated(bool aMemoryOnly,
nsICacheEntryOpenCallback* aCallback);

View File

@ -104,7 +104,6 @@ NS_IMETHODIMP CacheStorage::AsyncOpenURI(nsIURI *aURI,
RefPtr<CacheEntryHandle> entry;
rv = CacheStorageService::Self()->AddStorageEntry(
this, noRefURI, aIdExtension,
true, // create always
truncate, // replace any existing one?
getter_AddRefs(entry));
NS_ENSURE_SUCCESS(rv, rv);
@ -131,7 +130,6 @@ NS_IMETHODIMP CacheStorage::OpenTruncate(nsIURI *aURI, const nsACString & aIdExt
RefPtr<CacheEntryHandle> handle;
rv = CacheStorageService::Self()->AddStorageEntry(
this, noRefURI, aIdExtension,
true, // create always
true, // replace any existing one
getter_AddRefs(handle));
NS_ENSURE_SUCCESS(rv, rv);

View File

@ -769,6 +769,11 @@ NS_IMETHODIMP CacheStorageService::Clear()
{
mozilla::MutexAutoLock lock(mLock);
{
mozilla::MutexAutoLock forcedValidEntriesLock(mForcedValidEntriesLock);
mForcedValidEntries.Clear();
}
NS_ENSURE_TRUE(!mShutdown, NS_ERROR_NOT_INITIALIZED);
nsTArray<nsCString> keys;
@ -1021,7 +1026,7 @@ CacheStorageService::RemoveEntry(CacheEntry* aEntry, bool aOnlyUnreferenced)
return false;
}
if (!aEntry->IsUsingDisk() && IsForcedValidEntry(entryKey)) {
if (!aEntry->IsUsingDisk() && IsForcedValidEntry(aEntry->GetStorageID(), entryKey)) {
LOG((" forced valid, not removing"));
return false;
}
@ -1094,13 +1099,19 @@ CacheStorageService::RecordMemoryOnlyEntry(CacheEntry* aEntry,
// Checks if a cache entry is forced valid (will be loaded directly from cache
// without further validation) - see nsICacheEntry.idl for further details
bool CacheStorageService::IsForcedValidEntry(nsACString &aCacheEntryKey)
bool CacheStorageService::IsForcedValidEntry(nsACString const &aContextKey,
nsACString const &aEntryKey)
{
return IsForcedValidEntry(aContextKey + aEntryKey);
}
bool CacheStorageService::IsForcedValidEntry(nsACString const &aContextEntryKey)
{
mozilla::MutexAutoLock lock(mForcedValidEntriesLock);
TimeStamp validUntil;
if (!mForcedValidEntries.Get(aCacheEntryKey, &validUntil)) {
if (!mForcedValidEntries.Get(aContextEntryKey, &validUntil)) {
return false;
}
@ -1114,13 +1125,14 @@ bool CacheStorageService::IsForcedValidEntry(nsACString &aCacheEntryKey)
}
// Entry timeout has been reached
mForcedValidEntries.Remove(aCacheEntryKey);
mForcedValidEntries.Remove(aContextEntryKey);
return false;
}
// Allows a cache entry to be loaded directly from cache without further
// validation - see nsICacheEntry.idl for further details
void CacheStorageService::ForceEntryValidFor(nsACString &aCacheEntryKey,
void CacheStorageService::ForceEntryValidFor(nsACString const &aContextKey,
nsACString const &aEntryKey,
uint32_t aSecondsToTheFuture)
{
mozilla::MutexAutoLock lock(mForcedValidEntriesLock);
@ -1131,7 +1143,15 @@ void CacheStorageService::ForceEntryValidFor(nsACString &aCacheEntryKey,
// This will be the timeout
TimeStamp validUntil = now + TimeDuration::FromSeconds(aSecondsToTheFuture);
mForcedValidEntries.Put(aCacheEntryKey, validUntil);
mForcedValidEntries.Put(aContextKey + aEntryKey, validUntil);
}
void CacheStorageService::RemoveEntryForceValid(nsACString const &aContextKey,
nsACString const &aEntryKey)
{
mozilla::MutexAutoLock lock(mForcedValidEntriesLock);
mForcedValidEntries.Remove(aContextKey + aEntryKey);
}
// Cleans out the old entries in mForcedValidEntries
@ -1378,7 +1398,6 @@ nsresult
CacheStorageService::AddStorageEntry(CacheStorage const* aStorage,
nsIURI* aURI,
const nsACString & aIdExtension,
bool aCreateIfNotExist,
bool aReplace,
CacheEntryHandle** aResult)
{
@ -1393,7 +1412,7 @@ CacheStorageService::AddStorageEntry(CacheStorage const* aStorage,
aStorage->WriteToDisk(),
aStorage->SkipSizeCheck(),
aStorage->Pinning(),
aCreateIfNotExist, aReplace,
aReplace,
aResult);
}
@ -1404,7 +1423,6 @@ CacheStorageService::AddStorageEntry(nsCSubstring const& aContextKey,
bool aWriteToDisk,
bool aSkipSizeCheck,
bool aPin,
bool aCreateIfNotExist,
bool aReplace,
CacheEntryHandle** aResult)
{
@ -1440,7 +1458,7 @@ CacheStorageService::AddStorageEntry(nsCSubstring const& aContextKey,
if (entryExists && !aReplace) {
// check whether we want to turn this entry to a memory-only.
if (MOZ_UNLIKELY(!aWriteToDisk) && MOZ_LIKELY(entry->IsUsingDisk())) {
LOG((" entry is persistnet but we want mem-only, replacing it"));
LOG((" entry is persistent but we want mem-only, replacing it"));
aReplace = true;
}
}
@ -1457,10 +1475,20 @@ CacheStorageService::AddStorageEntry(nsCSubstring const& aContextKey,
entry = nullptr;
entryExists = false;
// Would only lead to deleting force-valid timestamp again. We don't need the
// replace information anymore after this point anyway.
aReplace = false;
}
// Ensure entry for the particular URL, if not read/only
if (!entryExists && (aCreateIfNotExist || aReplace)) {
// Ensure entry for the particular URL
if (!entryExists) {
// When replacing with a new entry, always remove the current force-valid timestamp,
// this is the only place to do it.
if (aReplace) {
RemoveEntryForceValid(aContextKey, entryKey);
}
// Entry is not in the hashtable or has just been truncated...
entry = new CacheEntry(aContextKey, aURI, aIdExtension, aWriteToDisk, aSkipSizeCheck, aPin);
entries->Put(entryKey, entry);
@ -1639,6 +1667,10 @@ CacheStorageService::DoomStorageEntry(CacheStorage const* aStorage,
}
}
}
if (!entry) {
RemoveEntryForceValid(contextKey, entryKey);
}
}
if (entry) {
@ -1764,6 +1796,21 @@ CacheStorageService::DoomStorageEntries(nsCSubstring const& aContextKey,
}
}
{
mozilla::MutexAutoLock lock(mForcedValidEntriesLock);
for (auto iter = mForcedValidEntries.Iter(); !iter.Done(); iter.Next()) {
bool matches;
DebugOnly<nsresult> rv = CacheFileUtils::KeyMatchesLoadContextInfo(
iter.Key(), aContext, &matches);
MOZ_ASSERT(NS_SUCCEEDED(rv));
if (matches) {
iter.Remove();
}
}
}
// An artificial callback. This is a candidate for removal tho. In the new
// cache any 'doom' or 'evict' function ensures that the entry or entries
// being doomed is/are not accessible after the function returns. So there is
@ -1824,24 +1871,28 @@ CacheStorageService::CacheFileDoomed(nsILoadContextInfo* aLoadContextInfo,
mozilla::MutexAutoLock lock(mLock);
if (mShutdown)
if (mShutdown) {
return;
}
CacheEntryTable* entries;
if (!sGlobalEntryTables->Get(contextKey, &entries))
return;
RefPtr<CacheEntry> entry;
if (!entries->Get(entryKey, getter_AddRefs(entry)))
return;
if (!entry->IsFileDoomed())
return;
if (sGlobalEntryTables->Get(contextKey, &entries) &&
entries->Get(entryKey, getter_AddRefs(entry))) {
if (entry->IsFileDoomed()) {
// Need to remove under the lock to avoid possible race leading
// to duplication of the entry per its key.
RemoveExactEntry(entries, entryKey, entry, false);
entry->DoomAlreadyRemoved();
}
// Need to remove under the lock to avoid possible race leading
// to duplication of the entry per its key.
RemoveExactEntry(entries, entryKey, entry, false);
entry->DoomAlreadyRemoved();
// Entry found, but it's not the entry that has been found doomed
// by the lower eviction layer. Just leave everything unchanged.
return;
}
RemoveEntryForceValid(contextKey, entryKey);
}
bool

View File

@ -158,23 +158,35 @@ private:
* directly from cache) for the given number of seconds
* See nsICacheEntry.idl for more details
*/
void ForceEntryValidFor(nsACString &aCacheEntryKey,
void ForceEntryValidFor(nsACString const &aContextKey,
nsACString const &aEntryKey,
uint32_t aSecondsToTheFuture);
/**
* Remove the validity info
*/
void RemoveEntryForceValid(nsACString const &aContextKey,
nsACString const &aEntryKey);
/**
* Retrieves the status of the cache entry to see if it has been forced valid
* (so it will loaded directly from cache without further validation)
*/
bool IsForcedValidEntry(nsACString const &aContextKey,
nsACString const &aEntryKey);
private:
friend class CacheIndex;
/**
* Retrieves the status of the cache entry to see if it has been forced valid
* (so it will loaded directly from cache without further validation)
* CacheIndex uses this to prevent a cache entry from being prememptively
* thrown away when forced valid
* See nsICacheEntry.idl for more details
*/
bool IsForcedValidEntry(nsACString &aCacheEntryKey);
bool IsForcedValidEntry(nsACString const &aEntryKeyWithContext);
private:
// These are helpers for telemetry monitorying of the memory pools.
// These are helpers for telemetry monitoring of the memory pools.
void TelemetryPrune(TimeStamp &now);
void TelemetryRecordEntryCreation(CacheEntry const* entry);
void TelemetryRecordEntryRemoval(CacheEntry const* entry);
@ -190,7 +202,6 @@ private:
nsresult AddStorageEntry(CacheStorage const* aStorage,
nsIURI* aURI,
const nsACString & aIdExtension,
bool aCreateIfNotExist,
bool aReplace,
CacheEntryHandle** aResult);
@ -286,7 +297,6 @@ private:
bool aWriteToDisk,
bool aSkipSizeCheck,
bool aPin,
bool aCreateIfNotExist,
bool aReplace,
CacheEntryHandle** aResult);

View File

@ -377,7 +377,7 @@ class BuildMonitor(MozbuildObject):
'Swap in/out (MB): {sin}/{sout}')
o = dict(
version=2,
version=3,
argv=sys.argv,
start=self.start_time,
end=self.end_time,
@ -411,22 +411,15 @@ class BuildMonitor(MozbuildObject):
o['resources'].append(entry)
# TODO: it would be nice to collect data on the storage device as well
o['system'] = dict(
architecture=list(platform.architecture()),
machine=platform.machine(),
python_version=platform.python_version(),
release=platform.release(),
system=platform.system(),
version=platform.version(),
)
# If the imports for this file ran before the in-tree virtualenv
# was bootstrapped (for instance, for a clobber build in automation),
# psutil might not be available.
#
# Treat psutil as optional to avoid an outright failure to log resources
# TODO: it would be nice to collect data on the storage device as well
# in this case.
o['system'] = {}
if psutil:
o['system'].update(dict(
logical_cpu_count=psutil.cpu_count(),
@ -435,17 +428,6 @@ class BuildMonitor(MozbuildObject):
vmem_total=psutil.virtual_memory()[0],
))
if platform.system() == 'Linux':
dist = list(platform.linux_distribution())
o['system']['linux_distribution'] = dist
elif platform.system() == 'Windows':
win32_ver=list((platform.win32_ver())),
o['system']['win32_ver'] = win32_ver
elif platform.system() == 'Darwin':
# mac version is a special Cupertino snowflake
r, v, m = platform.mac_ver()
o['system']['mac_ver'] = [r, list(v), m]
return o
def _log_resource_usage(self, prefix, m_type, duration, cpu_percent,

View File

@ -56,7 +56,7 @@ var currentResources;
* Interface for a build resources JSON file.
*/
function BuildResources(data) {
if (data.version != 1 && data.version != 2) {
if (data.version < 1 || data.version > 3) {
throw new Error("Unsupported version of the JSON format: " + data.version);
}

View File

@ -82,8 +82,7 @@ SECStatus
IsCertBuiltInRoot(CERTCertificate* cert, bool& result)
{
result = false;
ScopedPK11SlotList slots;
slots = PK11_GetAllSlotsForCert(cert, nullptr);
UniquePK11SlotList slots(PK11_GetAllSlotsForCert(cert, nullptr));
if (!slots) {
if (PORT_GetError() == SEC_ERROR_NO_TOKEN) {
// no list

View File

@ -1017,7 +1017,7 @@ LoadLoadableRoots(/*optional*/ const char* dir, const char* modNameUTF8)
return SECFailure;
}
ScopedSECMODModule rootsModule(SECMOD_LoadUserModule(pkcs11ModuleSpec.get(),
UniqueSECMODModule rootsModule(SECMOD_LoadUserModule(pkcs11ModuleSpec.get(),
nullptr, false));
if (!rootsModule) {
return SECFailure;
@ -1035,7 +1035,7 @@ void
UnloadLoadableRoots(const char* modNameUTF8)
{
PR_ASSERT(modNameUTF8);
ScopedSECMODModule rootsModule(SECMOD_FindModule(modNameUTF8));
UniqueSECMODModule rootsModule(SECMOD_FindModule(modNameUTF8));
if (rootsModule) {
SECMOD_UnloadUserModule(rootsModule.get());

View File

@ -6,6 +6,9 @@
// Require spacing around =>
"arrow-spacing": 2,
// No space before always a space after a comma
"comma-spacing": [2, {"before": false, "after": true}],
// Commas at the end of the line not the start
"comma-style": 2,
@ -105,6 +108,9 @@
// No using with
"no-with": 2,
// Always require semicolon at end of statement
"semi": [2, "always"],
// Require space before blocks
"space-before-blocks": 2,

View File

@ -55,14 +55,18 @@ function onCertSelected()
function doOK()
{
dialogParams.SetInt(0,1);
var index = parseInt(document.getElementById("nicknames").value);
// Signal that the user accepted.
dialogParams.SetInt(0, 1);
// Signal the index of the selected cert in the list of cert nicknames
// provided.
let index = parseInt(document.getElementById("nicknames").value);
dialogParams.SetInt(1, index);
return true;
}
function doCancel()
{
dialogParams.SetInt(0,0);
dialogParams.SetInt(0, 0); // Signal that the user cancelled.
return true;
}

View File

@ -28,15 +28,16 @@ function onLoad()
function doOK()
{
var tokenList = document.getElementById("tokens");
var token = tokenList.value;
dialogParams.SetInt(0,1);
dialogParams.SetString(0, token);
let tokenList = document.getElementById("tokens");
// Signal that the user accepted.
dialogParams.SetInt(0, 1);
// Signal the name of the token the user chose.
dialogParams.SetString(0, tokenList.value);
return true;
}
function doCancel()
{
dialogParams.SetInt(0,0);
dialogParams.SetInt(0, 0); // Signal that the user cancelled.
return true;
}

View File

@ -80,17 +80,24 @@ function onCertSelected()
function doOK()
{
dialogParams.SetInt(0,1);
var index = parseInt(document.getElementById("nicknames").value);
// Signal that the user accepted.
dialogParams.SetInt(0, 1);
let index = parseInt(document.getElementById("nicknames").value);
// Signal the index of the selected cert in the list of cert nicknames
// provided.
dialogParams.SetInt(1, index);
// Signal whether the user wanted to remember the selection.
dialogParams.SetInt(2, rememberBox.checked);
return true;
}
function doCancel()
{
dialogParams.SetInt(0,0);
// Signal that the user cancelled.
dialogParams.SetInt(0, 0);
// Signal some invalid index value since a cert hasn't actually been chosen.
dialogParams.SetInt(1, -1); // invalid value
// Signal whether the user wanted to remember the "selection".
dialogParams.SetInt(2, rememberBox.checked);
return true;
}

View File

@ -60,7 +60,7 @@ function setWindowName()
var impactReference = document.getElementById('impact');
document.title = title;
setText("confirm",confirm);
setText("confirm", confirm);
let box = document.getElementById("certlist");
for (let x = 0; x < numberOfCerts; x++) {
@ -71,7 +71,7 @@ function setWindowName()
box.appendChild(listItem);
}
setText("impact",impact);
setText("impact", impact);
}
function doOK()

View File

@ -468,7 +468,7 @@ function doLoadDevice()
var name_box = document.getElementById("device_name");
var path_box = document.getElementById("device_path");
try {
getPKCS11().addModule(name_box.value, path_box.value, 0,0);
getPKCS11().addModule(name_box.value, path_box.value, 0, 0);
} catch (e) {
if (e.result == Components.results.NS_ERROR_ILLEGAL_VALUE) {
doPrompt(getNSSString("AddModuleDup"));

View File

@ -48,6 +48,6 @@ function doOK()
function doCancel()
{
params.SetInt(1,0);
params.SetInt(1, 0); // Signal that the user cancelled.
return true;
}

View File

@ -41,7 +41,7 @@ badCertListener.prototype = {
this.handle_test_result();
return true; // suppress error UI
}
}
};
function initExceptionDialog() {
gNeedReset = false;

View File

@ -65,7 +65,7 @@ function onLoad()
var sel = document.getElementById("tokenMenu");
sel.setAttribute("hidden", "true");
var tag = document.getElementById("tokenName");
tag.setAttribute("value",tokenName);
tag.setAttribute("value", tokenName);
}
process();

View File

@ -21,7 +21,7 @@ function setText(id, value) {
}
const nsICertificateDialogs = Components.interfaces.nsICertificateDialogs;
const nsCertificateDialogs = "@mozilla.org/nsCertificateDialogs;1"
const nsCertificateDialogs = "@mozilla.org/nsCertificateDialogs;1";
function viewCertHelper(parent, cert) {
if (!cert) {

View File

@ -11,7 +11,7 @@ const nsIASN1Object = Components.interfaces.nsIASN1Object;
const nsIASN1Sequence = Components.interfaces.nsIASN1Sequence;
const nsIASN1PrintableItem = Components.interfaces.nsIASN1PrintableItem;
const nsIASN1Tree = Components.interfaces.nsIASN1Tree;
const nsASN1Tree = "@mozilla.org/security/nsASN1Tree;1"
const nsASN1Tree = "@mozilla.org/security/nsASN1Tree;1";
const nsIDialogParamBlock = Components.interfaces.nsIDialogParamBlock;
var bundle;
@ -23,12 +23,19 @@ function doPrompt(msg)
prompts.alert(window, null, msg);
}
function AddCertChain(node, chain, idPrefix)
/**
* Fills out the "Certificate Hierarchy" tree of the cert viewer "Details" tab.
*
* @param {tree} node
* Parent tree node to append to.
* @param {nsIArray<nsIX509Cert>} chain
* Chain where cert element n is issued by cert element n + 1.
*/
function AddCertChain(node, chain)
{
var child = document.getElementById(node);
var currCert;
var displayVal;
var addTwistie;
for (let i = chain.length - 1; i >= 0; i--) {
currCert = chain.queryElementAt(i, nsIX509Cert);
if (currCert.commonName) {
@ -36,18 +43,22 @@ function AddCertChain(node, chain, idPrefix)
} else {
displayVal = currCert.windowTitle;
}
if (0 == i) {
addTwistie = false;
} else {
addTwistie = true;
}
child = addChildrenToTree(child, displayVal, currCert.dbKey,addTwistie);
let addTwistie = i != 0;
child = addChildrenToTree(child, displayVal, currCert.dbKey, addTwistie);
}
}
function AddUsage(usage,verifyInfoBox)
/**
* Adds a "verified usage" of a cert to the "General" tab of the cert viewer.
*
* @param {String} usage
* Verified usage to add.
* @param {Node} verifyInfoBox
* Parent node to append to.
*/
function AddUsage(usage, verifyInfoBox)
{
var text = document.createElement("textbox");
let text = document.createElement("textbox");
text.setAttribute("value", usage);
text.setAttribute("style", "margin: 2px 5px");
text.setAttribute("readonly", "true");
@ -86,33 +97,33 @@ function setWindowName()
//
// The chain of trust
var chain = cert.getChain();
AddCertChain("treesetDump", chain, "dump_");
AddCertChain("treesetDump", cert.getChain());
DisplayGeneralDataFromCert(cert);
BuildPrettyPrint(cert);
cert.requestUsagesArrayAsync(new listener());
}
function addChildrenToTree(parentTree,label,value,addTwistie)
function addChildrenToTree(parentTree, label, value, addTwistie)
{
var treeChild1 = document.createElement("treechildren");
var treeElement = addTreeItemToTreeChild(treeChild1,label,value,addTwistie);
let treeChild1 = document.createElement("treechildren");
let treeElement = addTreeItemToTreeChild(treeChild1, label, value,
addTwistie);
parentTree.appendChild(treeChild1);
return treeElement;
}
function addTreeItemToTreeChild(treeChild,label,value,addTwistie)
function addTreeItemToTreeChild(treeChild, label, value, addTwistie)
{
var treeElem1 = document.createElement("treeitem");
let treeElem1 = document.createElement("treeitem");
if (addTwistie) {
treeElem1.setAttribute("container","true");
treeElem1.setAttribute("open","true");
treeElem1.setAttribute("container", "true");
treeElem1.setAttribute("open", "true");
}
var treeRow = document.createElement("treerow");
var treeCell = document.createElement("treecell");
treeCell.setAttribute("label",label);
let treeRow = document.createElement("treerow");
let treeCell = document.createElement("treecell");
treeCell.setAttribute("label", label);
if (value) {
treeCell.setAttribute("display",value);
treeCell.setAttribute("display", value);
}
treeRow.appendChild(treeCell);
treeElem1.appendChild(treeRow);
@ -163,12 +174,12 @@ listener.prototype.QueryInterface =
}
throw Components.results.NS_ERROR_NO_INTERFACE;
}
};
listener.prototype.notify =
function(cert, result) {
DisplayVerificationData(cert, result);
}
};
function DisplayVerificationData(cert, result)
{
@ -221,38 +232,31 @@ function DisplayVerificationData(cert, result)
if (count > 0) {
var verifyInfoBox = document.getElementById('verify_info_box');
for (let i = 0; i < count; i++) {
AddUsage(usageList[i],verifyInfoBox);
AddUsage(usageList[i], verifyInfoBox);
}
}
}
/**
* Displays information about a cert in the "General" tab of the cert viewer.
*
* @param {nsIX509Cert} cert
* Cert to display information about.
*/
function DisplayGeneralDataFromCert(cert)
{
// Common Name
addAttributeFromCert('commonname', cert.commonName);
// Organization
addAttributeFromCert('organization', cert.organization);
// Organizational Unit
addAttributeFromCert('orgunit', cert.organizationalUnit);
// Serial Number
addAttributeFromCert('serialnumber',cert.serialNumber);
// SHA-256 Fingerprint
addAttributeFromCert('sha256fingerprint', cert.sha256Fingerprint);
// SHA1 Fingerprint
addAttributeFromCert('sha1fingerprint',cert.sha1Fingerprint);
// Validity start
addAttributeFromCert('validitystart', cert.validity.notBeforeLocalDay);
// Validity end
addAttributeFromCert('validityend', cert.validity.notAfterLocalDay);
addAttributeFromCert("commonname", cert.commonName);
addAttributeFromCert("organization", cert.organization);
addAttributeFromCert("orgunit", cert.organizationalUnit);
addAttributeFromCert("serialnumber", cert.serialNumber);
addAttributeFromCert("sha256fingerprint", cert.sha256Fingerprint);
addAttributeFromCert("sha1fingerprint", cert.sha1Fingerprint);
addAttributeFromCert("validitystart", cert.validity.notBeforeLocalDay);
addAttributeFromCert("validityend", cert.validity.notAfterLocalDay);
//Now to populate the fields that correspond to the issuer.
var issuerCommonname, issuerOrg, issuerOrgUnit;
issuerCommonname = cert.issuerCommonName;
issuerOrg = cert.issuerOrganization;
issuerOrgUnit = cert.issuerOrganizationUnit;
addAttributeFromCert('issuercommonname', issuerCommonname);
addAttributeFromCert('issuerorganization', issuerOrg);
addAttributeFromCert('issuerorgunit', issuerOrgUnit);
addAttributeFromCert("issuercommonname", cert.issuerCommonName);
addAttributeFromCert("issuerorganization", cert.issuerOrganization);
addAttributeFromCert("issuerorgunit", cert.issuerOrganizationUnit);
}
function updateCertDump()

View File

@ -1088,7 +1088,7 @@ GatherEKUTelemetry(const ScopedCERTCertList& certList)
}
// Parse the EKU extension
ScopedCERTOidSequence ekuSequence(
UniqueCERTOidSequence ekuSequence(
CERT_DecodeOidSequence(&ekuExtension->value));
if (!ekuSequence) {
return;

View File

@ -4,6 +4,9 @@
* 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/. */
// This header provides smart pointers and various helpers for code that needs
// to interact with NSS.
#ifndef mozilla_ScopedNSSTypes_h
#define mozilla_ScopedNSSTypes_h
@ -70,6 +73,7 @@ MapSECStatus(SECStatus rv)
}
// Alphabetical order by NSS type
// Deprecated: use the equivalent UniquePtr templates instead.
MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedPRFileDesc,
PRFileDesc,
PR_Close)
@ -88,25 +92,13 @@ MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedCERTCertList,
MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedCERTName,
CERTName,
CERT_DestroyName)
MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedCERTOidSequence,
CERTOidSequence,
CERT_DestroyOidSequence)
MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedCERTCertNicknames,
CERTCertNicknames,
CERT_FreeNicknames)
MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedCERTSubjectPublicKeyInfo,
CERTSubjectPublicKeyInfo,
SECKEY_DestroySubjectPublicKeyInfo)
MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedCERTValidity,
CERTValidity,
CERT_DestroyValidity)
MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedNSSCMSMessage,
NSSCMSMessage,
NSS_CMSMessage_Destroy)
MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedNSSCMSSignedData,
NSSCMSSignedData,
NSS_CMSSignedData_Destroy)
// Deprecated: use the equivalent UniquePtr templates instead.
namespace psm {
@ -115,30 +107,15 @@ PK11_DestroyContext_true(PK11Context * ctx) {
PK11_DestroyContext(ctx, true);
}
inline void
SGN_DestroyContext_true(SGNContext* ctx) {
SGN_DestroyContext(ctx, true);
}
inline void
VFY_DestroyContext_true(VFYContext * ctx) {
VFY_DestroyContext(ctx, true);
}
} // namespace mozilla::psm
// Deprecated: use the equivalent UniquePtr templates instead.
MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedPK11Context,
PK11Context,
mozilla::psm::PK11_DestroyContext_true)
MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedSGNContext,
SGNContext,
mozilla::psm::SGN_DestroyContext_true)
MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedSGNDigestInfo,
SGNDigestInfo,
SGN_DestroyDigestInfo)
MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedVFYContext,
VFYContext,
mozilla::psm::VFY_DestroyContext_true)
/** A more convenient way of dealing with digests calculated into
* stack-allocated buffers. NSS must be initialized on the main thread before
@ -231,23 +208,16 @@ private:
SECItem item;
};
// Deprecated: use the equivalent UniquePtr templates instead.
MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedPK11SlotInfo,
PK11SlotInfo,
PK11_FreeSlot)
MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedPK11SlotList,
PK11SlotList,
PK11_FreeSlotList)
MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedPK11SymKey,
PK11SymKey,
PK11_FreeSymKey)
MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedPK11GenericObject,
PK11GenericObject,
PK11_DestroyGenericObject)
MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedSEC_PKCS7ContentInfo,
SEC_PKCS7ContentInfo,
SEC_PKCS7DestroyContentInfo)
MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedSEC_PKCS12DecoderContext,
SEC_PKCS12DecoderContext,
SEC_PKCS12DecoderFinish)
@ -263,6 +233,7 @@ PORT_FreeArena_false(PLArenaPool* arena)
} // namespace internal
// Deprecated: use the equivalent UniquePtr templates instead.
MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedPLArenaPool,
PLArenaPool,
internal::PORT_FreeArena_false)
@ -325,10 +296,10 @@ inline void SECKEYEncryptedPrivateKeyInfo_true(SECKEYEncryptedPrivateKeyInfo * e
} // namespace internal
// Deprecated: use the equivalent UniquePtr templates instead.
MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedSECItem,
SECItem,
internal::SECITEM_FreeItem_true)
MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedSECKEYPrivateKey,
SECKEYPrivateKey,
SECKEY_DestroyPrivateKey)
@ -341,8 +312,6 @@ MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedSECKEYPublicKey,
MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedSECAlgorithmID,
SECAlgorithmID,
internal::SECOID_DestroyAlgorithmID_true)
MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedSECMODModule, SECMODModule,
SECMOD_DestroyModule)
// Emulates MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE, but for UniquePtrs.
#define MOZ_TYPE_SPECIFIC_UNIQUE_PTR_TEMPLATE(name, Type, Deleter) \
@ -355,21 +324,40 @@ typedef UniquePtr<Type, name##DeletePolicy> name;
MOZ_TYPE_SPECIFIC_UNIQUE_PTR_TEMPLATE(UniqueCERTCertificatePolicies,
CERTCertificatePolicies,
CERT_DestroyCertificatePoliciesExtension)
MOZ_TYPE_SPECIFIC_UNIQUE_PTR_TEMPLATE(UniqueCERTCertNicknames,
CERTCertNicknames,
CERT_FreeNicknames)
MOZ_TYPE_SPECIFIC_UNIQUE_PTR_TEMPLATE(UniqueCERTOidSequence,
CERTOidSequence,
CERT_DestroyOidSequence)
MOZ_TYPE_SPECIFIC_UNIQUE_PTR_TEMPLATE(UniqueCERTUserNotice,
CERTUserNotice,
CERT_DestroyUserNotice)
MOZ_TYPE_SPECIFIC_UNIQUE_PTR_TEMPLATE(UniqueNSSCMSMessage,
NSSCMSMessage,
NSS_CMSMessage_Destroy)
MOZ_TYPE_SPECIFIC_UNIQUE_PTR_TEMPLATE(UniqueNSSCMSSignedData,
NSSCMSSignedData,
NSS_CMSSignedData_Destroy)
MOZ_TYPE_SPECIFIC_UNIQUE_PTR_TEMPLATE(UniquePK11SlotList,
PK11SlotList,
PK11_FreeSlotList)
MOZ_TYPE_SPECIFIC_UNIQUE_PTR_TEMPLATE(UniquePLArenaPool,
PLArenaPool,
internal::PORT_FreeArena_false)
MOZ_TYPE_SPECIFIC_UNIQUE_PTR_TEMPLATE(UniqueSECItem,
SECItem,
internal::SECITEM_FreeItem_true)
MOZ_TYPE_SPECIFIC_UNIQUE_PTR_TEMPLATE(UniqueSECKEYPublicKey,
SECKEYPublicKey,
SECKEY_DestroyPublicKey)
MOZ_TYPE_SPECIFIC_UNIQUE_PTR_TEMPLATE(UniqueSECMODModule,
SECMODModule,
SECMOD_DestroyModule)
} // namespace mozilla
#endif // mozilla_ScopedNSSTypes_h

View File

@ -103,7 +103,8 @@ NS_IMETHODIMP nsCertPicker::PickByUsage(nsIInterfaceRequestor *ctx,
}
}
ScopedCERTCertNicknames nicknames(getNSSCertNicknamesFromCertList(certList.get()));
UniqueCERTCertNicknames nicknames(
getNSSCertNicknamesFromCertList(certList.get()));
if (!nicknames) {
return NS_ERROR_NOT_AVAILABLE;
}

View File

@ -51,7 +51,7 @@ nsPkcs11::DeleteModule(const nsAString& aModuleName)
// before we call SECMOD_DeleteModule, below.
#ifndef MOZ_NO_SMART_CARDS
{
mozilla::ScopedSECMODModule module(SECMOD_FindModule(moduleName.get()));
mozilla::UniqueSECMODModule module(SECMOD_FindModule(moduleName.get()));
if (!module) {
return NS_ERROR_FAILURE;
}
@ -100,7 +100,7 @@ nsPkcs11::AddModule(const nsAString& aModuleName,
}
#ifndef MOZ_NO_SMART_CARDS
mozilla::ScopedSECMODModule module(SECMOD_FindModule(moduleName.get()));
mozilla::UniqueSECMODModule module(SECMOD_FindModule(moduleName.get()));
if (!module) {
return NS_ERROR_FAILURE;
}

View File

@ -129,7 +129,7 @@ VerifyCMSDetachedSignatureIncludingCertificate(
return NS_ERROR_INVALID_ARG;
}
ScopedNSSCMSMessage
UniqueNSSCMSMessage
cmsMsg(NSS_CMSMessage_CreateFromDER(const_cast<SECItem*>(&buffer), nullptr,
nullptr, nullptr, nullptr, nullptr,
nullptr));

View File

@ -11,6 +11,7 @@
#include "CertVerifier.h"
#include "ExtendedValidation.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/unused.h"
#include "pkix/pkixnss.h"
#include "pkix/pkixtypes.h"
#include "nsNSSComponent.h" // for PIPNSS string bundle calls.
@ -923,14 +924,13 @@ nsNSSCertificate::GetAllTokenNames(uint32_t* aLength, char16_t*** aTokenNames)
*aTokenNames = nullptr;
// Get the slots from NSS
ScopedPK11SlotList slots;
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("Getting slots for \"%s\"\n", mCert->nickname));
slots = PK11_GetAllSlotsForCert(mCert.get(), nullptr);
UniquePK11SlotList slots(PK11_GetAllSlotsForCert(mCert.get(), nullptr));
if (!slots) {
if (PORT_GetError() == SEC_ERROR_NO_TOKEN)
if (PORT_GetError() == SEC_ERROR_NO_TOKEN) {
return NS_OK; // List of slots is empty, return empty array
else
return NS_ERROR_FAILURE;
}
return NS_ERROR_FAILURE;
}
// read the token names from slots
@ -1149,7 +1149,7 @@ nsNSSCertificate::ExportAsCMS(uint32_t chainMode,
return NS_ERROR_INVALID_ARG;
}
ScopedNSSCMSMessage cmsg(NSS_CMSMessage_Create(nullptr));
UniqueNSSCMSMessage cmsg(NSS_CMSMessage_Create(nullptr));
if (!cmsg) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
("nsNSSCertificate::ExportAsCMS - can't create CMS message\n"));
@ -1157,8 +1157,8 @@ nsNSSCertificate::ExportAsCMS(uint32_t chainMode,
}
// first, create SignedData with the certificate only (no chain)
ScopedNSSCMSSignedData sigd(
NSS_CMSSignedData_CreateCertsOnly(cmsg, mCert.get(), false));
UniqueNSSCMSSignedData sigd(
NSS_CMSSignedData_CreateCertsOnly(cmsg.get(), mCert.get(), false));
if (!sigd) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
("nsNSSCertificate::ExportAsCMS - can't create SignedData\n"));
@ -1182,7 +1182,7 @@ nsNSSCertificate::ExportAsCMS(uint32_t chainMode,
ScopedCERTCertificateList certChain(
CERT_CertChainFromCert(issuerCert, certUsageAnyCA, includeRoot));
if (certChain) {
if (NSS_CMSSignedData_AddCertList(sigd, certChain) == SECSuccess) {
if (NSS_CMSSignedData_AddCertList(sigd.get(), certChain) == SECSuccess) {
certChain.forget();
}
else {
@ -1193,7 +1193,7 @@ nsNSSCertificate::ExportAsCMS(uint32_t chainMode,
}
else {
// try to add the issuerCert, at least
if (NSS_CMSSignedData_AddCertificate(sigd, issuerCert)
if (NSS_CMSSignedData_AddCertificate(sigd.get(), issuerCert)
== SECSuccess) {
issuerCert.forget();
}
@ -1206,10 +1206,10 @@ nsNSSCertificate::ExportAsCMS(uint32_t chainMode,
}
}
NSSCMSContentInfo* cinfo = NSS_CMSMessage_GetContentInfo(cmsg);
if (NSS_CMSContentInfo_SetContent_SignedData(cmsg, cinfo, sigd)
NSSCMSContentInfo* cinfo = NSS_CMSMessage_GetContentInfo(cmsg.get());
if (NSS_CMSContentInfo_SetContent_SignedData(cmsg.get(), cinfo, sigd.get())
== SECSuccess) {
sigd.forget();
Unused << sigd.release();
}
else {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
@ -1225,7 +1225,7 @@ nsNSSCertificate::ExportAsCMS(uint32_t chainMode,
}
SECItem certP7 = { siBuffer, nullptr, 0 };
NSSCMSEncoderContext* ecx = NSS_CMSEncoder_Start(cmsg, nullptr, nullptr,
NSSCMSEncoderContext* ecx = NSS_CMSEncoder_Start(cmsg.get(), nullptr, nullptr,
&certP7, arena, nullptr,
nullptr, nullptr, nullptr,
nullptr, nullptr);

View File

@ -2092,7 +2092,7 @@ ClientAuthDataRunnable::RunOnTargetThread()
ScopedSECKEYPrivateKey privKey;
ScopedCERTCertList certList;
CERTCertListNode* node;
ScopedCERTCertNicknames nicknames;
UniqueCERTCertNicknames nicknames;
int keyError = 0; // used for private key retrieval error
SSM_UserCertChoice certChoice;
int32_t NumberOfCerts = 0;
@ -2296,7 +2296,7 @@ ClientAuthDataRunnable::RunOnTargetThread()
goto noCert;
}
nicknames = getNSSCertNicknamesFromCertList(certList.get());
nicknames.reset(getNSSCertNicknamesFromCertList(certList.get()));
if (!nicknames) {
goto loser;

View File

@ -23,7 +23,7 @@ FakeSSLStatus.prototype = {
}
throw Components.results.NS_ERROR_NO_INTERFACE;
},
}
};
// This is a template to help porting global private browsing tests
// to per-window private browsing tests

View File

@ -11,8 +11,8 @@
.getInterface(SpecialPowers.Ci.nsIWebNavigation)
.goBack();
}, 100);
}
};
</script>
</head>
</html>

View File

@ -13,7 +13,7 @@
window.location =
"https://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/bug383369step3.html?runtest";
}, 0);
}
};
function afterNavigationTest()
{

Some files were not shown because too many files have changed in this diff Show More