This commit is contained in:
Carsten "Tomcat" Book 2015-10-13 12:43:53 +02:00
Родитель c19a5b10ac 944b9ebefa
Коммит 2803b80084
134 изменённых файлов: 4325 добавлений и 2069 удалений

Просмотреть файл

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="0b934d06c04adff2cd9bdd0bc204f974a18b710f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="d400cda6bf0f8b30dcf7d7d71bfa61f29a3f1588"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7938df689aa87769fad3f2cf9097fb4ecb106a43"/>

Просмотреть файл

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="0b934d06c04adff2cd9bdd0bc204f974a18b710f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="d400cda6bf0f8b30dcf7d7d71bfa61f29a3f1588"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7938df689aa87769fad3f2cf9097fb4ecb106a43"/>
@ -135,7 +135,7 @@
<project groups="invensense" name="platform/hardware/invensense" path="hardware/invensense" revision="e6d9ab28b4f4e7684f6c07874ee819c9ea0002a2"/>
<project name="platform/hardware/ril" path="hardware/ril" revision="865ce3b4a2ba0b3a31421ca671f4d6c5595f8690"/>
<project name="kernel/common" path="kernel" revision="0f36762ab0c1d8ce10c6a5eda948b05d5d6cc379"/>
<project name="platform/system/core" path="system/core" revision="4b989b1bec28b0838420c4d5bb454c78afa62bea"/>
<project name="platform/system/core" path="system/core" revision="4776448ebcd3f07d58b91503c478da9b54cb58a0"/>
<project name="u-boot" path="u-boot" revision="f1502910977ac88f43da7bf9277c3523ad4b0b2f"/>
<project name="vendor/sprd/gps" path="vendor/sprd/gps" revision="7d6e1269be7186b2073fa568958b357826692c4b"/>
<project name="vendor/sprd/open-source" path="vendor/sprd/open-source" revision="295ff253b74353751a99aafd687196a28c84a58e"/>

Просмотреть файл

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="0b934d06c04adff2cd9bdd0bc204f974a18b710f"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="d400cda6bf0f8b30dcf7d7d71bfa61f29a3f1588"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7938df689aa87769fad3f2cf9097fb4ecb106a43"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="4ace9aaee0e048dfda11bb787646c59982a3dc80"/>

Просмотреть файл

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="0b934d06c04adff2cd9bdd0bc204f974a18b710f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="d400cda6bf0f8b30dcf7d7d71bfa61f29a3f1588"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7938df689aa87769fad3f2cf9097fb4ecb106a43"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="31a7849fe9a8b743d6f5e5facc212f0ef9d57499"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="25554535ee69d4c0c24a51f6a55bbabe5cb0a6b8"/>

Просмотреть файл

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="0b934d06c04adff2cd9bdd0bc204f974a18b710f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="d400cda6bf0f8b30dcf7d7d71bfa61f29a3f1588"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7938df689aa87769fad3f2cf9097fb4ecb106a43"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

Просмотреть файл

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="c9d4fe680662ee44a4bdea42ae00366f5df399cf">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="0b934d06c04adff2cd9bdd0bc204f974a18b710f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="d400cda6bf0f8b30dcf7d7d71bfa61f29a3f1588"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7938df689aa87769fad3f2cf9097fb4ecb106a43"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

Просмотреть файл

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="0b934d06c04adff2cd9bdd0bc204f974a18b710f"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="d400cda6bf0f8b30dcf7d7d71bfa61f29a3f1588"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7938df689aa87769fad3f2cf9097fb4ecb106a43"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="4ace9aaee0e048dfda11bb787646c59982a3dc80"/>

Просмотреть файл

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="0b934d06c04adff2cd9bdd0bc204f974a18b710f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="d400cda6bf0f8b30dcf7d7d71bfa61f29a3f1588"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7938df689aa87769fad3f2cf9097fb4ecb106a43"/>

Просмотреть файл

@ -1,9 +1,9 @@
{
"git": {
"git_revision": "0b934d06c04adff2cd9bdd0bc204f974a18b710f",
"git_revision": "d400cda6bf0f8b30dcf7d7d71bfa61f29a3f1588",
"remote": "https://git.mozilla.org/releases/gaia.git",
"branch": ""
},
"revision": "dee47434923493d57f151448eec00f793f113bfd",
"revision": "d382a1ff9028efabb8bbc18812ff7de12759a29e",
"repo_path": "integration/gaia-central"
}

Просмотреть файл

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="0b934d06c04adff2cd9bdd0bc204f974a18b710f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="d400cda6bf0f8b30dcf7d7d71bfa61f29a3f1588"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7938df689aa87769fad3f2cf9097fb4ecb106a43"/>

Просмотреть файл

@ -18,7 +18,7 @@
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="0b934d06c04adff2cd9bdd0bc204f974a18b710f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="d400cda6bf0f8b30dcf7d7d71bfa61f29a3f1588"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7938df689aa87769fad3f2cf9097fb4ecb106a43"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="31a7849fe9a8b743d6f5e5facc212f0ef9d57499"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="25554535ee69d4c0c24a51f6a55bbabe5cb0a6b8"/>

Просмотреть файл

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="c9d4fe680662ee44a4bdea42ae00366f5df399cf">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="0b934d06c04adff2cd9bdd0bc204f974a18b710f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="d400cda6bf0f8b30dcf7d7d71bfa61f29a3f1588"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7938df689aa87769fad3f2cf9097fb4ecb106a43"/>

Просмотреть файл

