diff --git a/README.md b/README.md
index c246a14f50..6ac2499562 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
-Official Discord server
+Official Discord server | Official Telegram channel
diff --git a/browser/base/content/browser-places.js b/browser/base/content/browser-places.js
index 9e472ad6e4..e2408aaf8f 100644
--- a/browser/base/content/browser-places.js
+++ b/browser/base/content/browser-places.js
@@ -1731,14 +1731,14 @@ var BookmarkingUI = {
if (this._itemIds.length > 0) {
this.broadcaster.setAttribute("starred", "true");
this.broadcaster.setAttribute("buttontooltiptext", this._starredTooltip);
- if (this.button.getAttribute("overflowedItem") == "true") {
+ if (this.button && this.button.getAttribute("overflowedItem") == "true") {
this.button.setAttribute("label", this._starButtonOverflowedStarredLabel);
}
}
else {
this.broadcaster.removeAttribute("starred");
this.broadcaster.setAttribute("buttontooltiptext", this._unstarredTooltip);
- if (this.button.getAttribute("overflowedItem") == "true") {
+ if (this.button && this.button.getAttribute("overflowedItem") == "true") {
this.button.setAttribute("label", this._starButtonOverflowedLabel);
}
}
diff --git a/browser/base/content/tab-content.js b/browser/base/content/tab-content.js
index fd4612cc4d..a7b62d753c 100644
--- a/browser/base/content/tab-content.js
+++ b/browser/base/content/tab-content.js
@@ -133,8 +133,12 @@ var AboutHomeListener = {
onUpdate: function(aData) {
let doc = content.document;
- if (aData.showRestoreLastSession && !PrivateBrowsingUtils.isContentWindowPrivate(content))
- doc.getElementById("launcher").setAttribute("session", "true");
+ if (aData.showRestoreLastSession && !PrivateBrowsingUtils.isContentWindowPrivate(content)) {
+ let launcher = doc.getElementById("launcher");
+ if (launcher) {
+ launcher.setAttribute("session", "true");
+ }
+ }
// Inject search engine URL.
let docElt = doc.documentElement;
diff --git a/browser/base/content/tabbrowser.xml b/browser/base/content/tabbrowser.xml
index 4600cfefd3..9c2a8b019b 100644
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -2920,6 +2920,18 @@
// Finish tearing down the tab that's going away.
remoteBrowser._endRemoveTab(aOtherTab);
+ // Notify WebExtensions when one tab is replaced by another. Tab
+ // adoption uses this same swap internally, but represents a move
+ // and is marked below so it does not generate a replacement event.
+ if (!aOurTab._adoptingTab) {
+ let event = new CustomEvent("TabReplaced", {
+ bubbles: true,
+ detail: {addedTab: aOurTab, removedTab: aOtherTab},
+ });
+ aOurTab.dispatchEvent(event);
+ }
+ delete aOurTab._adoptingTab;
+
if (isBusy)
this.setTabTitleLoading(aOurTab);
else
@@ -3359,6 +3371,7 @@
params.userContextId = aTab.getAttribute("usercontextid");
}
let newTab = this.addTab("about:blank", params);
+ newTab._adoptingTab = aTab;
let newBrowser = this.getBrowserForTab(newTab);
let newURL = aTab.linkedBrowser.currentURI.spec;
diff --git a/browser/components/nsBrowserGlue.js b/browser/components/nsBrowserGlue.js
index a9d95bb0cf..f25c6c0d67 100644
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -406,7 +406,7 @@ BrowserGlue.prototype = {
os.addObserver(this, "flash-plugin-hang", false);
os.addObserver(this, "xpi-signature-changed", false);
os.addObserver(this, "autocomplete-did-enter-text", false);
- Services.prefs.addObserver(PREF_INTERNAL_USERSCRIPTS_ENABLED, this);
+ Services.prefs.addObserver(PREF_INTERNAL_USERSCRIPTS_ENABLED, this, false);
if (AppConstants.NIGHTLY_BUILD) {
os.addObserver(this, AddonWatcher.TOPIC_SLOW_ADDON_DETECTED, false);
diff --git a/browser/components/webextensions/ext-browserAction.js b/browser/components/webextensions/ext-browserAction.js
index 981885052d..ebd9f14ed8 100644
--- a/browser/components/webextensions/ext-browserAction.js
+++ b/browser/components/webextensions/ext-browserAction.js
@@ -68,6 +68,13 @@ function BrowserAction(options, extension) {
"or not in your browser_action options.");
}
+ this.defaultArea = {
+ navbar: CustomizableUI.AREA_NAVBAR,
+ menupanel: CustomizableUI.AREA_PANEL,
+ tabstrip: CustomizableUI.AREA_TABSTRIP,
+ personaltoolbar: CustomizableUI.AREA_BOOKMARKS,
+ }[options.default_area] || CustomizableUI.AREA_NAVBAR;
+
this.tabContext = new TabContext(tab => Object.create(this.defaults),
extension);
@@ -83,7 +90,7 @@ BrowserAction.prototype = {
removable: true,
label: this.defaults.title || this.extension.name,
tooltiptext: this.defaults.title || "",
- defaultArea: CustomizableUI.AREA_NAVBAR,
+ defaultArea: this.defaultArea,
onBeforeCreated: document => {
let view = document.createElementNS(XUL_NS, "panelview");
@@ -146,7 +153,7 @@ BrowserAction.prototype = {
// Ensure browser actions remain discoverable in the main toolbar while
// respecting an existing user-selected placement.
if (!CustomizableUI.getPlacementOfWidget(this.id)) {
- CustomizableUI.addWidgetToArea(this.id, CustomizableUI.AREA_NAVBAR);
+ CustomizableUI.addWidgetToArea(this.id, this.defaultArea);
}
this.tabContext.on("tab-select", // eslint-disable-line mozilla/balanced-listeners
diff --git a/browser/components/webextensions/ext-desktop-runtime.js b/browser/components/webextensions/ext-desktop-runtime.js
index 0fdb455621..7a48969513 100644
--- a/browser/components/webextensions/ext-desktop-runtime.js
+++ b/browser/components/webextensions/ext-desktop-runtime.js
@@ -15,7 +15,8 @@ global.openOptionsPage = (extension) => {
}
if (extension.manifest.options_ui.open_in_tab) {
- window.switchToTabHavingURI(extension.manifest.options_ui.page, true);
+ let optionsURL = extension.baseURI.resolve(extension.manifest.options_ui.page);
+ window.switchToTabHavingURI(optionsURL, true);
return Promise.resolve();
}
@@ -23,4 +24,3 @@ global.openOptionsPage = (extension) => {
return window.BrowserOpenAddonsMgr(viewId);
};
-
diff --git a/browser/components/webextensions/ext-tabs.js b/browser/components/webextensions/ext-tabs.js
index 580282b934..cd9f8873ac 100644
--- a/browser/components/webextensions/ext-tabs.js
+++ b/browser/components/webextensions/ext-tabs.js
@@ -103,6 +103,7 @@ let tabListener = {
AllWindowEvents.addListener("TabClose", this);
AllWindowEvents.addListener("TabOpen", this);
+ AllWindowEvents.addListener("TabReplaced", this);
WindowListManager.addOpenListener(this.handleWindowOpen);
WindowListManager.addCloseListener(this.handleWindowClose);
@@ -138,6 +139,10 @@ let tabListener = {
this.emitRemoved(tab, false);
}
break;
+
+ case "TabReplaced":
+ this.emitReplaced(event.detail.addedTab, event.detail.removedTab);
+ break;
}
},
@@ -220,6 +225,13 @@ let tabListener = {
}, Ci.nsIThread.DISPATCH_NORMAL);
},
+ emitReplaced(addedTab, removedTab) {
+ this.emit("tab-replaced", {
+ addedTabId: TabManager.getId(addedTab),
+ removedTabId: TabManager.getId(removedTab),
+ });
+ },
+
tabReadyInitialized: false,
tabReadyPromises: new WeakMap(),
initializingTabs: new WeakSet(),
@@ -347,7 +359,15 @@ extensions.registerSchemaAPI("tabs", "addon_parent", context => {
};
}).api(),
- onReplaced: ignoreEvent(context, "tabs.onReplaced"),
+ onReplaced: new EventManager(context, "tabs.onReplaced", fire => {
+ let listener = (eventName, event) => {
+ fire(event.addedTabId, event.removedTabId);
+ };
+ tabListener.on("tab-replaced", listener);
+ return () => {
+ tabListener.off("tab-replaced", listener);
+ };
+ }).api(),
onMoved: new EventManager(context, "tabs.onMoved", fire => {
// There are certain circumstances where we need to ignore a move event.
diff --git a/browser/components/webextensions/schemas/browser_action.json b/browser/components/webextensions/schemas/browser_action.json
index 1a7da956a1..854a3bebbf 100644
--- a/browser/components/webextensions/schemas/browser_action.json
+++ b/browser/components/webextensions/schemas/browser_action.json
@@ -31,6 +31,11 @@
"browser_style": {
"type": "boolean",
"optional": true
+ },
+ "default_area": {
+ "type": "string",
+ "enum": ["navbar", "menupanel", "tabstrip", "personaltoolbar"],
+ "optional": true
}
},
"optional": true
diff --git a/browser/components/webextensions/schemas/context_menus.json b/browser/components/webextensions/schemas/context_menus.json
index b31af51f3f..ae8d0c01d8 100644
--- a/browser/components/webextensions/schemas/context_menus.json
+++ b/browser/components/webextensions/schemas/context_menus.json
@@ -20,7 +20,7 @@
{
"namespace": "contextMenus",
"description": "Use the browser.contextMenus API to add items to the browser's context menu. You can choose what types of objects your context menu additions apply to, such as images, hyperlinks, and pages.",
- "permissions": ["contextMenus"],
+ "permissions": ["contextMenus", "menus"],
"properties": {
"ACTION_MENU_TOP_LEVEL_LIMIT": {
"value": 6,
diff --git a/browser/internaluserscripts/components/internaluserscripts.js b/browser/internaluserscripts/components/internaluserscripts.js
index 8876acaac7..7469ed2e26 100644
--- a/browser/internaluserscripts/components/internaluserscripts.js
+++ b/browser/internaluserscripts/components/internaluserscripts.js
@@ -106,9 +106,17 @@ InternalUserscriptsService.prototype = {
// The codec shim is deliberately limited to YouTube. Use the browser's
// decoder probe rather than guessing from the user's graphics settings.
- if (documentURI &&
- documentURI.host &&
- /(^|\.)youtube(?:-nocookie)?\.com$/i.test(documentURI.host)) {
+ let documentHost = null;
+ try {
+ // nsIURI.host is not implemented by hostless URI schemes (about:, data:,
+ // moz-extension:, and others), so reading it can throw.
+ if (documentURI) {
+ documentHost = documentURI.host;
+ }
+ } catch (e) {}
+
+ if (documentHost &&
+ /(^|\.)youtube(?:-nocookie)?\.com$/i.test(documentHost)) {
let settings = {
hideUnaccelerated: Services.prefs.getBoolPref(
"browser.video.youtube.hide-unaccelerated", true),
diff --git a/dom/indexedDB/IDBRequest.cpp b/dom/indexedDB/IDBRequest.cpp
index 06e8b80a50..f0e38a800c 100644
--- a/dom/indexedDB/IDBRequest.cpp
+++ b/dom/indexedDB/IDBRequest.cpp
@@ -46,6 +46,28 @@ namespace {
NS_DEFINE_IID(kIDBRequestIID, PRIVATE_IDBREQUEST_IID);
+bool
+IsExtensionDatabase(IDBTransaction* aTransaction)
+{
+ if (!aTransaction || !aTransaction->Database()) {
+ return false;
+ }
+
+ IDBFactory* factory = aTransaction->Database()->Factory();
+ if (!factory || !factory->GetPrincipalInfo()) {
+ return false;
+ }
+
+ const PrincipalInfo* principalInfo = factory->GetPrincipalInfo();
+ if (principalInfo->type() != PrincipalInfo::TContentPrincipalInfo) {
+ return false;
+ }
+
+ return StringBeginsWith(
+ principalInfo->get_ContentPrincipalInfo().originNoSuffix(),
+ NS_LITERAL_CSTRING("moz-extension://"));
+}
+
} // namespace
IDBRequest::IDBRequest(IDBDatabase* aDatabase)
@@ -389,6 +411,20 @@ IDBRequest::SetResultCallback(ResultCallback* aCallback)
// as NS_ERROR_DOM_DATA_CLONE_ERR here.
MOZ_ASSERT(rv == NS_ERROR_DOM_DATA_CLONE_ERR);
+ // Legacy WebExtension caches may contain structured-clone values that
+ // this older IndexedDB implementation cannot materialize (uBO discards
+ // these records while migrating its disposable cache). Treat such a
+ // record as absent so the extension can use its storage.local fallback.
+ // Keep the standards-required failure behavior for regular web origins.
+ if (rv == NS_ERROR_DOM_DATA_CLONE_ERR &&
+ IsExtensionDatabase(mTransaction)) {
+ JS_ClearPendingException(cx);
+ mError = nullptr;
+ mResultVal.setUndefined();
+ mHaveResultOrErrorCode = true;
+ return;
+ }
+
// We are not setting a result or an error object here since we want to
// throw an exception when the 'result' property is being touched.
return;
diff --git a/js/src/builtin/TypedObject.cpp b/js/src/builtin/TypedObject.cpp
index c2517abde2..10ae8902dd 100644
--- a/js/src/builtin/TypedObject.cpp
+++ b/js/src/builtin/TypedObject.cpp
@@ -2040,7 +2040,7 @@ InlineTypedObject::createCopy(JSContext* cx, Handle template
if (!res)
return nullptr;
- js_memcpy(res->inlineTypedMem(), templateObject->inlineTypedMem(), templateObject->size());
+ memcpy(res->inlineTypedMem(), templateObject->inlineTypedMem(), templateObject->size());
return res;
}
@@ -2767,7 +2767,7 @@ TypeDescr::initInstances(const JSRuntime* rt, uint8_t* mem, size_t length)
MemoryInitVisitor visitor(rt);
// Initialize the 0th instance
- js_memset(mem, 0, size());
+ memset(mem, 0, size());
if (opaque())
visitReferences(*this, mem, visitor);
@@ -2775,7 +2775,7 @@ TypeDescr::initInstances(const JSRuntime* rt, uint8_t* mem, size_t length)
uint8_t* target = mem;
for (size_t i = 1; i < length; i++) {
target += size();
- js_memcpy(target, mem, size());
+ memcpy(target, mem, size());
}
}
diff --git a/js/src/irregexp/RegExpInterpreter.cpp b/js/src/irregexp/RegExpInterpreter.cpp
index f7f7f6eeb7..f53acfb606 100644
--- a/js/src/irregexp/RegExpInterpreter.cpp
+++ b/js/src/irregexp/RegExpInterpreter.cpp
@@ -31,7 +31,6 @@
#include "irregexp/RegExpBytecode.h"
#include "irregexp/RegExpMacroAssembler.h"
-#include "jsutil.h"
#include "vm/MatchPairs.h"
using namespace js;
@@ -198,8 +197,7 @@ irregexp::InterpretCode(JSContext* cx, const uint8_t* byteCode, const CharT* cha
return RegExpRunStatus_Success_NotFound;
BYTECODE(SUCCEED)
if (matches)
- js_memcpy(matches->pairsRaw(), registers.begin(),
- matches->length() * 2 * sizeof(int32_t));
+ memcpy(matches->pairsRaw(), registers.begin(), matches->length() * 2 * sizeof(int32_t));
else if (endIndex)
*endIndex = registers[1];
return RegExpRunStatus_Success;
diff --git a/js/src/jit-test/tests/latin1/sse2-search.js b/js/src/jit-test/tests/latin1/sse2-search.js
index 1bf2f70ea1..064e802b87 100644
--- a/js/src/jit-test/tests/latin1/sse2-search.js
+++ b/js/src/jit-test/tests/latin1/sse2-search.js
@@ -19,21 +19,3 @@ for (var length of [0, 1, 7, 8, 9, 15, 16, 17, 31, 32, 33, 63, 64, 65]) {
assertEq(wide.indexOf("\xff"), length + 1);
assertEq(wide.indexOf(latin1), 1);
}
-
-// Mixed-encoding searches should use the same SIMD first-character scan, and
-// an impossible UTF-16 character should reject a Latin-1 haystack immediately.
-var latin1Haystack = "x".repeat(4096);
-assertEq(latin1Haystack.indexOf("x\u0100x"), -1);
-var wideHaystack = "\u0100" + "x".repeat(4096) + "needle";
-assertEq(wideHaystack.indexOf("needle"), 4097);
-
-// Exercise the mixed-width EqualChars fast path through string equality.
-var wideLatin1 = ("\u0100" + latin1Haystack).slice(1);
-assertEq(wideLatin1, latin1Haystack);
-assertEq(wideLatin1 + "y", latin1Haystack + "z");
-assertEq(wideLatin1 + "\u0100" > latin1Haystack + "z", true);
-assertEq(latin1Haystack + "z" < wideLatin1 + "\u0100", true);
-
-assertEq(latin1Haystack.lastIndexOf("x\u0100x"), -1);
-assertEq(wideHaystack.lastIndexOf("needle"), 4097);
-assertEq(wideHaystack.lastIndexOf("x"), 4096);
diff --git a/js/src/jit/BaselineBailouts.cpp b/js/src/jit/BaselineBailouts.cpp
index 073f198288..be69f3f1ee 100644
--- a/js/src/jit/BaselineBailouts.cpp
+++ b/js/src/jit/BaselineBailouts.cpp
@@ -150,7 +150,7 @@ struct BaselineStackBuilder
uint8_t* newBuffer = reinterpret_cast(js_calloc(newSize));
if (!newBuffer)
return false;
- js_memcpy((newBuffer + newSize) - bufferUsed_, header_->copyStackBottom, bufferUsed_);
+ memcpy((newBuffer + newSize) - bufferUsed_, header_->copyStackBottom, bufferUsed_);
memcpy(newBuffer, header_, sizeof(BaselineBailoutInfo));
js_free(buffer_);
buffer_ = newBuffer;
diff --git a/js/src/jit/BaselineJIT.cpp b/js/src/jit/BaselineJIT.cpp
index adf6f7590c..70f7c79eb8 100644
--- a/js/src/jit/BaselineJIT.cpp
+++ b/js/src/jit/BaselineJIT.cpp
@@ -18,7 +18,6 @@
#include "vm/Interpreter.h"
#include "vm/TraceLogging.h"
#include "wasm/WasmInstance.h"
-#include "jsutil.h"
#include "jsobjinlines.h"
#include "jsopcodeinlines.h"
@@ -813,7 +812,7 @@ BaselineScript::copyPCMappingEntries(const CompactBufferWriter& entries)
MOZ_ASSERT(entries.length() > 0);
MOZ_ASSERT(entries.length() == pcMappingSize_);
- js_memcpy(pcMappingData(), entries.buffer(), entries.length());
+ memcpy(pcMappingData(), entries.buffer(), entries.length());
}
void
diff --git a/js/src/jit/CompileInfo.h b/js/src/jit/CompileInfo.h
index 36b06571db..f10d09e410 100644
--- a/js/src/jit/CompileInfo.h
+++ b/js/src/jit/CompileInfo.h
@@ -442,18 +442,14 @@ class CompileInfo
// the frame is active on the stack. This implies that these definitions
// would have to be executed and that they cannot be removed even if they
// are unused.
- inline bool isObservableSlot(uint32_t slot) const {
- if (slot >= firstLocalSlot()) {
- // The |this| slot for a derived class constructor is a local slot.
- if (thisSlotForDerivedClassConstructor_)
- return *thisSlotForDerivedClassConstructor_ == slot;
- return false;
- }
+ bool isObservableSlot(uint32_t slot) const {
+ if (isObservableFrameSlot(slot))
+ return true;
- if (slot < firstArgSlot())
- return isObservableFrameSlot(slot);
+ if (isObservableArgumentSlot(slot))
+ return true;
- return isObservableArgumentSlot(slot);
+ return false;
}
bool isObservableFrameSlot(uint32_t slot) const {
diff --git a/js/src/jit/Ion.cpp b/js/src/jit/Ion.cpp
index 4ee44ba576..8e28a93c0e 100644
--- a/js/src/jit/Ion.cpp
+++ b/js/src/jit/Ion.cpp
@@ -13,7 +13,6 @@
#include "jscompartment.h"
#include "jsgc.h"
#include "jsprf.h"
-#include "jsutil.h"
#include "gc/Marking.h"
#include "jit/AliasAnalysis.h"
@@ -1043,33 +1042,33 @@ void
IonScript::copySnapshots(const SnapshotWriter* writer)
{
MOZ_ASSERT(writer->listSize() == snapshotsListSize_);
- js_memcpy((uint8_t*)this + snapshots_,
- writer->listBuffer(), snapshotsListSize_);
+ memcpy((uint8_t*)this + snapshots_,
+ writer->listBuffer(), snapshotsListSize_);
MOZ_ASSERT(snapshotsRVATableSize_);
MOZ_ASSERT(writer->RVATableSize() == snapshotsRVATableSize_);
- js_memcpy((uint8_t*)this + snapshots_ + snapshotsListSize_,
- writer->RVATableBuffer(), snapshotsRVATableSize_);
+ memcpy((uint8_t*)this + snapshots_ + snapshotsListSize_,
+ writer->RVATableBuffer(), snapshotsRVATableSize_);
}
void
IonScript::copyRecovers(const RecoverWriter* writer)
{
MOZ_ASSERT(writer->size() == recoversSize_);
- js_memcpy((uint8_t*)this + recovers_, writer->buffer(), recoversSize_);
+ memcpy((uint8_t*)this + recovers_, writer->buffer(), recoversSize_);
}
void
IonScript::copySafepoints(const SafepointWriter* writer)
{
MOZ_ASSERT(writer->size() == safepointsSize_);
- js_memcpy((uint8_t*)this + safepointsStart_, writer->buffer(), safepointsSize_);
+ memcpy((uint8_t*)this + safepointsStart_, writer->buffer(), safepointsSize_);
}
void
IonScript::copyBailoutTable(const SnapshotOffset* table)
{
- js_memcpy(bailoutTable(), table, bailoutEntries_ * sizeof(uint32_t));
+ memcpy(bailoutTable(), table, bailoutEntries_ * sizeof(uint32_t));
}
void
@@ -1115,25 +1114,25 @@ IonScript::copySafepointIndices(const SafepointIndex* si, MacroAssembler& masm)
// code, not the absolute positions of the jumps. Update according to the
// final code address now.
SafepointIndex* table = safepointIndices();
- js_memcpy(table, si, safepointIndexEntries_ * sizeof(SafepointIndex));
+ memcpy(table, si, safepointIndexEntries_ * sizeof(SafepointIndex));
}
void
IonScript::copyOsiIndices(const OsiIndex* oi, MacroAssembler& masm)
{
- js_memcpy(osiIndices(), oi, osiIndexEntries_ * sizeof(OsiIndex));
+ memcpy(osiIndices(), oi, osiIndexEntries_ * sizeof(OsiIndex));
}
void
IonScript::copyRuntimeData(const uint8_t* data)
{
- js_memcpy(runtimeData(), data, runtimeSize());
+ memcpy(runtimeData(), data, runtimeSize());
}
void
IonScript::copyCacheEntries(const uint32_t* caches, MacroAssembler& masm)
{
- js_memcpy(cacheIndex(), caches, numCaches() * sizeof(uint32_t));
+ memcpy(cacheIndex(), caches, numCaches() * sizeof(uint32_t));
// Jumps in the caches reflect the offset of those jumps in the compiled
// code, not the absolute positions of the jumps. Update according to the
diff --git a/js/src/jit/IonAnalysis.cpp b/js/src/jit/IonAnalysis.cpp
index 6d0b8deaf1..6f424098e8 100644
--- a/js/src/jit/IonAnalysis.cpp
+++ b/js/src/jit/IonAnalysis.cpp
@@ -196,8 +196,6 @@ FlagPhiInputsAsHavingRemovedUses(MIRGenerator* mir, MBasicBlock* block, MBasicBl
static bool
FlagAllOperandsAsHavingRemovedUses(MIRGenerator* mir, MBasicBlock* block)
{
- const CompileInfo& info = block->info();
-
// Flag all instructions operands as having removed uses.
MInstructionIterator end = block->end();
for (MInstructionIterator it = block->begin(); it != end; it++) {
@@ -216,7 +214,7 @@ FlagAllOperandsAsHavingRemovedUses(MIRGenerator* mir, MBasicBlock* block)
if (mir->shouldCancel("FlagAllOperandsAsHavingRemovedUses inner loop"))
return false;
- if (!info.isObservableSlot(i))
+ if (!rp->isObservableOperand(i))
continue;
rp->getOperand(i)->setUseRemovedUnchecked();
}
@@ -229,9 +227,8 @@ FlagAllOperandsAsHavingRemovedUses(MIRGenerator* mir, MBasicBlock* block)
if (mir->shouldCancel("FlagAllOperandsAsHavingRemovedUses loop 2"))
return false;
- const CompileInfo& info = rp->block()->info();
for (size_t i = 0, e = rp->numOperands(); i < e; i++) {
- if (!info.isObservableSlot(i))
+ if (!rp->isObservableOperand(i))
continue;
rp->getOperand(i)->setUseRemovedUnchecked();
}
diff --git a/js/src/jit/shared/CodeGenerator-shared.cpp b/js/src/jit/shared/CodeGenerator-shared.cpp
index 3e86fe87b6..78f66bb9da 100644
--- a/js/src/jit/shared/CodeGenerator-shared.cpp
+++ b/js/src/jit/shared/CodeGenerator-shared.cpp
@@ -16,7 +16,6 @@
#include "jit/MIR.h"
#include "jit/MIRGenerator.h"
#include "jit/OptimizationTracking.h"
-#include "jsutil.h"
#include "js/Conversions.h"
#include "vm/TraceLogging.h"
@@ -755,7 +754,7 @@ CodeGeneratorShared::generateCompactNativeToBytecodeMap(JSContext* cx, JitCode*
return false;
}
- js_memcpy(data, writer.buffer(), writer.length());
+ memcpy(data, writer.buffer(), writer.length());
nativeToBytecodeMap_ = data;
nativeToBytecodeMapSize_ = writer.length();
nativeToBytecodeTableOffset_ = tableOffset;
@@ -909,7 +908,7 @@ CodeGeneratorShared::generateCompactTrackedOptimizationsMap(JSContext* cx, JitCo
if (!data)
return false;
- js_memcpy(data, writer.buffer(), writer.length());
+ memcpy(data, writer.buffer(), writer.length());
trackedOptimizationsMap_ = data;
trackedOptimizationsMapSize_ = writer.length();
trackedOptimizationsRegionTableOffset_ = regionTableOffset;
diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp
index 07a80026ca..3ea147eaff 100644
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -6005,7 +6005,7 @@ EncodeLatin1(ExclusiveContext* cx, JSString* str)
return nullptr;
}
- js_memcpy(buf, linear->latin1Chars(nogc), len);
+ mozilla::PodCopy(buf, linear->latin1Chars(nogc), len);
buf[len] = '\0';
return reinterpret_cast(buf);
}
diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp
index fc2871c70f..15cb23a213 100644
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -153,21 +153,6 @@ StringIsArrayIndex(const CharT* s, uint32_t length, uint32_t* indexp)
if (length == 0 || length > (sizeof("4294967294") - 1) || !JS7_ISDEC(*s))
return false;
- // Small indices are by far the most common property keys. Handle them
- // without entering the general overflow-checking loop below.
- if (length == 1) {
- *indexp = JS7_UNDEC(*s);
- return true;
- }
-
- if (length == 2) {
- uint32_t first = JS7_UNDEC(s[0]);
- if (first == 0 || !JS7_ISDEC(s[1]))
- return false;
- *indexp = first * 10 + JS7_UNDEC(s[1]);
- return true;
- }
-
uint32_t c = 0, previous = 0;
uint32_t index = JS7_UNDEC(*s++);
@@ -2212,7 +2197,7 @@ ShiftMoveBoxedOrUnboxedDenseElements(JSObject* obj)
} else {
uint8_t* data = obj->as().elements();
size_t elementSize = UnboxedTypeSize(Type);
- js_memmove(data, data + elementSize, initlen * elementSize);
+ memmove(data, data + elementSize, initlen * elementSize);
}
return DenseElementResult::Success;
diff --git a/js/src/jsatominlines.h b/js/src/jsatominlines.h
index 2af4b7355d..ab91f974d1 100644
--- a/js/src/jsatominlines.h
+++ b/js/src/jsatominlines.h
@@ -8,6 +8,7 @@
#include "jsatom.h"
+#include "mozilla/PodOperations.h"
#include "mozilla/RangedPtr.h"
#include "jscntxt.h"
@@ -176,14 +177,14 @@ AtomHasher::match(const AtomStateEntry& entry, const Lookup& lookup)
if (key->hasLatin1Chars()) {
const Latin1Char* keyChars = key->latin1Chars(lookup.nogc);
if (lookup.isLatin1)
- return EqualChars(keyChars, lookup.latin1Chars, lookup.length);
+ return mozilla::PodEqual(keyChars, lookup.latin1Chars, lookup.length);
return EqualChars(keyChars, lookup.twoByteChars, lookup.length);
}
const char16_t* keyChars = key->twoByteChars(lookup.nogc);
if (lookup.isLatin1)
return EqualChars(lookup.latin1Chars, keyChars, lookup.length);
- return EqualChars(keyChars, lookup.twoByteChars, lookup.length);
+ return mozilla::PodEqual(keyChars, lookup.twoByteChars, lookup.length);
}
inline Handle
diff --git a/js/src/jsfriendapi.h b/js/src/jsfriendapi.h
index ef89efc8b8..2697cb5337 100644
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -12,8 +12,6 @@
#include "mozilla/MemoryReporting.h"
#include "mozilla/UniquePtr.h"
-#include
-
#include "jsapi.h" // For JSAutoByteString. See bug 1033916.
#include "jsbytecode.h"
#include "jspubtd.h"
@@ -23,12 +21,6 @@
#include "js/Class.h"
#include "js/Utility.h"
-#if defined(__SSE2__) || defined(_M_X64) || \
- (defined(_M_IX86_FP) && _M_IX86_FP >= 2)
-# define JS_FRIENDAPI_USE_SSE2_CHARACTER_OPERATIONS
-# include
-#endif
-
#if JS_STACK_GROWTH_DIRECTION > 0
# define JS_CHECK_STACK_SIZE(limit, sp) (MOZ_LIKELY((uintptr_t)(sp) < (limit)))
#else
@@ -885,21 +877,8 @@ CopyLinearStringChars(char16_t* dest, JSLinearString* s, size_t len, size_t star
JS::AutoCheckCannotGC nogc;
if (LinearStringHasLatin1Chars(s)) {
const JS::Latin1Char* src = GetLatin1LinearStringChars(nogc, s);
-#if defined(JS_FRIENDAPI_USE_SSE2_CHARACTER_OPERATIONS)
- size_t i = 0;
- const __m128i zero = _mm_setzero_si128();
- for (; i + 8 <= len; i += 8) {
- const __m128i bytes8 = _mm_loadl_epi64(
- reinterpret_cast(src + start + i));
- _mm_storeu_si128(reinterpret_cast<__m128i*>(dest + i),
- _mm_unpacklo_epi8(bytes8, zero));
- }
- for (; i < len; i++)
- dest[i] = src[start + i];
-#else
for (size_t i = 0; i < len; i++)
dest[i] = src[start + i];
-#endif
} else {
const char16_t* src = GetTwoByteLinearStringChars(nogc, s);
mozilla::PodCopy(dest, src + start, len);
@@ -913,26 +892,12 @@ CopyLinearStringChars(char* dest, JSLinearString* s, size_t len, size_t start =
JS::AutoCheckCannotGC nogc;
if (LinearStringHasLatin1Chars(s)) {
const JS::Latin1Char* src = GetLatin1LinearStringChars(nogc, s);
- memcpy(dest, src + start, len);
+ for (size_t i = 0; i < len; i++)
+ dest[i] = char(src[start + i]);
} else {
const char16_t* src = GetTwoByteLinearStringChars(nogc, s);
-#if defined(JS_FRIENDAPI_USE_SSE2_CHARACTER_OPERATIONS)
- size_t i = 0;
- const __m128i lowByteMask = _mm_set1_epi16(0xff);
- const __m128i zero = _mm_setzero_si128();
- for (; i + 8 <= len; i += 8) {
- const __m128i wide = _mm_loadu_si128(
- reinterpret_cast(src + start + i));
- const __m128i lowBytes = _mm_and_si128(wide, lowByteMask);
- _mm_storel_epi64(reinterpret_cast<__m128i*>(dest + i),
- _mm_packus_epi16(lowBytes, zero));
- }
- for (; i < len; i++)
- dest[i] = char(src[start + i]);
-#else
for (size_t i = 0; i < len; i++)
dest[i] = char(src[start + i]);
-#endif
}
}
@@ -3074,8 +3039,4 @@ class MemProfiler
}
};
-#ifdef JS_FRIENDAPI_USE_SSE2_CHARACTER_OPERATIONS
-# undef JS_FRIENDAPI_USE_SSE2_CHARACTER_OPERATIONS
-#endif
-
#endif /* jsfriendapi_h */
diff --git a/js/src/jsobjinlines.h b/js/src/jsobjinlines.h
index bb29474d34..a27a13fd6c 100644
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -12,7 +12,6 @@
#include "jsfriendapi.h"
#include "jsfun.h"
-#include "jsutil.h"
#include "builtin/MapObject.h"
#include "builtin/TypedObject.h"
@@ -402,7 +401,7 @@ JSObject::create(js::ExclusiveContext* cx, js::gc::AllocKind kind, js::gc::Initi
kind == js::gc::AllocKind::FUNCTION_EXTENDED);
size_t size =
kind == js::gc::AllocKind::FUNCTION ? sizeof(JSFunction) : sizeof(js::FunctionExtended);
- js_memset(obj->as().fixedSlots(), 0, size - sizeof(js::NativeObject));
+ memset(obj->as().fixedSlots(), 0, size - sizeof(js::NativeObject));
if (kind == js::gc::AllocKind::FUNCTION_EXTENDED) {
// SetNewObjectMetadata may gc, which will be unhappy if flags &
// EXTENDED doesn't match the arena's AllocKind.
diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp
index 3e76e39522..ca51bb1b19 100644
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -3530,7 +3530,7 @@ js::detail::CopyScript(JSContext* cx, HandleScript src, HandleScript dst,
dst->dataSize_ = size;
MOZ_ASSERT(bool(dst->data) == bool(src->data));
if (dst->data)
- js_memcpy(dst->data, src->data, size);
+ memcpy(dst->data, src->data, size);
/* Script filenames, bytecodes and atoms are runtime-wide. */
dst->setScriptData(src->scriptData());
diff --git a/js/src/jsstr.cpp b/js/src/jsstr.cpp
index e78d626834..d8374e8e43 100644
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -68,6 +68,7 @@ using mozilla::IsNegativeZero;
using mozilla::IsSame;
using mozilla::Move;
using mozilla::PodCopy;
+using mozilla::PodEqual;
using mozilla::RangedPtr;
using JS::AutoCheckCannotGC;
@@ -1084,18 +1085,6 @@ ToUpperCaseLength(const CharT* chars, size_t startIndex, size_t length)
return upperLength;
}
-static inline void
-CopyChars(char16_t* destChars, const char* srcChars, size_t length)
-{
- CopyAndInflateChars(destChars, srcChars, length);
-}
-
-static inline void
-CopyChars(char16_t* destChars, const Latin1Char* srcChars, size_t length)
-{
- CopyAndInflateChars(destChars, srcChars, length);
-}
-
template
static inline void
CopyChars(DestChar* destChars, const SrcChar* srcChars, size_t length)
@@ -1717,16 +1706,6 @@ template
static int
Matcher(const TextChar* text, uint32_t textlen, const PatChar* pat, uint32_t patlen)
{
- // A Latin-1 string can never contain a UTF-16 code unit above 0xff. Do
- // this check once instead of repeatedly testing every candidate position
- // in the mixed-encoding matcher. This is particularly useful for search
- // strings containing supplementary-plane or otherwise non-Latin-1 text.
- if (sizeof(TextChar) == 1 && sizeof(PatChar) == 2 &&
- !CharactersFitInLatin1(reinterpret_cast(pat), patlen))
- {
- return -1;
- }
-
const typename InnerMatch::Extent extent = InnerMatch::computeExtent(pat, patlen);
uint32_t i = 0;
@@ -1738,16 +1717,6 @@ Matcher(const TextChar* text, uint32_t textlen, const PatChar* pat, uint32_t pat
pos = (TextChar*) FirstCharMatcher16bit((char16_t*)text + i, n - i, pat[0]);
else if (sizeof(TextChar) == 1 && sizeof(PatChar) == 1)
pos = (TextChar*) FirstCharMatcher8bit((char*) text + i, n - i, pat[0]);
- else if (sizeof(TextChar) == 1 && sizeof(PatChar) == 2)
- // The complete pattern was checked above, so this narrowing is
- // lossless and keeps the other mixed-width direction on SIMD.
- pos = FindCharacter(text + i, n - i, TextChar(pat[0]));
- else if (sizeof(TextChar) == 2 && sizeof(PatChar) == 1)
- // FindCharacter is encoding-independent for the text and keeps
- // mixed Latin-1/UTF-16 searches on the SSE2 fast path.
- pos = reinterpret_cast(
- FindCharacter(reinterpret_cast(text) + i,
- n - i, char16_t(pat[0])));
else
pos = (TextChar*) FirstCharMatcherUnrolled(text + i, n - i, pat[0]);
@@ -1773,9 +1742,9 @@ StringMatch(const TextChar* text, uint32_t textLen, const PatChar* pat, uint32_t
if (textLen < patLen)
return -1;
-#ifdef JS_HAS_SSE2_CHARACTER_OPERATIONS
- // Avoid the generic substring matcher for a single character when the
- // bounded SSE2 search helper is available, including mixed encodings.
+#if defined(__i386__) || defined(_M_IX86) || defined(__i386)
+ // Avoid the generic substring matcher for a single character on x86.
+ // FindCharacter uses SSE2 where available, including mixed encodings.
if (patLen == 1) {
// A two-byte needle cannot match Latin1 text if it exceeds 0xff.
if (sizeof(TextChar) == 1 && uint32_t(*pat) > 0xff)
@@ -2193,35 +2162,17 @@ LastIndexOfImpl(const TextChar* text, size_t textLen, const PatChar* pat, size_t
const PatChar* patNext = pat + 1;
const PatChar* patEnd = pat + patLen;
- // Search candidate first characters backwards in SIMD-sized blocks. The
- // bounded helper keeps the scan safe at allocation and page boundaries,
- // while the scalar comparison below still verifies the rest of the
- // pattern exactly.
- size_t searchLength = start + 1;
- while (searchLength) {
- const TextChar* t;
- if (sizeof(TextChar) == 1 && sizeof(PatChar) == 2) {
- if (uint32_t(p0) > 0xff)
- return -1;
- t = FindCharacterReverse(text, searchLength, TextChar(p0));
- } else {
- t = FindCharacterReverse(text, searchLength, TextChar(p0));
- }
- if (!t)
- return -1;
-
- const TextChar* t1 = t + 1;
- bool match = true;
- for (const PatChar* p1 = patNext; p1 < patEnd; ++p1, ++t1) {
- if (*t1 != *p1) {
- match = false;
- break;
+ for (const TextChar* t = text + start; t >= text; --t) {
+ if (*t == p0) {
+ const TextChar* t1 = t + 1;
+ for (const PatChar* p1 = patNext; p1 < patEnd; ++p1, ++t1) {
+ if (*t1 != *p1)
+ goto break_continue;
}
- }
- if (match)
return static_cast(t - text);
- searchLength = static_cast(t - text);
+ }
+ break_continue:;
}
return -1;
@@ -2320,14 +2271,14 @@ js::HasSubstringAt(JSLinearString* text, JSLinearString* pat, size_t start)
if (text->hasLatin1Chars()) {
const Latin1Char* textChars = text->latin1Chars(nogc) + start;
if (pat->hasLatin1Chars())
- return EqualChars(textChars, pat->latin1Chars(nogc), patLen);
+ return PodEqual(textChars, pat->latin1Chars(nogc), patLen);
return EqualChars(textChars, pat->twoByteChars(nogc), patLen);
}
const char16_t* textChars = text->twoByteChars(nogc) + start;
if (pat->hasTwoByteChars())
- return EqualChars(textChars, pat->twoByteChars(nogc), patLen);
+ return PodEqual(textChars, pat->twoByteChars(nogc), patLen);
return EqualChars(pat->latin1Chars(nogc), textChars, patLen);
}
@@ -4037,13 +3988,13 @@ js::EqualChars(JSLinearString* str1, JSLinearString* str2)
AutoCheckCannotGC nogc;
if (str1->hasTwoByteChars()) {
if (str2->hasTwoByteChars())
- return EqualChars(str1->twoByteChars(nogc), str2->twoByteChars(nogc), len);
+ return PodEqual(str1->twoByteChars(nogc), str2->twoByteChars(nogc), len);
return EqualChars(str2->latin1Chars(nogc), str1->twoByteChars(nogc), len);
}
if (str2->hasLatin1Chars())
- return EqualChars(str1->latin1Chars(nogc), str2->latin1Chars(nogc), len);
+ return PodEqual(str1->latin1Chars(nogc), str2->latin1Chars(nogc), len);
return EqualChars(str1->latin1Chars(nogc), str2->twoByteChars(nogc), len);
}
@@ -4159,7 +4110,7 @@ js::StringEqualsAscii(JSLinearString* str, const char* asciiBytes)
AutoCheckCannotGC nogc;
return str->hasLatin1Chars()
- ? EqualChars(latin1, str->latin1Chars(nogc), length)
+ ? PodEqual(latin1, str->latin1Chars(nogc), length)
: EqualChars(latin1, str->twoByteChars(nogc), length);
}
@@ -4256,15 +4207,12 @@ template
const CharT*
js_strchr_limit(const CharT* s, char16_t c, const CharT* limit)
{
- MOZ_ASSERT(limit >= s);
-
- // A Latin-1 buffer cannot contain a UTF-16 code unit above 0xff. Apart
- // from avoiding a scan, this guard is required before narrowing |c| for
- // the SIMD helper.
- if (sizeof(CharT) == 1 && c > 0xff)
- return nullptr;
-
- return FindCharacter(s, size_t(limit - s), CharT(c));
+ while (s < limit) {
+ if (*s == c)
+ return s;
+ s++;
+ }
+ return nullptr;
}
template const Latin1Char*
@@ -4284,20 +4232,8 @@ js::InflateString(ExclusiveContext* cx, const char* bytes, size_t* lengthp)
chars = cx->pod_malloc(nchars + 1);
if (!chars)
goto bad;
-#if defined(JS_HAVE_SSE2_INTRINSICS)
- size_t i = 0;
- const __m128i zero = _mm_setzero_si128();
- for (; i + 8 <= nchars; i += 8) {
- const __m128i bytes8 = _mm_loadl_epi64(reinterpret_cast(bytes + i));
- _mm_storeu_si128(reinterpret_cast<__m128i*>(chars + i),
- _mm_unpacklo_epi8(bytes8, zero));
- }
- for (; i < nchars; i++)
- chars[i] = (unsigned char) bytes[i];
-#else
for (size_t i = 0; i < nchars; i++)
chars[i] = (unsigned char) bytes[i];
-#endif
*lengthp = nchars;
chars[nchars] = 0;
return chars;
@@ -4309,49 +4245,6 @@ js::InflateString(ExclusiveContext* cx, const char* bytes, size_t* lengthp)
return nullptr;
}
-template
-static inline void
-DeflateChars(char* dst, const CharT* src, size_t length)
-{
- static_assert(sizeof(CharT) == 1 || sizeof(CharT) == 2, "character width");
-
- if (sizeof(CharT) == 1) {
- memcpy(dst, src, length);
- return;
- }
-
-#if defined(JS_HAVE_SSE2_INTRINSICS)
- size_t i = 0;
- const __m128i lowByteMask = _mm_set1_epi16(0xff);
- const __m128i zero = _mm_setzero_si128();
- for (; i + 32 <= length; i += 32) {
- const __m128i wide0 = _mm_loadu_si128(reinterpret_cast(src + i));
- const __m128i wide1 = _mm_loadu_si128(reinterpret_cast(src + i + 8));
- const __m128i wide2 = _mm_loadu_si128(reinterpret_cast(src + i + 16));
- const __m128i wide3 = _mm_loadu_si128(reinterpret_cast(src + i + 24));
- _mm_storel_epi64(reinterpret_cast<__m128i*>(dst + i),
- _mm_packus_epi16(_mm_and_si128(wide0, lowByteMask), zero));
- _mm_storel_epi64(reinterpret_cast<__m128i*>(dst + i + 8),
- _mm_packus_epi16(_mm_and_si128(wide1, lowByteMask), zero));
- _mm_storel_epi64(reinterpret_cast<__m128i*>(dst + i + 16),
- _mm_packus_epi16(_mm_and_si128(wide2, lowByteMask), zero));
- _mm_storel_epi64(reinterpret_cast<__m128i*>(dst + i + 24),
- _mm_packus_epi16(_mm_and_si128(wide3, lowByteMask), zero));
- }
- for (; i + 8 <= length; i += 8) {
- const __m128i wide = _mm_loadu_si128(reinterpret_cast(src + i));
- const __m128i lowBytes = _mm_and_si128(wide, lowByteMask);
- const __m128i packed = _mm_packus_epi16(lowBytes, zero);
- _mm_storel_epi64(reinterpret_cast<__m128i*>(dst + i), packed);
- }
- for (; i < length; i++)
- dst[i] = char(src[i]);
-#else
- for (size_t i = 0; i < length; i++)
- dst[i] = char(src[i]);
-#endif
-}
-
template
bool
js::DeflateStringToBuffer(JSContext* maybecx, const CharT* src, size_t srclen,
@@ -4359,7 +4252,8 @@ js::DeflateStringToBuffer(JSContext* maybecx, const CharT* src, size_t srclen,
{
size_t dstlen = *dstlenp;
if (srclen > dstlen) {
- DeflateChars(dst, src, dstlen);
+ for (size_t i = 0; i < dstlen; i++)
+ dst[i] = char(src[i]);
if (maybecx) {
AutoSuppressGC suppress(maybecx);
JS_ReportErrorNumberASCII(maybecx, GetErrorMessage, nullptr,
@@ -4367,7 +4261,8 @@ js::DeflateStringToBuffer(JSContext* maybecx, const CharT* src, size_t srclen,
}
return false;
}
- DeflateChars(dst, src, srclen);
+ for (size_t i = 0; i < srclen; i++)
+ dst[i] = char(src[i]);
*dstlenp = srclen;
return true;
}
diff --git a/js/src/jsstr.h b/js/src/jsstr.h
index b86d8bde20..cd2be4e59b 100644
--- a/js/src/jsstr.h
+++ b/js/src/jsstr.h
@@ -53,100 +53,7 @@ template
inline int32_t
CompareChars(const Char1* s1, size_t len1, const Char2* s2, size_t len2)
{
- if (mozilla::IsSame::value &&
- reinterpret_cast(s1) == reinterpret_cast(s2))
- {
- return int32_t(len1 - len2);
- }
-
size_t n = Min(len1, len2);
-
-#if defined(JS_HAVE_SSE2_INTRINSICS)
- if (sizeof(Char1) == 1 && sizeof(Char2) == 1) {
- const uint8_t* left = reinterpret_cast(s1);
- const uint8_t* right = reinterpret_cast(s2);
- while (n >= 16) {
- const __m128i leftBlock = _mm_loadu_si128(reinterpret_cast(left));
- const __m128i rightBlock = _mm_loadu_si128(reinterpret_cast(right));
- const uint32_t equalMask = static_cast(
- _mm_movemask_epi8(_mm_cmpeq_epi8(leftBlock, rightBlock)));
- if (equalMask != 0xffff) {
- const uint32_t lane = mozilla::CountTrailingZeroes32((~equalMask) & 0xffff);
- return int32_t(left[lane]) - int32_t(right[lane]);
- }
- left += 16;
- right += 16;
- n -= 16;
- }
- s1 = reinterpret_cast(left);
- s2 = reinterpret_cast(right);
- } else if (sizeof(Char1) == 2 && sizeof(Char2) == 2) {
- const char16_t* left = reinterpret_cast(s1);
- const char16_t* right = reinterpret_cast(s2);
- while (n >= 8) {
- const __m128i leftBlock = _mm_loadu_si128(reinterpret_cast(left));
- const __m128i rightBlock = _mm_loadu_si128(reinterpret_cast(right));
- const uint32_t equalMask = static_cast(
- _mm_movemask_epi8(_mm_cmpeq_epi16(leftBlock, rightBlock)));
- if (equalMask != 0xffff) {
- const uint32_t lane = mozilla::CountTrailingZeroes32((~equalMask) & 0xffff) / 2;
- return int32_t(left[lane]) - int32_t(right[lane]);
- }
- left += 8;
- right += 8;
- n -= 8;
- }
- s1 = reinterpret_cast(left);
- s2 = reinterpret_cast(right);
- }
-
- // Find the first differing code unit in eight mixed-width characters at
- // once. The scalar result is still used for the first mismatch, so this
- // preserves CompareChars' ordering semantics rather than merely testing
- // equality.
- if (sizeof(Char1) == 1 && sizeof(Char2) == 2) {
- const uint8_t* bytes = reinterpret_cast(s1);
- const char16_t* wide = reinterpret_cast(s2);
- const __m128i zero = _mm_setzero_si128();
- while (n >= 8) {
- const __m128i byteBlock = _mm_loadl_epi64(reinterpret_cast(bytes));
- const __m128i wideBlock = _mm_loadu_si128(reinterpret_cast(wide));
- const __m128i expanded = _mm_unpacklo_epi8(byteBlock, zero);
- const uint32_t equalMask = static_cast(
- _mm_movemask_epi8(_mm_cmpeq_epi16(expanded, wideBlock)));
- if (equalMask != 0xffff) {
- const uint32_t lane = mozilla::CountTrailingZeroes32((~equalMask) & 0xffff) / 2;
- return int32_t(bytes[lane]) - int32_t(wide[lane]);
- }
- bytes += 8;
- wide += 8;
- n -= 8;
- }
- s1 = reinterpret_cast(bytes);
- s2 = reinterpret_cast(wide);
- } else if (sizeof(Char1) == 2 && sizeof(Char2) == 1) {
- const char16_t* wide = reinterpret_cast(s1);
- const uint8_t* bytes = reinterpret_cast(s2);
- const __m128i zero = _mm_setzero_si128();
- while (n >= 8) {
- const __m128i wideBlock = _mm_loadu_si128(reinterpret_cast(wide));
- const __m128i byteBlock = _mm_loadl_epi64(reinterpret_cast(bytes));
- const __m128i expanded = _mm_unpacklo_epi8(byteBlock, zero);
- const uint32_t equalMask = static_cast(
- _mm_movemask_epi8(_mm_cmpeq_epi16(wideBlock, expanded)));
- if (equalMask != 0xffff) {
- const uint32_t lane = mozilla::CountTrailingZeroes32((~equalMask) & 0xffff) / 2;
- return int32_t(wide[lane]) - int32_t(bytes[lane]);
- }
- wide += 8;
- bytes += 8;
- n -= 8;
- }
- s1 = reinterpret_cast(wide);
- s2 = reinterpret_cast(bytes);
- }
-#endif
-
for (size_t i = 0; i < n; i++) {
if (int32_t cmp = s1[i] - s2[i])
return cmp;
@@ -345,67 +252,6 @@ template
inline bool
EqualChars(const Char1* s1, const Char1* s2, size_t len)
{
- if (s1 == s2)
- return true;
-
-#if defined(JS_HAVE_SSE2_INTRINSICS)
- if (sizeof(Char1) == 1) {
- const uint8_t* left = reinterpret_cast(s1);
- const uint8_t* right = reinterpret_cast(s2);
- while (len >= 64) {
- for (unsigned block = 0; block < 4; block++) {
- const __m128i leftBlock = _mm_loadu_si128(
- reinterpret_cast(left + block * 16));
- const __m128i rightBlock = _mm_loadu_si128(
- reinterpret_cast(right + block * 16));
- if (_mm_movemask_epi8(_mm_cmpeq_epi8(leftBlock, rightBlock)) != 0xffff)
- return false;
- }
- left += 64;
- right += 64;
- len -= 64;
- }
- while (len >= 16) {
- const __m128i leftBlock = _mm_loadu_si128(reinterpret_cast(left));
- const __m128i rightBlock = _mm_loadu_si128(reinterpret_cast(right));
- if (_mm_movemask_epi8(_mm_cmpeq_epi8(leftBlock, rightBlock)) != 0xffff)
- return false;
- left += 16;
- right += 16;
- len -= 16;
- }
- s1 = reinterpret_cast(left);
- s2 = reinterpret_cast(right);
- } else if (sizeof(Char1) == 2) {
- const char16_t* left = reinterpret_cast(s1);
- const char16_t* right = reinterpret_cast(s2);
- while (len >= 32) {
- for (unsigned block = 0; block < 4; block++) {
- const __m128i leftBlock = _mm_loadu_si128(
- reinterpret_cast(left + block * 8));
- const __m128i rightBlock = _mm_loadu_si128(
- reinterpret_cast(right + block * 8));
- if (_mm_movemask_epi8(_mm_cmpeq_epi16(leftBlock, rightBlock)) != 0xffff)
- return false;
- }
- left += 32;
- right += 32;
- len -= 32;
- }
- while (len >= 8) {
- const __m128i leftBlock = _mm_loadu_si128(reinterpret_cast(left));
- const __m128i rightBlock = _mm_loadu_si128(reinterpret_cast(right));
- if (_mm_movemask_epi8(_mm_cmpeq_epi16(leftBlock, rightBlock)) != 0xffff)
- return false;
- left += 8;
- right += 8;
- len -= 8;
- }
- s1 = reinterpret_cast(left);
- s2 = reinterpret_cast(right);
- }
-#endif
-
return mozilla::PodEqual(s1, s2, len);
}
@@ -413,45 +259,6 @@ template
inline bool
EqualChars(const Char1* s1, const Char2* s2, size_t len)
{
-#if defined(JS_HAVE_SSE2_INTRINSICS)
- // Compare eight mixed-width characters at a time. Widening the Latin-1
- // bytes before comparing also makes values above 0xff fail naturally,
- // preserving the scalar implementation's semantics.
- if (sizeof(Char1) == 1 && sizeof(Char2) == 2) {
- const uint8_t* bytes = reinterpret_cast(s1);
- const char16_t* wide = reinterpret_cast(s2);
- const __m128i zero = _mm_setzero_si128();
- while (len >= 8) {
- const __m128i byteBlock = _mm_loadl_epi64(reinterpret_cast(bytes));
- const __m128i wideBlock = _mm_loadu_si128(reinterpret_cast(wide));
- const __m128i expanded = _mm_unpacklo_epi8(byteBlock, zero);
- if (_mm_movemask_epi8(_mm_cmpeq_epi16(expanded, wideBlock)) != 0xffff)
- return false;
- bytes += 8;
- wide += 8;
- len -= 8;
- }
- s1 = reinterpret_cast(bytes);
- s2 = reinterpret_cast(wide);
- } else if (sizeof(Char1) == 2 && sizeof(Char2) == 1) {
- const char16_t* wide = reinterpret_cast(s1);
- const uint8_t* bytes = reinterpret_cast(s2);
- const __m128i zero = _mm_setzero_si128();
- while (len >= 8) {
- const __m128i wideBlock = _mm_loadu_si128(reinterpret_cast(wide));
- const __m128i byteBlock = _mm_loadl_epi64(reinterpret_cast(bytes));
- const __m128i expanded = _mm_unpacklo_epi8(byteBlock, zero);
- if (_mm_movemask_epi8(_mm_cmpeq_epi16(wideBlock, expanded)) != 0xffff)
- return false;
- wide += 8;
- bytes += 8;
- len -= 8;
- }
- s1 = reinterpret_cast(wide);
- s2 = reinterpret_cast(bytes);
- }
-#endif
-
for (const Char1* s1end = s1 + len; s1 < s1end; s1++, s2++) {
if (*s1 != *s2)
return false;
@@ -483,81 +290,15 @@ InflateString(ExclusiveContext* cx, const char* bytes, size_t* length);
inline void
CopyAndInflateChars(char16_t* dst, const char* src, size_t srclen)
{
-#if defined(JS_HAVE_SSE2_INTRINSICS)
- size_t i = 0;
- const __m128i zero = _mm_setzero_si128();
- for (; i + 32 <= srclen; i += 32) {
- uint64_t value0, value1, value2, value3;
- js_memcpy(&value0, src + i, sizeof(value0));
- js_memcpy(&value1, src + i + 8, sizeof(value1));
- js_memcpy(&value2, src + i + 16, sizeof(value2));
- js_memcpy(&value3, src + i + 24, sizeof(value3));
- const __m128i bytes0 = _mm_cvtsi64_si128(static_cast(value0));
- const __m128i bytes1 = _mm_cvtsi64_si128(static_cast(value1));
- const __m128i bytes2 = _mm_cvtsi64_si128(static_cast(value2));
- const __m128i bytes3 = _mm_cvtsi64_si128(static_cast(value3));
- _mm_storeu_si128(reinterpret_cast<__m128i*>(dst + i),
- _mm_unpacklo_epi8(bytes0, zero));
- _mm_storeu_si128(reinterpret_cast<__m128i*>(dst + i + 8),
- _mm_unpacklo_epi8(bytes1, zero));
- _mm_storeu_si128(reinterpret_cast<__m128i*>(dst + i + 16),
- _mm_unpacklo_epi8(bytes2, zero));
- _mm_storeu_si128(reinterpret_cast<__m128i*>(dst + i + 24),
- _mm_unpacklo_epi8(bytes3, zero));
- }
- for (; i + 8 <= srclen; i += 8) {
- uint64_t value;
- js_memcpy(&value, src + i, sizeof(value));
- const __m128i bytes8 = _mm_cvtsi64_si128(static_cast(value));
- _mm_storeu_si128(reinterpret_cast<__m128i*>(dst + i),
- _mm_unpacklo_epi8(bytes8, zero));
- }
- for (; i < srclen; i++)
- dst[i] = (unsigned char) src[i];
-#else
for (size_t i = 0; i < srclen; i++)
dst[i] = (unsigned char) src[i];
-#endif
}
inline void
CopyAndInflateChars(char16_t* dst, const JS::Latin1Char* src, size_t srclen)
{
-#if defined(JS_HAVE_SSE2_INTRINSICS)
- size_t i = 0;
- const __m128i zero = _mm_setzero_si128();
- for (; i + 32 <= srclen; i += 32) {
- uint64_t value0, value1, value2, value3;
- js_memcpy(&value0, src + i, sizeof(value0));
- js_memcpy(&value1, src + i + 8, sizeof(value1));
- js_memcpy(&value2, src + i + 16, sizeof(value2));
- js_memcpy(&value3, src + i + 24, sizeof(value3));
- const __m128i bytes0 = _mm_cvtsi64_si128(static_cast(value0));
- const __m128i bytes1 = _mm_cvtsi64_si128(static_cast(value1));
- const __m128i bytes2 = _mm_cvtsi64_si128(static_cast(value2));
- const __m128i bytes3 = _mm_cvtsi64_si128(static_cast(value3));
- _mm_storeu_si128(reinterpret_cast<__m128i*>(dst + i),
- _mm_unpacklo_epi8(bytes0, zero));
- _mm_storeu_si128(reinterpret_cast<__m128i*>(dst + i + 8),
- _mm_unpacklo_epi8(bytes1, zero));
- _mm_storeu_si128(reinterpret_cast<__m128i*>(dst + i + 16),
- _mm_unpacklo_epi8(bytes2, zero));
- _mm_storeu_si128(reinterpret_cast<__m128i*>(dst + i + 24),
- _mm_unpacklo_epi8(bytes3, zero));
- }
- for (; i + 8 <= srclen; i += 8) {
- uint64_t value;
- js_memcpy(&value, src + i, sizeof(value));
- const __m128i bytes8 = _mm_cvtsi64_si128(static_cast(value));
- _mm_storeu_si128(reinterpret_cast<__m128i*>(dst + i),
- _mm_unpacklo_epi8(bytes8, zero));
- }
- for (; i < srclen; i++)
- dst[i] = src[i];
-#else
for (size_t i = 0; i < srclen; i++)
dst[i] = src[i];
-#endif
}
/*
diff --git a/js/src/jsutil.h b/js/src/jsutil.h
index 3de1bbeff6..1969a2e823 100644
--- a/js/src/jsutil.h
+++ b/js/src/jsutil.h
@@ -113,21 +113,6 @@ js_memmove(void* dst_, const void* src_, size_t len)
d += len;
s += len;
- while (len >= 64) {
- d -= 64;
- s -= 64;
- // Load the complete chunk before storing it: the ranges may
- // overlap, so an early store must not destroy a later load.
- __m128i v0 = _mm_loadu_si128((const __m128i*)(s + 0));
- __m128i v1 = _mm_loadu_si128((const __m128i*)(s + 16));
- __m128i v2 = _mm_loadu_si128((const __m128i*)(s + 32));
- __m128i v3 = _mm_loadu_si128((const __m128i*)(s + 48));
- _mm_storeu_si128((__m128i*)(d + 0), v0);
- _mm_storeu_si128((__m128i*)(d + 16), v1);
- _mm_storeu_si128((__m128i*)(d + 32), v2);
- _mm_storeu_si128((__m128i*)(d + 48), v3);
- len -= 64;
- }
while (len >= 16) {
d -= 16;
s -= 16;
diff --git a/js/src/vm/ArgumentsObject.cpp b/js/src/vm/ArgumentsObject.cpp
index 2fd0f1de61..e23de30d66 100644
--- a/js/src/vm/ArgumentsObject.cpp
+++ b/js/src/vm/ArgumentsObject.cpp
@@ -11,7 +11,6 @@
#include "vm/AsyncFunction.h"
#include "vm/GlobalObject.h"
#include "vm/Stack.h"
-#include "jsutil.h"
#include "jsobjinlines.h"
@@ -37,7 +36,7 @@ RareArgumentsData::create(JSContext* cx, ArgumentsObject* obj)
if (!data)
return nullptr;
- js_memset(data, 0, bytes);
+ mozilla::PodZero(data, bytes);
return new(data) RareArgumentsData();
}
@@ -300,7 +299,7 @@ ArgumentsObject::create(JSContext* cx, HandleFunction callee, unsigned numActual
// Zero the argument Values. This sets each value to DoubleValue(0), which
// is safe for GC tracing.
- js_memset(data->args, 0, numArgs * sizeof(Value));
+ memset(data->args, 0, numArgs * sizeof(Value));
MOZ_ASSERT(DoubleValue(0).asRawBits() == 0x0);
MOZ_ASSERT_IF(numArgs > 0, data->args[0].asRawBits() == 0x0);
@@ -816,7 +815,7 @@ ArgumentsObject::objectMovedDuringMinorGC(JSTracer* trc, JSObject* dst, JSObject
oomUnsafe.crash("Failed to allocate ArgumentsObject data while tenuring.");
ndst->initFixedSlot(DATA_SLOT, PrivateValue(data));
- js_memcpy(data, reinterpret_cast(nsrc->data()), nbytes);
+ mozilla::PodCopy(data, reinterpret_cast(nsrc->data()), nbytes);
nbytesTotal += nbytes;
}
@@ -831,7 +830,7 @@ ArgumentsObject::objectMovedDuringMinorGC(JSTracer* trc, JSObject* dst, JSObject
oomUnsafe.crash("Failed to allocate RareArgumentsData data while tenuring.");
ndst->data()->rareData = (RareArgumentsData*)dstRareData;
- js_memcpy(dstRareData, reinterpret_cast(srcRareData), nbytes);
+ mozilla::PodCopy(dstRareData, reinterpret_cast(srcRareData), nbytes);
nbytesTotal += nbytes;
}
}
diff --git a/js/src/vm/ArrayBufferObject.cpp b/js/src/vm/ArrayBufferObject.cpp
index b0c0037169..666fc774df 100644
--- a/js/src/vm/ArrayBufferObject.cpp
+++ b/js/src/vm/ArrayBufferObject.cpp
@@ -656,7 +656,7 @@ ResizeArrayBuffer(JSContext* cx, Handle buffer, uint32_t new
uint32_t copyLength = std::min(newByteLength, buffer->byteLength());
if (copyLength > 0)
- js_memcpy(newContents.data(), buffer->dataPointer(), copyLength);
+ memcpy(newContents.data(), buffer->dataPointer(), copyLength);
buffer->changeContentsForResize(cx, newContents, ArrayBufferObject::OwnsData, newByteLength);
return true;
@@ -729,7 +729,7 @@ ArrayBufferTransfer(JSContext* cx, const CallArgs& args, bool preserveResizabili
uint32_t copyLength = std::min(newByteLength, buffer->byteLength());
if (copyLength > 0)
- js_memcpy(newBuffer->dataPointer(), buffer->dataPointer(), copyLength);
+ memcpy(newBuffer->dataPointer(), buffer->dataPointer(), copyLength);
ArrayBufferObject::BufferContents detachedContents =
buffer->hasStealableContents() ? ArrayBufferObject::BufferContents::createPlain(nullptr)
@@ -1428,7 +1428,7 @@ ArrayBufferObject::create(JSContext* cx, uint32_t nbytes, BufferContents content
if (!contents) {
void* data = obj->inlineDataPointer();
- js_memset(data, 0, nbytes);
+ memset(data, 0, nbytes);
obj->initialize(nbytes, BufferContents::createPlain(data), DoesntOwnData,
maxByteLength, resizable);
} else {
diff --git a/js/src/vm/CharacterEncoding.cpp b/js/src/vm/CharacterEncoding.cpp
index 585f6a150a..b126e8a05a 100644
--- a/js/src/vm/CharacterEncoding.cpp
+++ b/js/src/vm/CharacterEncoding.cpp
@@ -9,12 +9,10 @@
#include "mozilla/Sprintf.h"
#include
-#include
#include
#include "jscntxt.h"
#include "jsprf.h"
-#include "vm/CharacterOperations.h"
using namespace js;
@@ -27,40 +25,8 @@ JS::LossyTwoByteCharsToNewLatin1CharsZ(js::ExclusiveContext* cx,
unsigned char* latin1 = cx->pod_malloc(len + 1);
if (!latin1)
return Latin1CharsZ();
-#if defined(JS_HAS_SSE2_CHARACTER_OPERATIONS)
- size_t i = 0;
- const __m128i lowByteMask = _mm_set1_epi16(0xff);
- const __m128i zero = _mm_setzero_si128();
- for (; i + 32 <= len; i += 32) {
- const __m128i wide0 = _mm_loadu_si128(
- reinterpret_cast(tbchars.begin().get() + i));
- const __m128i wide1 = _mm_loadu_si128(
- reinterpret_cast(tbchars.begin().get() + i + 8));
- const __m128i wide2 = _mm_loadu_si128(
- reinterpret_cast(tbchars.begin().get() + i + 16));
- const __m128i wide3 = _mm_loadu_si128(
- reinterpret_cast(tbchars.begin().get() + i + 24));
- _mm_storel_epi64(reinterpret_cast<__m128i*>(latin1 + i),
- _mm_packus_epi16(_mm_and_si128(wide0, lowByteMask), zero));
- _mm_storel_epi64(reinterpret_cast<__m128i*>(latin1 + i + 8),
- _mm_packus_epi16(_mm_and_si128(wide1, lowByteMask), zero));
- _mm_storel_epi64(reinterpret_cast<__m128i*>(latin1 + i + 16),
- _mm_packus_epi16(_mm_and_si128(wide2, lowByteMask), zero));
- _mm_storel_epi64(reinterpret_cast<__m128i*>(latin1 + i + 24),
- _mm_packus_epi16(_mm_and_si128(wide3, lowByteMask), zero));
- }
- for (; i + 8 <= len; i += 8) {
- const __m128i wide = _mm_loadu_si128(reinterpret_cast(tbchars.begin().get() + i));
- const __m128i lowBytes = _mm_and_si128(wide, lowByteMask);
- const __m128i packed = _mm_packus_epi16(lowBytes, zero);
- _mm_storel_epi64(reinterpret_cast<__m128i*>(latin1 + i), packed);
- }
- for (; i < len; ++i)
- latin1[i] = static_cast(tbchars[i]);
-#else
for (size_t i = 0; i < len; ++i)
latin1[i] = static_cast(tbchars[i]);
-#endif
latin1[len] = '\0';
return Latin1CharsZ(latin1, len);
}
@@ -457,43 +423,8 @@ InflateUTF8StringHelper(ContextT* cx, const UTF8Chars src, size_t* outlen)
if (encoding == JS::SmallestEncoding::ASCII) {
size_t srclen = src.length();
MOZ_ASSERT(*outlen == srclen);
- if (sizeof(CharT) == 1) {
- memcpy(dst, src.begin().get(), srclen);
- } else {
-#if defined(JS_HAS_SSE2_CHARACTER_OPERATIONS)
- size_t i = 0;
- const __m128i zero = _mm_setzero_si128();
- for (; i + 32 <= srclen; i += 32) {
- const __m128i bytes0 = _mm_loadl_epi64(
- reinterpret_cast(src.begin().get() + i));
- const __m128i bytes1 = _mm_loadl_epi64(
- reinterpret_cast(src.begin().get() + i + 8));
- const __m128i bytes2 = _mm_loadl_epi64(
- reinterpret_cast(src.begin().get() + i + 16));
- const __m128i bytes3 = _mm_loadl_epi64(
- reinterpret_cast(src.begin().get() + i + 24));
- _mm_storeu_si128(reinterpret_cast<__m128i*>(dst + i),
- _mm_unpacklo_epi8(bytes0, zero));
- _mm_storeu_si128(reinterpret_cast<__m128i*>(dst + i + 8),
- _mm_unpacklo_epi8(bytes1, zero));
- _mm_storeu_si128(reinterpret_cast<__m128i*>(dst + i + 16),
- _mm_unpacklo_epi8(bytes2, zero));
- _mm_storeu_si128(reinterpret_cast<__m128i*>(dst + i + 24),
- _mm_unpacklo_epi8(bytes3, zero));
- }
- for (; i + 8 <= srclen; i += 8) {
- const __m128i bytes8 = _mm_loadl_epi64(
- reinterpret_cast(src.begin().get() + i));
- _mm_storeu_si128(reinterpret_cast<__m128i*>(dst + i),
- _mm_unpacklo_epi8(bytes8, zero));
- }
- for (; i < srclen; i++)
- dst[i] = CharT(src[i]);
-#else
- for (size_t i = 0; i < srclen; i++)
- dst[i] = CharT(src[i]);
-#endif
- }
+ for (uint32_t i = 0; i < srclen; i++)
+ dst[i] = CharT(src[i]);
} else {
MOZ_ALWAYS_TRUE((InflateUTF8StringToBuffer(cx, src, dst, outlen, &encoding)));
}
diff --git a/js/src/vm/CharacterOperations.h b/js/src/vm/CharacterOperations.h
index f7f9dab52e..591a3216bf 100644
--- a/js/src/vm/CharacterOperations.h
+++ b/js/src/vm/CharacterOperations.h
@@ -31,47 +31,7 @@ FindCharacter(const CharT* chars, size_t length, CharT match)
const __m128i needle = sizeof(CharT) == 1
? _mm_set1_epi8(static_cast(match))
: _mm_set1_epi16(static_cast(match));
- while (length >= 4 * lanes) {
- const __m128i block0 = _mm_loadu_si128(
- reinterpret_cast(chars));
- const uint32_t mask0 = static_cast(
- _mm_movemask_epi8(sizeof(CharT) == 1
- ? _mm_cmpeq_epi8(block0, needle)
- : _mm_cmpeq_epi16(block0, needle)));
- if (mask0)
- return chars + mozilla::CountTrailingZeroes32(mask0) / sizeof(CharT);
-
- const __m128i block1 = _mm_loadu_si128(
- reinterpret_cast(chars + lanes));
- const uint32_t mask1 = static_cast(
- _mm_movemask_epi8(sizeof(CharT) == 1
- ? _mm_cmpeq_epi8(block1, needle)
- : _mm_cmpeq_epi16(block1, needle)));
- if (mask1)
- return chars + lanes + mozilla::CountTrailingZeroes32(mask1) / sizeof(CharT);
-
- const __m128i block2 = _mm_loadu_si128(
- reinterpret_cast(chars + 2 * lanes));
- const uint32_t mask2 = static_cast(
- _mm_movemask_epi8(sizeof(CharT) == 1
- ? _mm_cmpeq_epi8(block2, needle)
- : _mm_cmpeq_epi16(block2, needle)));
- if (mask2)
- return chars + 2 * lanes + mozilla::CountTrailingZeroes32(mask2) / sizeof(CharT);
-
- const __m128i block3 = _mm_loadu_si128(
- reinterpret_cast(chars + 3 * lanes));
- const uint32_t mask3 = static_cast(
- _mm_movemask_epi8(sizeof(CharT) == 1
- ? _mm_cmpeq_epi8(block3, needle)
- : _mm_cmpeq_epi16(block3, needle)));
- if (mask3)
- return chars + 3 * lanes + mozilla::CountTrailingZeroes32(mask3) / sizeof(CharT);
-
- chars += 4 * lanes;
- length -= 4 * lanes;
- }
- while (length >= lanes) {
+ do {
// Never read beyond the supplied span, even at a page boundary.
const __m128i block = _mm_loadu_si128(reinterpret_cast(chars));
const __m128i equal = sizeof(CharT) == 1
@@ -82,7 +42,7 @@ FindCharacter(const CharT* chars, size_t length, CharT match)
return chars + mozilla::CountTrailingZeroes32(mask) / sizeof(CharT);
chars += lanes;
length -= lanes;
- }
+ } while (length >= lanes);
}
#endif
for (; length; --length, ++chars) {
@@ -92,86 +52,6 @@ FindCharacter(const CharT* chars, size_t length, CharT match)
return nullptr;
}
-template
-inline const CharT*
-FindCharacterReverse(const CharT* chars, size_t length, CharT match)
-{
- static_assert(sizeof(CharT) == 1 || sizeof(CharT) == 2, "character width");
-#ifdef JS_HAS_SSE2_CHARACTER_OPERATIONS
- const size_t lanes = 16 / sizeof(CharT);
- const CharT* end = chars + length;
- if (length >= lanes) {
- const __m128i needle = sizeof(CharT) == 1
- ? _mm_set1_epi8(static_cast(match))
- : _mm_set1_epi16(static_cast(match));
- while (length >= 4 * lanes) {
- end -= 4 * lanes;
- length -= 4 * lanes;
-
- const __m128i block3 = _mm_loadu_si128(
- reinterpret_cast(end + 3 * lanes));
- const uint32_t mask3 = static_cast(
- _mm_movemask_epi8(sizeof(CharT) == 1
- ? _mm_cmpeq_epi8(block3, needle)
- : _mm_cmpeq_epi16(block3, needle)));
- if (mask3)
- return end + 3 * lanes +
- (31 - mozilla::CountLeadingZeroes32(mask3)) / sizeof(CharT);
-
- const __m128i block2 = _mm_loadu_si128(
- reinterpret_cast(end + 2 * lanes));
- const uint32_t mask2 = static_cast(
- _mm_movemask_epi8(sizeof(CharT) == 1
- ? _mm_cmpeq_epi8(block2, needle)
- : _mm_cmpeq_epi16(block2, needle)));
- if (mask2)
- return end + 2 * lanes +
- (31 - mozilla::CountLeadingZeroes32(mask2)) / sizeof(CharT);
-
- const __m128i block1 = _mm_loadu_si128(
- reinterpret_cast(end + lanes));
- const uint32_t mask1 = static_cast(
- _mm_movemask_epi8(sizeof(CharT) == 1
- ? _mm_cmpeq_epi8(block1, needle)
- : _mm_cmpeq_epi16(block1, needle)));
- if (mask1)
- return end + lanes +
- (31 - mozilla::CountLeadingZeroes32(mask1)) / sizeof(CharT);
-
- const __m128i block0 = _mm_loadu_si128(
- reinterpret_cast(end));
- const uint32_t mask0 = static_cast(
- _mm_movemask_epi8(sizeof(CharT) == 1
- ? _mm_cmpeq_epi8(block0, needle)
- : _mm_cmpeq_epi16(block0, needle)));
- if (mask0)
- return end + (31 - mozilla::CountLeadingZeroes32(mask0)) / sizeof(CharT);
- }
- while (length >= lanes) {
- end -= lanes;
- length -= lanes;
- const __m128i block = _mm_loadu_si128(reinterpret_cast(end));
- const __m128i equal = sizeof(CharT) == 1
- ? _mm_cmpeq_epi8(block, needle)
- : _mm_cmpeq_epi16(block, needle);
- const uint32_t mask = static_cast(_mm_movemask_epi8(equal));
- if (mask)
- return end + (31 - mozilla::CountLeadingZeroes32(mask)) / sizeof(CharT);
- }
- }
-#else
- const CharT* end = chars + length;
-#endif
-
- while (length) {
- --end;
- --length;
- if (*end == match)
- return end;
- }
- return nullptr;
-}
-
inline bool
CharactersFitInLatin1(const char16_t* chars, size_t length)
{
@@ -179,34 +59,6 @@ CharactersFitInLatin1(const char16_t* chars, size_t length)
if (length >= 8) {
const __m128i highBytes = _mm_set1_epi16(static_cast(0xff00));
const __m128i zero = _mm_setzero_si128();
- while (length >= 32) {
- const __m128i block0 = _mm_loadu_si128(
- reinterpret_cast(chars));
- if (_mm_movemask_epi8(_mm_cmpeq_epi16(
- _mm_and_si128(block0, highBytes), zero)) != 0xffff)
- return false;
-
- const __m128i block1 = _mm_loadu_si128(
- reinterpret_cast(chars + 8));
- if (_mm_movemask_epi8(_mm_cmpeq_epi16(
- _mm_and_si128(block1, highBytes), zero)) != 0xffff)
- return false;
-
- const __m128i block2 = _mm_loadu_si128(
- reinterpret_cast(chars + 16));
- if (_mm_movemask_epi8(_mm_cmpeq_epi16(
- _mm_and_si128(block2, highBytes), zero)) != 0xffff)
- return false;
-
- const __m128i block3 = _mm_loadu_si128(
- reinterpret_cast(chars + 24));
- if (_mm_movemask_epi8(_mm_cmpeq_epi16(
- _mm_and_si128(block3, highBytes), zero)) != 0xffff)
- return false;
-
- chars += 32;
- length -= 32;
- }
do {
const __m128i block = _mm_loadu_si128(reinterpret_cast(chars));
const __m128i fits = _mm_cmpeq_epi16(_mm_and_si128(block, highBytes), zero);
diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp
index 50ce7a1728..ad52234a31 100644
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -31,7 +31,6 @@
#include "jsprf.h"
#include "jsscript.h"
#include "jsstr.h"
-#include "jsutil.h"
#include "builtin/Eval.h"
#include "builtin/ModuleObject.h"
@@ -2148,7 +2147,7 @@ CASE(JSOP_PICK)
unsigned i = GET_UINT8(REGS.pc);
MOZ_ASSERT(REGS.stackDepth() >= i + 1);
Value lval = REGS.sp[-int(i + 1)];
- js_memmove(REGS.sp - (i + 1), REGS.sp - i, sizeof(Value) * i);
+ memmove(REGS.sp - (i + 1), REGS.sp - i, sizeof(Value) * i);
REGS.sp[-1] = lval;
}
END_CASE(JSOP_PICK)
@@ -2158,7 +2157,7 @@ CASE(JSOP_UNPICK)
int i = GET_UINT8(REGS.pc);
MOZ_ASSERT(REGS.stackDepth() >= unsigned(i) + 1);
Value lval = REGS.sp[-1];
- js_memmove(REGS.sp - i, REGS.sp - (i + 1), sizeof(Value) * i);
+ memmove(REGS.sp - i, REGS.sp - (i + 1), sizeof(Value) * i);
REGS.sp[-(i + 1)] = lval;
}
END_CASE(JSOP_UNPICK)
diff --git a/js/src/vm/NativeObject.h b/js/src/vm/NativeObject.h
index 63779d8142..67fd3a7a46 100644
--- a/js/src/vm/NativeObject.h
+++ b/js/src/vm/NativeObject.h
@@ -13,7 +13,6 @@
#include "jsfriendapi.h"
#include "jsobj.h"
-#include "jsutil.h"
#include "NamespaceImports.h"
#include "gc/Barrier.h"
@@ -1123,8 +1122,8 @@ class NativeObject : public ShapedObject
for (uint32_t i = 0; i < count; ++i)
elements_[dstStart + i].set(this, HeapSlot::Element, dstStart + i, src[i]);
} else {
- js_memcpy(reinterpret_cast(&elements_[dstStart]), src,
- count * sizeof(Value));
+ memcpy(reinterpret_cast(&elements_[dstStart]), src,
+ count * sizeof(Value));
elementsRangeWriteBarrierPost(dstStart, count);
}
}
@@ -1133,7 +1132,7 @@ class NativeObject : public ShapedObject
MOZ_ASSERT(dstStart + count <= getDenseCapacity());
MOZ_ASSERT(!denseElementsAreCopyOnWrite());
MOZ_ASSERT(!denseElementsAreFrozen());
- js_memcpy(reinterpret_cast(&elements_[dstStart]), src, count * sizeof(Value));
+ memcpy(reinterpret_cast(&elements_[dstStart]), src, count * sizeof(Value));
elementsRangeWriteBarrierPost(dstStart, count);
}
@@ -1168,7 +1167,7 @@ class NativeObject : public ShapedObject
dst->set(this, HeapSlot::Element, dst - elements_, *src);
}
} else {
- js_memmove(elements_ + dstStart, elements_ + srcStart, count * sizeof(HeapSlot));
+ memmove(elements_ + dstStart, elements_ + srcStart, count * sizeof(HeapSlot));
elementsRangeWriteBarrierPost(dstStart, count);
}
}
@@ -1181,7 +1180,7 @@ class NativeObject : public ShapedObject
MOZ_ASSERT(!denseElementsAreCopyOnWrite());
MOZ_ASSERT(!denseElementsAreFrozen());
- js_memmove(elements_ + dstStart, elements_ + srcStart, count * sizeof(HeapSlot));
+ memmove(elements_ + dstStart, elements_ + srcStart, count * sizeof(HeapSlot));
elementsRangeWriteBarrierPost(dstStart, count);
}
diff --git a/js/src/vm/String-inl.h b/js/src/vm/String-inl.h
index f186f02afc..52261d0f75 100644
--- a/js/src/vm/String-inl.h
+++ b/js/src/vm/String-inl.h
@@ -8,11 +8,11 @@
#include "vm/String.h"
+#include "mozilla/PodOperations.h"
#include "mozilla/Range.h"
#include "jscntxt.h"
#include "jscompartment.h"
-#include "jsutil.h"
#include "gc/Allocator.h"
#include "gc/Marking.h"
@@ -57,7 +57,7 @@ NewInlineString(ExclusiveContext* cx, mozilla::Range chars)
if (!str)
return nullptr;
- js_memcpy(storage, chars.begin().get(), len);
+ mozilla::PodCopy(storage, chars.begin().get(), len);
storage[len] = 0;
return str;
}
@@ -75,7 +75,7 @@ NewInlineString(ExclusiveContext* cx, HandleLinearString base, size_t start, siz
return nullptr;
JS::AutoCheckCannotGC nogc;
- js_memcpy(chars, base->chars(nogc) + start, length * sizeof(CharT));
+ mozilla::PodCopy(chars, base->chars(nogc) + start, length);
chars[length] = 0;
return s;
}
diff --git a/js/src/vm/String.cpp b/js/src/vm/String.cpp
index 2a292c9927..3ef6fb229d 100644
--- a/js/src/vm/String.cpp
+++ b/js/src/vm/String.cpp
@@ -7,6 +7,7 @@
#include "mozilla/MathAlgorithms.h"
#include "mozilla/MemoryReporting.h"
+#include "mozilla/PodOperations.h"
#include "mozilla/RangedPtr.h"
#include "mozilla/SizePrintfMacros.h"
#include "mozilla/TypeTraits.h"
@@ -19,11 +20,11 @@
#include "jscntxtinlines.h"
#include "jscompartmentinlines.h"
-#include "jsutil.h"
using namespace js;
using mozilla::IsSame;
+using mozilla::PodCopy;
using mozilla::RangedPtr;
using mozilla::RoundUpPow2;
@@ -345,7 +346,7 @@ CopyChars(char16_t* dest, const JSLinearString& str)
{
AutoCheckCannotGC nogc;
if (str.hasTwoByteChars())
- js_memcpy(dest, str.twoByteChars(nogc), str.length() * sizeof(char16_t));
+ PodCopy(dest, str.twoByteChars(nogc), str.length());
else
CopyAndInflateChars(dest, str.latin1Chars(nogc), str.length());
}
@@ -356,7 +357,7 @@ CopyChars(Latin1Char* dest, const JSLinearString& str)
{
AutoCheckCannotGC nogc;
if (str.hasLatin1Chars()) {
- js_memcpy(dest, str.latin1Chars(nogc), str.length());
+ PodCopy(dest, str.latin1Chars(nogc), str.length());
} else {
/*
* When we flatten a TwoByte rope, we turn child ropes (including Latin1
@@ -368,24 +369,10 @@ CopyChars(Latin1Char* dest, const JSLinearString& str)
*/
size_t len = str.length();
const char16_t* chars = str.twoByteChars(nogc);
-#if defined(JS_HAS_SSE2_CHARACTER_OPERATIONS)
- size_t i = 0;
- const __m128i zero = _mm_setzero_si128();
- for (; i + 8 <= len; i += 8) {
- const __m128i wide = _mm_loadu_si128(reinterpret_cast(chars + i));
- const __m128i packed = _mm_packus_epi16(wide, zero);
- _mm_storel_epi64(reinterpret_cast<__m128i*>(dest + i), packed);
- }
- for (; i < len; i++) {
- MOZ_ASSERT(chars[i] <= JSString::MAX_LATIN1_CHAR);
- dest[i] = chars[i];
- }
-#else
for (size_t i = 0; i < len; i++) {
MOZ_ASSERT(chars[i] <= JSString::MAX_LATIN1_CHAR);
dest[i] = chars[i];
}
-#endif
}
}
@@ -652,17 +639,16 @@ js::ConcatStrings(ExclusiveContext* cx,
return nullptr;
if (isLatin1) {
- js_memcpy(latin1Buf, leftLinear->latin1Chars(nogc), leftLen);
- js_memcpy(latin1Buf + leftLen, rightLinear->latin1Chars(nogc), rightLen);
+ PodCopy(latin1Buf, leftLinear->latin1Chars(nogc), leftLen);
+ PodCopy(latin1Buf + leftLen, rightLinear->latin1Chars(nogc), rightLen);
latin1Buf[wholeLength] = 0;
} else {
if (leftLinear->hasTwoByteChars())
- js_memcpy(twoByteBuf, leftLinear->twoByteChars(nogc), leftLen * sizeof(char16_t));
+ PodCopy(twoByteBuf, leftLinear->twoByteChars(nogc), leftLen);
else
CopyAndInflateChars(twoByteBuf, leftLinear->latin1Chars(nogc), leftLen);
if (rightLinear->hasTwoByteChars())
- js_memcpy(twoByteBuf + leftLen, rightLinear->twoByteChars(nogc),
- rightLen * sizeof(char16_t));
+ PodCopy(twoByteBuf + leftLen, rightLinear->twoByteChars(nogc), rightLen);
else
CopyAndInflateChars(twoByteBuf + leftLen, rightLinear->latin1Chars(nogc), rightLen);
twoByteBuf[wholeLength] = 0;
@@ -690,7 +676,7 @@ JSDependentString::undependInternal(JSContext* cx)
return nullptr;
AutoCheckCannotGC nogc;
- js_memcpy(s, nonInlineChars(nogc), n * sizeof(CharT));
+ PodCopy(s, nonInlineChars(nogc), n);
s[n] = '\0';
setNonInlineChars(s);
@@ -1040,7 +1026,7 @@ AutoStableStringChars::copyLatin1Chars(JSContext* cx, HandleLinearString linearS
if (!chars)
return false;
- js_memcpy(chars, linearString->rawLatin1Chars(), length);
+ PodCopy(chars, linearString->rawLatin1Chars(), length);
chars[length] = 0;
state_ = Latin1;
@@ -1057,7 +1043,7 @@ AutoStableStringChars::copyTwoByteChars(JSContext* cx, HandleLinearString linear
if (!chars)
return false;
- js_memcpy(chars, linearString->rawTwoByteChars(), length * sizeof(char16_t));
+ PodCopy(chars, linearString->rawTwoByteChars(), length);
chars[length] = 0;
state_ = TwoByte;
@@ -1091,7 +1077,7 @@ JSExternalString::ensureFlat(JSContext* cx)
// Copy the chars before finalizing the string.
{
AutoCheckCannotGC nogc;
- js_memcpy(s, nonInlineChars(nogc), n * sizeof(char16_t));
+ PodCopy(s, nonInlineChars(nogc), n);
s[n] = '\0';
}
@@ -1172,41 +1158,6 @@ CanStoreCharsAsLatin1(const Latin1Char* s, size_t length)
MOZ_CRASH("Shouldn't be called for Latin1 chars");
}
-static MOZ_ALWAYS_INLINE void
-CopyAndDeflateLatin1Chars(Latin1Char* dest, const char16_t* src, size_t length)
-{
-#if defined(JS_HAS_SSE2_CHARACTER_OPERATIONS)
- size_t i = 0;
- const __m128i lowByteMask = _mm_set1_epi16(0xff);
- const __m128i zero = _mm_setzero_si128();
- for (; i + 32 <= length; i += 32) {
- const __m128i wide0 = _mm_loadu_si128(reinterpret_cast(src + i));
- const __m128i wide1 = _mm_loadu_si128(reinterpret_cast(src + i + 8));
- const __m128i wide2 = _mm_loadu_si128(reinterpret_cast(src + i + 16));
- const __m128i wide3 = _mm_loadu_si128(reinterpret_cast(src + i + 24));
- _mm_storel_epi64(reinterpret_cast<__m128i*>(dest + i),
- _mm_packus_epi16(_mm_and_si128(wide0, lowByteMask), zero));
- _mm_storel_epi64(reinterpret_cast<__m128i*>(dest + i + 8),
- _mm_packus_epi16(_mm_and_si128(wide1, lowByteMask), zero));
- _mm_storel_epi64(reinterpret_cast<__m128i*>(dest + i + 16),
- _mm_packus_epi16(_mm_and_si128(wide2, lowByteMask), zero));
- _mm_storel_epi64(reinterpret_cast<__m128i*>(dest + i + 24),
- _mm_packus_epi16(_mm_and_si128(wide3, lowByteMask), zero));
- }
- for (; i + 8 <= length; i += 8) {
- const __m128i wide = _mm_loadu_si128(reinterpret_cast(src + i));
- const __m128i lowBytes = _mm_and_si128(wide, lowByteMask);
- _mm_storel_epi64(reinterpret_cast<__m128i*>(dest + i),
- _mm_packus_epi16(lowBytes, zero));
- }
- for (; i < length; i++)
- dest[i] = Latin1Char(src[i]);
-#else
- for (size_t i = 0; i < length; i++)
- dest[i] = Latin1Char(src[i]);
-#endif
-}
-
template
static MOZ_ALWAYS_INLINE JSInlineString*
NewInlineStringDeflated(ExclusiveContext* cx, mozilla::Range chars)
@@ -1219,8 +1170,8 @@ NewInlineStringDeflated(ExclusiveContext* cx, mozilla::Range cha
for (size_t i = 0; i < len; i++) {
MOZ_ASSERT(chars[i] <= JSString::MAX_LATIN1_CHAR);
+ storage[i] = Latin1Char(chars[i]);
}
- CopyAndDeflateLatin1Chars(storage, chars.begin().get(), len);
storage[len] = '\0';
return str;
}
@@ -1259,8 +1210,8 @@ NewStringDeflated(ExclusiveContext* cx, const char16_t* s, size_t n)
for (size_t i = 0; i < n; i++) {
MOZ_ASSERT(s[i] <= JSString::MAX_LATIN1_CHAR);
+ news.get()[i] = Latin1Char(s[i]);
}
- CopyAndDeflateLatin1Chars(news.get(), s, n);
news[n] = '\0';
JSFlatString* str = JSFlatString::new_(cx, news.get(), n);
@@ -1362,7 +1313,7 @@ NewStringCopyNDontDeflate(ExclusiveContext* cx, const CharT* s, size_t n)
return nullptr;
}
- js_memcpy(news.get(), s, n * sizeof(CharT));
+ PodCopy(news.get(), s, n);
news[n] = 0;
JSFlatString* str = JSFlatString::new_(cx, news.get(), n);
diff --git a/js/src/vm/TypedArrayObject.cpp b/js/src/vm/TypedArrayObject.cpp
index 5a759db27f..22d21c8550 100644
--- a/js/src/vm/TypedArrayObject.cpp
+++ b/js/src/vm/TypedArrayObject.cpp
@@ -3413,22 +3413,6 @@ js::StringIsTypedArrayIndex(const CharT* s, size_t length, uint64_t* indexp)
index = digit;
- // Most typed-array accesses use one- or two-digit indices. Once the
- // digits have been validated, these forms cannot overflow uint64_t and
- // need no general-purpose accumulation loop.
- if (s == end) {
- *indexp = negative ? UINT64_MAX : index;
- return true;
- }
-
- if (end - s == 1) {
- if (!JS7_ISDEC(*s))
- return false;
- digit = JS7_UNDEC(*s);
- *indexp = negative ? UINT64_MAX : index * 10 + digit;
- return true;
- }
-
for (; s < end; s++) {
if (!JS7_ISDEC(*s))
return false;
diff --git a/js/src/vm/UnboxedObject-inl.h b/js/src/vm/UnboxedObject-inl.h
index 3a983e2f96..fa986a7575 100644
--- a/js/src/vm/UnboxedObject-inl.h
+++ b/js/src/vm/UnboxedObject-inl.h
@@ -583,9 +583,9 @@ MoveBoxedOrUnboxedDenseElements(JSContext* cx, JSObject* obj, uint32_t dstStart,
obj->as().triggerPreBarrier(dstStart + i);
}
- js_memmove(data + dstStart * elementSize,
- data + srcStart * elementSize,
- length * elementSize);
+ memmove(data + dstStart * elementSize,
+ data + srcStart * elementSize,
+ length * elementSize);
}
return DenseElementResult::Success;
@@ -619,9 +619,9 @@ CopyBoxedOrUnboxedDenseElements(JSContext* cx, JSObject* dst, JSObject* src,
uint8_t* srcData = src->as().elements();
size_t elementSize = UnboxedTypeSize(DstType);
- js_memcpy(dstData + dstStart * elementSize,
- srcData + srcStart * elementSize,
- length * elementSize);
+ memcpy(dstData + dstStart * elementSize,
+ srcData + srcStart * elementSize,
+ length * elementSize);
// Add a store buffer entry if we might have copied a nursery pointer to dst.
if (UnboxedTypeNeedsPostBarrier(DstType) && !IsInsideNursery(dst))
diff --git a/js/src/vm/UnboxedObject.cpp b/js/src/vm/UnboxedObject.cpp
index bfb5bbc7bc..2ed89e32e4 100644
--- a/js/src/vm/UnboxedObject.cpp
+++ b/js/src/vm/UnboxedObject.cpp
@@ -1895,7 +1895,7 @@ UnboxedPlainObject::fillAfterConvert(ExclusiveContext* cx,
Handle> values, size_t* valueCursor)
{
initExpando();
- js_memset(data(), 0, layout().size());
+ memset(data(), 0, layout().size());
for (size_t i = 0; i < layout().properties().length(); i++)
JS_ALWAYS_TRUE(setValue(cx, layout().properties()[i], NextValue(values, valueCursor)));
}
diff --git a/mfbt/HashFunctions.cpp b/mfbt/HashFunctions.cpp
index 63418401a2..6ba3c2d6e9 100644
--- a/mfbt/HashFunctions.cpp
+++ b/mfbt/HashFunctions.cpp
@@ -20,17 +20,7 @@ HashBytes(const void* aBytes, size_t aLength)
/* Walk word by word. */
size_t i = 0;
- const size_t wordLength = aLength - (aLength % sizeof(size_t));
- const size_t doubleWordLength = wordLength - (wordLength % (2 * sizeof(size_t)));
- for (; i < doubleWordLength; i += 2 * sizeof(size_t)) {
- size_t data0;
- size_t data1;
- memcpy(&data0, b + i, sizeof(data0));
- memcpy(&data1, b + i + sizeof(data0), sizeof(data1));
- hash = AddToHash(hash, data0, sizeof(data0));
- hash = AddToHash(hash, data1, sizeof(data1));
- }
- for (; i < wordLength; i += sizeof(size_t)) {
+ for (; i < aLength - (aLength % sizeof(size_t)); i += sizeof(size_t)) {
/* Do an explicitly unaligned load of the data. */
size_t data;
memcpy(&data, b + i, sizeof(size_t));
diff --git a/mfbt/HashFunctions.h b/mfbt/HashFunctions.h
index fa123d1085..d287081174 100644
--- a/mfbt/HashFunctions.h
+++ b/mfbt/HashFunctions.h
@@ -230,17 +230,8 @@ uint32_t
HashKnownLength(const T* aStr, size_t aLength)
{
uint32_t hash = 0;
- while (aLength >= 4) {
- hash = AddToHash(hash, aStr[0]);
- hash = AddToHash(hash, aStr[1]);
- hash = AddToHash(hash, aStr[2]);
- hash = AddToHash(hash, aStr[3]);
- aStr += 4;
- aLength -= 4;
- }
- while (aLength) {
- hash = AddToHash(hash, *aStr++);
- --aLength;
+ for (size_t i = 0; i < aLength; i++) {
+ hash = AddToHash(hash, aStr[i]);
}
return hash;
}
diff --git a/toolkit/components/webextensions/ExtensionChild.jsm b/toolkit/components/webextensions/ExtensionChild.jsm
index 5dc4e22779..592271c00b 100644
--- a/toolkit/components/webextensions/ExtensionChild.jsm
+++ b/toolkit/components/webextensions/ExtensionChild.jsm
@@ -518,7 +518,8 @@ class ProxyAPIImplementation extends SchemaAPIInterface {
map.ids.set(id, listener);
map.listeners.set(listener, id);
- this.childApiManager.messageManager.sendAsyncMessage("API:AddListener", {
+ MessageChannel.sendAsyncMessage(this.childApiManager.messageManager,
+ "API:AddListener", {
childId: this.childApiManager.id,
listenerId: id,
path: this.path,
@@ -537,7 +538,8 @@ class ProxyAPIImplementation extends SchemaAPIInterface {
map.listeners.delete(listener);
map.ids.delete(id);
- this.childApiManager.messageManager.sendAsyncMessage("API:RemoveListener", {
+ MessageChannel.sendAsyncMessage(this.childApiManager.messageManager,
+ "API:RemoveListener", {
childId: this.childApiManager.id,
listenerId: id,
path: this.path,
@@ -587,7 +589,8 @@ class ChildAPIManager {
};
Object.assign(params, contextData);
- this.messageManager.sendAsyncMessage("API:CreateProxyContext", params);
+ MessageChannel.sendAsyncMessage(this.messageManager,
+ "API:CreateProxyContext", params);
}
receiveMessage({name, messageName, data}) {
@@ -626,7 +629,7 @@ class ChildAPIManager {
* @param {Array} args The parameters for the function.
*/
callParentFunctionNoReturn(path, args) {
- this.messageManager.sendAsyncMessage("API:Call", {
+ MessageChannel.sendAsyncMessage(this.messageManager, "API:Call", {
childId: this.id,
path,
args,
@@ -649,7 +652,7 @@ class ChildAPIManager {
let deferred = PromiseUtils.defer();
this.callPromises.set(callId, deferred);
- this.messageManager.sendAsyncMessage("API:Call", {
+ MessageChannel.sendAsyncMessage(this.messageManager, "API:Call", {
childId: this.id,
callId,
path,
@@ -684,7 +687,8 @@ class ChildAPIManager {
}
close() {
- this.messageManager.sendAsyncMessage("API:CloseProxyContext", {childId: this.id});
+ MessageChannel.sendAsyncMessage(this.messageManager,
+ "API:CloseProxyContext", {childId: this.id});
}
get cloneScope() {
@@ -773,6 +777,41 @@ class ExtensionPageContextChild extends BaseContext {
}
this.sender = sender;
+ // Older UXP WebIDL bindings throw synchronously when extensions use
+ // createImageBitmap() as a zero-argument feature probe. Keep valid calls
+ // native, but make the probe harmless in extension pages.
+ if (typeof contentWindow.createImageBitmap == "function") {
+ let nativeCreateImageBitmap = contentWindow.createImageBitmap;
+ let extensionCreateImageBitmap = function(...args) {
+ if (args.length == 0) {
+ return contentWindow.Promise.resolve(null);
+ }
+ return nativeCreateImageBitmap.apply(this, args);
+ };
+ try {
+ // Some older bindings reject assignment to the WebIDL method. Define
+ // an own property on this extension window so no other window is
+ // affected.
+ Object.defineProperty(contentWindow, "createImageBitmap", {
+ configurable: true,
+ enumerable: true,
+ writable: true,
+ value: extensionCreateImageBitmap,
+ });
+ } catch (e) {
+ try {
+ // This also works through the Window Xray wrapper used by older
+ // UXP extension globals.
+ Cu.exportFunction(extensionCreateImageBitmap, contentWindow,
+ {defineAs: "createImageBitmap"});
+ } catch (e2) {
+ try {
+ contentWindow.createImageBitmap = extensionCreateImageBitmap;
+ } catch (e3) {}
+ }
+ }
+ }
+
Schemas.exportLazyGetter(contentWindow, "browser", () => {
let browserObj = Cu.createObjectIn(contentWindow);
Schemas.inject(browserObj, this.childManager);
@@ -1055,4 +1094,3 @@ Object.assign(ExtensionChild, {
Messenger,
Port,
});
-
diff --git a/toolkit/components/webextensions/ExtensionStorage.jsm b/toolkit/components/webextensions/ExtensionStorage.jsm
index 0b0ffb0003..728cba728c 100644
--- a/toolkit/components/webextensions/ExtensionStorage.jsm
+++ b/toolkit/components/webextensions/ExtensionStorage.jsm
@@ -197,6 +197,19 @@ this.ExtensionStorage = {
});
},
+ getManaged(keys) {
+ // Managed storage is populated by enterprise policy, which this UXP
+ // branch does not implement. Return the requested defaults, matching the
+ // WebExtension storage contract for an empty managed area.
+ if (keys === null || keys === undefined) {
+ return Promise.resolve({});
+ }
+ if (typeof(keys) == "object" && !Array.isArray(keys)) {
+ return Promise.resolve(Object.assign({}, keys));
+ }
+ return Promise.resolve({});
+ },
+
addOnChangedListener(extensionId, listener) {
let listeners = this.listeners.get(extensionId) || new Set();
listeners.add(listener);
diff --git a/toolkit/components/webextensions/ExtensionUtils.jsm b/toolkit/components/webextensions/ExtensionUtils.jsm
index 04e767cb5c..af4df1bb39 100644
--- a/toolkit/components/webextensions/ExtensionUtils.jsm
+++ b/toolkit/components/webextensions/ExtensionUtils.jsm
@@ -434,6 +434,13 @@ LocaleData.prototype = {
options = Object.assign(defaultOptions, options);
+ // Some extensions probe optional localization attributes with an empty
+ // value. There is no message to look up in that case; avoid turning the
+ // probe into a misleading "Unknown localization message" warning.
+ if (message == null || message === "") {
+ return options.defaultValue;
+ }
+
let locales = new Set([this.BUILTIN, options.locale, this.defaultLocale]
.filter(locale => this.messages.has(locale)));
@@ -743,9 +750,12 @@ SingletonEventManager.prototype = {
};
// Simple API for event listeners where events never fire.
-function ignoreEvent(context, name) {
+function ignoreEvent(context, name, warn = true) {
return {
addListener: function(callback) {
+ if (!warn) {
+ return;
+ }
let id = context.extension.id;
let frame = Components.stack.caller;
let msg = `In add-on ${id}, attempting to use listener "${name}", which is unimplemented.`;
@@ -1088,8 +1098,8 @@ class MessageManagerProxy {
if (this.messageManager) {
return this.messageManager.sendAsyncMessage(...args);
}
- /* globals uneval */
- Cu.reportError(`Cannot send message: Other side disconnected: ${uneval(args)}`);
+ // Message senders can outlive their child process during normal teardown.
+ // Treat this as a dropped message instead of reporting a spurious error.
}
/**
diff --git a/toolkit/components/webextensions/MessageChannel.jsm b/toolkit/components/webextensions/MessageChannel.jsm
index c5b326405d..e418bafd2d 100644
--- a/toolkit/components/webextensions/MessageChannel.jsm
+++ b/toolkit/components/webextensions/MessageChannel.jsm
@@ -278,7 +278,72 @@ class FilteringMessageManagerMap extends Map {
const MESSAGE_MESSAGE = "MessageChannel:Message";
const MESSAGE_RESPONSE = "MessageChannel:Response";
+function makeMessageCloneable(value, seen = new Set()) {
+ if (value === null || value === undefined ||
+ typeof value == "string" || typeof value == "number" ||
+ typeof value == "boolean") {
+ return value;
+ }
+ if (typeof value != "object") {
+ return undefined;
+ }
+
+ try {
+ if (value instanceof Ci.nsIURI) {
+ return value.spec;
+ }
+ if (value instanceof Ci.nsIFile) {
+ return value.path;
+ }
+ } catch (e) {}
+
+ if (seen.has(value)) {
+ return undefined;
+ }
+ seen.add(value);
+
+ let className;
+ try {
+ className = Cu.getClassName(value, true);
+ } catch (e) {
+ return undefined;
+ }
+ if (className == "Array") {
+ return value.map(item => makeMessageCloneable(item, seen));
+ }
+ if (className != "Object") {
+ return undefined;
+ }
+
+ let result = {};
+ for (let key of Object.keys(value)) {
+ let item = makeMessageCloneable(value[key], seen);
+ if (item !== undefined) {
+ result[key] = item;
+ }
+ }
+ return result;
+}
+
+function sendMessageWithCloneFallback(target, name, data) {
+ try {
+ target.sendAsyncMessage(name, data);
+ } catch (e) {
+ let message = String(e && e.message || e);
+ if (!e || (e.result != Cr.NS_ERROR_DOM_DATA_CLONE_ERR &&
+ message.indexOf("clone") == -1)) {
+ throw e;
+ }
+ target.sendAsyncMessage(name, makeMessageCloneable(data));
+ }
+}
+
this.MessageChannel = {
+ // Keep direct extension API messages on the clone-safe UXP path too.
+ sendAsyncMessage(target, name, data) {
+ sendMessageWithCloneFallback(target, name, data);
+ },
+
init() {
Services.obs.addObserver(this, "message-manager-close", false);
Services.obs.addObserver(this, "message-manager-disconnect", false);
@@ -517,7 +582,7 @@ this.MessageChannel = {
if (responseType == this.RESPONSE_NONE) {
try {
- target.sendAsyncMessage(MESSAGE_MESSAGE, message);
+ sendMessageWithCloneFallback(target, MESSAGE_MESSAGE, message);
} catch (e) {
// Caller is not expecting a reply, so dump the error to the console.
Cu.reportError(e);
@@ -544,7 +609,7 @@ this.MessageChannel = {
deferred.promise.then(cleanup, cleanup);
try {
- target.sendAsyncMessage(MESSAGE_MESSAGE, message);
+ sendMessageWithCloneFallback(target, MESSAGE_MESSAGE, message);
} catch (e) {
deferred.reject(e);
}
@@ -644,7 +709,7 @@ this.MessageChannel = {
value,
};
- target.sendAsyncMessage(MESSAGE_RESPONSE, response);
+ sendMessageWithCloneFallback(target, MESSAGE_RESPONSE, response);
},
error => {
let response = {
@@ -668,7 +733,7 @@ this.MessageChannel = {
}
}
- target.sendAsyncMessage(MESSAGE_RESPONSE, response);
+ sendMessageWithCloneFallback(target, MESSAGE_RESPONSE, response);
}).catch(e => {
Cu.reportError(e);
}).then(() => {
diff --git a/toolkit/components/webextensions/ext-c-storage.js b/toolkit/components/webextensions/ext-c-storage.js
index e8d53058f6..34abcd2254 100644
--- a/toolkit/components/webextensions/ext-c-storage.js
+++ b/toolkit/components/webextensions/ext-c-storage.js
@@ -41,6 +41,27 @@ function storageApiFactory(context) {
},
},
+ managed: {
+ get: function(keys) {
+ keys = sanitize(keys);
+ return context.childManager.callParentAsyncFunction("storage.managed.get", [
+ keys,
+ ]);
+ },
+ set: function() {
+ throw new context.cloneScope.Error(
+ "storage.managed is read-only");
+ },
+ remove: function() {
+ throw new context.cloneScope.Error(
+ "storage.managed is read-only");
+ },
+ clear: function() {
+ throw new context.cloneScope.Error(
+ "storage.managed is read-only");
+ },
+ },
+
sync: {
get: function(keys) {
keys = sanitize(keys);
diff --git a/toolkit/components/webextensions/ext-storage.js b/toolkit/components/webextensions/ext-storage.js
index b1e22c46c0..4bc5168fd1 100644
--- a/toolkit/components/webextensions/ext-storage.js
+++ b/toolkit/components/webextensions/ext-storage.js
@@ -29,6 +29,27 @@ function storageApiFactory(context) {
},
},
+ // UXP has no enterprise managed-storage backend. Expose the namespace
+ // as an empty, read-only area so extensions can feature-detect it and
+ // continue using their defaults.
+ managed: {
+ get: function(spec) {
+ return ExtensionStorage.getManaged(spec);
+ },
+ set: function() {
+ throw new context.cloneScope.Error(
+ "storage.managed is read-only");
+ },
+ remove: function() {
+ throw new context.cloneScope.Error(
+ "storage.managed is read-only");
+ },
+ clear: function() {
+ throw new context.cloneScope.Error(
+ "storage.managed is read-only");
+ },
+ },
+
onChanged: new EventManager(context, "storage.onChanged", fire => {
let listenerLocal = changes => {
fire(changes, "local");
diff --git a/toolkit/components/webextensions/moz.build b/toolkit/components/webextensions/moz.build
index a38f17c380..b8d5641d74 100644
--- a/toolkit/components/webextensions/moz.build
+++ b/toolkit/components/webextensions/moz.build
@@ -12,7 +12,6 @@ EXTRA_JS_MODULES += [
'ExtensionContent.jsm',
'ExtensionManagement.jsm',
'ExtensionParent.jsm',
-# 'ExtensionStorage.jsm',
'ExtensionUtils.jsm',
'LegacyExtensionsUtils.jsm',
'MessageChannel.jsm',
diff --git a/toolkit/components/webextensions/schemas/manifest.json b/toolkit/components/webextensions/schemas/manifest.json
index 291e668323..b78bde34db 100644
--- a/toolkit/components/webextensions/schemas/manifest.json
+++ b/toolkit/components/webextensions/schemas/manifest.json
@@ -183,6 +183,29 @@
"optional": true
},
+ "optional_permissions": {
+ "type": "array",
+ "items": {
+ "choices": [
+ { "$ref": "Permission" },
+ {
+ "type": "string",
+ "deprecated": "Unknown optional permission ${value}"
+ }
+ ]
+ },
+ "optional": true
+ },
+
+ "user_scripts": {
+ "type": "object",
+ "optional": true,
+ "properties": {
+ "api_script": { "$ref": "ExtensionURL" }
+ },
+ "additionalProperties": { "$ref": "UnrecognizedProperty" }
+ },
+
"web_accessible_resources": {
"type": "array",
"items": { "type": "string" },
@@ -218,10 +241,13 @@
"enum": [
"alarms",
"clipboardWrite",
+ "contextualIdentities",
"dns",
"idle",
+ "menus",
"notifications",
"privacy",
+ "proxy",
"storage"
,"unlimitedStorage"
]
@@ -386,8 +412,7 @@
},
{
"id": "PersistentBackgroundProperty",
- "type": "boolean",
- "deprecated": "Event pages are not currently supported. This will run as a persistent background page."
+ "type": "boolean"
}
]
}
diff --git a/toolkit/components/webextensions/schemas/storage.json b/toolkit/components/webextensions/schemas/storage.json
index a54a209424..35e3931902 100644
--- a/toolkit/components/webextensions/schemas/storage.json
+++ b/toolkit/components/webextensions/schemas/storage.json
@@ -220,7 +220,6 @@
}
},
"managed": {
- "unsupported": true,
"$ref": "StorageArea",
"description": "Items in the managed storage area are set by the domain administrator, and are read-only for the extension; trying to modify this namespace results in an error."
}
diff --git a/toolkit/components/webextensions/test/xpcshell/test_match_pattern_schemes.js b/toolkit/components/webextensions/test/xpcshell/test_match_pattern_schemes.js
new file mode 100644
index 0000000000..1afc7b5bcf
--- /dev/null
+++ b/toolkit/components/webextensions/test/xpcshell/test_match_pattern_schemes.js
@@ -0,0 +1,26 @@
+"use strict";
+
+add_task(function* test_explicit_webextension_schemes() {
+ let {MatchPattern} = Cu.import("resource://gre/modules/MatchPattern.jsm", {});
+ let patterns = [
+ ["moz-extension://6e20d047-ef47-41c0-a95f-93aa35f1798d/web_accessible_resources/*",
+ "moz-extension://6e20d047-ef47-41c0-a95f-93aa35f1798d/web_accessible_resources/file.js"],
+ ["ws://*/*", "ws://example.com/socket"],
+ ["wss://*/*", "wss://example.com/socket"],
+ ];
+
+ for (let [pattern, url] of patterns) {
+ let matcher = new MatchPattern(pattern);
+ ok(matcher.matches(Services.io.newURI(url, null, null)),
+ `explicit scheme is accepted: ${pattern}`);
+ }
+});
+
+add_task(function* test_wildcard_remains_web_only() {
+ let {MatchPattern} = Cu.import("resource://gre/modules/MatchPattern.jsm", {});
+ let matcher = new MatchPattern("*://*/*");
+ ok(!matcher.matches(Services.io.newURI("ws://example.com/socket", null, null)),
+ "scheme wildcard does not implicitly include WebSockets");
+ ok(!matcher.matches(Services.io.newURI("moz-extension://example/", null, null)),
+ "scheme wildcard does not include extension URLs");
+});
diff --git a/toolkit/components/webextensions/test/xpcshell/xpcshell.ini b/toolkit/components/webextensions/test/xpcshell/xpcshell.ini
index 7abf9fe3cd..bad1b67f13 100644
--- a/toolkit/components/webextensions/test/xpcshell/xpcshell.ini
+++ b/toolkit/components/webextensions/test/xpcshell/xpcshell.ini
@@ -9,6 +9,7 @@ tags = webextensions
[test_csp_custom_policies.js]
[test_webrequest_backend.js]
+[test_match_pattern_schemes.js]
[test_webnavigation_created_target.js]
[test_csp_validator.js]
[test_ext_alarms.js]
diff --git a/toolkit/modules/ExtensionStorage.jsm b/toolkit/modules/ExtensionStorage.jsm
index 0b0ffb0003..728cba728c 100644
--- a/toolkit/modules/ExtensionStorage.jsm
+++ b/toolkit/modules/ExtensionStorage.jsm
@@ -197,6 +197,19 @@ this.ExtensionStorage = {
});
},
+ getManaged(keys) {
+ // Managed storage is populated by enterprise policy, which this UXP
+ // branch does not implement. Return the requested defaults, matching the
+ // WebExtension storage contract for an empty managed area.
+ if (keys === null || keys === undefined) {
+ return Promise.resolve({});
+ }
+ if (typeof(keys) == "object" && !Array.isArray(keys)) {
+ return Promise.resolve(Object.assign({}, keys));
+ }
+ return Promise.resolve({});
+ },
+
addOnChangedListener(extensionId, listener) {
let listeners = this.listeners.get(extensionId) || new Set();
listeners.add(listener);
diff --git a/toolkit/modules/addons/MatchPattern.jsm b/toolkit/modules/addons/MatchPattern.jsm
index 4dff81fd23..e46102b75d 100644
--- a/toolkit/modules/addons/MatchPattern.jsm
+++ b/toolkit/modules/addons/MatchPattern.jsm
@@ -18,7 +18,11 @@ this.EXPORTED_SYMBOLS = ["MatchPattern", "MatchGlobs", "MatchURLFilters"];
/* globals MatchPattern, MatchGlobs */
-const PERMITTED_SCHEMES = ["http", "https", "file", "ftp", "data"];
+// Keep explicit scheme support broad enough for WebExtensions, while the
+// match-pattern wildcard remains restricted to web content schemes below.
+const PERMITTED_SCHEMES = ["http", "https", "file", "ftp", "data",
+ "ws", "wss", "moz-extension"];
+const ALL_URLS_SCHEMES = ["http", "https", "file", "ftp", "data", "ws", "wss"];
const PERMITTED_SCHEMES_REGEXP = PERMITTED_SCHEMES.join("|");
// This function converts a glob pattern (containing * and possibly ?
@@ -40,7 +44,7 @@ function globToRegexp(pat, allowQuestion) {
// https://developer.chrome.com/extensions/match_patterns
function SingleMatchPattern(pat) {
if (pat == "") {
- this.schemes = PERMITTED_SCHEMES;
+ this.schemes = ALL_URLS_SCHEMES;
this.hostMatch = () => true;
this.pathMatch = () => true;
} else if (!pat) {
@@ -85,9 +89,22 @@ SingleMatchPattern.prototype = {
let suffix = host.substr(2);
let dotSuffix = "." + suffix;
- return ({host}) => host === suffix || host.endsWith(dotSuffix);
+ return uri => {
+ try {
+ let host = uri.host;
+ return host === suffix || host.endsWith(dotSuffix);
+ } catch (e) {
+ return false;
+ }
+ };
}
- return uri => uri.host === host;
+ return uri => {
+ try {
+ return uri.host === host;
+ } catch (e) {
+ return false;
+ }
+ };
},
matches(uri, ignorePath = false) {
diff --git a/toolkit/mozapps/webextensions/AddonManager.jsm b/toolkit/mozapps/webextensions/AddonManager.jsm
index 1203ec0da2..380fcde848 100644
--- a/toolkit/mozapps/webextensions/AddonManager.jsm
+++ b/toolkit/mozapps/webextensions/AddonManager.jsm
@@ -321,13 +321,60 @@ function webAPIForAddon(addon) {
let result = {};
+ function cloneable(value, seen = new Set()) {
+ if (value === null || value === undefined ||
+ typeof value == "string" || typeof value == "number" ||
+ typeof value == "boolean") {
+ return value;
+ }
+
+ if (typeof value != "object") {
+ return undefined;
+ }
+
+ // Older message managers cannot structured-clone these XPCOM values.
+ try {
+ if (value instanceof Ci.nsIURI) {
+ return value.spec;
+ }
+ if (value instanceof Ci.nsIFile) {
+ return value.path;
+ }
+ } catch (e) {}
+
+ if (seen.has(value)) {
+ return undefined;
+ }
+ seen.add(value);
+
+ let className = Cu.getClassName(value, true);
+ if (className == "Array") {
+ return value.map(item => cloneable(item, seen));
+ }
+ if (className != "Object") {
+ return undefined;
+ }
+
+ let copy = {};
+ for (let key of Object.keys(value)) {
+ let item = cloneable(value[key], seen);
+ if (item !== undefined) {
+ copy[key] = item;
+ }
+ }
+ return copy;
+ }
+
// By default just pass through any plain property, the webidl will
// control access. Also filter out private properties, regular Addon
// objects are okay but MockAddon used in tests has non-serializable
// private properties.
for (let prop in addon) {
if (prop[0] != "_" && typeof(addon[prop]) != "function") {
- result[prop] = addon[prop];
+ let value = cloneable(addon[prop]);
+ if (value !== undefined) {
+ result[prop] = value;
+ }
}
}
diff --git a/toolkit/mozapps/webextensions/addonManager.js b/toolkit/mozapps/webextensions/addonManager.js
index d34cbaf624..9113f5eb37 100644
--- a/toolkit/mozapps/webextensions/addonManager.js
+++ b/toolkit/mozapps/webextensions/addonManager.js
@@ -36,6 +36,20 @@ const CHILD_SCRIPT = "resource://gre/modules/addons/Content.js";
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
+function deserializeTriggeringPrincipal(principal) {
+ if (typeof principal != "string") {
+ return principal;
+ }
+ try {
+ return Cc["@mozilla.org/network/serialization-helper;1"]
+ .getService(Ci.nsISerializationHelper)
+ .deserializeObject(principal)
+ .QueryInterface(Ci.nsIPrincipal);
+ } catch (e) {
+ return null;
+ }
+}
+
var gSingleton = null;
function amManager() {
@@ -219,7 +233,7 @@ amManager.prototype = {
}
return this.installAddonsFromWebpage(payload.mimetype,
- aMessage.target, payload.triggeringPrincipal, payload.uris,
+ aMessage.target, deserializeTriggeringPrincipal(payload.triggeringPrincipal), payload.uris,
payload.hashes, payload.names, payload.icons, callback);
}
diff --git a/toolkit/mozapps/webextensions/amInstallTrigger.js b/toolkit/mozapps/webextensions/amInstallTrigger.js
index 382791d326..31e98b9865 100644
--- a/toolkit/mozapps/webextensions/amInstallTrigger.js
+++ b/toolkit/mozapps/webextensions/amInstallTrigger.js
@@ -76,7 +76,11 @@ RemoteMediator.prototype = {
let callbackID = this._addCallback(callback, installs.uris);
installs.mimetype = XPINSTALL_MIMETYPE;
- installs.triggeringPrincipal = principal;
+ // nsIPrincipal is an XPCOM object and cannot cross the legacy message
+ // manager boundary used by content processes. Serialize it explicitly.
+ installs.triggeringPrincipal = Cc["@mozilla.org/network/serialization-helper;1"]
+ .getService(Ci.nsISerializationHelper)
+ .serializeToString(principal);
installs.callbackID = callbackID;
if (Services.appinfo.processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT) {