@ -1,5 +1,14 @@
add_task(function* test_simple() {
let extension = ExtensionTestUtils.loadExtension("simple");
let extensionData = {
manifest: {
"name": "Simple extension test",
"version": "1.0",
"manifest_version": 2,
"description": ""
}
};
let extension = ExtensionTestUtils.loadExtension(extensionData);
info("load complete");
yield extension.startup();
info("startup complete");
@ -8,7 +17,30 @@ add_task(function* test_simple() {
});
add_task(function* test_background() {
let extension = ExtensionTestUtils.loadExtension("background");
function backgroundScript() {
browser.test.log("running background script");
browser.test.onMessage.addListener((x, y) => {
browser.test.assertEq(x, 10, "x is 10");
browser.test.assertEq(y, 20, "y is 20");
browser.test.notifyPass("background test passed");
});
browser.test.sendMessage("running", 1);
}
let extensionData = {
background: "(" + backgroundScript.toString() + ")()",
manifest: {
"name": "Simple extension test",
"version": "1.0",
"manifest_version": 2,
"description": ""
}
};
let extension = ExtensionTestUtils.loadExtension(extensionData);
info("load complete");
let [, x] = yield Promise.all([extension.startup(), extension.awaitMessage("running")]);
is(x, 1, "got correct value from extension");

Просмотреть файл

@ -109,8 +109,8 @@ function getFilePath(aName, aAllowMissing=false, aUsePlatformPathSeparator=false
return path;
}
function saveNewHeapSnapshot() {
const filePath = ChromeUtils.saveHeapSnapshot({ runtime: true });
function saveNewHeapSnapshot(opts = { runtime: true }) {
const filePath = ChromeUtils.saveHeapSnapshot(opts);
ok(filePath, "Should get a file path to save the core dump to.");
ok(true, "Saved a heap snapshot to " + filePath);
return filePath;

Просмотреть файл

@ -0,0 +1,118 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that the HeapAnalyses{Client,Worker} can send SavedFrame stacks from
// by-allocation-stack reports from the worker.
function run_test() {
run_next_test();
}
add_task(function* test() {
const client = new HeapAnalysesClient();
// Track some allocation stacks.
const g = newGlobal();
const dbg = new Debugger(g);
g.eval(` // 1
this.log = []; // 2
function f() { this.log.push(allocationMarker()); } // 3
function g() { this.log.push(allocationMarker()); } // 4
function h() { this.log.push(allocationMarker()); } // 5
`); // 6
// Create one allocationMarker with tracking turned off,
// so it will have no associated stack.
g.f();
dbg.memory.allocationSamplingProbability = 1;
for (let [func, n] of [ [g.f, 20],
[g.g, 10],
[g.h, 5] ]) {
for (let i = 0; i < n; i++) {
dbg.memory.trackingAllocationSites = true;
// All allocations of allocationMarker occur with this line as the oldest
// stack frame.
func();
dbg.memory.trackingAllocationSites = false;
}
}
// Take a heap snapshot.
const snapshotFilePath = saveNewHeapSnapshot({ debugger: dbg });
yield client.readHeapSnapshot(snapshotFilePath);
ok(true, "Should have read the heap snapshot");
// Run a census broken down by class name -> allocation stack so we can grab
// only the AllocationMarker objects we have complete control over.
const report = yield client.takeCensus(snapshotFilePath, {
breakdown: { by: 'objectClass',
then: { by: 'allocationStack',
then: { by: 'count',
bytes: true,
count: true
},
noStack: { by: 'count',
bytes: true,
count: true
}
}
}
});
// Test the generated report.
ok(report, "Should get a report");
const map = report.AllocationMarker;
ok(map, "Should get AllocationMarkers in the report.");
// From a module with a different global, and therefore a different Map
// constructor, so we can't use instanceof.
equal(map.__proto__.constructor.name, "Map");
equal(map.size, 4, "Should have 4 allocation stacks (including the lack of a stack)")
// Gather the stacks we are expecting to appear as keys, and
// check that there are no unexpected keys.
let stacks = {};
map.forEach((v, k) => {
if (k === 'noStack') {
// No need to save this key.
} else if (k.functionDisplayName === 'f' &&
k.parent.functionDisplayName === 'test') {
stacks.f = k;
} else if (k.functionDisplayName === 'g' &&
k.parent.functionDisplayName === 'test') {
stacks.g = k;
} else if (k.functionDisplayName === 'h' &&
k.parent.functionDisplayName === 'test') {
stacks.h = k;
} else {
dumpn("Unexpected allocation stack:")
k.toString().split(/\n/g).forEach(s => dumpn(s));
ok(false);
}
});
ok(map.get('noStack'));
equal(map.get('noStack').count, 1);
ok(stacks.f);
ok(map.get(stacks.f));
equal(map.get(stacks.f).count, 20);
ok(stacks.g);
ok(map.get(stacks.g));
equal(map.get(stacks.g).count, 10);
ok(stacks.h);
ok(map.get(stacks.h));
equal(map.get(stacks.h).count, 5);
client.destroy();
});

Просмотреть файл

@ -16,6 +16,7 @@ support-files =
[test_HeapAnalyses_takeCensus_01.js]
[test_HeapAnalyses_takeCensus_02.js]
[test_HeapAnalyses_takeCensus_03.js]
[test_HeapAnalyses_takeCensus_04.js]
[test_HeapSnapshot_takeCensus_01.js]
[test_HeapSnapshot_takeCensus_02.js]
[test_HeapSnapshot_takeCensus_03.js]

Просмотреть файл

@ -80,7 +80,6 @@ skip-if = os == 'linux' || os == 'mac' # Bug 1026815
[test_bug690056.xul]
[test_bug789773.xul]
[test_bug846906.xul]
skip-if = (os == 'linux' && asan) || debug # Bug 1207161
[test_bug89419.xul]
[test_bug909218.html]
[test_bug92598.xul]

Просмотреть файл

@ -2710,6 +2710,9 @@ nsContentUtils::SubjectPrincipal()
MOZ_ASSERT(NS_IsMainThread());
JSContext* cx = GetCurrentJSContext();
if (!cx) {
#ifndef RELEASE_BUILD
MOZ_CRASH("Accessing the Subject Principal without an AutoJSAPI on the stack is forbidden");
#endif
Telemetry::Accumulate(Telemetry::SUBJECT_PRINCIPAL_ACCESSED_WITHOUT_SCRIPT_ON_STACK, true);
return GetSystemPrincipal();
}

Просмотреть файл

@ -1982,6 +1982,7 @@ public:
{
InternalFocusEvent event(true, mEventMessage);
event.mFlags.mBubbles = false;
event.mFlags.mCancelable = false;
event.fromRaise = mWindowRaised;
event.isRefocus = mIsRefocus;
return EventDispatcher::Dispatch(mTarget, mContext, &event);

Просмотреть файл

@ -1074,13 +1074,6 @@ nsINode::IsEqualNode(nsINode* aOther)
if (!string1.Equals(string2)) {
return false;
}
// Internal subset
docType1->GetInternalSubset(string1);
docType2->GetInternalSubset(string2);
if (!string1.Equals(string2)) {
return false;
}
break;
}

Просмотреть файл

@ -38,8 +38,7 @@ function checkDoc(title, expectedtitle, normalizedtitle) {
}
isElement(doc.documentElement.lastChild, "body");
is(doc.documentElement.lastChild.childNodes.length, 0);
((!title || title.indexOf("\f") === -1) ? is : todo_is)
(doc.title, normalizedtitle);
is(doc.title, normalizedtitle);
doc.body.innerHTML = "foo";
is(doc.body.innerHTML, "foo", "innerHTML should work in HTML data documents!");
}

Просмотреть файл

@ -11,7 +11,6 @@
#include "BluetoothSocket.h"
#include "BluetoothUtils.h"
#include "BluetoothUuid.h"
#include "ObexBase.h"
#include "mozilla/dom/BluetoothPbapParametersBinding.h"
#include "mozilla/dom/File.h"
@ -46,6 +45,31 @@ namespace {
}
};
// App parameters to pull phonebook
static const AppParameterTag sPhonebookTags[] = {
AppParameterTag::Format,
AppParameterTag::PropertySelector,
AppParameterTag::MaxListCount,
AppParameterTag::ListStartOffset,
AppParameterTag::vCardSelector
};
// App parameters to pull vCard listing
static const AppParameterTag sVCardListingTags[] = {
AppParameterTag::Order,
AppParameterTag::SearchValue,
AppParameterTag::SearchProperty,
AppParameterTag::MaxListCount,
AppParameterTag::ListStartOffset,
AppParameterTag::vCardSelector
};
// App parameters to pull vCard entry
static const AppParameterTag sVCardEntryTags[] = {
AppParameterTag::Format,
AppParameterTag::PropertySelector
};
StaticRefPtr<BluetoothPbapManager> sPbapManager;
static bool sInShutdown = false;
}
@ -261,7 +285,7 @@ BluetoothPbapManager::ReceiveSocketData(BluetoothSocket* aSocket,
return;
}
uint8_t response = SetPhoneBookPath(data[3], pktHeaders);
ObexResponseCode response = SetPhoneBookPath(pktHeaders, data[3]);
if (response != ObexResponseCode::Success) {
ReplyError(response);
return;
@ -271,18 +295,22 @@ BluetoothPbapManager::ReceiveSocketData(BluetoothSocket* aSocket,
break;
}
case ObexRequestCode::Get:
// Section 6.2.2 "OBEX Headers in Multi-Packet Responses", IrOBEX 1.2
// All OBEX request messages shall be sent as one OBEX packet containing
// all of the headers. I.e. OBEX GET with opcode 0x83 shall always be
// used. OBEX GET with opcode 0x03 shall never be used.
/*
* Section 6.2.2 "OBEX Headers in Multi-Packet Responses", IrOBEX 1.2
* All OBEX request messages shall be sent as one OBEX packet containing
* all the headers, i.e., OBEX GET with opcode 0x83 shall always be
* used, and GET with opcode 0x03 shall never be used.
*/
BT_LOGR("PBAP shall always use OBEX GetFinal instead of Get.");
// no break. Treat 'Get' as 'GetFinal' for error tolerance.
case ObexRequestCode::GetFinal: {
// When |mVCardDataStream| requires multiple response packets to complete,
// the client should continue to issue GET requests until the final body
// information (i.e., End-of-Body header) arrives, along with
// ObexResponseCode::Success
/*
* When |mVCardDataStream| requires multiple response packets to complete,
* the client should continue to issue GET requests until the final body
* information (i.e., End-of-Body header) arrives, along with
* ObexResponseCode::Success
*/
if (mVCardDataStream) {
if (!ReplyToGet()) {
BT_LOGR("Failed to reply to PBAP GET request.");
@ -300,33 +328,18 @@ BluetoothPbapManager::ReceiveSocketData(BluetoothSocket* aSocket,
return;
}
nsString type;
pktHeaders.GetContentType(type);
uint8_t response;
if (type.EqualsLiteral("x-bt/vcard-listing")) {
response = PullvCardListing(pktHeaders);
} else if (type.EqualsLiteral("x-bt/vcard")) {
response = PullvCardEntry(pktHeaders);
} else if (type.EqualsLiteral("x-bt/phonebook")) {
response = PullPhonebook(pktHeaders);
} else {
response = ObexResponseCode::BadRequest;
BT_LOGR("Unknown PBAP request type: %s",
NS_ConvertUTF16toUTF8(type).get());
}
// The OBEX success response will be sent after Gaia replies the PBAP
// request.
ObexResponseCode response = NotifyPbapRequest(pktHeaders);
if (response != ObexResponseCode::Success) {
ReplyError(response);
return;
}
// OBEX success response will be sent after gaia replies PBAP request
break;
}
case ObexRequestCode::Put:
case ObexRequestCode::PutFinal:
ReplyError(ObexResponseCode::BadRequest);
BT_LOGR("Unsupported ObexRequestCode %x", opCode);
break;
default:
ReplyError(ObexResponseCode::NotImplemented);
@ -363,9 +376,9 @@ BluetoothPbapManager::CompareHeaderTarget(const ObexHeaderSet& aHeader)
return true;
}
uint8_t
BluetoothPbapManager::SetPhoneBookPath(uint8_t flags,
const ObexHeaderSet& aHeader)
ObexResponseCode
BluetoothPbapManager::SetPhoneBookPath(const ObexHeaderSet& aHeader,
uint8_t flags)
{
// Section 5.2 "SetPhoneBook Function", PBAP 1.2
// flags bit 1 must be 1 and bit 2~7 be 0
@ -424,103 +437,66 @@ BluetoothPbapManager::SetPhoneBookPath(uint8_t flags,
return ObexResponseCode::Success;
}
uint8_t
BluetoothPbapManager::PullPhonebook(const ObexHeaderSet& aHeader)
ObexResponseCode
BluetoothPbapManager::NotifyPbapRequest(const ObexHeaderSet& aHeader)
{
MOZ_ASSERT(NS_IsMainThread());
BluetoothService* bs = BluetoothService::Get();
if (!bs) {
return ObexResponseCode::PreconditionFailed;
}
InfallibleTArray<BluetoothNamedValue> data;
nsString name;
// Get content type and name
nsString type, name;
aHeader.GetContentType(type);
aHeader.GetName(name);
// Ensure the name of phonebook object is legal
if (!IsLegalPhonebookName(name)) {
BT_LOGR("Illegal phone book object name [%s]",
NS_ConvertUTF16toUTF8(name).get());
return ObexResponseCode::NotFound;
// Configure request based on content type
nsString reqId;
uint8_t tagCount;
const AppParameterTag* tags;
if (type.EqualsLiteral("x-bt/phonebook")) {
reqId.AssignLiteral(PULL_PHONEBOOK_REQ_ID);
tagCount = MOZ_ARRAY_LENGTH(sPhonebookTags);
tags = sPhonebookTags;
// Ensure the name of phonebook object is legal
if (!IsLegalPhonebookName(name)) {
BT_LOGR("Illegal phone book object name [%s]",
NS_ConvertUTF16toUTF8(name).get());
return ObexResponseCode::NotFound;
}
} else if (type.EqualsLiteral("x-bt/vcard-listing")) {
reqId.AssignLiteral(PULL_VCARD_LISTING_REQ_ID);
tagCount = MOZ_ARRAY_LENGTH(sVCardListingTags);
tags = sVCardListingTags;
// Section 5.3.3 "Name", PBAP 1.2:
// ... PullvCardListing function uses relative paths. An empty name header
// may be sent to retrieve the vCard Listing object of the current folder.
name = name.IsEmpty() ? mCurrentPath
: mCurrentPath + NS_LITERAL_STRING("/") + name;
} else if (type.EqualsLiteral("x-bt/vcard")) {
reqId.AssignLiteral(PULL_VCARD_ENTRY_REQ_ID);
tagCount = MOZ_ARRAY_LENGTH(sVCardEntryTags);
tags = sVCardEntryTags;
} else {
BT_LOGR("Unknown PBAP request type: %s",
NS_ConvertUTF16toUTF8(type).get());
return ObexResponseCode::BadRequest;
}
AppendNamedValue(data, "name", name);
AppendNamedValueByTagId(aHeader, data, AppParameterTag::Format);
AppendNamedValueByTagId(aHeader, data, AppParameterTag::PropertySelector);
AppendNamedValueByTagId(aHeader, data, AppParameterTag::MaxListCount);
AppendNamedValueByTagId(aHeader, data, AppParameterTag::ListStartOffset);
AppendNamedValueByTagId(aHeader, data, AppParameterTag::vCardSelector);
bs->DistributeSignal(NS_LITERAL_STRING(PULL_PHONEBOOK_REQ_ID),
NS_LITERAL_STRING(KEY_ADAPTER),
data);
return ObexResponseCode::Success;
}
uint8_t
BluetoothPbapManager::PullvCardListing(const ObexHeaderSet& aHeader)
{
MOZ_ASSERT(NS_IsMainThread());
// Ensure bluetooth service is available
BluetoothService* bs = BluetoothService::Get();
if (!bs) {
BT_LOGR("Failed to get Bluetooth service");
return ObexResponseCode::PreconditionFailed;
}
// Pack PBAP request
InfallibleTArray<BluetoothNamedValue> data;
nsString folderName;
aHeader.GetName(folderName);
// Section 5.3.3 "Name", PBAP 1.2
// ... PullvCardListing function uses relative paths. An empty name header may
// be sent to retrieve the vCard Listing object of the current folder.
nsString folderPath = mCurrentPath;
if (!folderName.IsEmpty()) {
folderPath += NS_LITERAL_STRING("/") + folderName;
}
AppendNamedValue(data, "name", folderPath);
AppendNamedValueByTagId(aHeader, data, AppParameterTag::Order);
AppendNamedValueByTagId(aHeader, data, AppParameterTag::SearchValue);
AppendNamedValueByTagId(aHeader, data, AppParameterTag::SearchProperty);
AppendNamedValueByTagId(aHeader, data, AppParameterTag::MaxListCount);
AppendNamedValueByTagId(aHeader, data, AppParameterTag::ListStartOffset);
AppendNamedValueByTagId(aHeader, data, AppParameterTag::vCardSelector);
bs->DistributeSignal(NS_LITERAL_STRING(PULL_VCARD_LISTING_REQ_ID),
NS_LITERAL_STRING(KEY_ADAPTER),
data);
return ObexResponseCode::Success;
}
uint8_t
BluetoothPbapManager::PullvCardEntry(const ObexHeaderSet& aHeader)
{
MOZ_ASSERT(NS_IsMainThread());
BluetoothService* bs = BluetoothService::Get();
if (!bs) {
return ObexResponseCode::PreconditionFailed;
}
InfallibleTArray<BluetoothNamedValue> data;
nsString name;
aHeader.GetName(name);
AppendNamedValue(data, "name", name);
for (uint8_t i = 0; i < tagCount; i++) {
AppendNamedValueByTagId(aHeader, data, tags[i]);
}
AppendNamedValueByTagId(aHeader, data, AppParameterTag::Format);
AppendNamedValueByTagId(aHeader, data, AppParameterTag::PropertySelector);
bs->DistributeSignal(NS_LITERAL_STRING(PULL_VCARD_ENTRY_REQ_ID),
NS_LITERAL_STRING(KEY_ADAPTER),
data);
bs->DistributeSignal(reqId, NS_LITERAL_STRING(KEY_ADAPTER), data);
return ObexResponseCode::Success;
}
@ -553,64 +529,41 @@ BluetoothPbapManager::AppendNamedValueByTagId(
AppendNamedValue(aValues, "searchKey", searchKey);
break;
}
case AppParameterTag::SearchValue: {
case AppParameterTag::SearchValue:
// Section 5.3.4.3 "SearchValue {<text string>}", PBAP 1.2
// The UTF-8 character set shall be used for <text string>.
// Use nsCString to store UTF-8 string here to follow the suggestion of
// 'MDN:Internal_strings'.
nsCString text((char *) buf);
AppendNamedValue(aValues, "searchText", text);
// Store UTF-8 string with nsCString to follow MDN:Internal_strings
AppendNamedValue(aValues, "searchText", nsCString((char *) buf));
break;
}
case AppParameterTag::MaxListCount: {
uint16_t maxListCount = *((uint16_t *)buf);
// convert big endian to little endian
maxListCount = (maxListCount >> 8) | (maxListCount << 8);
// Section 5 "Phone Book Access Profile Functions", PBAP 1.2
// Replying 'PhonebookSize' is mandatory if 'MaxListCount' parameter is
// present in the request with a value of 0, else it is excluded.
mPhonebookSizeRequired = !maxListCount;
uint16_t maxListCount = ReadLittleEndianUInt16(buf);
AppendNamedValue(aValues, "maxListCount",
static_cast<uint32_t>(maxListCount));
// Section 5 "Phone Book Access Profile Functions", PBAP 1.2
// Replying 'PhonebookSize' is mandatory if 'MaxListCount' parameter
// is present in the request with a value of 0, else it is excluded.
mPhonebookSizeRequired = !maxListCount;
break;
}
case AppParameterTag::ListStartOffset: {
uint16_t listStartOffset = *((uint16_t *)buf);
// convert big endian to little endian
listStartOffset = (listStartOffset >> 8) | (listStartOffset << 8);
case AppParameterTag::ListStartOffset:
AppendNamedValue(aValues, "listStartOffset",
static_cast<uint32_t>(listStartOffset));
static_cast<uint32_t>(ReadLittleEndianUInt16(buf)));
break;
}
case AppParameterTag::PropertySelector: {
InfallibleTArray<uint32_t> props = PackPropertiesMask(buf, 64);
AppendNamedValue(aValues, "propSelector", props);
case AppParameterTag::PropertySelector:
AppendNamedValue(aValues, "propSelector", PackPropertiesMask(buf, 64));
break;
}
case AppParameterTag::Format: {
bool usevCard3 = buf[0];
AppendNamedValue(aValues, "format", usevCard3);
case AppParameterTag::Format:
AppendNamedValue(aValues, "format", static_cast<bool>(buf[0]));
break;
}
case AppParameterTag::vCardSelector: {
InfallibleTArray<uint32_t> props = PackPropertiesMask(buf, 64);
bool hasVCardSelectorOperator = aHeader.GetAppParameter(
bool hasSelectorOperator = aHeader.GetAppParameter(
AppParameterTag::vCardSelectorOperator, buf, 64);
if (hasVCardSelectorOperator && buf[0]) {
AppendNamedValue(aValues, "vCardSelector_AND", BluetoothValue(props));
} else {
AppendNamedValue(aValues, "vCardSelector_OR", BluetoothValue(props));
}
AppendNamedValue(aValues,
hasSelectorOperator && buf[0] ? "vCardSelector_AND"
: "vCardSelector_OR",
PackPropertiesMask(buf, 64));
break;
}
default:
@ -906,10 +859,7 @@ BluetoothPbapManager::ReplyToGet(uint16_t aPhonebookSize)
if (mPhonebookSizeRequired) {
// ---- Part 2: [headerId:1][length:2][PhonebookSize:4] ---- //
// convert little endian to big endian
uint8_t phonebookSize[2];
phonebookSize[0] = (aPhonebookSize & 0xFF00) >> 8;
phonebookSize[1] = aPhonebookSize & 0x00FF;
uint16_t pbSizeBigEndian = ConvertEndiannessUInt16(aPhonebookSize);
// Section 6.2.1 "Application Parameters Header", PBAP 1.2
// appParameters: [headerId:1][length:2][PhonebookSize:4], where
@ -917,9 +867,9 @@ BluetoothPbapManager::ReplyToGet(uint16_t aPhonebookSize)
uint8_t appParameters[4];
AppendAppParameter(appParameters,
sizeof(appParameters),
(uint8_t) AppParameterTag::PhonebookSize,
phonebookSize,
sizeof(phonebookSize));
static_cast<uint8_t>(AppParameterTag::PhonebookSize),
(uint8_t*) &pbSizeBigEndian,
sizeof(pbSizeBigEndian));
index += AppendHeaderAppParameters(&res[index],
mRemoteMaxPacketLength,

Просмотреть файл

@ -12,9 +12,9 @@
#include "BluetoothSocketObserver.h"
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
#include "mozilla/ipc/SocketBase.h"
#include "ObexBase.h"
class nsIInputStream;
namespace mozilla {
namespace dom {
class Blob;
@ -141,20 +141,18 @@ private:
void ReplyToConnect();
void ReplyToDisconnectOrAbort();
void ReplyToSetPath();
bool ReplyToGet(uint16_t aPhonebookSize = 0);
void ReplyError(uint8_t aError);
void SendObexData(uint8_t* aData, uint8_t aOpcode, int aSize);
bool ReplyToGet(uint16_t aPhonebookSize = 0);
uint8_t SetPhoneBookPath(uint8_t flags, const ObexHeaderSet& aHeader);
uint8_t PullPhonebook(const ObexHeaderSet& aHeader);
uint8_t PullvCardListing(const ObexHeaderSet& aHeader);
uint8_t PullvCardEntry(const ObexHeaderSet& aHeader);
void AppendNamedValueByTagId(
const ObexHeaderSet& aHeader,
InfallibleTArray<BluetoothNamedValue>& aValues,
const AppParameterTag aTagId);
ObexResponseCode SetPhoneBookPath(const ObexHeaderSet& aHeader,
uint8_t flags);
ObexResponseCode NotifyPbapRequest(const ObexHeaderSet& aHeader);
void AppendNamedValueByTagId(const ObexHeaderSet& aHeader,
InfallibleTArray<BluetoothNamedValue>& aValues,
const AppParameterTag aTagId);
InfallibleTArray<uint32_t> PackPropertiesMask(uint8_t* aData, int aSize);
InfallibleTArray<uint32_t> PackPropertiesMask(uint8_t* aData, int aSize);
bool CompareHeaderTarget(const ObexHeaderSet& aHeader);
bool IsLegalPath(const nsAString& aPath);
bool IsLegalPhonebookName(const nsAString& aName);

Просмотреть файл

@ -604,4 +604,16 @@ InsertNamedValue(InfallibleTArray<BluetoothNamedValue>& aArray,
aArray.InsertElementAt(aIndex, BluetoothNamedValue(name, aValue));
}
uint16_t
ConvertEndiannessUInt16(uint16_t aValue)
{
return (aValue >> 8) | (aValue << 8);
}
uint16_t
ReadLittleEndianUInt16(const uint8_t* aBuf)
{
return ConvertEndiannessUInt16(*((uint16_t *) aBuf));
}
END_BLUETOOTH_NAMESPACE

Просмотреть файл

@ -272,6 +272,20 @@ void InsertNamedValue(InfallibleTArray<BluetoothNamedValue>& aArray,
uint8_t aIndex, const char* aName,
const BluetoothValue& aValue);
//
// Big/Little endianness conversion
//
/**
* Convert a big/little endian uint16_t value to little/big endian one.
*/
uint16_t ConvertEndiannessUInt16(uint16_t aValue);
/**
* Read an uint16_t from array and convert it to little endian one.
*/
uint16_t ReadLittleEndianUInt16(const uint8_t* aBuf);
END_BLUETOOTH_NAMESPACE
#endif // mozilla_dom_bluetooth_BluetoothUtils_h

Просмотреть файл

@ -6,7 +6,6 @@ support-files =
[test_Document-createElement-namespace.html.json]
[test_Document-createElementNS.html.json]
[test_Document-getElementsByTagName.html.json]
[test_Node-isEqualNode.xhtml.json]
[test_Node-properties.html.json]
[test_attributes.html.json]
[test_case.html.json]

Просмотреть файл

@ -1,3 +0,0 @@
{
"isEqualNode should return true when only the internal subsets of DocumentTypes differ.": true
}

Просмотреть файл

@ -3,10 +3,7 @@
support-files =
[test_document.title-03.html.json]
[test_document.title-04.xhtml.json]
[test_document.title-06.html.json]
[test_document.title-07.html.json]
[test_nameditem-02.html.json]
[test_nameditem-03.html.json]
[test_nameditem-04.html.json]

Просмотреть файл

@ -1,3 +0,0 @@
{
" document.title and space normalization ": true
}

Просмотреть файл

@ -1,3 +0,0 @@
{
" document.title and space normalization ": true
}

Просмотреть файл

@ -1,3 +0,0 @@
{
"Document.title and DOMImplementation.createHTMLDocument 6": true
}

Просмотреть файл

@ -1,6 +0,0 @@
# THIS FILE IS AUTOGENERATED BY parseFailures.py - DO NOT EDIT
[DEFAULT]
support-files =
[test_option-text-spaces.html.json]

Просмотреть файл

@ -1,15 +0,0 @@
{
"option.text should strip leading space characters (\"\\f\")": true,
"option.text should strip trailing space characters (\"\\f\")": true,
"option.text should strip leading and trailing space characters (\"\\f\")": true,
"option.text should replace single internal space characters (\"\\f\")": true,
"option.text should replace multiple internal space characters (\" \", \"\\f\")": true,
"option.text should replace multiple internal space characters (\"\\t\", \"\\f\")": true,
"option.text should replace multiple internal space characters (\"\\n\", \"\\f\")": true,
"option.text should replace multiple internal space characters (\"\\f\", \" \")": true,
"option.text should replace multiple internal space characters (\"\\f\", \"\\t\")": true,
"option.text should replace multiple internal space characters (\"\\f\", \"\\n\")": true,
"option.text should replace multiple internal space characters (\"\\f\", \"\\f\")": true,
"option.text should replace multiple internal space characters (\"\\f\", \"\\r\")": true,
"option.text should replace multiple internal space characters (\"\\r\", \"\\f\")": true
}

Просмотреть файл

@ -24,7 +24,6 @@ MOCHITEST_MANIFESTS += [
'failures/html/html/dom/documents/dta/doc.gEBN/mochitest.ini',
'failures/html/html/dom/documents/dta/mochitest.ini',
'failures/html/html/obsolete/implreq/oeaaa/mochitest.ini',
'failures/html/html/semantics/forms/the-option-element/mochitest.ini',
'failures/html/html/semantics/forms/the-select-element/mochitest.ini',
'failures/html/html/semantics/scripting-1/the-script-element/mochitest.ini',
'failures/html/html/semantics/tabular-data/the-table-element/mochitest.ini',

Просмотреть файл

@ -146,11 +146,11 @@ class VersionChangeTransaction;
// If JS_STRUCTURED_CLONE_VERSION changes then we need to update our major
// schema version.
static_assert(JS_STRUCTURED_CLONE_VERSION == 5,
static_assert(JS_STRUCTURED_CLONE_VERSION == 6,
"Need to update the major schema version.");
// Major schema version. Bump for almost everything.
const uint32_t kMajorSchemaVersion = 21;
const uint32_t kMajorSchemaVersion = 22;
// Minor schema version. Should almost always be 0 (maybe bump on release
// branches if we have to).
@ -4066,6 +4066,19 @@ UpgradeSchemaFrom20_0To21_0(mozIStorageConnection* aConnection)
return NS_OK;
}
nsresult
UpgradeSchemaFrom21_0To22_0(mozIStorageConnection* aConnection)
{
// The only change between 21 and 22 was a different structured clone format,
// but it's backwards-compatible.
nsresult rv = aConnection->SetSchemaVersion(MakeSchemaVersion(22, 0));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
nsresult
GetDatabaseFileURL(nsIFile* aDatabaseFile,
PersistenceType aPersistenceType,
@ -4558,7 +4571,7 @@ CreateStorageConnection(nsIFile* aDBFile,
}
} else {
// This logic needs to change next time we change the schema!
static_assert(kSQLiteSchemaVersion == int32_t((21 << 4) + 0),
static_assert(kSQLiteSchemaVersion == int32_t((22 << 4) + 0),
"Upgrade function needed due to schema version increase.");
while (schemaVersion != kSQLiteSchemaVersion) {
@ -4598,6 +4611,8 @@ CreateStorageConnection(nsIFile* aDBFile,
rv = UpgradeSchemaFrom19_0To20_0(aFMDirectory, connection);
} else if (schemaVersion == MakeSchemaVersion(20, 0)) {
rv = UpgradeSchemaFrom20_0To21_0(connection);
} else if (schemaVersion == MakeSchemaVersion(21, 0)) {
rv = UpgradeSchemaFrom21_0To22_0(connection);
} else {
IDB_WARNING("Unable to open IndexedDB database, no upgrade path is "
"available!");

Просмотреть файл

@ -299,6 +299,43 @@ PreallocatedProcessManagerImpl::GetSpareProcess()
return process.forget();
}
static bool
TestCaseEnabled()
{
return Preferences::GetBool("dom.ipc.preallocatedProcessManager.testMode");
}
static void
SendTestOnlyNotification(const char* aMessage)
{
if (!TestCaseEnabled()) {
return;
}
AutoSafeJSContext cx;
nsString message;
message.AppendPrintf("%s", aMessage);
nsCOMPtr<nsIMessageBroadcaster> ppmm =
do_GetService("@mozilla.org/parentprocessmessagemanager;1");
mozilla::unused << ppmm->BroadcastAsyncMessage(
message, JS::NullHandleValue, JS::NullHandleValue, cx, 1);
}
static void
KillOrCloseProcess(ContentParent* aProcess)
{
if (TestCaseEnabled()) {
// KillHard() the process because we don't want the process to abort when we
// close the IPC channel while it's still running and creating actors.
aProcess->KillHard("Killed by test case.");
}
else {
aProcess->Close();
}
}
/**
* Publish a ContentParent to spare process list.
*/
@ -307,14 +344,7 @@ PreallocatedProcessManagerImpl::PublishSpareProcess(ContentParent* aContent)
{
MOZ_ASSERT(NS_IsMainThread());
if (Preferences::GetBool("dom.ipc.preallocatedProcessManager.testMode")) {
AutoJSContext cx;
nsCOMPtr<nsIMessageBroadcaster> ppmm =
do_GetService("@mozilla.org/parentprocessmessagemanager;1");
mozilla::unused << ppmm->BroadcastAsyncMessage(
NS_LITERAL_STRING("TEST-ONLY:nuwa-add-new-process"),
JS::NullHandleValue, JS::NullHandleValue, cx, 1);
}
SendTestOnlyNotification("TEST-ONLY:nuwa-add-new-process");
mSpareProcesses.AppendElement(aContent);
}
@ -333,7 +363,7 @@ PreallocatedProcessManagerImpl::MaybeForgetSpare(ContentParent* aContent)
mIsNuwaReady = false;
while (mSpareProcesses.Length() > 0) {
nsRefPtr<ContentParent> process = mSpareProcesses[mSpareProcesses.Length() - 1];
process->Close();
KillOrCloseProcess(aContent);
mSpareProcesses.RemoveElementAt(mSpareProcesses.Length() - 1);
}
ScheduleDelayedNuwaFork();
@ -353,14 +383,8 @@ PreallocatedProcessManagerImpl::OnNuwaReady()
ProcessPriorityManager::SetProcessPriority(mPreallocatedAppProcess,
hal::PROCESS_PRIORITY_MASTER);
mIsNuwaReady = true;
if (Preferences::GetBool("dom.ipc.preallocatedProcessManager.testMode")) {
AutoJSContext cx;
nsCOMPtr<nsIMessageBroadcaster> ppmm =
do_GetService("@mozilla.org/parentprocessmessagemanager;1");
mozilla::unused << ppmm->BroadcastAsyncMessage(
NS_LITERAL_STRING("TEST-ONLY:nuwa-ready"),
JS::NullHandleValue, JS::NullHandleValue, cx, 1);
}
SendTestOnlyNotification("TEST-ONLY:nuwa-ready");
NuwaFork();
}
@ -370,7 +394,6 @@ PreallocatedProcessManagerImpl::PreallocatedProcessReady()
return !mSpareProcesses.IsEmpty();
}
void
PreallocatedProcessManagerImpl::NuwaFork()
{
@ -399,7 +422,7 @@ PreallocatedProcessManagerImpl::Disable()
#ifdef MOZ_NUWA_PROCESS
while (mSpareProcesses.Length() > 0){
nsRefPtr<ContentParent> process = mSpareProcesses[0];
process->Close();
KillOrCloseProcess(process);
mSpareProcesses.RemoveElementAt(0);
}
mIsNuwaReady = false;

Просмотреть файл

@ -257,6 +257,10 @@ HangMonitorChild::HangMonitorChild(ProcessHangMonitor* aMonitor)
HangMonitorChild::~HangMonitorChild()
{
// For some reason IPDL doesn't automatically delete the channel for a
// bridged protocol (bug 1090570). So we have to do it ourselves.
XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new DeleteTask<Transport>(GetTransport()));
MOZ_RELEASE_ASSERT(NS_IsMainThread());
MOZ_ASSERT(sInstance == this);
sInstance = nullptr;
@ -469,7 +473,7 @@ DeleteMinidump(const uint32_t& aPluginId, nsString aCrashId, void* aUserData)
HangMonitorParent::~HangMonitorParent()
{
// For some reason IPDL doesn't autmatically delete the channel for a
// For some reason IPDL doesn't automatically delete the channel for a
// bridged protocol (bug 1090570). So we have to do it ourselves.
XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new DeleteTask<Transport>(GetTransport()));

Просмотреть файл

@ -14,7 +14,7 @@ skip-if = buildapp == 'b2g' || buildapp == 'mulet' || e10s || toolkit == 'androi
[test_cpow_cookies.html]
skip-if = buildapp == 'b2g' || buildapp == 'mulet'
[test_NuwaProcessCreation.html]
skip-if = true # bug 1166923
skip-if = toolkit != 'gonk'
[test_NuwaProcessDeadlock.html]
skip-if = true # bug 1166923
[test_child_docshell.html]

Просмотреть файл

@ -14,6 +14,9 @@ Test if Nuwa process created successfully.
function runTest()
{
info("Shut down processes by disabling process prelaunch");
SpecialPowers.setBoolPref('dom.ipc.processPrelaunch.enabled', false);
info("Launch the Nuwa process");
let cpmm = SpecialPowers.Cc["@mozilla.org/childprocessmessagemanager;1"]
.getService(SpecialPowers.Ci.nsISyncMessageSender);
@ -22,12 +25,11 @@ function runTest()
receiveMessage: function receiveMessage(msg) {
msg = SpecialPowers.wrap(msg);
if (msg.name == 'TEST-ONLY:nuwa-ready') {
ok(true, "Got nuwa-ready");
is(seenNuwaReady, false, "Already received nuwa ready");
is(seenNuwaReady, false, "The Nuwa process is launched");
seenNuwaReady = true;
} else if (msg.name == 'TEST-ONLY:nuwa-add-new-process') {
ok(true, "Got nuwa-add-new-process");
is(seenNuwaReady, true, "Receive nuwa-add-new-process before nuwa-ready");
is(seenNuwaReady, true, "The preallocated process is launched from the Nuwa process");
shutdown();
}
}
@ -56,7 +58,6 @@ function setup()
SpecialPowers.pushPrefEnv({
'set': [
['dom.ipc.processPrelaunch.enabled', false],
['dom.ipc.preallocatedProcessManager.testMode', true]
]
}, runTest);

Просмотреть файл

@ -98,7 +98,14 @@ MobileMessageDatabaseService::MarkMessageRead(int32_t aMessageId,
bool aSendReadReport,
nsIMobileMessageCallback* aRequest)
{
// TODO: This would need to be implemented as part of Bug 748391
if (!AndroidBridge::Bridge()) {
return NS_OK;
}
AndroidBridge::Bridge()->MarkMessageRead(aMessageId,
aValue,
aSendReadReport,
aRequest);
return NS_OK;
}

Просмотреть файл

@ -393,5 +393,36 @@ SmsManager::NotifyCursorDone(int32_t aRequestId)
NS_DispatchToMainThread(runnable);
}
} // namespace
/*static*/
void
SmsManager::NotifySmsMarkedAsRead(bool aMarkedAsRead, int32_t aRequestId)
{
nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableFunction([=]() {
nsCOMPtr<nsIMobileMessageCallback> request =
AndroidBridge::Bridge()->DequeueSmsRequest(aRequestId);
if (!request) {
return;
}
request->NotifyMessageMarkedRead(aMarkedAsRead);
});
NS_DispatchToMainThread(runnable);
}
/*static*/
void
SmsManager::NotifySmsMarkAsReadFailed(int32_t aError, int32_t aRequestId)
{
nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableFunction([=]() {
nsCOMPtr<nsIMobileMessageCallback> request =
AndroidBridge::Bridge()->DequeueSmsRequest(aRequestId);
if (!request) {
return;
}
request->NotifyMarkMessageReadFailed(aError);
});
NS_DispatchToMainThread(runnable);
}
} // namespace

Просмотреть файл

@ -66,6 +66,8 @@ public:
bool aRead,
int32_t aRequestId);
static void NotifyCursorDone(int32_t aRequestId);
static void NotifySmsMarkedAsRead(bool aMarkedAsRead, int32_t aRequestId);
static void NotifySmsMarkAsReadFailed(int32_t aError, int32_t aRequestId);
};
} // namespace

Просмотреть файл

@ -161,7 +161,7 @@ PluginModuleChild::PluginModuleChild(bool aIsChrome)
PluginModuleChild::~PluginModuleChild()
{
if (mTransport) {
// For some reason IPDL doesn't autmatically delete the channel for a
// For some reason IPDL doesn't automatically delete the channel for a
// bridged protocol (bug 1090570). So we have to do it ourselves. This
// code is only invoked for PluginModuleChild instances created via
// bridging; otherwise mTransport is null.

Просмотреть файл

@ -690,6 +690,9 @@ PluginModuleContentParent::PluginModuleContentParent(bool aAllowAsyncInit)
PluginModuleContentParent::~PluginModuleContentParent()
{
XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
new DeleteTask<Transport>(GetTransport()));
Preferences::UnregisterCallback(TimeoutChanged, kContentTimeoutPref, this);
}

Просмотреть файл

@ -96,16 +96,12 @@ NS_NewXMLContentSink(nsIXMLContentSink** aResult,
}
nsXMLContentSink::nsXMLContentSink()
: mConstrainSize(true),
mPrettyPrintXML(true)
: mPrettyPrintXML(true)
{
}
nsXMLContentSink::~nsXMLContentSink()
{
if (mText) {
PR_Free(mText); // Doesn't null out, unlike PR_FREEIF
}
}
nsresult
@ -475,7 +471,6 @@ nsXMLContentSink::CreateElement(const char16_t** aAtts, uint32_t aAttsCount,
nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(content);
sele->SetScriptLineNumber(aLineNumber);
sele->SetCreatorParser(GetParser());
mConstrainSize = false;
}
// XHTML needs some special attention
@ -552,7 +547,6 @@ nsXMLContentSink::CloseElement(nsIContent* aContent)
if (nodeInfo->Equals(nsGkAtoms::script, kNameSpaceID_XHTML)
|| nodeInfo->Equals(nsGkAtoms::script, kNameSpaceID_SVG)
) {
mConstrainSize = true;
nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(aContent);
if (mPreventScriptExecution) {
@ -778,26 +772,19 @@ nsXMLContentSink::FlushText(bool aReleaseTextNode)
if (mTextLength != 0) {
if (mLastTextNode) {
if ((mLastTextNodeSize + mTextLength) > mTextSize && !mXSLTProcessor) {
mLastTextNodeSize = 0;
mLastTextNode = nullptr;
FlushText(aReleaseTextNode);
} else {
bool notify = HaveNotifiedForCurrentContent();
// We could probably always increase mInNotification here since
// if AppendText doesn't notify it shouldn't trigger evil code.
// But just in case it does, we don't want to mask any notifications.
if (notify) {
++mInNotification;
}
rv = mLastTextNode->AppendText(mText, mTextLength, notify);
if (notify) {
--mInNotification;
}
mLastTextNodeSize += mTextLength;
mTextLength = 0;
bool notify = HaveNotifiedForCurrentContent();
// We could probably always increase mInNotification here since
// if AppendText doesn't notify it shouldn't trigger evil code.
// But just in case it does, we don't want to mask any notifications.
if (notify) {
++mInNotification;
}
rv = mLastTextNode->AppendText(mText, mTextLength, notify);
if (notify) {
--mInNotification;
}
mTextLength = 0;
} else {
nsRefPtr<nsTextNode> textContent = new nsTextNode(mNodeInfoManager);
@ -805,7 +792,6 @@ nsXMLContentSink::FlushText(bool aReleaseTextNode)
// Set the text in the text node
textContent->SetText(mText, mTextLength, false);
mLastTextNodeSize += mTextLength;
mTextLength = 0;
// Add text to its parent
@ -814,7 +800,6 @@ nsXMLContentSink::FlushText(bool aReleaseTextNode)
}
if (aReleaseTextNode) {
mLastTextNodeSize = 0;
mLastTextNode = nullptr;
}
@ -1437,41 +1422,19 @@ nsresult
nsXMLContentSink::AddText(const char16_t* aText,
int32_t aLength)
{
// Create buffer when we first need it
if (0 == mTextSize) {
mText = (char16_t *) PR_MALLOC(sizeof(char16_t) * NS_ACCUMULATION_BUFFER_SIZE);
if (nullptr == mText) {
return NS_ERROR_OUT_OF_MEMORY;
}
mTextSize = NS_ACCUMULATION_BUFFER_SIZE;
}
// Copy data from string into our buffer; flush buffer when it fills up
// Copy data from string into our buffer; flush buffer when it fills up.
int32_t offset = 0;
while (0 != aLength) {
int32_t amount = mTextSize - mTextLength;
int32_t amount = NS_ACCUMULATION_BUFFER_SIZE - mTextLength;
if (0 == amount) {
// XSLT wants adjacent textnodes merged.
if (mConstrainSize && !mXSLTProcessor) {
nsresult rv = FlushText();
if (NS_OK != rv) {
return rv;
}
amount = mTextSize - mTextLength;
}
else {
mTextSize += aLength;
mText = (char16_t *) PR_REALLOC(mText, sizeof(char16_t) * mTextSize);
if (nullptr == mText) {
mTextSize = 0;
return NS_ERROR_OUT_OF_MEMORY;
}
amount = aLength;
nsresult rv = FlushText(false);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
MOZ_ASSERT(mTextLength == 0);
amount = NS_ACCUMULATION_BUFFER_SIZE;
}
if (amount > aLength) {
amount = aLength;
}

Просмотреть файл

@ -171,18 +171,15 @@ protected:
nsCOMPtr<nsIContent> mDocElement;
nsCOMPtr<nsIContent> mCurrentHead; // When set, we're in an XHTML <haed>
char16_t* mText;
XMLContentSinkState mState;
// The length of the valid data in mText.
int32_t mTextLength;
int32_t mTextSize;
int32_t mNotifyLevel;
nsCOMPtr<nsIContent> mLastTextNode;
int32_t mLastTextNodeSize;
uint8_t mConstrainSize : 1;
uint8_t mPrettyPrintXML : 1;
uint8_t mPrettyPrintHasSpecialRoot : 1;
uint8_t mPrettyPrintHasFactoredElements : 1;
@ -194,6 +191,10 @@ protected:
nsTArray<StackNode> mContentStack;
nsCOMPtr<nsIDocumentTransformer> mXSLTProcessor;
static const int NS_ACCUMULATION_BUFFER_SIZE = 4096;
// Our currently accumulated text that we have not flushed to a textnode yet.
char16_t mText[NS_ACCUMULATION_BUFFER_SIZE];
};
#endif // nsXMLContentSink_h__

Просмотреть файл

@ -13,6 +13,7 @@
#include "mozilla/gfx/Matrix.h"
#include "mozilla/gfx/JobScheduler.h"
#include "mozilla/gfx/IterableArena.h"
#include "mozilla/RefCounted.h"
#include "DrawCommand.h"
namespace mozilla {

Просмотреть файл

@ -8,6 +8,7 @@
#include "mozilla/RefPtr.h"
#include "mozilla/gfx/Types.h"
#include "mozilla/RefCounted.h"
#ifdef WIN32
#include "mozilla/gfx/JobScheduler_win32.h"
@ -247,4 +248,4 @@ protected:
} // namespace
} // namespace
#endif
#endif

Просмотреть файл

@ -17,6 +17,7 @@
#include "mozilla/RefPtr.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/gfx/CriticalSection.h"
#include "mozilla/RefCounted.h"
namespace mozilla {
namespace gfx {

Просмотреть файл

@ -12,6 +12,7 @@
#include "mozilla/RefPtr.h"
#include "mozilla/gfx/CriticalSection.h"
#include "mozilla/RefCounted.h"
namespace mozilla {
namespace gfx {

Просмотреть файл

@ -45,6 +45,7 @@ typedef OSType (*IOSurfacePixelFormatFunc)(IOSurfacePtr io_surface);
#import <OpenGL/OpenGL.h>
#include "2D.h"
#include "mozilla/RefPtr.h"
#include "mozilla/RefCounted.h"
struct _CGLContextObject;

Просмотреть файл

@ -101,11 +101,13 @@ DCFromDrawTarget::DCFromDrawTarget(DrawTarget& aDrawTarget)
cairo_win32_scaled_font_select_font(scaled, mDC);
}
}
if (!mDC) {
mDC = GetDC(nullptr);
SetGraphicsMode(mDC, GM_ADVANCED);
mNeedsRelease = true;
}
}
if (!mDC) {
// Get the whole screen DC:
mDC = GetDC(nullptr);
SetGraphicsMode(mDC, GM_ADVANCED);
mNeedsRelease = true;
}
}
@ -684,10 +686,13 @@ gfxPlatformFontList*
gfxWindowsPlatform::CreatePlatformFontList()
{
gfxPlatformFontList *pfl;
#ifdef CAIRO_HAS_DWRITE_FONT
// bug 630201 - older pre-RTM versions of Direct2D/DirectWrite cause odd
// crashers so blacklist them altogether
if (IsNotWin7PreRTM() && GetDWriteFactory()) {
if (IsNotWin7PreRTM() && GetDWriteFactory() &&
// Skia doesn't support DirectWrite fonts yet.
(gfxPlatform::GetDefaultContentBackend() != BackendType::SKIA)) {
pfl = new gfxDWriteFontList();
if (NS_SUCCEEDED(pfl->InitFontList())) {
return pfl;

Просмотреть файл

@ -1221,9 +1221,6 @@ VectorImage::OnSVGDocumentError()
{
CancelAllListeners();
// XXXdholbert Need to do something more for the parsing failed case -- right
// now, this just makes us draw the "object" icon, rather than the (jagged)
// "broken image" icon. See bug 594505.
mError = true;
if (mProgressTracker) {

Просмотреть файл

@ -121,7 +121,7 @@ typedef void (*FreeTransferStructuredCloneOp)(uint32_t tag, JS::TransferableOwne
// Increment this when anything at all changes in the serialization format.
// (Note that this does not need to be bumped for Transferable-only changes,
// since they are never saved to persistent storage.)
#define JS_STRUCTURED_CLONE_VERSION 5
#define JS_STRUCTURED_CLONE_VERSION 6
struct JSStructuredCloneCallbacks {
ReadStructuredCloneOp read;

Просмотреть файл

@ -2216,6 +2216,15 @@ GetPropertyIC::maybeDisable(bool emitted)
return;
}
if (!canAttachStub() && id().constant()) {
// Don't disable the cache (and discard stubs) if we have a GETPROP and
// attached the maximum number of stubs. This can happen when JS code
// uses an AST-like data structure and accesses a field of a "base
// class", like node.nodeType. This should be temporary until we handle
// this case better, see bug 1107515.
return;
}
if (!canAttachStub() || (stubCount_ == 0 && failedUpdates_ > MAX_FAILED_UPDATES)) {
JitSpew(JitSpew_IonIC, "Disable inline cache");
disable();

Просмотреть файл

@ -2339,9 +2339,9 @@ MacroAssemblerARMCompat::store32(Imm32 src, const Address& address)
void
MacroAssemblerARMCompat::store32(Imm32 imm, const BaseIndex& dest)
{
AutoRegisterScope scratch2(asMasm(), secondScratchReg_);
ma_mov(imm, scratch2);
store32(scratch2, dest);
ScratchRegisterScope scratch(asMasm());
ma_mov(imm, scratch);
store32(scratch, dest);
}
void
@ -2350,11 +2350,11 @@ MacroAssemblerARMCompat::store32(Register src, const BaseIndex& dest)
Register base = dest.base;
uint32_t scale = Imm32::ShiftOf(dest.scale).value;
ScratchRegisterScope scratch(asMasm());
AutoRegisterScope scratch2(asMasm(), secondScratchReg_);
if (dest.offset != 0) {
ma_add(base, Imm32(dest.offset), scratch);
base = scratch;
ma_add(base, Imm32(dest.offset), scratch2);
base = scratch2;
}
ma_str(src, DTRAddr(base, DtrRegImmShift(dest.index, LSL, scale)));
}

Просмотреть файл

@ -480,12 +480,31 @@ AssemblerMIPSShared::as_addiu(Register rd, Register rs, int32_t j)
return writeInst(InstImm(op_addiu, rs, rd, Imm16(j)).encode());
}
BufferOffset
AssemblerMIPSShared::as_daddu(Register rd, Register rs, Register rt)
{
return writeInst(InstReg(op_special, rs, rt, rd, ff_daddu).encode());
}
BufferOffset
AssemblerMIPSShared::as_daddiu(Register rd, Register rs, int32_t j)
{
MOZ_ASSERT(Imm16::IsInSignedRange(j));
return writeInst(InstImm(op_daddiu, rs, rd, Imm16(j)).encode());
}
BufferOffset
AssemblerMIPSShared::as_subu(Register rd, Register rs, Register rt)
{
return writeInst(InstReg(op_special, rs, rt, rd, ff_subu).encode());
}
BufferOffset
AssemblerMIPSShared::as_dsubu(Register rd, Register rs, Register rt)
{
return writeInst(InstReg(op_special, rs, rt, rd, ff_dsubu).encode());
}
BufferOffset
AssemblerMIPSShared::as_mult(Register rs, Register rt)
{
@ -498,6 +517,18 @@ AssemblerMIPSShared::as_multu(Register rs, Register rt)
return writeInst(InstReg(op_special, rs, rt, ff_multu).encode());
}
BufferOffset
AssemblerMIPSShared::as_dmult(Register rs, Register rt)
{
return writeInst(InstReg(op_special, rs, rt, ff_dmult).encode());
}
BufferOffset
AssemblerMIPSShared::as_dmultu(Register rs, Register rt)
{
return writeInst(InstReg(op_special, rs, rt, ff_dmultu).encode());
}
BufferOffset
AssemblerMIPSShared::as_div(Register rs, Register rt)
{
@ -510,6 +541,18 @@ AssemblerMIPSShared::as_divu(Register rs, Register rt)
return writeInst(InstReg(op_special, rs, rt, ff_divu).encode());
}
BufferOffset
AssemblerMIPSShared::as_ddiv(Register rs, Register rt)
{
return writeInst(InstReg(op_special, rs, rt, ff_ddiv).encode());
}
BufferOffset
AssemblerMIPSShared::as_ddivu(Register rs, Register rt)
{
return writeInst(InstReg(op_special, rs, rt, ff_ddivu).encode());
}
BufferOffset
AssemblerMIPSShared::as_mul(Register rd, Register rs, Register rt)
{
@ -531,12 +574,32 @@ AssemblerMIPSShared::as_sll(Register rd, Register rt, uint16_t sa)
return writeInst(InstReg(op_special, rs_zero, rt, rd, sa, ff_sll).encode());
}
BufferOffset
AssemblerMIPSShared::as_dsll(Register rd, Register rt, uint16_t sa)
{
MOZ_ASSERT(sa < 32);
return writeInst(InstReg(op_special, rs_zero, rt, rd, sa, ff_dsll).encode());
}
BufferOffset
AssemblerMIPSShared::as_dsll32(Register rd, Register rt, uint16_t sa)
{
MOZ_ASSERT(31 < sa && sa < 64);
return writeInst(InstReg(op_special, rs_zero, rt, rd, sa - 32, ff_dsll32).encode());
}
BufferOffset
AssemblerMIPSShared::as_sllv(Register rd, Register rt, Register rs)
{
return writeInst(InstReg(op_special, rs, rt, rd, ff_sllv).encode());
}
BufferOffset
AssemblerMIPSShared::as_dsllv(Register rd, Register rt, Register rs)
{
return writeInst(InstReg(op_special, rs, rt, rd, ff_dsllv).encode());
}
BufferOffset
AssemblerMIPSShared::as_srl(Register rd, Register rt, uint16_t sa)
{
@ -544,12 +607,32 @@ AssemblerMIPSShared::as_srl(Register rd, Register rt, uint16_t sa)
return writeInst(InstReg(op_special, rs_zero, rt, rd, sa, ff_srl).encode());
}
BufferOffset
AssemblerMIPSShared::as_dsrl(Register rd, Register rt, uint16_t sa)
{
MOZ_ASSERT(sa < 32);
return writeInst(InstReg(op_special, rs_zero, rt, rd, sa, ff_dsrl).encode());
}
BufferOffset
AssemblerMIPSShared::as_dsrl32(Register rd, Register rt, uint16_t sa)
{
MOZ_ASSERT(31 < sa && sa < 64);
return writeInst(InstReg(op_special, rs_zero, rt, rd, sa - 32, ff_dsrl32).encode());
}
BufferOffset
AssemblerMIPSShared::as_srlv(Register rd, Register rt, Register rs)
{
return writeInst(InstReg(op_special, rs, rt, rd, ff_srlv).encode());
}
BufferOffset
AssemblerMIPSShared::as_dsrlv(Register rd, Register rt, Register rs)
{
return writeInst(InstReg(op_special, rs, rt, rd, ff_dsrlv).encode());
}
BufferOffset
AssemblerMIPSShared::as_sra(Register rd, Register rt, uint16_t sa)
{
@ -557,12 +640,32 @@ AssemblerMIPSShared::as_sra(Register rd, Register rt, uint16_t sa)
return writeInst(InstReg(op_special, rs_zero, rt, rd, sa, ff_sra).encode());
}
BufferOffset
AssemblerMIPSShared::as_dsra(Register rd, Register rt, uint16_t sa)
{
MOZ_ASSERT(sa < 32);
return writeInst(InstReg(op_special, rs_zero, rt, rd, sa, ff_dsra).encode());
}
BufferOffset
AssemblerMIPSShared::as_dsra32(Register rd, Register rt, uint16_t sa)
{
MOZ_ASSERT(31 < sa && sa < 64);
return writeInst(InstReg(op_special, rs_zero, rt, rd, sa - 32, ff_dsra32).encode());
}
BufferOffset
AssemblerMIPSShared::as_srav(Register rd, Register rt, Register rs)
{
return writeInst(InstReg(op_special, rs, rt, rd, ff_srav).encode());
}
BufferOffset
AssemblerMIPSShared::as_dsrav(Register rd, Register rt, Register rs)
{
return writeInst(InstReg(op_special, rs, rt, rd, ff_dsrav).encode());
}
BufferOffset
AssemblerMIPSShared::as_rotr(Register rd, Register rt, uint16_t sa)
{
@ -570,12 +673,32 @@ AssemblerMIPSShared::as_rotr(Register rd, Register rt, uint16_t sa)
return writeInst(InstReg(op_special, rs_one, rt, rd, sa, ff_srl).encode());
}
BufferOffset
AssemblerMIPSShared::as_drotr(Register rd, Register rt, uint16_t sa)
{
MOZ_ASSERT(sa < 32);
return writeInst(InstReg(op_special, rs_one, rt, rd, sa, ff_dsrl).encode());
}
BufferOffset
AssemblerMIPSShared::as_drotr32(Register rd, Register rt, uint16_t sa)
{
MOZ_ASSERT(31 < sa && sa < 64);
return writeInst(InstReg(op_special, rs_one, rt, rd, sa - 32, ff_dsrl32).encode());
}
BufferOffset
AssemblerMIPSShared::as_rotrv(Register rd, Register rt, Register rs)
{
return writeInst(InstReg(op_special, rs, rt, rd, 1, ff_srlv).encode());
}
BufferOffset
AssemblerMIPSShared::as_drotrv(Register rd, Register rt, Register rs)
{
return writeInst(InstReg(op_special, rs, rt, rd, 1, ff_dsrlv).encode());
}
// Load and store instructions
BufferOffset
AssemblerMIPSShared::as_lb(Register rd, Register rs, int16_t off)
@ -607,6 +730,12 @@ AssemblerMIPSShared::as_lw(Register rd, Register rs, int16_t off)
return writeInst(InstImm(op_lw, rs, rd, Imm16(off)).encode());
}
BufferOffset
AssemblerMIPSShared::as_lwu(Register rd, Register rs, int16_t off)
{
return writeInst(InstImm(op_lwu, rs, rd, Imm16(off)).encode());
}
BufferOffset
AssemblerMIPSShared::as_lwl(Register rd, Register rs, int16_t off)
{
@ -619,6 +748,30 @@ AssemblerMIPSShared::as_lwr(Register rd, Register rs, int16_t off)
return writeInst(InstImm(op_lwr, rs, rd, Imm16(off)).encode());
}
BufferOffset
AssemblerMIPSShared::as_ll(Register rd, Register rs, int16_t off)
{
return writeInst(InstImm(op_ll, rs, rd, Imm16(off)).encode());
}
BufferOffset
AssemblerMIPSShared::as_ld(Register rd, Register rs, int16_t off)
{
return writeInst(InstImm(op_ld, rs, rd, Imm16(off)).encode());
}
BufferOffset
AssemblerMIPSShared::as_ldl(Register rd, Register rs, int16_t off)
{
return writeInst(InstImm(op_ldl, rs, rd, Imm16(off)).encode());
}
BufferOffset
AssemblerMIPSShared::as_ldr(Register rd, Register rs, int16_t off)
{
return writeInst(InstImm(op_ldr, rs, rd, Imm16(off)).encode());
}
BufferOffset
AssemblerMIPSShared::as_sb(Register rd, Register rs, int16_t off)
{
@ -649,6 +802,30 @@ AssemblerMIPSShared::as_swr(Register rd, Register rs, int16_t off)
return writeInst(InstImm(op_swr, rs, rd, Imm16(off)).encode());
}
BufferOffset
AssemblerMIPSShared::as_sc(Register rd, Register rs, int16_t off)
{
return writeInst(InstImm(op_sc, rs, rd, Imm16(off)).encode());
}
BufferOffset
AssemblerMIPSShared::as_sd(Register rd, Register rs, int16_t off)
{
return writeInst(InstImm(op_sd, rs, rd, Imm16(off)).encode());
}
BufferOffset
AssemblerMIPSShared::as_sdl(Register rd, Register rs, int16_t off)
{
return writeInst(InstImm(op_sdl, rs, rd, Imm16(off)).encode());
}
BufferOffset
AssemblerMIPSShared::as_sdr(Register rd, Register rs, int16_t off)
{
return writeInst(InstImm(op_sdr, rs, rd, Imm16(off)).encode());
}
// Move from HI/LO register.
BufferOffset
AssemblerMIPSShared::as_mfhi(Register rd)
@ -725,6 +902,12 @@ AssemblerMIPSShared::as_clz(Register rd, Register rs)
return writeInst(InstReg(op_special2, rs, rd, rd, ff_clz).encode());
}
BufferOffset
AssemblerMIPSShared::as_dclz(Register rd, Register rs)
{
return writeInst(InstReg(op_special2, rs, rd, rd, ff_dclz).encode());
}
BufferOffset
AssemblerMIPSShared::as_ins(Register rt, Register rs, uint16_t pos, uint16_t size)
{
@ -734,6 +917,33 @@ AssemblerMIPSShared::as_ins(Register rt, Register rs, uint16_t pos, uint16_t siz
return writeInst(InstReg(op_special3, rs, rt, rd, pos, ff_ins).encode());
}
BufferOffset
AssemblerMIPSShared::as_dins(Register rt, Register rs, uint16_t pos, uint16_t size)
{
MOZ_ASSERT(pos < 32 && size != 0 && size <= 32 && pos + size != 0 && pos + size <= 32);
Register rd;
rd = Register::FromCode(pos + size - 1);
return writeInst(InstReg(op_special3, rs, rt, rd, pos, ff_dins).encode());
}
BufferOffset
AssemblerMIPSShared::as_dinsm(Register rt, Register rs, uint16_t pos, uint16_t size)
{
MOZ_ASSERT(pos < 32 && size >= 2 && size <= 64 && pos + size > 32 && pos + size <= 64);
Register rd;
rd = Register::FromCode(pos + size - 1 - 32);
return writeInst(InstReg(op_special3, rs, rt, rd, pos, ff_dinsm).encode());
}
BufferOffset
AssemblerMIPSShared::as_dinsu(Register rt, Register rs, uint16_t pos, uint16_t size)
{
MOZ_ASSERT(pos >= 32 && pos < 64 && size >= 1 && size <= 32 && pos + size > 32 && pos + size <= 64);
Register rd;
rd = Register::FromCode(pos + size - 1 - 32);
return writeInst(InstReg(op_special3, rs, rt, rd, pos - 32, ff_dinsu).encode());
}
BufferOffset
AssemblerMIPSShared::as_ext(Register rt, Register rs, uint16_t pos, uint16_t size)
{
@ -743,6 +953,46 @@ AssemblerMIPSShared::as_ext(Register rt, Register rs, uint16_t pos, uint16_t siz
return writeInst(InstReg(op_special3, rs, rt, rd, pos, ff_ext).encode());
}
// Sign extend
BufferOffset
AssemblerMIPSShared::as_seb(Register rd, Register rt)
{
return writeInst(InstReg(op_special3, zero, rt, rd, 16, ff_bshfl).encode());
}
BufferOffset
AssemblerMIPSShared::as_seh(Register rd, Register rt)
{
return writeInst(InstReg(op_special3, zero, rt, rd, 24, ff_bshfl).encode());
}
BufferOffset
AssemblerMIPSShared::as_dext(Register rt, Register rs, uint16_t pos, uint16_t size)
{
MOZ_ASSERT(pos < 32 && size != 0 && size <= 32 && pos + size != 0 && pos + size <= 63);
Register rd;
rd = Register::FromCode(size - 1);
return writeInst(InstReg(op_special3, rs, rt, rd, pos, ff_dext).encode());
}
BufferOffset
AssemblerMIPSShared::as_dextm(Register rt, Register rs, uint16_t pos, uint16_t size)
{
MOZ_ASSERT(pos < 32 && size > 32 && size <= 64 && pos + size > 32 && pos + size <= 64);
Register rd;
rd = Register::FromCode(size - 1 - 32);
return writeInst(InstReg(op_special3, rs, rt, rd, pos, ff_dextm).encode());
}
BufferOffset
AssemblerMIPSShared::as_dextu(Register rt, Register rs, uint16_t pos, uint16_t size)
{
MOZ_ASSERT(pos >= 32 && pos < 64 && size != 0 && size <= 32 && pos + size > 32 && pos + size <= 64);
Register rd;
rd = Register::FromCode(size - 1);
return writeInst(InstReg(op_special3, rs, rt, rd, pos - 32, ff_dextu).encode());
}
// FP instructions
BufferOffset
AssemblerMIPSShared::as_ld(FloatRegister fd, Register base, int32_t off)
@ -796,6 +1046,30 @@ AssemblerMIPSShared::as_mfc1(Register rt, FloatRegister fs)
return writeInst(InstReg(op_cop1, rs_mfc1, rt, fs).encode());
}
BufferOffset
AssemblerMIPSShared::as_mthc1(Register rt, FloatRegister fs)
{
return writeInst(InstReg(op_cop1, rs_mthc1, rt, fs).encode());
}
BufferOffset
AssemblerMIPSShared::as_mfhc1(Register rt, FloatRegister fs)
{
return writeInst(InstReg(op_cop1, rs_mfhc1, rt, fs).encode());
}
BufferOffset
AssemblerMIPSShared::as_dmtc1(Register rt, FloatRegister fs)
{
return writeInst(InstReg(op_cop1, rs_dmtc1, rt, fs).encode());
}
BufferOffset
AssemblerMIPSShared::as_dmfc1(Register rt, FloatRegister fs)
{
return writeInst(InstReg(op_cop1, rs_dmfc1, rt, fs).encode());
}
// FP convert instructions
BufferOffset
AssemblerMIPSShared::as_ceilws(FloatRegister fd, FloatRegister fs)
@ -845,6 +1119,12 @@ AssemblerMIPSShared::as_truncwd(FloatRegister fd, FloatRegister fs)
return writeInst(InstReg(op_cop1, rs_d, zero, fs, fd, ff_trunc_w_fmt).encode());
}
BufferOffset
AssemblerMIPSShared::as_cvtdl(FloatRegister fd, FloatRegister fs)
{
return writeInst(InstReg(op_cop1, rs_l, zero, fs, fd, ff_cvt_d_fmt).encode());
}
BufferOffset
AssemblerMIPSShared::as_cvtds(FloatRegister fd, FloatRegister fs)
{

Просмотреть файл

@ -30,14 +30,18 @@ static MOZ_CONSTEXPR_VAR Register a0 = { Registers::a0 };
static MOZ_CONSTEXPR_VAR Register a1 = { Registers::a1 };
static MOZ_CONSTEXPR_VAR Register a2 = { Registers::a2 };
static MOZ_CONSTEXPR_VAR Register a3 = { Registers::a3 };
static MOZ_CONSTEXPR_VAR Register a4 = { Registers::ta0 };
static MOZ_CONSTEXPR_VAR Register a5 = { Registers::ta1 };
static MOZ_CONSTEXPR_VAR Register a6 = { Registers::ta2 };
static MOZ_CONSTEXPR_VAR Register a7 = { Registers::ta3 };
static MOZ_CONSTEXPR_VAR Register t0 = { Registers::t0 };
static MOZ_CONSTEXPR_VAR Register t1 = { Registers::t1 };
static MOZ_CONSTEXPR_VAR Register t2 = { Registers::t2 };
static MOZ_CONSTEXPR_VAR Register t3 = { Registers::t3 };
static MOZ_CONSTEXPR_VAR Register t4 = { Registers::t4 };
static MOZ_CONSTEXPR_VAR Register t5 = { Registers::t5 };
static MOZ_CONSTEXPR_VAR Register t6 = { Registers::t6 };
static MOZ_CONSTEXPR_VAR Register t7 = { Registers::t7 };
static MOZ_CONSTEXPR_VAR Register t4 = { Registers::ta0 };
static MOZ_CONSTEXPR_VAR Register t5 = { Registers::ta1 };
static MOZ_CONSTEXPR_VAR Register t6 = { Registers::ta2 };
static MOZ_CONSTEXPR_VAR Register t7 = { Registers::ta3 };
static MOZ_CONSTEXPR_VAR Register s0 = { Registers::s0 };
static MOZ_CONSTEXPR_VAR Register s1 = { Registers::s1 };
static MOZ_CONSTEXPR_VAR Register s2 = { Registers::s2 };
@ -85,6 +89,10 @@ static MOZ_CONSTEXPR_VAR Register IntArgReg0 = a0;
static MOZ_CONSTEXPR_VAR Register IntArgReg1 = a1;
static MOZ_CONSTEXPR_VAR Register IntArgReg2 = a2;
static MOZ_CONSTEXPR_VAR Register IntArgReg3 = a3;
static MOZ_CONSTEXPR_VAR Register IntArgReg4 = a4;
static MOZ_CONSTEXPR_VAR Register IntArgReg5 = a5;
static MOZ_CONSTEXPR_VAR Register IntArgReg6 = a6;
static MOZ_CONSTEXPR_VAR Register IntArgReg7 = a7;
static MOZ_CONSTEXPR_VAR Register GlobalReg = s6; // used by Odin
static MOZ_CONSTEXPR_VAR Register HeapReg = s7; // used by Odin
static MOZ_CONSTEXPR_VAR Register CallTempNonArgRegs[] = CALL_TEMP_NON_ARG_REGS;
@ -246,6 +254,12 @@ enum Opcode {
op_blezl = 22 << OpcodeShift,
op_bgtzl = 23 << OpcodeShift,
op_daddi = 24 << OpcodeShift,
op_daddiu = 25 << OpcodeShift,
op_ldl = 26 << OpcodeShift,
op_ldr = 27 << OpcodeShift,
op_special2 = 28 << OpcodeShift,
op_special3 = 31 << OpcodeShift,
@ -256,17 +270,24 @@ enum Opcode {
op_lbu = 36 << OpcodeShift,
op_lhu = 37 << OpcodeShift,
op_lwr = 38 << OpcodeShift,
op_lwu = 39 << OpcodeShift,
op_sb = 40 << OpcodeShift,
op_sh = 41 << OpcodeShift,
op_swl = 42 << OpcodeShift,
op_sw = 43 << OpcodeShift,
op_sdl = 44 << OpcodeShift,
op_sdr = 45 << OpcodeShift,
op_swr = 46 << OpcodeShift,
op_ll = 48 << OpcodeShift,
op_lwc1 = 49 << OpcodeShift,
op_ldc1 = 53 << OpcodeShift,
op_ld = 55 << OpcodeShift,
op_sc = 56 << OpcodeShift,
op_swc1 = 57 << OpcodeShift,
op_sdc1 = 61 << OpcodeShift
op_sdc1 = 61 << OpcodeShift,
op_sd = 63 << OpcodeShift,
};
enum RSField {
@ -274,9 +295,11 @@ enum RSField {
// cop1 encoding of RS field.
rs_mfc1 = 0 << RSShift,
rs_one = 1 << RSShift,
rs_dmfc1 = 1 << RSShift,
rs_cfc1 = 2 << RSShift,
rs_mfhc1 = 3 << RSShift,
rs_mtc1 = 4 << RSShift,
rs_dmtc1 = 5 << RSShift,
rs_ctc1 = 6 << RSShift,
rs_mthc1 = 7 << RSShift,
rs_bc1 = 8 << RSShift,
@ -316,10 +339,18 @@ enum FunctionField {
ff_mfhi = 16,
ff_mflo = 18,
ff_dsllv = 20,
ff_dsrlv = 22,
ff_dsrav = 23,
ff_mult = 24,
ff_multu = 25,
ff_div = 26,
ff_divu = 27,
ff_dmult = 28,
ff_dmultu = 29,
ff_ddiv = 30,
ff_ddivu = 31,
ff_add = 32,
ff_addu = 33,
@ -332,6 +363,10 @@ enum FunctionField {
ff_slt = 42,
ff_sltu = 43,
ff_dadd = 44,
ff_daddu = 45,
ff_dsub = 46,
ff_dsubu = 47,
ff_tge = 48,
ff_tgeu = 49,
@ -339,15 +374,29 @@ enum FunctionField {
ff_tltu = 51,
ff_teq = 52,
ff_tne = 54,
ff_dsll = 56,
ff_dsrl = 58,
ff_dsra = 59,
ff_dsll32 = 60,
ff_dsrl32 = 62,
ff_dsra32 = 63,
// special2 encoding of function field.
ff_mul = 2,
ff_clz = 32,
ff_clo = 33,
ff_dclz = 36,
// special3 encoding of function field.
ff_ext = 0,
ff_dextm = 1,
ff_dextu = 2,
ff_dext = 3,
ff_ins = 4,
ff_dinsm = 5,
ff_dinsu = 6,
ff_dins = 7,
ff_bshfl = 32,
// cop1 encoding of function field.
ff_add_fmt = 0,
@ -812,12 +861,19 @@ class AssemblerMIPSShared : public AssemblerShared
// Arithmetic instructions
BufferOffset as_addu(Register rd, Register rs, Register rt);
BufferOffset as_addiu(Register rd, Register rs, int32_t j);
BufferOffset as_daddu(Register rd, Register rs, Register rt);
BufferOffset as_daddiu(Register rd, Register rs, int32_t j);
BufferOffset as_subu(Register rd, Register rs, Register rt);
BufferOffset as_dsubu(Register rd, Register rs, Register rt);
BufferOffset as_mult(Register rs, Register rt);
BufferOffset as_multu(Register rs, Register rt);
BufferOffset as_dmult(Register rs, Register rt);
BufferOffset as_dmultu(Register rs, Register rt);
BufferOffset as_div(Register rs, Register rt);
BufferOffset as_divu(Register rs, Register rt);
BufferOffset as_mul(Register rd, Register rs, Register rt);
BufferOffset as_ddiv(Register rs, Register rt);
BufferOffset as_ddivu(Register rs, Register rt);
// Logical instructions
BufferOffset as_and(Register rd, Register rs, Register rt);
@ -833,13 +889,25 @@ class AssemblerMIPSShared : public AssemblerShared
// Shift instructions
// as_sll(zero, zero, x) instructions are reserved as nop
BufferOffset as_sll(Register rd, Register rt, uint16_t sa);
BufferOffset as_dsll(Register rd, Register rt, uint16_t sa);
BufferOffset as_dsll32(Register rd, Register rt, uint16_t sa);
BufferOffset as_sllv(Register rd, Register rt, Register rs);
BufferOffset as_dsllv(Register rd, Register rt, Register rs);
BufferOffset as_srl(Register rd, Register rt, uint16_t sa);
BufferOffset as_dsrl(Register rd, Register rt, uint16_t sa);
BufferOffset as_dsrl32(Register rd, Register rt, uint16_t sa);
BufferOffset as_srlv(Register rd, Register rt, Register rs);
BufferOffset as_dsrlv(Register rd, Register rt, Register rs);
BufferOffset as_sra(Register rd, Register rt, uint16_t sa);
BufferOffset as_dsra(Register rd, Register rt, uint16_t sa);
BufferOffset as_dsra32(Register rd, Register rt, uint16_t sa);
BufferOffset as_srav(Register rd, Register rt, Register rs);
BufferOffset as_rotr(Register rd, Register rt, uint16_t sa);
BufferOffset as_rotrv(Register rd, Register rt, Register rs);
BufferOffset as_dsrav(Register rd, Register rt, Register rs);
BufferOffset as_drotr(Register rd, Register rt, uint16_t sa);
BufferOffset as_drotr32(Register rd, Register rt, uint16_t sa);
BufferOffset as_drotrv(Register rd, Register rt, Register rs);
// Load and store instructions
BufferOffset as_lb(Register rd, Register rs, int16_t off);
@ -847,13 +915,22 @@ class AssemblerMIPSShared : public AssemblerShared
BufferOffset as_lh(Register rd, Register rs, int16_t off);
BufferOffset as_lhu(Register rd, Register rs, int16_t off);
BufferOffset as_lw(Register rd, Register rs, int16_t off);
BufferOffset as_lwu(Register rd, Register rs, int16_t off);
BufferOffset as_lwl(Register rd, Register rs, int16_t off);
BufferOffset as_lwr(Register rd, Register rs, int16_t off);
BufferOffset as_ll(Register rd, Register rs, int16_t off);
BufferOffset as_ld(Register rd, Register rs, int16_t off);
BufferOffset as_ldl(Register rd, Register rs, int16_t off);
BufferOffset as_ldr(Register rd, Register rs, int16_t off);
BufferOffset as_sb(Register rd, Register rs, int16_t off);
BufferOffset as_sh(Register rd, Register rs, int16_t off);
BufferOffset as_sw(Register rd, Register rs, int16_t off);
BufferOffset as_swl(Register rd, Register rs, int16_t off);
BufferOffset as_swr(Register rd, Register rs, int16_t off);
BufferOffset as_sc(Register rd, Register rs, int16_t off);
BufferOffset as_sd(Register rd, Register rs, int16_t off);
BufferOffset as_sdl(Register rd, Register rs, int16_t off);
BufferOffset as_sdr(Register rd, Register rs, int16_t off);
// Move from HI/LO register.
BufferOffset as_mfhi(Register rd);
@ -873,8 +950,19 @@ class AssemblerMIPSShared : public AssemblerShared
// Bit twiddling.
BufferOffset as_clz(Register rd, Register rs);
BufferOffset as_dclz(Register rd, Register rs);
BufferOffset as_ins(Register rt, Register rs, uint16_t pos, uint16_t size);
BufferOffset as_dins(Register rt, Register rs, uint16_t pos, uint16_t size);
BufferOffset as_dinsm(Register rt, Register rs, uint16_t pos, uint16_t size);
BufferOffset as_dinsu(Register rt, Register rs, uint16_t pos, uint16_t size);
BufferOffset as_ext(Register rt, Register rs, uint16_t pos, uint16_t size);
BufferOffset as_dext(Register rt, Register rs, uint16_t pos, uint16_t size);
BufferOffset as_dextm(Register rt, Register rs, uint16_t pos, uint16_t size);
BufferOffset as_dextu(Register rt, Register rs, uint16_t pos, uint16_t size);
// Sign extend
BufferOffset as_seb(Register rd, Register rt);
BufferOffset as_seh(Register rd, Register rt);
// FP instructions
@ -892,6 +980,10 @@ class AssemblerMIPSShared : public AssemblerShared
BufferOffset as_mtc1(Register rt, FloatRegister fs);
BufferOffset as_mfc1(Register rt, FloatRegister fs);
BufferOffset as_mthc1(Register rt, FloatRegister fs);
BufferOffset as_mfhc1(Register rt, FloatRegister fs);
BufferOffset as_dmtc1(Register rt, FloatRegister fs);
BufferOffset as_dmfc1(Register rt, FloatRegister fs);
public:
// FP convert instructions
@ -972,7 +1064,8 @@ class AssemblerMIPSShared : public AssemblerShared
public:
static bool SupportsFloatingPoint() {
#if (defined(__mips_hard_float) && !defined(__mips_single_float)) || defined(JS_SIMULATOR_MIPS32)
#if (defined(__mips_hard_float) && !defined(__mips_single_float)) || \
defined(JS_SIMULATOR_MIPS32) || defined(JS_SIMULATOR_MIPS64)
return true;
#else
return false;

Просмотреть файл

@ -210,6 +210,7 @@ JitRuntime::generateEnterJIT(JSContext* cx, EnterJitType type)
regs.take(OsrFrameReg);
regs.take(BaselineFrameReg);
regs.take(reg_code);
regs.take(ReturnReg);
const Address slotNumStackValues(BaselineFrameReg, sizeof(EnterJITRegs) +
offsetof(EnterJITArgs, numStackValues));
@ -265,10 +266,7 @@ JitRuntime::generateEnterJIT(JSContext* cx, EnterJitType type)
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, jit::InitBaselineFrameForOsr));
regs.add(OsrFrameReg);
regs.add(scratch);
regs.add(numStackValues);
regs.take(JSReturnOperand);
regs.take(ReturnReg);
Register jitcode = regs.takeAny();
masm.loadPtr(Address(StackPointer, 0), jitcode);
masm.loadPtr(Address(StackPointer, sizeof(uintptr_t)), framePtr);

Просмотреть файл

@ -0,0 +1,493 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "jit/mips64/Assembler-mips64.h"
#include "mozilla/DebugOnly.h"
using mozilla::DebugOnly;
using namespace js;
using namespace js::jit;
ABIArgGenerator::ABIArgGenerator()
: usedArgSlots_(0),
firstArgFloat(false),
current_()
{}
ABIArg
ABIArgGenerator::next(MIRType type)
{
switch (type) {
case MIRType_Int32:
case MIRType_Pointer: {
Register destReg;
if (GetIntArgReg(usedArgSlots_, &destReg))
current_ = ABIArg(destReg);
else
current_ = ABIArg(GetArgStackDisp(usedArgSlots_));
usedArgSlots_++;
break;
}
case MIRType_Float32:
case MIRType_Double: {
FloatRegister destFReg;
FloatRegister::ContentType contentType;
if (!usedArgSlots_)
firstArgFloat = true;
contentType = (type == MIRType_Double) ?
FloatRegisters::Double : FloatRegisters::Single;
if (GetFloatArgReg(usedArgSlots_, &destFReg))
current_ = ABIArg(FloatRegister(destFReg.id(), contentType));
else
current_ = ABIArg(GetArgStackDisp(usedArgSlots_));
usedArgSlots_++;
break;
}
default:
MOZ_CRASH("Unexpected argument type");
}
return current_;
}
const Register ABIArgGenerator::NonArgReturnReg0 = t0;
const Register ABIArgGenerator::NonArgReturnReg1 = t1;
const Register ABIArgGenerator::NonArg_VolatileReg = v0;
const Register ABIArgGenerator::NonReturn_VolatileReg0 = a0;
const Register ABIArgGenerator::NonReturn_VolatileReg1 = a1;
uint32_t
js::jit::RT(FloatRegister r)
{
MOZ_ASSERT(r.id() < FloatRegisters::TotalPhys);
return r.id() << RTShift;
}
uint32_t
js::jit::RD(FloatRegister r)
{
MOZ_ASSERT(r.id() < FloatRegisters::TotalPhys);
return r.id() << RDShift;
}
uint32_t
js::jit::SA(FloatRegister r)
{
MOZ_ASSERT(r.id() < FloatRegisters::TotalPhys);
return r.id() << SAShift;
}
// Used to patch jumps created by MacroAssemblerMIPS64Compat::jumpWithPatch.
void
jit::PatchJump(CodeLocationJump& jump_, CodeLocationLabel label, ReprotectCode reprotect)
{
Instruction* inst = (Instruction*)jump_.raw();
// Six instructions used in load 64-bit imm.
MaybeAutoWritableJitCode awjc(inst, 6 * sizeof(uint32_t), reprotect);
Assembler::UpdateLoad64Value(inst, (uint64_t)label.raw());
AutoFlushICache::flush(uintptr_t(inst), 6 * sizeof(uint32_t));
}
// For more infromation about backedges look at comment in
// MacroAssemblerMIPS64Compat::backedgeJump()
void
jit::PatchBackedge(CodeLocationJump& jump, CodeLocationLabel label,
JitRuntime::BackedgeTarget target)
{
uintptr_t sourceAddr = (uintptr_t)jump.raw();
uintptr_t targetAddr = (uintptr_t)label.raw();
InstImm* branch = (InstImm*)jump.raw();
MOZ_ASSERT(branch->extractOpcode() == (uint32_t(op_beq) >> OpcodeShift));
if (BOffImm16::IsInRange(targetAddr - sourceAddr)) {
branch->setBOffImm16(BOffImm16(targetAddr - sourceAddr));
} else {
if (target == JitRuntime::BackedgeLoopHeader) {
Instruction* inst = &branch[1];
Assembler::UpdateLoad64Value(inst, targetAddr);
// Jump to first ori. The lui will be executed in delay slot.
branch->setBOffImm16(BOffImm16(2 * sizeof(uint32_t)));
} else {
Instruction* inst = &branch[6];
Assembler::UpdateLoad64Value(inst, targetAddr);
// Jump to first ori of interrupt loop.
branch->setBOffImm16(BOffImm16(6 * sizeof(uint32_t)));
}
}
}
void
Assembler::executableCopy(uint8_t* buffer)
{
MOZ_ASSERT(isFinished);
m_buffer.executableCopy(buffer);
// Patch all long jumps during code copy.
for (size_t i = 0; i < longJumps_.length(); i++) {
Instruction* inst = (Instruction*) ((uintptr_t)buffer + longJumps_[i]);
uint64_t value = Assembler::ExtractLoad64Value(inst);
Assembler::UpdateLoad64Value(inst, (uint64_t)buffer + value);
}
AutoFlushICache::setRange(uintptr_t(buffer), m_buffer.size());
}
uintptr_t
Assembler::GetPointer(uint8_t* instPtr)
{
Instruction* inst = (Instruction*)instPtr;
return Assembler::ExtractLoad64Value(inst);
}
static JitCode *
CodeFromJump(Instruction* jump)
{
uint8_t* target = (uint8_t*)Assembler::ExtractLoad64Value(jump);
return JitCode::FromExecutable(target);
}
void
Assembler::TraceJumpRelocations(JSTracer* trc, JitCode* code, CompactBufferReader& reader)
{
while (reader.more()) {
JitCode* child = CodeFromJump((Instruction*)(code->raw() + reader.readUnsigned()));
TraceManuallyBarrieredEdge(trc, &child, "rel32");
}
}
static void
TraceOneDataRelocation(JSTracer* trc, Instruction* inst)
{
void* ptr = (void*)Assembler::ExtractLoad64Value(inst);
void* prior = ptr;
// All pointers on MIPS64 will have the top bits cleared. If those bits
// are not cleared, this must be a Value.
uintptr_t word = reinterpret_cast<uintptr_t>(ptr);
if (word >> JSVAL_TAG_SHIFT) {
jsval_layout layout;
layout.asBits = word;
Value v = IMPL_TO_JSVAL(layout);
TraceManuallyBarrieredEdge(trc, &v, "ion-masm-value");
ptr = (void*)JSVAL_TO_IMPL(v).asBits;
} else {
// No barrier needed since these are constants.
TraceManuallyBarrieredGenericPointerEdge(trc, reinterpret_cast<gc::Cell**>(&ptr),
"ion-masm-ptr");
}
if (ptr != prior) {
Assembler::UpdateLoad64Value(inst, uint64_t(ptr));
AutoFlushICache::flush(uintptr_t(inst), 6 * sizeof(uint32_t));
}
}
static void
TraceDataRelocations(JSTracer* trc, uint8_t* buffer, CompactBufferReader& reader)
{
while (reader.more()) {
size_t offset = reader.readUnsigned();
Instruction* inst = (Instruction*)(buffer + offset);
TraceOneDataRelocation(trc, inst);
}
}
static void
TraceDataRelocations(JSTracer* trc, MIPSBuffer* buffer, CompactBufferReader& reader)
{
while (reader.more()) {
BufferOffset bo (reader.readUnsigned());
MIPSBuffer::AssemblerBufferInstIterator iter(bo, buffer);
TraceOneDataRelocation(trc, iter.cur());
}
}
void
Assembler::TraceDataRelocations(JSTracer* trc, JitCode* code, CompactBufferReader& reader)
{
::TraceDataRelocations(trc, code->raw(), reader);
}
void
Assembler::trace(JSTracer* trc)
{
for (size_t i = 0; i < jumps_.length(); i++) {
RelativePatch& rp = jumps_[i];
if (rp.kind == Relocation::JITCODE) {
JitCode* code = JitCode::FromExecutable((uint8_t*)rp.target);
TraceManuallyBarrieredEdge(trc, &code, "masmrel32");
MOZ_ASSERT(code == JitCode::FromExecutable((uint8_t*)rp.target));
}
}
if (dataRelocations_.length()) {
CompactBufferReader reader(dataRelocations_);
::TraceDataRelocations(trc, &m_buffer, reader);
}
}
int64_t
Assembler::ExtractCodeLabelOffset(uint8_t* code)
{
Instruction* inst = (Instruction*)code;
return Assembler::ExtractLoad64Value(inst);
}
void
Assembler::Bind(uint8_t* rawCode, AbsoluteLabel* label, const void* address)
{
if (label->used()) {
int64_t src = label->offset();
do {
Instruction* inst = (Instruction*) (rawCode + src);
uint64_t next = Assembler::ExtractLoad64Value(inst);
Assembler::UpdateLoad64Value(inst, (uint64_t)address);
src = next;
} while (src != AbsoluteLabel::INVALID_OFFSET);
}
label->bind();
}
void
Assembler::bind(InstImm* inst, uint64_t branch, uint64_t target)
{
int64_t offset = target - branch;
InstImm inst_bgezal = InstImm(op_regimm, zero, rt_bgezal, BOffImm16(0));
InstImm inst_beq = InstImm(op_beq, zero, zero, BOffImm16(0));
// If encoded offset is 4, then the jump must be short
if (BOffImm16(inst[0]).decode() == 4) {
MOZ_ASSERT(BOffImm16::IsInRange(offset));
inst[0].setBOffImm16(BOffImm16(offset));
inst[1].makeNop();
return;
}
// Generate the long jump for calls because return address has to be the
// address after the reserved block.
if (inst[0].encode() == inst_bgezal.encode()) {
addLongJump(BufferOffset(branch));
Assembler::WriteLoad64Instructions(inst, ScratchRegister, target);
inst[4] = InstReg(op_special, ScratchRegister, zero, ra, ff_jalr).encode();
// There is 1 nop after this.
return;
}
if (BOffImm16::IsInRange(offset)) {
bool conditional = (inst[0].encode() != inst_bgezal.encode() &&
inst[0].encode() != inst_beq.encode());
inst[0].setBOffImm16(BOffImm16(offset));
inst[1].makeNop();
// Skip the trailing nops in conditional branches.
// FIXME: On Loongson3 platform, the branch degrade performance.
if (0 && conditional) {
inst[2] = InstImm(op_regimm, zero, rt_bgez, BOffImm16(5 * sizeof(uint32_t))).encode();
// There are 4 nops after this
}
return;
}
if (inst[0].encode() == inst_beq.encode()) {
// Handle long unconditional jump.
addLongJump(BufferOffset(branch));
Assembler::WriteLoad64Instructions(inst, ScratchRegister, target);
inst[4] = InstReg(op_special, ScratchRegister, zero, zero, ff_jr).encode();
// There is 1 nop after this.
} else {
// Handle long conditional jump.
inst[0] = invertBranch(inst[0], BOffImm16(7 * sizeof(uint32_t)));
// No need for a "nop" here because we can clobber scratch.
addLongJump(BufferOffset(branch + sizeof(uint32_t)));
Assembler::WriteLoad64Instructions(&inst[1], ScratchRegister, target);
inst[5] = InstReg(op_special, ScratchRegister, zero, zero, ff_jr).encode();
// There is 1 nop after this.
}
}
void
Assembler::bind(RepatchLabel* label)
{
BufferOffset dest = nextOffset();
if (label->used()) {
// If the label has a use, then change this use to refer to
// the bound label;
BufferOffset b(label->offset());
InstImm* inst1 = (InstImm*)editSrc(b);
// If first instruction is branch, then this is a loop backedge.
if (inst1->extractOpcode() == ((uint32_t)op_beq >> OpcodeShift)) {
// Backedges are short jumps when bound, but can become long
// when patched.
uint64_t offset = dest.getOffset() - label->offset();
MOZ_ASSERT(BOffImm16::IsInRange(offset));
inst1->setBOffImm16(BOffImm16(offset));
} else {
Assembler::UpdateLoad64Value(inst1, dest.getOffset());
}
}
label->bind(dest.getOffset());
}
uint32_t
Assembler::PatchWrite_NearCallSize()
{
// Load an address needs 4 instructions, and a jump with a delay slot.
return (4 + 2) * sizeof(uint32_t);
}
void
Assembler::PatchWrite_NearCall(CodeLocationLabel start, CodeLocationLabel toCall)
{
Instruction* inst = (Instruction*) start.raw();
uint8_t* dest = toCall.raw();
// Overwrite whatever instruction used to be here with a call.
// Always use long jump for two reasons:
// - Jump has to be the same size because of PatchWrite_NearCallSize.
// - Return address has to be at the end of replaced block.
// Short jump wouldn't be more efficient.
Assembler::WriteLoad64Instructions(inst, ScratchRegister, (uint64_t)dest);
inst[4] = InstReg(op_special, ScratchRegister, zero, ra, ff_jalr);
inst[5] = InstNOP();
// Ensure everyone sees the code that was just written into memory.
AutoFlushICache::flush(uintptr_t(inst), PatchWrite_NearCallSize());
}
uint64_t
Assembler::ExtractLoad64Value(Instruction* inst0)
{
InstImm* i0 = (InstImm*) inst0;
InstImm* i1 = (InstImm*) i0->next();
InstReg* i2 = (InstReg*) i1->next();
InstImm* i3 = (InstImm*) i2->next();
InstImm* i5 = (InstImm*) i3->next()->next();
MOZ_ASSERT(i0->extractOpcode() == ((uint32_t)op_lui >> OpcodeShift));
MOZ_ASSERT(i1->extractOpcode() == ((uint32_t)op_ori >> OpcodeShift));
MOZ_ASSERT(i3->extractOpcode() == ((uint32_t)op_ori >> OpcodeShift));
if ((i2->extractOpcode() == ((uint32_t)op_special >> OpcodeShift)) &&
(i2->extractFunctionField() == ff_dsrl32))
{
uint64_t value = (uint64_t(i0->extractImm16Value()) << 32) |
(uint64_t(i1->extractImm16Value()) << 16) |
uint64_t(i3->extractImm16Value());
return uint64_t((int64_t(value) <<16) >> 16);
}
MOZ_ASSERT(i5->extractOpcode() == ((uint32_t)op_ori >> OpcodeShift));
uint64_t value = (uint64_t(i0->extractImm16Value()) << 48) |
(uint64_t(i1->extractImm16Value()) << 32) |
(uint64_t(i3->extractImm16Value()) << 16) |
uint64_t(i5->extractImm16Value());
return value;
}
void
Assembler::UpdateLoad64Value(Instruction* inst0, uint64_t value)
{
InstImm* i0 = (InstImm*) inst0;
InstImm* i1 = (InstImm*) i0->next();
InstReg* i2 = (InstReg*) i1->next();
InstImm* i3 = (InstImm*) i2->next();
InstImm* i5 = (InstImm*) i3->next()->next();
MOZ_ASSERT(i0->extractOpcode() == ((uint32_t)op_lui >> OpcodeShift));
MOZ_ASSERT(i1->extractOpcode() == ((uint32_t)op_ori >> OpcodeShift));
MOZ_ASSERT(i3->extractOpcode() == ((uint32_t)op_ori >> OpcodeShift));
if ((i2->extractOpcode() == ((uint32_t)op_special >> OpcodeShift)) &&
(i2->extractFunctionField() == ff_dsrl32))
{
i0->setImm16(Imm16::Lower(Imm32(value >> 32)));
i1->setImm16(Imm16::Upper(Imm32(value)));
i3->setImm16(Imm16::Lower(Imm32(value)));
return;
}
MOZ_ASSERT(i5->extractOpcode() == ((uint32_t)op_ori >> OpcodeShift));
i0->setImm16(Imm16::Upper(Imm32(value >> 32)));
i1->setImm16(Imm16::Lower(Imm32(value >> 32)));
i3->setImm16(Imm16::Upper(Imm32(value)));
i5->setImm16(Imm16::Lower(Imm32(value)));
}
void
Assembler::WriteLoad64Instructions(Instruction* inst0, Register reg, uint64_t value)
{
Instruction* inst1 = inst0->next();
Instruction* inst2 = inst1->next();
Instruction* inst3 = inst2->next();
*inst0 = InstImm(op_lui, zero, reg, Imm16::Lower(Imm32(value >> 32)));
*inst1 = InstImm(op_ori, reg, reg, Imm16::Upper(Imm32(value)));
*inst2 = InstReg(op_special, rs_one, reg, reg, 48 - 32, ff_dsrl32);
*inst3 = InstImm(op_ori, reg, reg, Imm16::Lower(Imm32(value)));
}
void
Assembler::PatchDataWithValueCheck(CodeLocationLabel label, PatchedImmPtr newValue,
PatchedImmPtr expectedValue)
{
Instruction* inst = (Instruction*) label.raw();
// Extract old Value
DebugOnly<uint64_t> value = Assembler::ExtractLoad64Value(inst);
MOZ_ASSERT(value == uint64_t(expectedValue.value));
// Replace with new value
Assembler::UpdateLoad64Value(inst, uint64_t(newValue.value));
AutoFlushICache::flush(uintptr_t(inst), 6 * sizeof(uint32_t));
}
void
Assembler::PatchInstructionImmediate(uint8_t* code, PatchedImmPtr imm)
{
InstImm* inst = (InstImm*)code;
Assembler::UpdateLoad64Value(inst, (uint64_t)imm.value);
}
void
Assembler::ToggleCall(CodeLocationLabel inst_, bool enabled)
{
Instruction* inst = (Instruction*)inst_.raw();
InstImm* i0 = (InstImm*) inst;
InstImm* i1 = (InstImm*) i0->next();
InstImm* i3 = (InstImm*) i1->next()->next();
Instruction* i4 = (Instruction*) i3->next();
MOZ_ASSERT(i0->extractOpcode() == ((uint32_t)op_lui >> OpcodeShift));
MOZ_ASSERT(i1->extractOpcode() == ((uint32_t)op_ori >> OpcodeShift));
MOZ_ASSERT(i3->extractOpcode() == ((uint32_t)op_ori >> OpcodeShift));
if (enabled) {
MOZ_ASSERT(i4->extractOpcode() != ((uint32_t)op_lui >> OpcodeShift));
InstReg jalr = InstReg(op_special, ScratchRegister, zero, ra, ff_jalr);
*i4 = jalr;
} else {
InstNOP nop;
*i4 = nop;
}
AutoFlushICache::flush(uintptr_t(i4), sizeof(uint32_t));
}
void
Assembler::UpdateBoundsCheck(uint64_t heapSize, Instruction* inst)
{
// Replace with new value
Assembler::UpdateLoad64Value(inst, heapSize);
}

Просмотреть файл

@ -0,0 +1,186 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef jit_mips64_Assembler_mips64_h
#define jit_mips64_Assembler_mips64_h
// NOTE: Don't use these macros directly
// CallTempNonArgRegs
#define CALL_TEMP_NON_ARG_REGS \
{ t0, t1, t2, t3 };
// NumIntArgRegs
#define NUM_INT_ARG_REGS 8;
#include "jit/mips-shared/Assembler-mips-shared.h"
#include "jit/mips64/Architecture-mips64.h"
namespace js {
namespace jit {
static MOZ_CONSTEXPR_VAR Register CallTempReg4 = a4;
static MOZ_CONSTEXPR_VAR Register CallTempReg5 = a5;
class ABIArgGenerator
{
unsigned usedArgSlots_;
bool firstArgFloat;
ABIArg current_;
public:
ABIArgGenerator();
ABIArg next(MIRType argType);
ABIArg& current() { return current_; }
uint32_t stackBytesConsumedSoFar() const {
if (usedArgSlots_ <= 8)
return 0;
return (usedArgSlots_ - 8) * sizeof(int64_t);
}
static const Register NonArgReturnReg0;
static const Register NonArgReturnReg1;
static const Register NonArg_VolatileReg;
static const Register NonReturn_VolatileReg0;
static const Register NonReturn_VolatileReg1;
};
static MOZ_CONSTEXPR_VAR Register JSReturnReg = v1;
static MOZ_CONSTEXPR_VAR Register JSReturnReg_Type = JSReturnReg;
static MOZ_CONSTEXPR_VAR Register JSReturnReg_Data = JSReturnReg;
static MOZ_CONSTEXPR_VAR FloatRegister ReturnFloat32Reg = { FloatRegisters::f0, FloatRegisters::Single };
static MOZ_CONSTEXPR_VAR FloatRegister ReturnDoubleReg = { FloatRegisters::f0, FloatRegisters::Double };
static MOZ_CONSTEXPR_VAR FloatRegister ScratchFloat32Reg = { FloatRegisters::f23, FloatRegisters::Single };
static MOZ_CONSTEXPR_VAR FloatRegister ScratchDoubleReg = { FloatRegisters::f23, FloatRegisters::Double };
static MOZ_CONSTEXPR_VAR FloatRegister SecondScratchFloat32Reg = { FloatRegisters::f21, FloatRegisters::Single };
static MOZ_CONSTEXPR_VAR FloatRegister SecondScratchDoubleReg = { FloatRegisters::f21, FloatRegisters::Double };
// Registers used in the GenerateFFIIonExit Disable Activation block.
// None of these may be the second scratch register (t8).
static MOZ_CONSTEXPR_VAR Register AsmJSIonExitRegReturnData = JSReturnReg_Data;
static MOZ_CONSTEXPR_VAR Register AsmJSIonExitRegReturnType = JSReturnReg_Type;
static MOZ_CONSTEXPR_VAR FloatRegister f0 = { FloatRegisters::f0, FloatRegisters::Double };
static MOZ_CONSTEXPR_VAR FloatRegister f1 = { FloatRegisters::f1, FloatRegisters::Double };
static MOZ_CONSTEXPR_VAR FloatRegister f2 = { FloatRegisters::f2, FloatRegisters::Double };
static MOZ_CONSTEXPR_VAR FloatRegister f3 = { FloatRegisters::f3, FloatRegisters::Double };
static MOZ_CONSTEXPR_VAR FloatRegister f4 = { FloatRegisters::f4, FloatRegisters::Double };
static MOZ_CONSTEXPR_VAR FloatRegister f5 = { FloatRegisters::f5, FloatRegisters::Double };
static MOZ_CONSTEXPR_VAR FloatRegister f6 = { FloatRegisters::f6, FloatRegisters::Double };
static MOZ_CONSTEXPR_VAR FloatRegister f7 = { FloatRegisters::f7, FloatRegisters::Double };
static MOZ_CONSTEXPR_VAR FloatRegister f8 = { FloatRegisters::f8, FloatRegisters::Double };
static MOZ_CONSTEXPR_VAR FloatRegister f9 = { FloatRegisters::f9, FloatRegisters::Double };
static MOZ_CONSTEXPR_VAR FloatRegister f10 = { FloatRegisters::f10, FloatRegisters::Double };
static MOZ_CONSTEXPR_VAR FloatRegister f11 = { FloatRegisters::f11, FloatRegisters::Double };
static MOZ_CONSTEXPR_VAR FloatRegister f12 = { FloatRegisters::f12, FloatRegisters::Double };
static MOZ_CONSTEXPR_VAR FloatRegister f13 = { FloatRegisters::f13, FloatRegisters::Double };
static MOZ_CONSTEXPR_VAR FloatRegister f14 = { FloatRegisters::f14, FloatRegisters::Double };
static MOZ_CONSTEXPR_VAR FloatRegister f15 = { FloatRegisters::f15, FloatRegisters::Double };
static MOZ_CONSTEXPR_VAR FloatRegister f16 = { FloatRegisters::f16, FloatRegisters::Double };
static MOZ_CONSTEXPR_VAR FloatRegister f17 = { FloatRegisters::f17, FloatRegisters::Double };
static MOZ_CONSTEXPR_VAR FloatRegister f18 = { FloatRegisters::f18, FloatRegisters::Double };
static MOZ_CONSTEXPR_VAR FloatRegister f19 = { FloatRegisters::f19, FloatRegisters::Double };
static MOZ_CONSTEXPR_VAR FloatRegister f20 = { FloatRegisters::f20, FloatRegisters::Double };
static MOZ_CONSTEXPR_VAR FloatRegister f21 = { FloatRegisters::f21, FloatRegisters::Double };
static MOZ_CONSTEXPR_VAR FloatRegister f22 = { FloatRegisters::f22, FloatRegisters::Double };
static MOZ_CONSTEXPR_VAR FloatRegister f23 = { FloatRegisters::f23, FloatRegisters::Double };
static MOZ_CONSTEXPR_VAR FloatRegister f24 = { FloatRegisters::f24, FloatRegisters::Double };
static MOZ_CONSTEXPR_VAR FloatRegister f25 = { FloatRegisters::f25, FloatRegisters::Double };
static MOZ_CONSTEXPR_VAR FloatRegister f26 = { FloatRegisters::f26, FloatRegisters::Double };
static MOZ_CONSTEXPR_VAR FloatRegister f27 = { FloatRegisters::f27, FloatRegisters::Double };
static MOZ_CONSTEXPR_VAR FloatRegister f28 = { FloatRegisters::f28, FloatRegisters::Double };
static MOZ_CONSTEXPR_VAR FloatRegister f29 = { FloatRegisters::f29, FloatRegisters::Double };
static MOZ_CONSTEXPR_VAR FloatRegister f30 = { FloatRegisters::f30, FloatRegisters::Double };
static MOZ_CONSTEXPR_VAR FloatRegister f31 = { FloatRegisters::f31, FloatRegisters::Double };
// MIPS64 CPUs can only load multibyte data that is "naturally"
// eight-byte-aligned, sp register should be sixteen-byte-aligned.
static MOZ_CONSTEXPR_VAR uint32_t ABIStackAlignment = 16;
static MOZ_CONSTEXPR_VAR uint32_t JitStackAlignment = 16;
static MOZ_CONSTEXPR_VAR uint32_t JitStackValueAlignment = JitStackAlignment / sizeof(Value);
static_assert(JitStackAlignment % sizeof(Value) == 0 && JitStackValueAlignment >= 1,
"Stack alignment should be a non-zero multiple of sizeof(Value)");
// TODO this is just a filler to prevent a build failure. The MIPS SIMD
// alignment requirements still need to be explored.
// TODO Copy the static_asserts from x64/x86 assembler files.
static MOZ_CONSTEXPR_VAR uint32_t SimdMemoryAlignment = 16;
static MOZ_CONSTEXPR_VAR uint32_t AsmJSStackAlignment = SimdMemoryAlignment;
static MOZ_CONSTEXPR_VAR Scale ScalePointer = TimesEight;
class Assembler : public AssemblerMIPSShared
{
public:
Assembler()
: AssemblerMIPSShared()
{ }
// MacroAssemblers hold onto gcthings, so they are traced by the GC.
void trace(JSTracer* trc);
static uintptr_t GetPointer(uint8_t*);
using AssemblerMIPSShared::bind;
using AssemblerMIPSShared::PatchDataWithValueCheck;
void bind(RepatchLabel* label);
void Bind(uint8_t* rawCode, AbsoluteLabel* label, const void* address);
static void TraceJumpRelocations(JSTracer* trc, JitCode* code, CompactBufferReader& reader);
static void TraceDataRelocations(JSTracer* trc, JitCode* code, CompactBufferReader& reader);
void bind(InstImm* inst, uint64_t branch, uint64_t target);
// Copy the assembly code to the given buffer, and perform any pending
// relocations relying on the target address.
void executableCopy(uint8_t* buffer);
static uint32_t PatchWrite_NearCallSize();
static uint64_t ExtractLoad64Value(Instruction* inst0);
static void UpdateLoad64Value(Instruction* inst0, uint64_t value);
static void WriteLoad64Instructions(Instruction* inst0, Register reg, uint64_t value);
static void PatchWrite_NearCall(CodeLocationLabel start, CodeLocationLabel toCall);
static void PatchDataWithValueCheck(CodeLocationLabel label, PatchedImmPtr newValue,
PatchedImmPtr expectedValue);
static void PatchInstructionImmediate(uint8_t* code, PatchedImmPtr imm);
static void ToggleCall(CodeLocationLabel inst_, bool enabled);
static void UpdateBoundsCheck(uint64_t logHeapSize, Instruction* inst);
static int64_t ExtractCodeLabelOffset(uint8_t* code);
}; // Assembler
static const uint32_t NumFloatArgRegs = NumIntArgRegs;
static inline bool
GetFloatArgReg(uint32_t usedArgSlots, FloatRegister* out)
{
if (usedArgSlots < NumFloatArgRegs) {
*out = FloatRegister::FromCode(f12.code() + usedArgSlots);
return true;
}
return false;
}
static inline uint32_t
GetArgStackDisp(uint32_t usedArgSlots)
{
MOZ_ASSERT(usedArgSlots >= NumIntArgRegs);
return (usedArgSlots - NumIntArgRegs) * sizeof(int64_t);
}
} // namespace jit
} // namespace js
#endif /* jit_mips64_Assembler_mips64_h */

Просмотреть файл

@ -0,0 +1,28 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "jscntxt.h"
#include "jscompartment.h"
#include "jit/mips-shared/Bailouts-mips-shared.h"
using namespace js;
using namespace js::jit;
BailoutFrameInfo::BailoutFrameInfo(const JitActivationIterator& activations,
BailoutStack* bailout)
: machine_(bailout->machine())
{
uint8_t* sp = bailout->parentStackPointer();
framePointer_ = sp + bailout->frameSize();
topFrameSize_ = framePointer_ - sp;
JSScript* script = ScriptFromCalleeToken(((JitFrameLayout*) framePointer_)->calleeToken());
topIonScript_ = script->ionScript();
attachOnJitActivation(activations);
snapshotOffset_ = bailout->snapshotOffset();
}

Просмотреть файл

@ -0,0 +1,16 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "jit/mips64/BaselineCompiler-mips64.h"
using namespace js;
using namespace js::jit;
BaselineCompilerMIPS64::BaselineCompilerMIPS64(JSContext* cx, TempAllocator& alloc,
JSScript* script)
: BaselineCompilerMIPSShared(cx, alloc, script)
{
}

Просмотреть файл

@ -0,0 +1,26 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef jit_mips64_BaselineCompiler_mips64_h
#define jit_mips64_BaselineCompiler_mips64_h
#include "jit/mips-shared/BaselineCompiler-mips-shared.h"
namespace js {
namespace jit {
class BaselineCompilerMIPS64 : public BaselineCompilerMIPSShared
{
protected:
BaselineCompilerMIPS64(JSContext* cx, TempAllocator& alloc, JSScript* script);
};
typedef BaselineCompilerMIPS64 BaselineCompilerSpecific;
} // namespace jit
} // namespace js
#endif /* jit_mips64_BaselineCompiler_mips64_h */

Просмотреть файл

@ -0,0 +1,47 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "jit/BaselineCompiler.h"
#include "jit/BaselineIC.h"
#include "jit/BaselineJIT.h"
#include "jit/Linker.h"
#include "jit/SharedICHelpers.h"
using namespace js;
using namespace js::jit;
namespace js {
namespace jit {
// ICCompare_Int32
bool
ICCompare_Int32::Compiler::generateStubCode(MacroAssembler& masm)
{
// Guard that R0 is an integer and R1 is an integer.
Label failure;
Label conditionTrue;
masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
masm.branchTestInt32(Assembler::NotEqual, R1, &failure);
// Compare payload regs of R0 and R1.
masm.unboxInt32(R0, ExtractTemp0);
masm.unboxInt32(R1, ExtractTemp1);
Assembler::Condition cond = JSOpToCondition(op, /* signed = */true);
masm.ma_cmp_set(R0.valueReg(), ExtractTemp0, ExtractTemp1, cond);
masm.tagValue(JSVAL_TYPE_BOOLEAN, R0.valueReg(), R0);
EmitReturnFromIC(masm);
// Failure case - jump to next stub
masm.bind(&failure);
EmitStubGuardFailure(masm);
return true;
}
} // namespace jit
} // namespace js

Просмотреть файл

@ -78,3 +78,151 @@ BEGIN_TEST(testStructuredClone_string)
return true;
}
END_TEST(testStructuredClone_string)
struct StructuredCloneTestPrincipals final : public JSPrincipals {
uint32_t rank;
explicit StructuredCloneTestPrincipals(uint32_t rank, int32_t rc = 1) : rank(rank) {
this->refcount = rc;
}
bool write(JSContext* cx, JSStructuredCloneWriter* writer) override {
return JS_WriteUint32Pair(writer, rank, 0);
}
static bool read(JSContext* cx, JSStructuredCloneReader *reader, JSPrincipals** outPrincipals) {
uint32_t rank;
uint32_t unused;
if (!JS_ReadUint32Pair(reader, &rank, &unused))
return false;
*outPrincipals = new StructuredCloneTestPrincipals(rank);
return !!*outPrincipals;
}
static void destroy(JSPrincipals* p) {
auto p1 = static_cast<StructuredCloneTestPrincipals*>(p);
delete p1;
}
static uint32_t getRank(JSPrincipals* p) {
if (!p)
return 0;
return static_cast<StructuredCloneTestPrincipals*>(p)->rank;
}
static bool subsumes(JSPrincipals* a, JSPrincipals* b) {
return getRank(a) > getRank(b);
}
static JSSecurityCallbacks securityCallbacks;
static StructuredCloneTestPrincipals testPrincipals;
};
JSSecurityCallbacks StructuredCloneTestPrincipals::securityCallbacks = {
nullptr, // contentSecurityPolicyAllows
subsumes
};
BEGIN_TEST(testStructuredClone_SavedFrame)
{
JS_SetSecurityCallbacks(rt, &StructuredCloneTestPrincipals::securityCallbacks);
JS_InitDestroyPrincipalsCallback(rt, StructuredCloneTestPrincipals::destroy);
JS_InitReadPrincipalsCallback(rt, StructuredCloneTestPrincipals::read);
auto testPrincipals = new StructuredCloneTestPrincipals(42, 0);
CHECK(testPrincipals);
auto DONE = (JSPrincipals*) 0xDEADBEEF;
struct {
const char* name;
JSPrincipals* principals;
} principalsToTest[] = {
{ "IsSystem", &js::ReconstructedSavedFramePrincipals::IsSystem },
{ "IsNotSystem", &js::ReconstructedSavedFramePrincipals::IsNotSystem },
{ "testPrincipals", testPrincipals },
{ "nullptr principals", nullptr },
{ "DONE", DONE }
};
const char* FILENAME = "filename.js";
for (auto* pp = principalsToTest; pp->principals != DONE; pp++) {
fprintf(stderr, "Testing with principals '%s'\n", pp->name);
JS::RootedObject g(cx, JS_NewGlobalObject(cx, getGlobalClass(), pp->principals,
JS::FireOnNewGlobalHook));
CHECK(g);
JSAutoCompartment ac(cx, g);
CHECK(js::DefineTestingFunctions(cx, g, false, false));
JS::RootedValue srcVal(cx);
CHECK(evaluate("(function one() { \n" // 1
" return (function two() { \n" // 2
" return (function three() { \n" // 3
" return saveStack(); \n" // 4
" }()); \n" // 5
" }()); \n" // 6
"}()); \n", // 7
FILENAME,
1,
&srcVal));
CHECK(srcVal.isObject());
JS::RootedObject srcObj(cx, &srcVal.toObject());
CHECK(srcObj->is<js::SavedFrame>());
js::RootedSavedFrame srcFrame(cx, &srcObj->as<js::SavedFrame>());
CHECK(srcFrame->getPrincipals() == pp->principals);
JS::RootedValue destVal(cx);
CHECK(JS_StructuredClone(cx, srcVal, &destVal, nullptr, nullptr));
CHECK(destVal.isObject());
JS::RootedObject destObj(cx, &destVal.toObject());
CHECK(destObj->is<js::SavedFrame>());
auto destFrame = &destObj->as<js::SavedFrame>();
size_t framesCopied = 0;
for (auto& f : *destFrame) {
framesCopied++;
CHECK(&f != srcFrame);
if (pp->principals == testPrincipals) {
// We shouldn't get a pointer to the same
// StructuredCloneTestPrincipals instance since we should have
// serialized and then deserialized it into a new instance.
CHECK(f.getPrincipals() != pp->principals);
// But it should certainly have the same rank.
CHECK(StructuredCloneTestPrincipals::getRank(f.getPrincipals()) ==
StructuredCloneTestPrincipals::getRank(pp->principals));
} else {
// For our singleton principals, we should always get the same
// pointer back.
CHECK(js::ReconstructedSavedFramePrincipals::is(pp->principals) ||
pp->principals == nullptr);
CHECK(f.getPrincipals() == pp->principals);
}
CHECK(EqualStrings(f.getSource(), srcFrame->getSource()));
CHECK(f.getLine() == srcFrame->getLine());
CHECK(f.getColumn() == srcFrame->getColumn());
CHECK(EqualStrings(f.getFunctionDisplayName(), srcFrame->getFunctionDisplayName()));
srcFrame = srcFrame->getParent();
}
// Four function frames + one global frame.
CHECK(framesCopied == 4);
}
return true;
}
END_TEST(testStructuredClone_SavedFrame)

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -2186,12 +2186,6 @@ extern JS_PUBLIC_API(void*)
JS_GetInstancePrivate(JSContext* cx, JS::Handle<JSObject*> obj, const JSClass* clasp,
JS::CallArgs* args);
extern JS_PUBLIC_API(bool)
JS_GetPrototype(JSContext* cx, JS::HandleObject obj, JS::MutableHandleObject protop);
extern JS_PUBLIC_API(bool)
JS_SetPrototype(JSContext* cx, JS::HandleObject obj, JS::HandleObject proto);
extern JS_PUBLIC_API(JSObject*)
JS_GetConstructor(JSContext* cx, JS::Handle<JSObject*> proto);
@ -2417,10 +2411,6 @@ JS_FireOnNewGlobalObject(JSContext* cx, JS::HandleObject global);
extern JS_PUBLIC_API(JSObject*)
JS_NewObject(JSContext* cx, const JSClass* clasp);
/* Queries the [[Extensible]] property of the object. */
extern JS_PUBLIC_API(bool)
JS_IsExtensible(JSContext* cx, JS::HandleObject obj, bool* extensible);
extern JS_PUBLIC_API(bool)
JS_IsNative(JSObject* obj);
@ -2452,29 +2442,6 @@ JS_DeepFreezeObject(JSContext* cx, JS::Handle<JSObject*> obj);
extern JS_PUBLIC_API(bool)
JS_FreezeObject(JSContext* cx, JS::Handle<JSObject*> obj);
/*
* Attempt to make |obj| non-extensible. If an error occurs while making the
* attempt, return false (with a pending exception set, depending upon the
* nature of the error). If no error occurs, return true with |result| set
* to indicate whether the attempt successfully set the [[Extensible]] property
* to false.
*/
extern JS_PUBLIC_API(bool)
JS_PreventExtensions(JSContext* cx, JS::HandleObject obj, JS::ObjectOpResult& result);
/*
* Attempt to make the [[Prototype]] of |obj| immutable, such that any attempt
* to modify it will fail. If an error occurs during the attempt, return false
* (with a pending exception set, depending upon the nature of the error). If
* no error occurs, return true with |*succeeded| set to indicate whether the
* attempt successfully made the [[Prototype]] immutable.
*/
extern JS_PUBLIC_API(bool)
JS_SetImmutablePrototype(JSContext* cx, JS::HandleObject obj, bool* succeeded);
extern JS_PUBLIC_API(JSObject*)
JS_New(JSContext* cx, JS::HandleObject ctor, const JS::HandleValueArray& args);
/*** Property descriptors ************************************************************************/
@ -2768,108 +2735,86 @@ ObjectToCompletePropertyDescriptor(JSContext* cx,
} // namespace JS
/*** [[DefineOwnProperty]] and variations ********************************************************/
/*** Standard internal methods ********************************************************************
*
* The functions below are the fundamental operations on objects.
*
* ES6 specifies 14 internal methods that define how objects behave. The
* standard is actually quite good on this topic, though you may have to read
* it a few times. See ES6 sections 6.1.7.2 and 6.1.7.3.
*
* When 'obj' is an ordinary object, these functions have boring standard
* behavior as specified by ES6 section 9.1; see the section about internal
* methods in js/src/vm/NativeObject.h.
*
* Proxies override the behavior of internal methods. So when 'obj' is a proxy,
* any one of the functions below could do just about anything. See
* js/public/Proxy.h.
*/
/**
* Get the prototype of obj, storing it in result.
*
* Implements: ES6 [[GetPrototypeOf]] internal method.
*/
extern JS_PUBLIC_API(bool)
JS_DefineProperty(JSContext* cx, JS::HandleObject obj, const char* name, JS::HandleValue value,
unsigned attrs,
JSNative getter = nullptr, JSNative setter = nullptr);
JS_GetPrototype(JSContext* cx, JS::HandleObject obj, JS::MutableHandleObject result);
/**
* Change the prototype of obj.
*
* Implements: ES6 [[SetPrototypeOf]] internal method.
*
* In cases where ES6 [[SetPrototypeOf]] returns false without an exception,
* JS_SetPrototype throws a TypeError and returns false.
*
* Performance warning: JS_SetPrototype is very bad for performance. It may
* cause compiled jit-code to be invalidated. It also causes not only obj but
* all other objects in the same "group" as obj to be permanently deoptimized.
* It's better to create the object with the right prototype from the start.
*/
extern JS_PUBLIC_API(bool)
JS_DefineProperty(JSContext* cx, JS::HandleObject obj, const char* name, JS::HandleObject value,
unsigned attrs,
JSNative getter = nullptr, JSNative setter = nullptr);
JS_SetPrototype(JSContext* cx, JS::HandleObject obj, JS::HandleObject proto);
/**
* Determine whether obj is extensible. Extensible objects can have new
* properties defined on them. Inextensible objects can't, and their
* [[Prototype]] slot is fixed as well.
*
* Implements: ES6 [[IsExtensible]] internal method.
*/
extern JS_PUBLIC_API(bool)
JS_DefineProperty(JSContext* cx, JS::HandleObject obj, const char* name, JS::HandleString value,
unsigned attrs,
JSNative getter = nullptr, JSNative setter = nullptr);
JS_IsExtensible(JSContext* cx, JS::HandleObject obj, bool* extensible);
/**
* Attempt to make |obj| non-extensible.
*
* Not all failures are treated as errors. See the comment on
* JS::ObjectOpResult in js/public/Class.h.
*
* Implements: ES6 [[PreventExtensions]] internal method.
*/
extern JS_PUBLIC_API(bool)
JS_DefineProperty(JSContext* cx, JS::HandleObject obj, const char* name, int32_t value,
unsigned attrs,
JSNative getter = nullptr, JSNative setter = nullptr);
JS_PreventExtensions(JSContext* cx, JS::HandleObject obj, JS::ObjectOpResult& result);
/**
* Attempt to make the [[Prototype]] of |obj| immutable, such that any attempt
* to modify it will fail. If an error occurs during the attempt, return false
* (with a pending exception set, depending upon the nature of the error). If
* no error occurs, return true with |*succeeded| set to indicate whether the
* attempt successfully made the [[Prototype]] immutable.
*
* This is a nonstandard internal method.
*/
extern JS_PUBLIC_API(bool)
JS_DefineProperty(JSContext* cx, JS::HandleObject obj, const char* name, uint32_t value,
unsigned attrs,
JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefineProperty(JSContext* cx, JS::HandleObject obj, const char* name, double value,
unsigned attrs,
JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue value,
unsigned attrs,
JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleObject value,
unsigned attrs,
JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleString value,
unsigned attrs,
JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, int32_t value,
unsigned attrs,
JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, uint32_t value,
unsigned attrs,
JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, double value,
unsigned attrs,
JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
JS::Handle<JSPropertyDescriptor> desc,
JS::ObjectOpResult& result);
extern JS_PUBLIC_API(bool)
JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
JS::Handle<JSPropertyDescriptor> desc);
extern JS_PUBLIC_API(JSObject*)
JS_DefineObject(JSContext* cx, JS::HandleObject obj, const char* name,
const JSClass* clasp = nullptr, unsigned attrs = 0);
extern JS_PUBLIC_API(bool)
JS_DefineConstDoubles(JSContext* cx, JS::HandleObject obj, const JSConstDoubleSpec* cds);
extern JS_PUBLIC_API(bool)
JS_DefineConstIntegers(JSContext* cx, JS::HandleObject obj, const JSConstIntegerSpec* cis);
extern JS_PUBLIC_API(bool)
JS_DefineProperties(JSContext* cx, JS::HandleObject obj, const JSPropertySpec* ps);
/* * */
extern JS_PUBLIC_API(bool)
JS_AlreadyHasOwnProperty(JSContext* cx, JS::HandleObject obj, const char* name,
bool* foundp);
extern JS_PUBLIC_API(bool)
JS_AlreadyHasOwnPropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
bool* foundp);
extern JS_PUBLIC_API(bool)
JS_HasProperty(JSContext* cx, JS::HandleObject obj, const char* name, bool* foundp);
extern JS_PUBLIC_API(bool)
JS_HasPropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* foundp);
JS_SetImmutablePrototype(JSContext* cx, JS::HandleObject obj, bool* succeeded);
/**
* Get a description of one of obj's own properties. If no such property exists
* on obj, return true with desc.object() set to null.
*
* Implements: ES6 [[GetOwnProperty]] internal method.
*/
extern JS_PUBLIC_API(bool)
JS_GetOwnPropertyDescriptorById(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
JS::MutableHandle<JSPropertyDescriptor> desc);
@ -2882,16 +2827,11 @@ extern JS_PUBLIC_API(bool)
JS_GetOwnUCPropertyDescriptor(JSContext* cx, JS::HandleObject obj, const char16_t* name,
JS::MutableHandle<JSPropertyDescriptor> desc);
extern JS_PUBLIC_API(bool)
JS_HasOwnPropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* foundp);
extern JS_PUBLIC_API(bool)
JS_HasOwnProperty(JSContext* cx, JS::HandleObject obj, const char* name, bool* foundp);
/*
* Like JS_GetOwnPropertyDescriptorById but will return a property on
* an object on the prototype chain (returned in desc->obj). If desc->obj is null,
* then this property was not found on the prototype chain.
/**
* Like JS_GetOwnPropertyDescriptorById, but also searches the prototype chain
* if no own property is found directly on obj. The object on which the
* property is found is returned in desc.object(). If the property is not found
* on the prototype chain, this returns true with desc.object() set to null.
*/
extern JS_PUBLIC_API(bool)
JS_GetPropertyDescriptorById(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
@ -2901,40 +2841,87 @@ extern JS_PUBLIC_API(bool)
JS_GetPropertyDescriptor(JSContext* cx, JS::HandleObject obj, const char* name,
JS::MutableHandle<JSPropertyDescriptor> desc);
/**
* Define a property on obj.
*
* This function uses JS::ObjectOpResult to indicate conditions that ES6
* specifies as non-error failures. This is inconvenient at best, so use this
* function only if you are implementing a proxy handler's defineProperty()
* method. For all other purposes, use one of the many DefineProperty functions
* below that throw an exception in all failure cases.
*
* Implements: ES6 [[DefineOwnProperty]] internal method.
*/
extern JS_PUBLIC_API(bool)
JS_GetProperty(JSContext* cx, JS::HandleObject obj, const char* name, JS::MutableHandleValue vp);
extern JS_PUBLIC_API(bool)
JS_GetPropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::MutableHandleValue vp);
extern JS_PUBLIC_API(bool)
JS_ForwardGetPropertyTo(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue onBehalfOf,
JS::MutableHandleValue vp);
extern JS_PUBLIC_API(bool)
JS_SetProperty(JSContext* cx, JS::HandleObject obj, const char* name, JS::HandleValue v);
extern JS_PUBLIC_API(bool)
JS_SetPropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue v);
extern JS_PUBLIC_API(bool)
JS_ForwardSetPropertyTo(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue v,
JS::HandleValue receiver, JS::ObjectOpResult& result);
extern JS_PUBLIC_API(bool)
JS_DeleteProperty(JSContext* cx, JS::HandleObject obj, const char* name);
extern JS_PUBLIC_API(bool)
JS_DeleteProperty(JSContext* cx, JS::HandleObject obj, const char* name,
JS::ObjectOpResult& result);
extern JS_PUBLIC_API(bool)
JS_DeletePropertyById(JSContext* cx, JS::HandleObject obj, jsid id);
extern JS_PUBLIC_API(bool)
JS_DeletePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
JS::Handle<JSPropertyDescriptor> desc,
JS::ObjectOpResult& result);
/**
* Define a property on obj, throwing a TypeError if the attempt fails.
* This is the C++ equivalent of `Object.defineProperty(obj, id, desc)`.
*/
extern JS_PUBLIC_API(bool)
JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
JS::Handle<JSPropertyDescriptor> desc);
extern JS_PUBLIC_API(bool)
JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue value,
unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleObject value,
unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleString value,
unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, int32_t value,
unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, uint32_t value,
unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, double value,
unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefineProperty(JSContext* cx, JS::HandleObject obj, const char* name, JS::HandleValue value,
unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefineProperty(JSContext* cx, JS::HandleObject obj, const char* name, JS::HandleObject value,
unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefineProperty(JSContext* cx, JS::HandleObject obj, const char* name, JS::HandleString value,
unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefineProperty(JSContext* cx, JS::HandleObject obj, const char* name, int32_t value,
unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefineProperty(JSContext* cx, JS::HandleObject obj, const char* name, uint32_t value,
unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefineProperty(JSContext* cx, JS::HandleObject obj, const char* name, double value,
unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefineUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen,
JS::Handle<JSPropertyDescriptor> desc,
JS::ObjectOpResult& result);
extern JS_PUBLIC_API(bool)
JS_DefineUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen,
JS::Handle<JSPropertyDescriptor> desc);
extern JS_PUBLIC_API(bool)
JS_DefineUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen,
JS::HandleValue value, unsigned attrs,
@ -2966,36 +2953,370 @@ JS_DefineUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, s
JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefineUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen,
JS::Handle<JSPropertyDescriptor> desc,
JS_DefineElement(JSContext* cx, JS::HandleObject obj, uint32_t index, JS::HandleValue value,
unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefineElement(JSContext* cx, JS::HandleObject obj, uint32_t index, JS::HandleObject value,
unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefineElement(JSContext* cx, JS::HandleObject obj, uint32_t index, JS::HandleString value,
unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefineElement(JSContext* cx, JS::HandleObject obj, uint32_t index, int32_t value,
unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefineElement(JSContext* cx, JS::HandleObject obj, uint32_t index, uint32_t value,
unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefineElement(JSContext* cx, JS::HandleObject obj, uint32_t index, double value,
unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
/**
* Compute the expression `id in obj`.
*
* If obj has an own or inherited property obj[id], set *foundp = true and
* return true. If not, set *foundp = false and return true. On error, return
* false with an exception pending.
*
* Implements: ES6 [[Has]] internal method.
*/
extern JS_PUBLIC_API(bool)
JS_HasPropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* foundp);
extern JS_PUBLIC_API(bool)
JS_HasProperty(JSContext* cx, JS::HandleObject obj, const char* name, bool* foundp);
extern JS_PUBLIC_API(bool)
JS_HasUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen,
bool* vp);
extern JS_PUBLIC_API(bool)
JS_HasElement(JSContext* cx, JS::HandleObject obj, uint32_t index, bool* foundp);
/**
* Determine whether obj has an own property with the key `id`.
*
* Implements: ES6 7.3.11 HasOwnProperty(O, P).
*/
extern JS_PUBLIC_API(bool)
JS_HasOwnPropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* foundp);
extern JS_PUBLIC_API(bool)
JS_HasOwnProperty(JSContext* cx, JS::HandleObject obj, const char* name, bool* foundp);
/**
* Get the value of the property `obj[id]`, or undefined if no such property
* exists. This is the C++ equivalent of `vp = Reflect.get(obj, id, receiver)`.
*
* Most callers don't need the `receiver` argument. Consider using
* JS_GetProperty instead. (But if you're implementing a proxy handler's set()
* method, it's often correct to call this function and pass the receiver
* through.)
*
* Implements: ES6 [[Get]] internal method.
*/
extern JS_PUBLIC_API(bool)
JS_ForwardGetPropertyTo(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
JS::HandleValue receiver, JS::MutableHandleValue vp);
extern JS_PUBLIC_API(bool)
JS_ForwardGetElementTo(JSContext* cx, JS::HandleObject obj, uint32_t index,
JS::HandleObject receiver, JS::MutableHandleValue vp);
/**
* Get the value of the property `obj[id]`, or undefined if no such property
* exists. The result is stored in vp.
*
* Implements: ES6 7.3.1 Get(O, P).
*/
extern JS_PUBLIC_API(bool)
JS_GetPropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
JS::MutableHandleValue vp);
extern JS_PUBLIC_API(bool)
JS_GetProperty(JSContext* cx, JS::HandleObject obj, const char* name, JS::MutableHandleValue vp);
extern JS_PUBLIC_API(bool)
JS_GetUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen,
JS::MutableHandleValue vp);
extern JS_PUBLIC_API(bool)
JS_GetElement(JSContext* cx, JS::HandleObject obj, uint32_t index, JS::MutableHandleValue vp);
/**
* Perform the same property assignment as `Reflect.set(obj, id, v, receiver)`.
*
* This function has a `receiver` argument that most callers don't need.
* Consider using JS_SetProperty instead.
*
* Implements: ES6 [[Set]] internal method.
*/
extern JS_PUBLIC_API(bool)
JS_ForwardSetPropertyTo(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue v,
JS::HandleValue receiver, JS::ObjectOpResult& result);
/**
* Perform the assignment `obj[id] = v`.
*
* This function performs non-strict assignment, so if the property is
* read-only, nothing happens and no error is thrown.
*/
extern JS_PUBLIC_API(bool)
JS_SetPropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue v);
extern JS_PUBLIC_API(bool)
JS_SetProperty(JSContext* cx, JS::HandleObject obj, const char* name, JS::HandleValue v);
extern JS_PUBLIC_API(bool)
JS_SetUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen,
JS::HandleValue v);
extern JS_PUBLIC_API(bool)
JS_SetElement(JSContext* cx, JS::HandleObject obj, uint32_t index, JS::HandleValue v);
extern JS_PUBLIC_API(bool)
JS_SetElement(JSContext* cx, JS::HandleObject obj, uint32_t index, JS::HandleObject v);
extern JS_PUBLIC_API(bool)
JS_SetElement(JSContext* cx, JS::HandleObject obj, uint32_t index, JS::HandleString v);
extern JS_PUBLIC_API(bool)
JS_SetElement(JSContext* cx, JS::HandleObject obj, uint32_t index, int32_t v);
extern JS_PUBLIC_API(bool)
JS_SetElement(JSContext* cx, JS::HandleObject obj, uint32_t index, uint32_t v);
extern JS_PUBLIC_API(bool)
JS_SetElement(JSContext* cx, JS::HandleObject obj, uint32_t index, double v);
/**
* Delete a property. This is the C++ equivalent of
* `result = Reflect.deleteProperty(obj, id)`.
*
* This function has a `result` out parameter that most callers don't need.
* Unless you can pass through an ObjectOpResult provided by your caller, it's
* probably best to use the JS_DeletePropertyById signature with just 3
* arguments.
*
* Implements: ES6 [[Delete]] internal method.
*/
extern JS_PUBLIC_API(bool)
JS_DeletePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
JS::ObjectOpResult& result);
extern JS_PUBLIC_API(bool)
JS_DeleteProperty(JSContext* cx, JS::HandleObject obj, const char* name,
JS::ObjectOpResult& result);
extern JS_PUBLIC_API(bool)
JS_DeleteUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen,
JS::ObjectOpResult& result);
extern JS_PUBLIC_API(bool)
JS_DefineUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen,
JS::Handle<JSPropertyDescriptor> desc);
JS_DeleteElement(JSContext* cx, JS::HandleObject obj, uint32_t index, JS::ObjectOpResult& result);
/**
* Delete a property, ignoring strict failures. This is the C++ equivalent of
* the JS `delete obj[id]` in non-strict mode code.
*/
extern JS_PUBLIC_API(bool)
JS_DeletePropertyById(JSContext* cx, JS::HandleObject obj, jsid id);
extern JS_PUBLIC_API(bool)
JS_DeleteProperty(JSContext* cx, JS::HandleObject obj, const char* name);
extern JS_PUBLIC_API(bool)
JS_DeleteElement(JSContext* cx, JS::HandleObject obj, uint32_t index);
/**
* Get an array of the non-symbol enumerable properties of obj.
* This function is roughly equivalent to:
*
* var result = [];
* for (key in obj)
* result.push(key);
* return result;
*
* This is the closest thing we currently have to the ES6 [[Enumerate]]
* internal method.
*
* The JSIdArray returned by JS_Enumerate must be rooted to protect its
* contents from garbage collection. Use JS::AutoIdArray.
*/
extern JS_PUBLIC_API(bool)
JS_Enumerate(JSContext* cx, JS::HandleObject obj, JS::MutableHandle<JS::IdVector> props);
/*
* API for determining callability and constructability. [[Call]] and
* [[Construct]] are internal methods that aren't present on all objects, so it
* is useful to ask if they are there or not. The standard itself asks these
* questions routinely.
*/
namespace JS {
/**
* Return true if the given object is callable. In ES6 terms, an object is
* callable if it has a [[Call]] internal method.
*
* Implements: ES6 7.2.3 IsCallable(argument).
*
* Functions are callable. A scripted proxy or wrapper is callable if its
* target is callable. Most other objects aren't callable.
*/
extern JS_PUBLIC_API(bool)
IsCallable(JSObject* obj);
/**
* Return true if the given object is a constructor. In ES6 terms, an object is
* a constructor if it has a [[Construct]] internal method. The expression
* `new obj()` throws a TypeError if obj is not a constructor.
*
* Implements: ES6 7.2.4 IsConstructor(argument).
*
* JS functions and classes are constructors. Arrow functions and most builtin
* functions are not. A scripted proxy or wrapper is a constructor if its
* target is a constructor.
*/
extern JS_PUBLIC_API(bool)
IsConstructor(JSObject* obj);
} /* namespace JS */
/**
* Call a function, passing a this-value and arguments. This is the C++
* equivalent of `rval = Reflect.apply(fun, obj, args)`.
*
* Implements: ES6 7.3.12 Call(F, V, [argumentsList]).
* Use this function to invoke the [[Call]] internal method.
*/
extern JS_PUBLIC_API(bool)
JS_CallFunctionValue(JSContext* cx, JS::HandleObject obj, JS::HandleValue fval,
const JS::HandleValueArray& args, JS::MutableHandleValue rval);
extern JS_PUBLIC_API(bool)
JS_CallFunction(JSContext* cx, JS::HandleObject obj, JS::HandleFunction fun,
const JS::HandleValueArray& args, JS::MutableHandleValue rval);
/**
* Perform the method call `rval = obj[name](args)`.
*/
extern JS_PUBLIC_API(bool)
JS_CallFunctionName(JSContext* cx, JS::HandleObject obj, const char* name,
const JS::HandleValueArray& args, JS::MutableHandleValue rval);
namespace JS {
static inline bool
Call(JSContext* cx, JS::HandleObject thisObj, JS::HandleFunction fun,
const JS::HandleValueArray& args, MutableHandleValue rval)
{
return !!JS_CallFunction(cx, thisObj, fun, args, rval);
}
static inline bool
Call(JSContext* cx, JS::HandleObject thisObj, JS::HandleValue fun, const JS::HandleValueArray& args,
MutableHandleValue rval)
{
return !!JS_CallFunctionValue(cx, thisObj, fun, args, rval);
}
static inline bool
Call(JSContext* cx, JS::HandleObject thisObj, const char* name, const JS::HandleValueArray& args,
MutableHandleValue rval)
{
return !!JS_CallFunctionName(cx, thisObj, name, args, rval);
}
extern JS_PUBLIC_API(bool)
Call(JSContext* cx, JS::HandleValue thisv, JS::HandleValue fun, const JS::HandleValueArray& args,
MutableHandleValue rval);
static inline bool
Call(JSContext* cx, JS::HandleValue thisv, JS::HandleObject funObj, const JS::HandleValueArray& args,
MutableHandleValue rval)
{
MOZ_ASSERT(funObj);
JS::RootedValue fun(cx, JS::ObjectValue(*funObj));
return Call(cx, thisv, fun, args, rval);
}
/**
* Invoke a constructor. This is the C++ equivalent of
* `rval = Reflect.construct(fun, args, newTarget)`.
*
* JS::Construct() takes a `newTarget` argument that most callers don't need.
* Consider using the four-argument Construct signature instead. (But if you're
* implementing a subclass or a proxy handler's construct() method, this is the
* right function to call.)
*
* Implements: ES6 7.3.13 Construct(F, [argumentsList], [newTarget]).
* Use this function to invoke the [[Construct]] internal method.
*/
extern JS_PUBLIC_API(bool)
Construct(JSContext* cx, JS::HandleValue fun, HandleObject newTarget,
const JS::HandleValueArray &args, MutableHandleValue rval);
/**
* Invoke a constructor. This is the C++ equivalent of
* `rval = new fun(...args)`.
*
* The value left in rval on success is always an object in practice,
* though at the moment this is not enforced by the C++ type system.
*
* Implements: ES6 7.3.13 Construct(F, [argumentsList], [newTarget]), when
* newTarget is omitted.
*/
extern JS_PUBLIC_API(bool)
Construct(JSContext* cx, JS::HandleValue fun, const JS::HandleValueArray& args,
MutableHandleValue rval);
} /* namespace JS */
/**
* Invoke a constructor, like the JS expression `new ctor(...args)`. Returns
* the new object, or null on error.
*/
extern JS_PUBLIC_API(JSObject*)
JS_New(JSContext* cx, JS::HandleObject ctor, const JS::HandleValueArray& args);
/*** Other property-defining functions ***********************************************************/
extern JS_PUBLIC_API(JSObject*)
JS_DefineObject(JSContext* cx, JS::HandleObject obj, const char* name,
const JSClass* clasp = nullptr, unsigned attrs = 0);
extern JS_PUBLIC_API(bool)
JS_DefineConstDoubles(JSContext* cx, JS::HandleObject obj, const JSConstDoubleSpec* cds);
extern JS_PUBLIC_API(bool)
JS_DefineConstIntegers(JSContext* cx, JS::HandleObject obj, const JSConstIntegerSpec* cis);
extern JS_PUBLIC_API(bool)
JS_DefineProperties(JSContext* cx, JS::HandleObject obj, const JSPropertySpec* ps);
/* * */
extern JS_PUBLIC_API(bool)
JS_AlreadyHasOwnPropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
bool* foundp);
extern JS_PUBLIC_API(bool)
JS_AlreadyHasOwnProperty(JSContext* cx, JS::HandleObject obj, const char* name,
bool* foundp);
extern JS_PUBLIC_API(bool)
JS_AlreadyHasOwnUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name,
size_t namelen, bool* foundp);
extern JS_PUBLIC_API(bool)
JS_HasUCProperty(JSContext* cx, JS::HandleObject obj,
const char16_t* name, size_t namelen,
bool* vp);
extern JS_PUBLIC_API(bool)
JS_GetUCProperty(JSContext* cx, JS::HandleObject obj,
const char16_t* name, size_t namelen,
JS::MutableHandleValue vp);
extern JS_PUBLIC_API(bool)
JS_SetUCProperty(JSContext* cx, JS::HandleObject obj,
const char16_t* name, size_t namelen,
JS::HandleValue v);
extern JS_PUBLIC_API(bool)
JS_DeleteUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen,
JS::ObjectOpResult& result);
JS_AlreadyHasOwnElement(JSContext* cx, JS::HandleObject obj, uint32_t index, bool* foundp);
extern JS_PUBLIC_API(JSObject*)
JS_NewArrayObject(JSContext* cx, const JS::HandleValueArray& contents);
@ -3025,73 +3346,6 @@ JS_GetArrayLength(JSContext* cx, JS::Handle<JSObject*> obj, uint32_t* lengthp);
extern JS_PUBLIC_API(bool)
JS_SetArrayLength(JSContext* cx, JS::Handle<JSObject*> obj, uint32_t length);
extern JS_PUBLIC_API(bool)
JS_DefineElement(JSContext* cx, JS::HandleObject obj, uint32_t index, JS::HandleValue value,
unsigned attrs,
JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefineElement(JSContext* cx, JS::HandleObject obj, uint32_t index, JS::HandleObject value,
unsigned attrs,
JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefineElement(JSContext* cx, JS::HandleObject obj, uint32_t index, JS::HandleString value,
unsigned attrs,
JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefineElement(JSContext* cx, JS::HandleObject obj, uint32_t index, int32_t value,
unsigned attrs,
JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefineElement(JSContext* cx, JS::HandleObject obj, uint32_t index, uint32_t value,
unsigned attrs,
JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefineElement(JSContext* cx, JS::HandleObject obj, uint32_t index, double value,
unsigned attrs,
JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_AlreadyHasOwnElement(JSContext* cx, JS::HandleObject obj, uint32_t index, bool* foundp);
extern JS_PUBLIC_API(bool)
JS_HasElement(JSContext* cx, JS::HandleObject obj, uint32_t index, bool* foundp);
extern JS_PUBLIC_API(bool)
JS_GetElement(JSContext* cx, JS::HandleObject obj, uint32_t index, JS::MutableHandleValue vp);
extern JS_PUBLIC_API(bool)
JS_ForwardGetElementTo(JSContext* cx, JS::HandleObject obj, uint32_t index,
JS::HandleObject onBehalfOf, JS::MutableHandleValue vp);
extern JS_PUBLIC_API(bool)
JS_SetElement(JSContext* cx, JS::HandleObject obj, uint32_t index, JS::HandleValue v);
extern JS_PUBLIC_API(bool)
JS_SetElement(JSContext* cx, JS::HandleObject obj, uint32_t index, JS::HandleObject v);
extern JS_PUBLIC_API(bool)
JS_SetElement(JSContext* cx, JS::HandleObject obj, uint32_t index, JS::HandleString v);
extern JS_PUBLIC_API(bool)
JS_SetElement(JSContext* cx, JS::HandleObject obj, uint32_t index, int32_t v);
extern JS_PUBLIC_API(bool)
JS_SetElement(JSContext* cx, JS::HandleObject obj, uint32_t index, uint32_t v);
extern JS_PUBLIC_API(bool)
JS_SetElement(JSContext* cx, JS::HandleObject obj, uint32_t index, double v);
extern JS_PUBLIC_API(bool)
JS_DeleteElement(JSContext* cx, JS::HandleObject obj, uint32_t index);
extern JS_PUBLIC_API(bool)
JS_DeleteElement(JSContext* cx, JS::HandleObject obj, uint32_t index, JS::ObjectOpResult& result);
/*
* Assign 'undefined' to all of the object's non-reserved slots. Note: this is
* done for all slots, regardless of the associated property descriptor.
@ -3141,15 +3395,13 @@ JS_CreateMappedArrayBufferContents(int fd, size_t offset, size_t length);
extern JS_PUBLIC_API(void)
JS_ReleaseMappedArrayBufferContents(void* contents, size_t length);
extern JS_PUBLIC_API(bool)
JS_Enumerate(JSContext* cx, JS::HandleObject obj, JS::MutableHandle<JS::IdVector> props);
extern JS_PUBLIC_API(JS::Value)
JS_GetReservedSlot(JSObject* obj, uint32_t index);
extern JS_PUBLIC_API(void)
JS_SetReservedSlot(JSObject* obj, uint32_t index, JS::Value v);
/************************************************************************/
/*
@ -3206,20 +3458,6 @@ JS_GetFunctionDisplayId(JSFunction* fun);
extern JS_PUBLIC_API(uint16_t)
JS_GetFunctionArity(JSFunction* fun);
/*
* API for determining callability and constructability. This does the right
* thing for proxies.
*/
namespace JS {
extern JS_PUBLIC_API(bool)
IsCallable(JSObject* obj);
extern JS_PUBLIC_API(bool)
IsConstructor(JSObject* obj);
} /* namespace JS */
/*
* Infallible predicate to test whether obj is a function object (faster than
* comparing obj's class name to "Function", but equivalent unless someone has
@ -3918,66 +4156,6 @@ Evaluate(JSContext* cx, const ReadOnlyCompileOptions& options,
} /* namespace JS */
extern JS_PUBLIC_API(bool)
JS_CallFunction(JSContext* cx, JS::HandleObject obj, JS::HandleFunction fun,
const JS::HandleValueArray& args, JS::MutableHandleValue rval);
extern JS_PUBLIC_API(bool)
JS_CallFunctionName(JSContext* cx, JS::HandleObject obj, const char* name,
const JS::HandleValueArray& args, JS::MutableHandleValue rval);
extern JS_PUBLIC_API(bool)
JS_CallFunctionValue(JSContext* cx, JS::HandleObject obj, JS::HandleValue fval,
const JS::HandleValueArray& args, JS::MutableHandleValue rval);
namespace JS {
static inline bool
Call(JSContext* cx, JS::HandleObject thisObj, JS::HandleFunction fun,
const JS::HandleValueArray& args, MutableHandleValue rval)
{
return !!JS_CallFunction(cx, thisObj, fun, args, rval);
}
static inline bool
Call(JSContext* cx, JS::HandleObject thisObj, const char* name, const JS::HandleValueArray& args,
MutableHandleValue rval)
{
return !!JS_CallFunctionName(cx, thisObj, name, args, rval);
}
static inline bool
Call(JSContext* cx, JS::HandleObject thisObj, JS::HandleValue fun, const JS::HandleValueArray& args,
MutableHandleValue rval)
{
return !!JS_CallFunctionValue(cx, thisObj, fun, args, rval);
}
extern JS_PUBLIC_API(bool)
Call(JSContext* cx, JS::HandleValue thisv, JS::HandleValue fun, const JS::HandleValueArray& args,
MutableHandleValue rval);
static inline bool
Call(JSContext* cx, JS::HandleValue thisv, JS::HandleObject funObj, const JS::HandleValueArray& args,
MutableHandleValue rval)
{
MOZ_ASSERT(funObj);
JS::RootedValue fun(cx, JS::ObjectValue(*funObj));
return Call(cx, thisv, fun, args, rval);
}
extern JS_PUBLIC_API(bool)
Construct(JSContext* cx, JS::HandleValue fun,
const JS::HandleValueArray& args,
MutableHandleValue rval);
extern JS_PUBLIC_API(bool)
Construct(JSContext* cx, JS::HandleValue fun,
HandleObject newTarget, const JS::HandleValueArray &args,
MutableHandleValue rval);
} /* namespace JS */
extern JS_PUBLIC_API(bool)
JS_CheckForInterrupt(JSContext* cx);

Просмотреть файл

@ -509,6 +509,10 @@ elif CONFIG['JS_CODEGEN_MIPS32'] or CONFIG['JS_CODEGEN_MIPS64']:
elif CONFIG['JS_CODEGEN_MIPS64']:
UNIFIED_SOURCES += [
'jit/mips64/Architecture-mips64.cpp',
'jit/mips64/Assembler-mips64.cpp',
'jit/mips64/Bailouts-mips64.cpp',
'jit/mips64/BaselineCompiler-mips64.cpp',
'jit/mips64/BaselineIC-mips64.cpp',
]
if CONFIG['OS_ARCH'] == 'WINNT':

Просмотреть файл

@ -7,12 +7,15 @@
#ifndef vm_SavedFrame_h
#define vm_SavedFrame_h
#include "jswrapper.h"
#include "js/UbiNode.h"
namespace js {
class SavedFrame : public NativeObject {
friend class SavedStacks;
friend struct ::JSStructuredCloneReader;
public:
static const Class class_;
@ -120,6 +123,13 @@ class SavedFrame : public NativeObject {
!obj.as<SavedFrame>().getReservedSlot(JSSLOT_SOURCE).isNull();
}
static bool isSavedFrameOrWrapperAndNotProto(JSObject& obj) {
auto unwrapped = CheckedUnwrap(&obj);
if (!unwrapped)
return false;
return isSavedFrameAndNotProto(*unwrapped);
}
struct Lookup;
struct HashPolicy;
@ -142,8 +152,17 @@ class SavedFrame : public NativeObject {
};
private:
static SavedFrame* create(JSContext* cx);
static bool finishSavedFrameInit(JSContext* cx, HandleObject ctor, HandleObject proto);
void initFromLookup(HandleLookup lookup);
void initSource(JSAtom* source);
void initLine(uint32_t line);
void initColumn(uint32_t column);
void initFunctionDisplayName(JSAtom* maybeName);
void initAsyncCause(JSAtom* maybeCause);
void initParent(SavedFrame* maybeParent);
void initPrincipalsAlreadyHeld(JSPrincipals* principals);
void initPrincipals(JSPrincipals* principals);
enum {
// The reserved slots in the SavedFrame class.

Просмотреть файл

@ -22,13 +22,7 @@
inline void
js::AssertObjectIsSavedFrameOrWrapper(JSContext* cx, HandleObject stack)
{
#ifdef DEBUG
if (stack) {
RootedObject savedFrameObj(cx, CheckedUnwrap(stack));
MOZ_ASSERT(savedFrameObj);
MOZ_ASSERT(js::SavedFrame::isSavedFrameAndNotProto(*savedFrameObj));
}
#endif
MOZ_ASSERT_IF(stack, js::SavedFrame::isSavedFrameOrWrapperAndNotProto(*stack));
}
#endif // vm_SavedStacksInl_h

Просмотреть файл

@ -406,29 +406,91 @@ SavedFrame::getPrincipals()
return static_cast<JSPrincipals*>(v.toPrivate());
}
void
SavedFrame::initSource(JSAtom* source)
{
MOZ_ASSERT(source);
initReservedSlot(JSSLOT_SOURCE, StringValue(source));
}
void
SavedFrame::initLine(uint32_t line)
{
initReservedSlot(JSSLOT_LINE, PrivateUint32Value(line));
}
void
SavedFrame::initColumn(uint32_t column)
{
initReservedSlot(JSSLOT_COLUMN, PrivateUint32Value(column));
}
void
SavedFrame::initPrincipals(JSPrincipals* principals)
{
if (principals)
JS_HoldPrincipals(principals);
initPrincipalsAlreadyHeld(principals);
}
void
SavedFrame::initPrincipalsAlreadyHeld(JSPrincipals* principals)
{
MOZ_ASSERT_IF(principals, principals->refcount > 0);
initReservedSlot(JSSLOT_PRINCIPALS, PrivateValue(principals));
}
void
SavedFrame::initFunctionDisplayName(JSAtom* maybeName)
{
initReservedSlot(JSSLOT_FUNCTIONDISPLAYNAME, maybeName ? StringValue(maybeName) : NullValue());
}
void
SavedFrame::initAsyncCause(JSAtom* maybeCause)
{
initReservedSlot(JSSLOT_ASYNCCAUSE, maybeCause ? StringValue(maybeCause) : NullValue());
}
void
SavedFrame::initParent(SavedFrame* maybeParent)
{
initReservedSlot(JSSLOT_PARENT, ObjectOrNullValue(maybeParent));
}
void
SavedFrame::initFromLookup(SavedFrame::HandleLookup lookup)
{
MOZ_ASSERT(lookup->source);
MOZ_ASSERT(getReservedSlot(JSSLOT_SOURCE).isUndefined());
setReservedSlot(JSSLOT_SOURCE, StringValue(lookup->source));
initSource(lookup->source);
initLine(lookup->line);
initColumn(lookup->column);
initFunctionDisplayName(lookup->functionDisplayName);
initAsyncCause(lookup->asyncCause);
initParent(lookup->parent);
initPrincipals(lookup->principals);
}
setReservedSlot(JSSLOT_LINE, PrivateUint32Value(lookup->line));
setReservedSlot(JSSLOT_COLUMN, PrivateUint32Value(lookup->column));
setReservedSlot(JSSLOT_FUNCTIONDISPLAYNAME,
lookup->functionDisplayName
? StringValue(lookup->functionDisplayName)
: NullValue());
setReservedSlot(JSSLOT_ASYNCCAUSE,
lookup->asyncCause
? StringValue(lookup->asyncCause)
: NullValue());
setReservedSlot(JSSLOT_PARENT, ObjectOrNullValue(lookup->parent));
/* static */ SavedFrame*
SavedFrame::create(JSContext* cx)
{
RootedGlobalObject global(cx, cx->global());
assertSameCompartment(cx, global);
MOZ_ASSERT(getReservedSlot(JSSLOT_PRINCIPALS).isUndefined());
if (lookup->principals)
JS_HoldPrincipals(lookup->principals);
setReservedSlot(JSSLOT_PRINCIPALS, PrivateValue(lookup->principals));
// Ensure that we don't try to capture the stack again in the
// `SavedStacksMetadataCallback` for this new SavedFrame object, and
// accidentally cause O(n^2) behavior.
SavedStacks::AutoReentrancyGuard guard(cx->compartment()->savedStacks());
RootedNativeObject proto(cx, GlobalObject::getOrCreateSavedFramePrototype(cx, global));
if (!proto)
return nullptr;
assertSameCompartment(cx, proto);
RootedObject frameObj(cx, NewObjectWithGivenProto(cx, &SavedFrame::class_, proto));
if (!frameObj)
return nullptr;
return &frameObj->as<SavedFrame>();
}
bool
@ -1222,30 +1284,15 @@ SavedStacks::getOrCreateSavedFrame(JSContext* cx, SavedFrame::HandleLookup looku
SavedFrame*
SavedStacks::createFrameFromLookup(JSContext* cx, SavedFrame::HandleLookup lookup)
{
RootedGlobalObject global(cx, cx->global());
assertSameCompartment(cx, global);
// Ensure that we don't try to capture the stack again in the
// `SavedStacksMetadataCallback` for this new SavedFrame object, and
// accidentally cause O(n^2) behavior.
SavedStacks::AutoReentrancyGuard guard(*this);
RootedNativeObject proto(cx, GlobalObject::getOrCreateSavedFramePrototype(cx, global));
if (!proto)
RootedSavedFrame frame(cx, SavedFrame::create(cx));
if (!frame)
return nullptr;
assertSameCompartment(cx, proto);
frame->initFromLookup(lookup);
RootedObject frameObj(cx, NewObjectWithGivenProto(cx, &SavedFrame::class_, proto));
if (!frameObj)
if (!FreezeObject(cx, frame))
return nullptr;
RootedSavedFrame f(cx, &frameObj->as<SavedFrame>());
f->initFromLookup(lookup);
if (!FreezeObject(cx, frameObj))
return nullptr;
return f.get();
return frame;
}
/*

Просмотреть файл

@ -148,6 +148,7 @@ namespace js {
// principals.
class SavedStacks {
friend class SavedFrame;
friend JSObject* SavedStacksMetadataCallback(JSContext* cx, JSObject* target);
friend bool JS::ubi::ConstructSavedFrameStackSlow(JSContext* cx,
JS::ubi::StackFrame& ubiFrame,

Просмотреть файл

@ -42,6 +42,7 @@
#include "builtin/MapObject.h"
#include "js/Date.h"
#include "js/TraceableHashTable.h"
#include "vm/SavedFrame.h"
#include "vm/SharedArrayObject.h"
#include "vm/TypedArrayObject.h"
#include "vm/WrapperObject.h"
@ -92,6 +93,12 @@ enum StructuredDataType : uint32_t {
SCTAG_END_OF_KEYS,
SCTAG_SHARED_TYPED_ARRAY_OBJECT,
SCTAG_DATA_VIEW_OBJECT,
SCTAG_SAVED_FRAME_OBJECT,
SCTAG_JSPRINCIPALS,
SCTAG_NULL_JSPRINCIPALS,
SCTAG_RECONSTRUCTED_SAVED_FRAME_PRINCIPALS_IS_SYSTEM,
SCTAG_RECONSTRUCTED_SAVED_FRAME_PRINCIPALS_IS_NOT_SYSTEM,
SCTAG_TYPED_ARRAY_V1_MIN = 0xFFFF0100,
SCTAG_TYPED_ARRAY_V1_INT8 = SCTAG_TYPED_ARRAY_V1_MIN + Scalar::Int8,
@ -243,6 +250,7 @@ struct JSStructuredCloneReader {
bool readSharedTypedArray(uint32_t arrayType, uint32_t nelems, MutableHandleValue vp);
bool readArrayBuffer(uint32_t nbytes, MutableHandleValue vp);
bool readV1ArrayBuffer(uint32_t arrayType, uint32_t nelems, MutableHandleValue vp);
JSObject* readSavedFrame(uint32_t principalsTag);
bool startRead(MutableHandleValue vp);
SCInput& in;
@ -305,6 +313,7 @@ struct JSStructuredCloneWriter {
bool traverseObject(HandleObject obj);
bool traverseMap(HandleObject obj);
bool traverseSet(HandleObject obj);
bool traverseSavedFrame(HandleObject obj);
bool parseTransferable();
bool reportErrorTransferable(uint32_t errorId);
@ -324,9 +333,10 @@ struct JSStructuredCloneWriter {
// counts.length() == objs.length() and sum(counts) == entries.length().
Vector<size_t> counts;
// For JSObject: Propery IDs as value
// For Map: Key followed by value.
// For JSObject: Property IDs as value
// For Map: Key followed by value
// For Set: Key
// For SavedFrame: parent SavedFrame
AutoValueVector entries;
// The "memory" list described in the HTML5 internal structured cloning algorithm.
@ -1037,6 +1047,103 @@ JSStructuredCloneWriter::traverseSet(HandleObject obj)
return out.writePair(SCTAG_SET_OBJECT, 0);
}
// Objects are written as a "preorder" traversal of the object graph: object
// "headers" (the class tag and any data needed for initial construction) are
// visited first, then the children are recursed through (where children are
// properties, Set or Map entries, etc.). So for example
//
// m = new Map();
// m.set(key1 = {}, value1 = {})
//
// would be stored as
//
// <Map tag>
// <key1 class tag>
// <value1 class tag>
// <end-of-children marker for key1>
// <end-of-children marker for value1>
// <end-of-children marker for Map>
//
// Notice how the end-of-children marker for key1 is sandwiched between the
// value1 beginning and end.
bool
JSStructuredCloneWriter::traverseSavedFrame(HandleObject obj)
{
RootedObject unwrapped(context(), js::CheckedUnwrap(obj));
MOZ_ASSERT(unwrapped && unwrapped->is<SavedFrame>());
RootedSavedFrame savedFrame(context(), &unwrapped->as<SavedFrame>());
RootedObject parent(context(), savedFrame->getParent());
if (!context()->compartment()->wrap(context(), &parent))
return false;
if (!objs.append(ObjectValue(*obj)) ||
!entries.append(parent ? ObjectValue(*parent) : NullValue()) ||
!counts.append(1))
{
return false;
}
checkStack();
// Write the SavedFrame tag and the SavedFrame's principals.
if (savedFrame->getPrincipals() == &ReconstructedSavedFramePrincipals::IsSystem) {
if (!out.writePair(SCTAG_SAVED_FRAME_OBJECT,
SCTAG_RECONSTRUCTED_SAVED_FRAME_PRINCIPALS_IS_SYSTEM))
{
return false;
};
} else if (savedFrame->getPrincipals() == &ReconstructedSavedFramePrincipals::IsNotSystem) {
if (!out.writePair(SCTAG_SAVED_FRAME_OBJECT,
SCTAG_RECONSTRUCTED_SAVED_FRAME_PRINCIPALS_IS_NOT_SYSTEM))
{
return false;
}
} else {
if (auto principals = savedFrame->getPrincipals()) {
if (!out.writePair(SCTAG_SAVED_FRAME_OBJECT, SCTAG_JSPRINCIPALS) ||
!principals->write(context(), this))
{
return false;
}
} else {
if (!out.writePair(SCTAG_SAVED_FRAME_OBJECT, SCTAG_NULL_JSPRINCIPALS))
return false;
}
}
// Write the SavedFrame's reserved slots, except for the parent, which is
// queued on objs for further traversal.
RootedValue val(context());
val = StringValue(savedFrame->getSource());
if (!startWrite(val))
return false;
val = NumberValue(savedFrame->getLine());
if (!startWrite(val))
return false;
val = NumberValue(savedFrame->getColumn());
if (!startWrite(val))
return false;
auto name = savedFrame->getFunctionDisplayName();
val = name ? StringValue(name) : NullValue();
if (!startWrite(val))
return false;
auto cause = savedFrame->getAsyncCause();
val = cause ? StringValue(cause) : NullValue();
if (!startWrite(val))
return false;
return true;
}
bool
JSStructuredCloneWriter::startWrite(HandleValue v)
{
@ -1111,6 +1218,8 @@ JSStructuredCloneWriter::startWrite(HandleValue v)
return traverseMap(obj);
} else if (cls == ESClass_Set) {
return traverseSet(obj);
} else if (SavedFrame::isSavedFrameOrWrapperAndNotProto(*obj)) {
return traverseSavedFrame(obj);
}
if (callbacks && callbacks->write)
@ -1268,7 +1377,7 @@ JSStructuredCloneWriter::write(HandleValue v)
if (!startWrite(key) || !startWrite(val))
return false;
} else if (cls == ESClass_Set) {
} else if (cls == ESClass_Set || SavedFrame::isSavedFrameOrWrapperAndNotProto(*obj)) {
if (!startWrite(key))
return false;
} else {
@ -1777,6 +1886,14 @@ JSStructuredCloneReader::startRead(MutableHandleValue vp)
break;
}
case SCTAG_SAVED_FRAME_OBJECT: {
auto obj = readSavedFrame(data);
if (!obj || !objs.append(ObjectValue(*obj)))
return false;
vp.setObject(*obj);
break;
}
default: {
if (tag <= SCTAG_FLOAT_MAX) {
double d = ReinterpretPairAsDouble(tag, data);
@ -1894,16 +2011,99 @@ JSStructuredCloneReader::readTransferMap()
return true;
}
JSObject*
JSStructuredCloneReader::readSavedFrame(uint32_t principalsTag)
{
RootedSavedFrame savedFrame(context(), SavedFrame::create(context()));
if (!savedFrame)
return nullptr;
JSPrincipals* principals;
if (principalsTag == SCTAG_JSPRINCIPALS) {
if (!context()->runtime()->readPrincipals) {
JS_ReportErrorNumber(context(), GetErrorMessage, nullptr,
JSMSG_SC_UNSUPPORTED_TYPE);
return nullptr;
}
if (!context()->runtime()->readPrincipals(context(), this, &principals))
return nullptr;
} else if (principalsTag == SCTAG_RECONSTRUCTED_SAVED_FRAME_PRINCIPALS_IS_SYSTEM) {
principals = &ReconstructedSavedFramePrincipals::IsSystem;
principals->refcount++;
} else if (principalsTag == SCTAG_RECONSTRUCTED_SAVED_FRAME_PRINCIPALS_IS_NOT_SYSTEM) {
principals = &ReconstructedSavedFramePrincipals::IsNotSystem;
principals->refcount++;
} else if (principalsTag == SCTAG_NULL_JSPRINCIPALS) {
principals = nullptr;
} else {
JS_ReportErrorNumber(context(), GetErrorMessage, nullptr,
JSMSG_SC_BAD_SERIALIZED_DATA, "bad SavedFrame principals");
return nullptr;
}
savedFrame->initPrincipalsAlreadyHeld(principals);
RootedValue source(context());
if (!startRead(&source) || !source.isString())
return nullptr;
auto atomSource = AtomizeString(context(), source.toString());
if (!atomSource)
return nullptr;
savedFrame->initSource(atomSource);
RootedValue lineVal(context());
uint32_t line;
if (!startRead(&lineVal) || !lineVal.isNumber() || !ToUint32(context(), lineVal, &line))
return nullptr;
savedFrame->initLine(line);
RootedValue columnVal(context());
uint32_t column;
if (!startRead(&columnVal) || !columnVal.isNumber() || !ToUint32(context(), columnVal, &column))
return nullptr;
savedFrame->initColumn(column);
RootedValue name(context());
if (!startRead(&name) || !(name.isString() || name.isNull()))
return nullptr;
JSAtom* atomName = nullptr;
if (name.isString()) {
atomName = AtomizeString(context(), name.toString());
if (!atomName)
return nullptr;
}
savedFrame->initFunctionDisplayName(atomName);
RootedValue cause(context());
if (!startRead(&cause) || !(cause.isString() || cause.isNull()))
return nullptr;
JSAtom* atomCause = nullptr;
if (cause.isString()) {
atomCause = AtomizeString(context(), cause.toString());
if (!atomCause)
return nullptr;
}
savedFrame->initAsyncCause(atomCause);
return savedFrame;
}
// Perform the whole recursive reading procedure.
bool
JSStructuredCloneReader::read(MutableHandleValue vp)
{
if (!readTransferMap())
return false;
// Start out by reading in the main object and pushing it onto the 'objs'
// stack. The data related to this object and its descendants extends from
// here to the SCTAG_END_OF_KEYS at the end of the stream.
if (!startRead(vp))
return false;
// Stop when the stack shows that all objects have been read.
while (objs.length() != 0) {
// What happens depends on the top obj on the objs stack.
RootedObject obj(context(), &objs.back().toObject());
uint32_t tag, data;
@ -1911,36 +2111,76 @@ JSStructuredCloneReader::read(MutableHandleValue vp)
return false;
if (tag == SCTAG_END_OF_KEYS) {
// Pop the current obj off the stack, since we are done with it and
// its children.
MOZ_ALWAYS_TRUE(in.readPair(&tag, &data));
objs.popBack();
continue;
}
// The input stream contains a sequence of "child" values, whose
// interpretation depends on the type of obj. These values can be
// anything, and startRead() will push onto 'objs' for any non-leaf
// value (i.e., anything that may contain children).
//
// startRead() will allocate the (empty) object, but note that when
// startRead() returns, 'key' is not yet initialized with any of its
// properties. Those will be filled in by returning to the head of this
// loop, processing the first child obj, and continuing until all
// children have been fully created.
//
// Note that this means the ordering in the stream is a little funky
// for things like Map. See the comment above startWrite() for an
// example.
RootedValue key(context());
if (!startRead(&key))
return false;
if (key.isNull() && !(obj->is<MapObject>() || obj->is<SetObject>())) {
// Backwards compatibility: Null used to indicate
// the end of object properties.
if (key.isNull() &&
!(obj->is<MapObject>() || obj->is<SetObject>() || obj->is<SavedFrame>()))
{
// Backwards compatibility: Null formerly indicated the end of
// object properties.
objs.popBack();
continue;
}
// Set object: the values between obj header (from startRead()) and
// SCTAG_END_OF_KEYS are all interpreted as values to add to the set.
if (obj->is<SetObject>()) {
if (!SetObject::add(context(), obj, key))
return false;
continue;
}
// SavedFrame object: there is one following value, the parent
// SavedFrame, which is either null or another SavedFrame object.
if (obj->is<SavedFrame>()) {
SavedFrame* parentFrame;
if (key.isNull())
parentFrame = nullptr;
else if (key.isObject() && key.toObject().is<SavedFrame>())
parentFrame = &key.toObject().as<SavedFrame>();
else
return false;
obj->as<SavedFrame>().initParent(parentFrame);
continue;
}
// Everything else uses a series of key,value,key,value,... Value
// objects.
RootedValue val(context());
if (!startRead(&val))
return false;
if (obj->is<MapObject>()) {
// For a Map, store those <key,value> pairs in the contained map
// data structure.
if (!MapObject::set(context(), obj, key, val))
return false;
} else {
// For any other Object, interpret them as plain properties.
RootedId id(context());
if (!ValueToId<CanGC>(context(), key, &id))
return false;

Просмотреть файл

@ -289,7 +289,7 @@ public:
/**
* Get the scrollframe to ignore, if any.
*/
nsIFrame* GetIgnoreScrollFrame() const { return mIgnoreScrollFrame; }
nsIFrame* GetIgnoreScrollFrame() { return mIgnoreScrollFrame; }
/**
* Get the ViewID of the nearest scrolling ancestor frame.
*/

Просмотреть файл

@ -3037,25 +3037,6 @@ nsLayoutUtils::CalculateAndSetDisplayPortMargins(nsIScrollableFrame* aScrollFram
content, presShell, displayportMargins, 0, aRepaintMode);
}
bool
nsLayoutUtils::WantDisplayPort(const nsDisplayListBuilder* aBuilder,
nsIFrame* aScrollFrame)
{
nsIScrollableFrame* scrollableFrame = do_QueryFrame(aScrollFrame);
if (!scrollableFrame) {
return false;
}
// We perform an optimization where we ensure that at least one
// async-scrollable frame (i.e. one that WantAsyncScroll()) has a displayport.
// If that's not the case yet, and we are async-scrollable, we will get a
// displayport.
return aBuilder->IsPaintingToWindow() &&
nsLayoutUtils::AsyncPanZoomEnabled(aScrollFrame) &&
!aBuilder->HaveScrollableDisplayPort() &&
scrollableFrame->WantAsyncScroll();
}
bool
nsLayoutUtils::GetOrMaybeCreateDisplayPort(nsDisplayListBuilder& aBuilder,
nsIFrame* aScrollFrame,
@ -3074,7 +3055,17 @@ nsLayoutUtils::GetOrMaybeCreateDisplayPort(nsDisplayListBuilder& aBuilder,
bool haveDisplayPort = GetDisplayPort(content, aOutDisplayport);
if (WantDisplayPort(&aBuilder, aScrollFrame)) {
// We perform an optimization where we ensure that at least one
// async-scrollable frame (i.e. one that WantsAsyncScroll()) has a displayport.
// If that's not the case yet, and we are async-scrollable, we will get a
// displayport.
// Note: we only do this in processes where we do subframe scrolling to
// begin with (i.e., not in the parent process on B2G).
if (aBuilder.IsPaintingToWindow() &&
nsLayoutUtils::AsyncPanZoomEnabled(aScrollFrame) &&
!aBuilder.HaveScrollableDisplayPort() &&
scrollableFrame->WantAsyncScroll()) {
// If we don't already have a displayport, calculate and set one.
if (!haveDisplayPort) {
CalculateAndSetDisplayPortMargins(scrollableFrame, nsLayoutUtils::RepaintMode::DoNotRepaint);
@ -3142,14 +3133,16 @@ nsLayoutUtils::PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFram
nsIFrame* rootScrollFrame = presShell->GetRootScrollFrame();
bool usingDisplayPort = false;
nsRect displayport;
if (rootScrollFrame && !aFrame->GetParent() &&
builder.IsPaintingToWindow() &&
gfxPrefs::LayoutUseContainersForRootFrames()) {
nsRect displayportBase(
nsPoint(0,0),
nsLayoutUtils::CalculateCompositionSizeForFrame(rootScrollFrame));
usingDisplayPort = nsLayoutUtils::GetOrMaybeCreateDisplayPort(
builder, rootScrollFrame, displayportBase, &displayport);
if (rootScrollFrame && !aFrame->GetParent()) {
nsIScrollableFrame* rootScrollableFrame = presShell->GetRootScrollFrameAsScrollable();
MOZ_ASSERT(rootScrollableFrame);
displayport = aFrame->GetVisualOverflowRectRelativeToSelf();
usingDisplayPort = rootScrollableFrame->DecideScrollableLayer(&builder,
&displayport, /* aAllowCreateDisplayPort = */ true);
if (!gfxPrefs::LayoutUseContainersForRootFrames()) {
usingDisplayPort = false;
}
}
nsDisplayList hoistedScrollItemStorage;

Просмотреть файл

@ -2651,12 +2651,6 @@ public:
static bool CalculateAndSetDisplayPortMargins(nsIScrollableFrame* aScrollFrame,
RepaintMode aRepaintMode);
/**
* Return true if GetOrMaybeCreateDisplayPort would create a displayport.
*/
static bool WantDisplayPort(const nsDisplayListBuilder* aBuilder,
nsIFrame* aScrollFrame);
/**
* Get the display port for |aScrollFrame|'s content. If |aScrollFrame|
* WantsAsyncScroll() and we don't have a scrollable displayport yet (as

Просмотреть файл

@ -5851,20 +5851,15 @@ bool
PresShell::AssumeAllImagesVisible()
{
static bool sImageVisibilityEnabled = true;
static bool sImageVisibilityEnabledForBrowserElementsOnly = false;
static bool sImageVisibilityPrefCached = false;
if (!sImageVisibilityPrefCached) {
Preferences::AddBoolVarCache(&sImageVisibilityEnabled,
"layout.imagevisibility.enabled", true);
Preferences::AddBoolVarCache(&sImageVisibilityEnabledForBrowserElementsOnly,
"layout.imagevisibility.enabled_for_browser_elements_only", false);
sImageVisibilityPrefCached = true;
}
if ((!sImageVisibilityEnabled &&
!sImageVisibilityEnabledForBrowserElementsOnly) ||
!mPresContext || !mDocument) {
if (!sImageVisibilityEnabled || !mPresContext || !mDocument) {
return true;
}
@ -5878,14 +5873,6 @@ PresShell::AssumeAllImagesVisible()
return true;
}
if (!sImageVisibilityEnabled &&
sImageVisibilityEnabledForBrowserElementsOnly) {
nsCOMPtr<nsIDocShell> docshell(mPresContext->GetDocShell());
if (!docshell || !docshell->GetIsInBrowserElement()) {
return true;
}
}
return false;
}

Просмотреть файл

@ -61,6 +61,7 @@
#include "nsPluginFrame.h"
#include <mozilla/layers/AxisPhysicsModel.h>
#include <mozilla/layers/AxisPhysicsMSDModel.h>
#include "mozilla/unused.h"
#include <algorithm>
#include <cstdlib> // for std::abs(int/long)
#include <cmath> // for std::abs(float/double)
@ -1845,7 +1846,7 @@ ScrollFrameHelper::ScrollFrameHelper(nsContainerFrame* aOuter,
, mUpdateScrollbarAttributes(false)
, mHasBeenScrolledRecently(false)
, mCollapsedResizer(false)
, mShouldBuildScrollableLayer(false)
, mWillBuildScrollableLayer(false)
, mIsScrollableLayerInRootContainer(false)
, mHasBeenScrolled(false)
, mIsResolutionSet(false)
@ -2824,53 +2825,6 @@ ClipListsExceptCaret(nsDisplayListCollection* aLists,
ClipItemsExceptCaret(aLists->Content(), aBuilder, aClipFrame, clip, aUsingDisplayPort);
}
bool
ScrollFrameHelper::IsUsingDisplayPort(const nsDisplayListBuilder* aBuilder) const
{
return aBuilder->IsPaintingToWindow() &&
nsLayoutUtils::GetDisplayPort(mOuter->GetContent());
}
bool
ScrollFrameHelper::WillUseDisplayPort(const nsDisplayListBuilder* aBuilder) const
{
bool wantsDisplayPort = nsLayoutUtils::WantDisplayPort(aBuilder, mOuter);
if (mIsRoot && gfxPrefs::LayoutUseContainersForRootFrames()) {
// This condition mirrors the calls to GetOrMaybeCreateDisplayPort in
// nsSubDocumentFrame::BuildDisplayList and nsLayoutUtils::PaintFrame.
if (wantsDisplayPort) {
return true;
}
}
// The following conditions mirror the checks in BuildDisplayList
if (IsUsingDisplayPort(aBuilder)) {
return true;
}
if (aBuilder->GetIgnoreScrollFrame() == mOuter || IsIgnoringViewportClipping()) {
return false;
}
return wantsDisplayPort;
}
bool
ScrollFrameHelper::WillBuildScrollableLayer(const nsDisplayListBuilder* aBuilder) const
{
if (WillUseDisplayPort(aBuilder)) {
return true;
}
if (aBuilder->GetIgnoreScrollFrame() == mOuter || IsIgnoringViewportClipping()) {
return false;
}
return nsContentUtils::HasScrollgrab(mOuter->GetContent());
}
void
ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
@ -2911,21 +2865,14 @@ ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder,
bool createLayersForScrollbars = mIsRoot &&
mOuter->PresContext()->IsRootContentDocument();
bool usingDisplayPort = IsUsingDisplayPort(aBuilder);
mShouldBuildScrollableLayer = WillBuildScrollableLayer(aBuilder);
if (aBuilder->GetIgnoreScrollFrame() == mOuter || IsIgnoringViewportClipping()) {
bool usingDisplayPort = aBuilder->IsPaintingToWindow() &&
nsLayoutUtils::GetDisplayPort(mOuter->GetContent());
// Root scrollframes have FrameMetrics and clipping on their container
// layers, so don't apply clipping again.
mAddClipRectToLayer = false;
if (usingDisplayPort) {
// There is a display port for this frame, so we want to appear as having
// active scrolling, so that animated geometry roots are assigned correctly.
MOZ_ASSERT(mShouldBuildScrollableLayer);
mIsScrollableLayerInRootContainer = true;
}
// If we are a root scroll frame that has a display port we want to add
// scrollbars, they will be children of the scrollable layer, but they get
// adjusted by the APZC automatically.
@ -2967,53 +2914,22 @@ ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder,
// dirty rect here.
nsRect dirtyRect = aDirtyRect.Intersect(mScrollPort);
nsRect displayPort;
if (aBuilder->IsPaintingToWindow()) {
bool wasUsingDisplayPort = usingDisplayPort;
unused << DecideScrollableLayer(aBuilder, &dirtyRect,
/* aAllowCreateDisplayPort = */ !mIsRoot);
if (mIsRoot && gfxPrefs::LayoutUseContainersForRootFrames()) {
// For a root frame in a container, just get the value of the existing
// display port if any.
usingDisplayPort = nsLayoutUtils::GetDisplayPort(mOuter->GetContent(), &displayPort);
} else {
// Override the value of the display port base rect, and possibly create a
// display port if there isn't one already.
nsRect displayportBase = dirtyRect;
if (mIsRoot && mOuter->PresContext()->IsRootContentDocument()) {
displayportBase =
nsRect(nsPoint(0, 0), nsLayoutUtils::CalculateCompositionSizeForFrame(mOuter));
}
usingDisplayPort = nsLayoutUtils::GetOrMaybeCreateDisplayPort(
*aBuilder, mOuter, displayportBase, &displayPort);
}
bool usingDisplayPort = aBuilder->IsPaintingToWindow() &&
nsLayoutUtils::GetDisplayPort(mOuter->GetContent());
// Override the dirty rectangle if the displayport has been set.
if (usingDisplayPort) {
dirtyRect = displayPort;
// The cached animated geometry root for the display builder is out of
// date if we just introduced a new animated geometry root.
if (!wasUsingDisplayPort) {
aBuilder->RecomputeCurrentAnimatedGeometryRoot();
}
}
}
// Since making new layers is expensive, only use nsDisplayScrollLayer
// if the area is scrollable and we're the content process (unless we're on
// B2G, where we support async scrolling for scrollable elements in the
// parent process as well).
// When a displayport is being used, force building of a layer so that
// CompositorParent can always find the scrollable layer for the root content
// document.
// If the element is marked 'scrollgrab', also force building of a layer
// so that APZ can implement scroll grabbing.
MOZ_ASSERT(mShouldBuildScrollableLayer == (usingDisplayPort || nsContentUtils::HasScrollgrab(mOuter->GetContent())));
bool shouldBuildLayer = false;
if (mShouldBuildScrollableLayer) {
shouldBuildLayer = true;
// Whether we might want to build a scrollable layer for this scroll frame
// at some point in the future. This controls whether we add the information
// to the layer tree (a scroll info layer if necessary, and add the right
// area to the dispatch to content layer event regions) necessary to activate
// a scroll frame so it creates a scrollable layer.
bool couldBuildLayer = false;
if (mWillBuildScrollableLayer) {
couldBuildLayer = true;
} else {
shouldBuildLayer =
couldBuildLayer =
nsLayoutUtils::AsyncPanZoomEnabled(mOuter) &&
WantAsyncScroll() &&
// If we are using containers for root frames, and we are the root
@ -3083,7 +2999,7 @@ ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder,
// and scroll info layers.
nsDisplayListBuilder::AutoCurrentScrollParentIdSetter idSetter(
aBuilder,
shouldBuildLayer && mScrolledFrame->GetContent()
couldBuildLayer && mScrolledFrame->GetContent()
? nsLayoutUtils::FindOrCreateIDFor(mScrolledFrame->GetContent())
: aBuilder->GetCurrentScrollParentId());
@ -3162,12 +3078,12 @@ ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder,
// above (where the idSetter variable is created).
//
// This is not compatible when using containes for root scrollframes.
MOZ_ASSERT(shouldBuildLayer && mScrolledFrame->GetContent());
mShouldBuildScrollableLayer = true;
MOZ_ASSERT(couldBuildLayer && mScrolledFrame->GetContent());
mWillBuildScrollableLayer = true;
}
}
if (mShouldBuildScrollableLayer && !gfxPrefs::LayoutUseContainersForRootFrames()) {
if (mWillBuildScrollableLayer && !gfxPrefs::LayoutUseContainersForRootFrames()) {
aBuilder->ForceLayerForScrollParent();
}
@ -3176,13 +3092,12 @@ ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder,
*contentBoxClipForNonCaretContent, usingDisplayPort);
}
if (shouldBuildLayer) {
if (couldBuildLayer) {
// Make sure that APZ will dispatch events back to content so we can create
// a displayport for this frame. We'll add the item later on.
nsDisplayLayerEventRegions* inactiveRegionItem = nullptr;
if (aBuilder->IsPaintingToWindow() &&
!mShouldBuildScrollableLayer &&
shouldBuildLayer &&
!mWillBuildScrollableLayer &&
aBuilder->IsBuildingLayerEventRegions())
{
inactiveRegionItem = new (aBuilder) nsDisplayLayerEventRegions(aBuilder, mScrolledFrame);
@ -3214,11 +3129,69 @@ ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder,
scrolledContent.MoveTo(aLists);
}
bool
ScrollFrameHelper::DecideScrollableLayer(nsDisplayListBuilder* aBuilder,
nsRect* aDirtyRect,
bool aAllowCreateDisplayPort)
{
bool usingDisplayPort = false;
nsIContent* content = mOuter->GetContent();
if (aBuilder->IsPaintingToWindow()) {
bool wasUsingDisplayPort = nsLayoutUtils::GetDisplayPort(content);
nsRect displayportBase = *aDirtyRect;
nsPresContext* pc = mOuter->PresContext();
if (mIsRoot && (pc->IsRootContentDocument() || !pc->GetParentPresContext())) {
displayportBase =
nsRect(nsPoint(0, 0), nsLayoutUtils::CalculateCompositionSizeForFrame(mOuter));
}
nsRect displayPort;
if (aAllowCreateDisplayPort) {
// Provide the value of the display port base rect, and possibly create a
// display port if there isn't one already.
usingDisplayPort = nsLayoutUtils::GetOrMaybeCreateDisplayPort(
*aBuilder, mOuter, displayportBase, &displayPort);
} else {
// We should have already been called with aAllowCreateDisplayPort == true
// which should have set a displayport base.
MOZ_ASSERT(content->GetProperty(nsGkAtoms::DisplayPortBase));
usingDisplayPort = nsLayoutUtils::GetDisplayPort(content, &displayPort);
}
// Override the dirty rectangle if the displayport has been set.
if (usingDisplayPort) {
*aDirtyRect = displayPort;
// The cached animated geometry root for the display builder is out of
// date if we just introduced a new animated geometry root.
if (!wasUsingDisplayPort) {
aBuilder->RecomputeCurrentAnimatedGeometryRoot();
}
}
}
// Since making new layers is expensive, only create a scrollable layer
// for some scroll frames.
// When a displayport is being used, force building of a layer so that
// the compositor can find the scrollable layer for async scrolling.
// If the element is marked 'scrollgrab', also force building of a layer
// so that APZ can implement scroll grabbing.
mWillBuildScrollableLayer = usingDisplayPort || nsContentUtils::HasScrollgrab(content);
if (gfxPrefs::LayoutUseContainersForRootFrames() && mWillBuildScrollableLayer && mIsRoot) {
mIsScrollableLayerInRootContainer = true;
}
return mWillBuildScrollableLayer;
}
Maybe<DisplayItemClip>
ScrollFrameHelper::ComputeScrollClip(bool aIsForCaret) const
{
const Maybe<DisplayItemClip>& ancestorClip = aIsForCaret ? mAncestorClipForCaret : mAncestorClip;
if (!mShouldBuildScrollableLayer || mIsScrollableLayerInRootContainer) {
if (!mWillBuildScrollableLayer || mIsScrollableLayerInRootContainer) {
return Nothing();
}
@ -3231,7 +3204,7 @@ ScrollFrameHelper::ComputeFrameMetrics(Layer* aLayer,
const ContainerLayerParameters& aParameters,
bool aIsForCaret) const
{
if (!mShouldBuildScrollableLayer || mIsScrollableLayerInRootContainer) {
if (!mWillBuildScrollableLayer || mIsScrollableLayerInRootContainer) {
return Nothing();
}
@ -4498,7 +4471,7 @@ ScrollFrameHelper::IsMaybeScrollingActive() const
return mHasBeenScrolledRecently ||
IsAlwaysActive() ||
mShouldBuildScrollableLayer;
mWillBuildScrollableLayer;
}
bool
@ -4512,8 +4485,7 @@ ScrollFrameHelper::IsScrollingActive(nsDisplayListBuilder* aBuilder) const
return mHasBeenScrolledRecently ||
IsAlwaysActive() ||
mShouldBuildScrollableLayer ||
WillBuildScrollableLayer(aBuilder);
mWillBuildScrollableLayer;
}
/**

Просмотреть файл

@ -81,10 +81,6 @@ public:
bool aCreateLayer,
bool aPositioned);
bool IsUsingDisplayPort(const nsDisplayListBuilder* aBuilder) const;
bool WillUseDisplayPort(const nsDisplayListBuilder* aBuilder) const;
bool WillBuildScrollableLayer(const nsDisplayListBuilder* aBuilder) const;
bool GetBorderRadii(const nsSize& aFrameSize, const nsSize& aBorderArea,
Sides aSkipSides, nscoord aRadii[8]) const;
@ -370,6 +366,10 @@ public:
bool UsesContainerScrolling() const;
bool DecideScrollableLayer(nsDisplayListBuilder* aBuilder,
nsRect* aDirtyRect,
bool aAllowCreateDisplayPort);
void ScheduleSyntheticMouseMove();
static void ScrollActivityCallback(nsITimer *aTimer, void* anInstance);
@ -390,7 +390,7 @@ public:
Layer* aLayer, nsIFrame* aContainerReferenceFrame,
const ContainerLayerParameters& aParameters,
bool aIsForCaret) const;
virtual mozilla::Maybe<mozilla::DisplayItemClip> ComputeScrollClip(bool aIsForCaret) const;
mozilla::Maybe<mozilla::DisplayItemClip> ComputeScrollClip(bool aIsForCaret) const;
// nsIScrollbarMediator
void ScrollByPage(nsScrollbarFrame* aScrollbar, int32_t aDirection,
@ -510,9 +510,9 @@ public:
// If true, the resizer is collapsed and not displayed
bool mCollapsedResizer:1;
// If true, the layer should always be active because we always build a
// scrollable layer. Used for asynchronous scrolling.
bool mShouldBuildScrollableLayer:1;
// If true, the scroll frame should always be active because we always build
// a scrollable layer. Used for asynchronous scrolling.
bool mWillBuildScrollableLayer:1;
// Whether we are the root scroll frame that is used for containerful
// scrolling with a display port. If true, the scrollable frame
@ -877,6 +877,11 @@ public:
virtual bool UsesContainerScrolling() const override {
return mHelper.UsesContainerScrolling();
}
virtual bool DecideScrollableLayer(nsDisplayListBuilder* aBuilder,
nsRect* aDirtyRect,
bool aAllowCreateDisplayPort) override {
return mHelper.DecideScrollableLayer(aBuilder, aDirtyRect, aAllowCreateDisplayPort);
}
// nsIStatefulFrame
NS_IMETHOD SaveState(nsPresState** aState) override {
@ -1355,6 +1360,12 @@ public:
void SetZoomableByAPZ(bool aZoomable) override {
mHelper.SetZoomableByAPZ(aZoomable);
}
virtual bool DecideScrollableLayer(nsDisplayListBuilder* aBuilder,
nsRect* aDirtyRect,
bool aAllowCreateDisplayPort) override {
return mHelper.DecideScrollableLayer(aBuilder, aDirtyRect, aAllowCreateDisplayPort);
}
#ifdef DEBUG_FRAME_DUMP
virtual nsresult GetFrameName(nsAString& aResult) const override;

Просмотреть файл

@ -455,6 +455,19 @@ public:
virtual bool UsesContainerScrolling() const = 0;
virtual mozilla::Maybe<mozilla::DisplayItemClip> ComputeScrollClip(bool aIsForCaret) const = 0;
/**
* Determine if we should build a scrollable layer for this scroll frame and
* return the result. It will also record this result on the scroll frame.
* Pass the dirty rect in aDirtyRect. On return it will be set to the
* displayport if there is one (ie the dirty rect that should be used).
* This function may create a display port where one did not exist before if
* aAllowCreateDisplayPort is true. It is only allowed to be false if there
* has been a call with it set to true before on the same paint.
*/
virtual bool DecideScrollableLayer(nsDisplayListBuilder* aBuilder,
nsRect* aDirtyRect,
bool aAllowCreateDisplayPort) = 0;
};
#endif

Просмотреть файл

@ -416,18 +416,13 @@ nsSubDocumentFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
dirty = dirty.ScaleToOtherAppUnitsRoundOut(parentAPD, subdocAPD);
if (nsIFrame* rootScrollFrame = presShell->GetRootScrollFrame()) {
if (gfxPrefs::LayoutUseContainersForRootFrames()) {
// for root content documents we want the base to be the composition bounds
nsRect displayportBase = presContext->IsRootContentDocument() ?
nsRect(nsPoint(0,0), nsLayoutUtils::CalculateCompositionSizeForFrame(rootScrollFrame)) :
dirty.Intersect(nsRect(nsPoint(0,0), subdocRootFrame->GetSize()));
nsRect displayPort;
if (aBuilder->IsPaintingToWindow() &&
nsLayoutUtils::GetOrMaybeCreateDisplayPort(
*aBuilder, rootScrollFrame, displayportBase, &displayPort)) {
haveDisplayPort = true;
dirty = displayPort;
}
nsIScrollableFrame* rootScrollableFrame = presShell->GetRootScrollFrameAsScrollable();
MOZ_ASSERT(rootScrollableFrame);
haveDisplayPort = rootScrollableFrame->DecideScrollableLayer(aBuilder,
&dirty, /* aAllowCreateDisplayPort = */ true);
if (!gfxPrefs::LayoutUseContainersForRootFrames()) {
haveDisplayPort = false;
}
ignoreViewportScrolling = presShell->IgnoringViewportScrolling();

Просмотреть файл

@ -18,6 +18,17 @@
#include "nsIXULRuntime.h"
#include "nsPrintfCString.h"
// Includes for the crash report annotation in ErrorLoadingBuiltinSheet.
#ifdef MOZ_CRASHREPORTER
#include "mozilla/Omnijar.h"
#include "nsDirectoryService.h"
#include "nsDirectoryServiceDefs.h"
#include "nsExceptionHandler.h"
#include "nsIChromeRegistry.h"
#include "nsISimpleEnumerator.h"
#include "nsISubstitutingProtocolHandler.h"
#endif
using namespace mozilla;
static bool sNumberControlEnabled;
@ -454,9 +465,249 @@ nsLayoutStylesheetCache::LoadSheetFile(nsIFile* aFile, nsRefPtr<CSSStyleSheet>&
LoadSheet(uri, aSheet, false);
}
#ifdef MOZ_CRASHREPORTER
static void
ListInterestingFiles(nsString& aAnnotation, nsIFile* aFile,
const nsTArray<nsString>& aInterestingFilenames)
{
nsString filename;
aFile->GetLeafName(filename);
for (const nsString& interestingFilename : aInterestingFilenames) {
if (interestingFilename == filename) {
nsString path;
aFile->GetPath(path);
aAnnotation.AppendLiteral(" ");
aAnnotation.Append(path);
aAnnotation.AppendLiteral(" (");
int64_t size;
if (NS_SUCCEEDED(aFile->GetFileSize(&size))) {
aAnnotation.AppendPrintf("%ld", size);
} else {
aAnnotation.AppendLiteral("???");
}
aAnnotation.AppendLiteral(" bytes)\n");
return;
}
}
bool isDir = false;
aFile->IsDirectory(&isDir);
if (!isDir) {
return;
}
nsCOMPtr<nsISimpleEnumerator> entries;
if (NS_FAILED(aFile->GetDirectoryEntries(getter_AddRefs(entries)))) {
aAnnotation.AppendLiteral(" (failed to enumerated directory)\n");
return;
}
for (;;) {
bool hasMore = false;
if (NS_FAILED(entries->HasMoreElements(&hasMore))) {
aAnnotation.AppendLiteral(" (failed during directory enumeration)\n");
return;
}
if (!hasMore) {
break;
}
nsCOMPtr<nsISupports> entry;
if (NS_FAILED(entries->GetNext(getter_AddRefs(entry)))) {
aAnnotation.AppendLiteral(" (failed during directory enumeration)\n");
return;
}
nsCOMPtr<nsIFile> file = do_QueryInterface(entry);
if (file) {
ListInterestingFiles(aAnnotation, file, aInterestingFilenames);
}
}
}
// Generate a crash report annotation to help debug issues with style
// sheets failing to load (bug 1194856).
static void
AnnotateCrashReport(nsIURI* aURI)
{
nsAutoCString spec;
nsAutoCString scheme;
nsDependentCSubstring filename;
if (aURI) {
aURI->GetSpec(spec);
aURI->GetScheme(scheme);
int32_t i = spec.RFindChar('/');
if (i != -1) {
filename.Rebind(spec, i + 1);
}
}
nsString annotation;
// The URL of the sheet that failed to load.
annotation.AppendLiteral("Error loading sheet: ");
annotation.Append(NS_ConvertUTF8toUTF16(spec).get());
annotation.Append('\n');
// The jar: or file: URL that the sheet's resource: or chrome: URL
// resolves to.
if (scheme.EqualsLiteral("resource")) {
annotation.AppendLiteral("Real location: ");
nsCOMPtr<nsISubstitutingProtocolHandler> handler;
nsCOMPtr<nsIIOService> io(do_GetIOService());
if (io) {
nsCOMPtr<nsIProtocolHandler> ph;
io->GetProtocolHandler(scheme.get(), getter_AddRefs(ph));
if (ph) {
handler = do_QueryInterface(ph);
}
}
if (!handler) {
annotation.AppendLiteral("(ResolveURI failed)\n");
} else {
nsAutoCString resolvedSpec;
handler->ResolveURI(aURI, resolvedSpec);
annotation.Append(NS_ConvertUTF8toUTF16(resolvedSpec));
annotation.Append('\n');
}
} else if (scheme.EqualsLiteral("chrome")) {
annotation.AppendLiteral("Real location: ");
nsCOMPtr<nsIChromeRegistry> reg =
mozilla::services::GetChromeRegistryService();
if (!reg) {
annotation.AppendLiteral("(no chrome registry)\n");
} else {
nsCOMPtr<nsIURI> resolvedURI;
reg->ConvertChromeURL(aURI, getter_AddRefs(resolvedURI));
if (!resolvedURI) {
annotation.AppendLiteral("(ConvertChromeURL failed)\n");
} else {
nsAutoCString resolvedSpec;
resolvedURI->GetSpec(resolvedSpec);
annotation.Append(NS_ConvertUTF8toUTF16(resolvedSpec));
annotation.Append('\n');
}
}
}
nsTArray<nsString> interestingFiles;
interestingFiles.AppendElement(NS_LITERAL_STRING("chrome.manifest"));
interestingFiles.AppendElement(NS_LITERAL_STRING("omni.ja"));
interestingFiles.AppendElement(NS_ConvertUTF8toUTF16(filename));
annotation.AppendLiteral("GRE directory: ");
nsCOMPtr<nsIFile> file;
nsDirectoryService::gService->Get(NS_GRE_DIR, NS_GET_IID(nsIFile),
getter_AddRefs(file));
if (file) {
// The Firefox installation directory.
nsString path;
file->GetPath(path);
annotation.Append(path);
annotation.Append('\n');
// List interesting files -- any chrome.manifest or omni.ja file or any file
// whose name is the sheet's filename -- under the Firefox installation
// directory.
annotation.AppendLiteral("Interesting files in the GRE directory:\n");
ListInterestingFiles(annotation, file, interestingFiles);
// If the Firefox installation directory has a chrome.manifest file, let's
// see what's in it.
file->Append(NS_LITERAL_STRING("chrome.manifest"));
bool exists = false;
file->Exists(&exists);
if (exists) {
annotation.AppendLiteral("Contents of chrome.manifest:\n[[[\n");
PRFileDesc* fd;
if (NS_SUCCEEDED(file->OpenNSPRFileDesc(PR_RDONLY, 0, &fd))) {
nsCString contents;
char buf[512];
int32_t n;
while ((n = PR_Read(fd, buf, sizeof(buf))) > 0) {
contents.Append(buf, n);
}
if (n < 0) {
annotation.AppendLiteral(" (error while reading)\n");
} else {
annotation.Append(NS_ConvertUTF8toUTF16(contents));
}
PR_Close(fd);
}
annotation.AppendLiteral("]]]\n");
}
} else {
annotation.AppendLiteral("(none)\n");
}
// The jar: or file: URL prefix that chrome: and resource: URLs get translated
// to.
annotation.AppendLiteral("GRE omnijar URI string: ");
nsCString uri;
nsresult rv = Omnijar::GetURIString(Omnijar::GRE, uri);
if (NS_FAILED(rv)) {
annotation.AppendLiteral("(failed)\n");
} else {
annotation.Append(NS_ConvertUTF8toUTF16(uri));
annotation.Append('\n');
}
nsRefPtr<nsZipArchive> zip = Omnijar::GetReader(Omnijar::GRE);
if (zip) {
// List interesting files in the GRE omnijar.
annotation.AppendLiteral("Interesting files in the GRE omnijar:\n");
nsZipFind* find;
rv = zip->FindInit(nullptr, &find);
if (NS_FAILED(rv)) {
annotation.AppendPrintf(" (FindInit failed with 0x%08x)\n", rv);
} else if (!find) {
annotation.AppendLiteral(" (FindInit returned null)\n");
} else {
const char* result;
uint16_t len;
while (NS_SUCCEEDED(find->FindNext(&result, &len))) {
nsCString itemPathname;
nsString itemFilename;
itemPathname.Append(result, len);
int32_t i = itemPathname.RFindChar('/');
if (i != -1) {
itemFilename = NS_ConvertUTF8toUTF16(Substring(itemPathname, i + 1));
}
for (const nsString& interestingFile : interestingFiles) {
if (interestingFile == itemFilename) {
annotation.AppendLiteral(" ");
annotation.Append(NS_ConvertUTF8toUTF16(itemPathname));
nsZipItem* item = zip->GetItem(itemPathname.get());
if (!item) {
annotation.AppendLiteral(" (GetItem failed)\n");
} else {
annotation.AppendPrintf(" (%d bytes, crc32 = 0x%08x)\n",
item->RealSize(),
item->CRC32());
}
break;
}
}
}
delete find;
}
} else {
annotation.AppendLiteral("No GRE omnijar\n");
}
CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("SheetLoadFailure"),
NS_ConvertUTF16toUTF8(annotation));
}
#endif
static void
ErrorLoadingBuiltinSheet(nsIURI* aURI, const char* aMsg)
{
#ifdef MOZ_CRASHREPORTER
AnnotateCrashReport(aURI);
#endif
nsAutoCString spec;
if (aURI) {
aURI->GetSpec(spec);

Просмотреть файл

@ -2361,6 +2361,15 @@ public class GeckoAppShell
SmsManager.getInstance().deleteMessage(aMessageId, aRequestId);
}
@WrapForJNI
public static void markMessageRead(int aMessageId, boolean aValue, boolean aSendReadReport, int aRequestId) {
if (!SmsManager.isEnabled()) {
return;
}
SmsManager.getInstance().markMessageRead(aMessageId, aValue, aSendReadReport, aRequestId);
}
@WrapForJNI(stubName = "CreateMessageCursorWrapper")
public static void createMessageCursor(long aStartDate, long aEndDate, String[] aNumbers, int aNumbersCount, String aDelivery, boolean aHasRead, boolean aRead, boolean aHasThreadId, long aThreadId, boolean aReverse, int aRequestId) {
if (!SmsManager.isEnabled()) {

Просмотреть файл

@ -762,6 +762,48 @@ public class GeckoSmsManager
aRequestId);
}
@Override
public void markMessageRead(int aMessageId, boolean aValue, boolean aSendReadReport, int aRequestId) {
class MarkMessageReadRunnable implements Runnable {
private final int mMessageId;
private final boolean mValue;
private final int mRequestId;
MarkMessageReadRunnable(int aMessageId, boolean aValue, int aRequestId) {
mMessageId = aMessageId;
mValue = aValue;
mRequestId = aRequestId;
}
@Override
public void run() {
try {
ContentResolver cr = GeckoAppShell.getContext().getContentResolver();
Uri message = ContentUris.withAppendedId(kSmsContentUri, mMessageId);
ContentValues updatedProps = new ContentValues();
updatedProps.put("read", mValue);
int count = cr.update(message, updatedProps, null, null);
notifySmsMarkedAsRead(count == 1, mRequestId);
} catch (Exception e) {
Log.e("GeckoSmsManager", "Error while trying to mark message as read: " + e);
notifySmsMarkAsReadFailed(kUnknownError, mRequestId);
}
}
}
if (aSendReadReport == true) {
Log.w("GeckoSmsManager", "Android SmsManager doesn't suport read receipts for SMS.");
}
if (!SmsIOThread.getInstance().execute(new MarkMessageReadRunnable(aMessageId, aValue, aRequestId))) {
Log.e("GeckoSmsManager", "Failed to add MarkMessageReadRunnable to the SmsIOThread");
notifySmsMarkAsReadFailed(kUnknownError, aRequestId);
}
}
@Override
public void createMessageCursor(long aStartDate, long aEndDate, String[] aNumbers, int aNumbersCount, String aDelivery, boolean aHasRead, boolean aRead, boolean aHasThreadId, long aThreadId, boolean aReverse, int aRequestId) {
class CreateMessageCursorRunnable implements Runnable {
@ -1101,6 +1143,10 @@ public class GeckoSmsManager
@WrapForJNI
private static native void notifySmsDeleteFailed(int aError, int aRequestId);
@WrapForJNI
private static native void notifySmsMarkedAsRead(boolean aMarkedAsRead, int aRequestId);
@WrapForJNI
private static native void notifySmsMarkAsReadFailed(int aError, int aRequestId);
@WrapForJNI
private static native void notifyCursorError(int aError, int aRequestId);
@WrapForJNI
private static native void notifyThreadCursorResult(long aId, String aLastMessageSubject, String aBody, long aUnreadCount, Object[] aParticipants, long aTimestamp, String aLastMessageType, int aRequestId);

Просмотреть файл

@ -31,6 +31,7 @@ public class SmsManager {
void send(String aNumber, String aMessage, int aRequestId);
void getMessage(int aMessageId, int aRequestId);
void deleteMessage(int aMessageId, int aRequestId);
void markMessageRead(int aMessageId, boolean aValue, boolean aSendReadReport, int aRequestId);
void createMessageCursor(long aStartDate, long aEndDate, String[] aNumbers, int aNumbersCount, String aDelivery, boolean aHasRead, boolean aRead, boolean aHasThreadId, long aThreadId, boolean aReverse, int aRequestId);
void createThreadCursor(int aRequestId);
void getNextThread(int aRequestId);

Просмотреть файл

@ -932,10 +932,6 @@ pref("nglayout.debug.invalidation", false);
// Whether image visibility is enabled globally (ie we will try to unlock images
// that are not visible).
pref("layout.imagevisibility.enabled", true);
// Whether image visibility is enabled in documents that are within a browser
// element as defined by nsDocShell::FrameType and GetInheritedFrameType. This
// pref only has an effect if layout.imagevisibility.enabled is false.
pref("layout.imagevisibility.enabled_for_browser_elements_only", false);
pref("layout.imagevisibility.numscrollportwidths", 0);
pref("layout.imagevisibility.numscrollportheights", 1);

Просмотреть файл

@ -8,6 +8,7 @@
#include <vector>
#include <dlfcn.h>
#include <signal.h>
#include "mozilla/RefCounted.h"
#include "mozilla/RefPtr.h"
#include "mozilla/UniquePtr.h"
#include "Zip.h"

Просмотреть файл

@ -11,6 +11,7 @@
#include <zlib.h>
#include "Utils.h"
#include "mozilla/Assertions.h"
#include "mozilla/RefCounted.h"
#include "mozilla/RefPtr.h"
/**

Просмотреть файл

@ -615,7 +615,7 @@ Http2Stream::GenerateOpen()
messageSize += Http2Session::kFrameHeaderBytes + 5; // frame header + priority overhead in HEADERS frame
messageSize += (numFrames - 1) * Http2Session::kFrameHeaderBytes; // frame header overhead in CONTINUATION frames
EnsureBuffer(mTxInlineFrame, messageSize,
EnsureBuffer(mTxInlineFrame, dataLength + messageSize,
mTxInlineFrameUsed, mTxInlineFrameSize);
mTxInlineFrameUsed += messageSize;

Просмотреть файл

@ -2586,9 +2586,6 @@ def run_test_harness(options):
if runner.getTestFlavor(options) == 'mochitest':
options.runByDir = True
if mozinfo.info['asan'] and options.e10s:
options.runByDir = False
if runner.getTestFlavor(options) == 'browser-chrome':
options.runByDir = True

Просмотреть файл

@ -20,7 +20,7 @@ task:
--test-suite crashtest
--installer-url {{build_url}}
--test-packages-url {{test_packages_url}}
--xre-url https://queue.taskcluster.net/v1/task/wXAHAaxDQpqxoWF1iljJjg/runs/0/artifacts/public/cache/xulrunner-sdk-40.zip
--xre-url https://queue.taskcluster.net/v1/task/YNNF94qRSyCXiSU_AQgFOQ/runs/0/artifacts/public/cache/xulrunner-sdk-40.zip
--this-chunk {{chunk}}
--total-chunk {{total_chunks}}
artifacts:

Просмотреть файл

@ -19,7 +19,7 @@ task:
--test-suite reftest
--installer-url {{build_url}}
--test-packages-url {{test_packages_url}}
--xre-url https://queue.taskcluster.net/v1/task/wXAHAaxDQpqxoWF1iljJjg/runs/0/artifacts/public/cache/xulrunner-sdk-40.zip
--xre-url https://queue.taskcluster.net/v1/task/YNNF94qRSyCXiSU_AQgFOQ/runs/0/artifacts/public/cache/xulrunner-sdk-40.zip
--this-chunk {{chunk}}
--total-chunk {{total_chunks}}
artifacts:

Просмотреть файл

@ -1,5 +0,0 @@
[Node-isEqualNode.xhtml]
type: testharness
[isEqualNode should return true when only the internal subsets of DocumentTypes differ.]
expected: FAIL

Просмотреть файл

@ -1,5 +0,0 @@
[document.title-03.html]
type: testharness
[ document.title and space normalization ]
expected: FAIL

Просмотреть файл

@ -1,5 +0,0 @@
[document.title-04.xhtml]
type: testharness
[ document.title and space normalization ]
expected: FAIL

Просмотреть файл

@ -1,5 +0,0 @@
[document.title-07.html]
type: testharness
[createHTMLDocument test 6: "foo\\f\\fbar baz","foo\\f\\fbar baz","foo bar baz"]
expected: FAIL

Просмотреть файл

@ -10,11 +10,9 @@
expected:
if not debug and e10s and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86") and (bits == 32): NOTRUN
if debug and e10s and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86") and (bits == 32): NOTRUN
FAIL
[focusing on a focusable element fires a blur event at the previous focussed element]
expected:
if not debug and e10s and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86") and (bits == 32): NOTRUN
if debug and e10s and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86") and (bits == 32): NOTRUN
FAIL

Просмотреть файл

@ -1,41 +0,0 @@
[option-text-spaces.html]
type: testharness
[option.text should strip leading space characters ("\\f")]
expected: FAIL
[option.text should strip trailing space characters ("\\f")]
expected: FAIL
[option.text should strip leading and trailing space characters ("\\f")]
expected: FAIL
[option.text should replace single internal space characters ("\\f")]
expected: FAIL
[option.text should replace multiple internal space characters (" ", "\\f")]
expected: FAIL
[option.text should replace multiple internal space characters ("\\t", "\\f")]
expected: FAIL
[option.text should replace multiple internal space characters ("\\n", "\\f")]
expected: FAIL
[option.text should replace multiple internal space characters ("\\f", " ")]
expected: FAIL
[option.text should replace multiple internal space characters ("\\f", "\\t")]
expected: FAIL
[option.text should replace multiple internal space characters ("\\f", "\\n")]
expected: FAIL
[option.text should replace multiple internal space characters ("\\f", "\\f")]
expected: FAIL
[option.text should replace multiple internal space characters ("\\f", "\\r")]
expected: FAIL
[option.text should replace multiple internal space characters ("\\r", "\\f")]
expected: FAIL

Просмотреть файл

@ -94,6 +94,29 @@ WebRequestEventManager.prototype = Object.create(SingletonEventManager.prototype
extensions.registerPrivilegedAPI("webRequest", (extension, context) => {
return {
webRequest: {
ResourceType: {
MAIN_FRAME: "main_frame",
SUB_FRAME: "sub_frame",
STYLESHEET: "stylesheet",
SCRIPT: "script",
IMAGE: "image",
OBJECT: "object",
OBJECT_SUBREQUEST: "object_subrequest",
XMLHTTPREQUEST: "xmlhttprequest",
XBL: "xbl",
XSLT: "xslt",
PING: "ping",
BEACON: "beacon",
XML_DTD: "xml_dtd",
FONT: "font",
MEDIA: "media",
WEBSOCKET: "websocket",
CSP_REPORT: "csp_report",
IMAGESET: "imageset",
WEB_MANIFEST: "web_manifest",
OTHER: "other",
},
onBeforeRequest: new WebRequestEventManager(context, "onBeforeRequest").api(),
onBeforeSendHeaders: new WebRequestEventManager(context, "onBeforeSendHeaders").api(),
onSendHeaders: new WebRequestEventManager(context, "onSendHeaders").api(),

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше