mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-20 23:37:33 +09:00
Compare commits
19 commits
5f2a3dd028
...
f3ce3c21ee
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f3ce3c21ee | ||
|
|
e98942c307 | ||
|
|
a16ea2362b | ||
|
|
990887b8af | ||
|
|
5f127cd9f8 | ||
|
|
cc3106406f | ||
|
|
5ac0d5acc3 | ||
|
|
e5a431b519 | ||
|
|
f20132edb0 | ||
|
|
bb1928da05 | ||
|
|
dbc2b42c7f | ||
|
|
1b90447aa4 | ||
|
|
a69e982b98 | ||
|
|
0ff6a01974 | ||
|
|
5eb353096b | ||
|
|
5bf0a6f099 | ||
|
|
639d4eb85f | ||
|
|
38d4836a94 | ||
|
|
57592e04c9 |
59 changed files with 555 additions and 916 deletions
|
|
@ -1,6 +1,6 @@
|
|||
<img src="browser/branding/unofficial/content/about-wordmark.svg" alt="Dactyloidae web browser" height="60">
|
||||
<br>
|
||||
<a href="https://discord.gg/ycmQAMej77">Official Discord server</a>
|
||||
<a href="https://discord.gg/ycmQAMej77">Official Discord server</a> | <a href="https://t.me/dactyloidae">Official Telegram channel</a>
|
||||
<br><br>
|
||||
<img src="docs/readme/demo.png" height="500">
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -31,6 +31,11 @@
|
|||
"browser_style": {
|
||||
"type": "boolean",
|
||||
"optional": true
|
||||
},
|
||||
"default_area": {
|
||||
"type": "string",
|
||||
"enum": ["navbar", "menupanel", "tabstrip", "personaltoolbar"],
|
||||
"optional": true
|
||||
}
|
||||
},
|
||||
"optional": true
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
{
|
||||
"namespace": "contextMenus",
|
||||
"description": "Use the <code>browser.contextMenus</code> 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,
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -2040,7 +2040,7 @@ InlineTypedObject::createCopy(JSContext* cx, Handle<InlineTypedObject*> 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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -150,7 +150,7 @@ struct BaselineStackBuilder
|
|||
uint8_t* newBuffer = reinterpret_cast<uint8_t*>(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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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<char*>(buf);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<UnboxedArrayObject>().elements();
|
||||
size_t elementSize = UnboxedTypeSize(Type);
|
||||
js_memmove(data, data + elementSize, initlen * elementSize);
|
||||
memmove(data, data + elementSize, initlen * elementSize);
|
||||
}
|
||||
|
||||
return DenseElementResult::Success;
|
||||
|
|
|
|||
|
|
@ -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<PropertyName*>
|
||||
|
|
|
|||
|
|
@ -12,8 +12,6 @@
|
|||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#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 <emmintrin.h>
|
||||
#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<const __m128i*>(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<const __m128i*>(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 */
|
||||
|
|
|
|||
|
|
@ -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<JSFunction>().fixedSlots(), 0, size - sizeof(js::NativeObject));
|
||||
memset(obj->as<JSFunction>().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.
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
159
js/src/jsstr.cpp
159
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 <typename DestChar, typename SrcChar>
|
||||
static inline void
|
||||
CopyChars(DestChar* destChars, const SrcChar* srcChars, size_t length)
|
||||
|
|
@ -1717,16 +1706,6 @@ template <class InnerMatch, typename TextChar, typename PatChar>
|
|||
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<const char16_t*>(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<const TextChar*>(
|
||||
FindCharacter(reinterpret_cast<const char16_t*>(text) + i,
|
||||
n - i, char16_t(pat[0])));
|
||||
else
|
||||
pos = (TextChar*) FirstCharMatcherUnrolled<TextChar, PatChar>(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<int32_t>(t - text);
|
||||
searchLength = static_cast<size_t>(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 <typename CharT>
|
|||
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<char16_t>(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<const __m128i*>(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 <typename CharT>
|
||||
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<const __m128i*>(src + i));
|
||||
const __m128i wide1 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(src + i + 8));
|
||||
const __m128i wide2 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(src + i + 16));
|
||||
const __m128i wide3 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(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<const __m128i*>(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 <typename CharT>
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
259
js/src/jsstr.h
259
js/src/jsstr.h
|
|
@ -53,100 +53,7 @@ template <typename Char1, typename Char2>
|
|||
inline int32_t
|
||||
CompareChars(const Char1* s1, size_t len1, const Char2* s2, size_t len2)
|
||||
{
|
||||
if (mozilla::IsSame<Char1, Char2>::value &&
|
||||
reinterpret_cast<const void*>(s1) == reinterpret_cast<const void*>(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<const uint8_t*>(s1);
|
||||
const uint8_t* right = reinterpret_cast<const uint8_t*>(s2);
|
||||
while (n >= 16) {
|
||||
const __m128i leftBlock = _mm_loadu_si128(reinterpret_cast<const __m128i*>(left));
|
||||
const __m128i rightBlock = _mm_loadu_si128(reinterpret_cast<const __m128i*>(right));
|
||||
const uint32_t equalMask = static_cast<uint32_t>(
|
||||
_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<const Char1*>(left);
|
||||
s2 = reinterpret_cast<const Char2*>(right);
|
||||
} else if (sizeof(Char1) == 2 && sizeof(Char2) == 2) {
|
||||
const char16_t* left = reinterpret_cast<const char16_t*>(s1);
|
||||
const char16_t* right = reinterpret_cast<const char16_t*>(s2);
|
||||
while (n >= 8) {
|
||||
const __m128i leftBlock = _mm_loadu_si128(reinterpret_cast<const __m128i*>(left));
|
||||
const __m128i rightBlock = _mm_loadu_si128(reinterpret_cast<const __m128i*>(right));
|
||||
const uint32_t equalMask = static_cast<uint32_t>(
|
||||
_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<const Char1*>(left);
|
||||
s2 = reinterpret_cast<const Char2*>(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<const uint8_t*>(s1);
|
||||
const char16_t* wide = reinterpret_cast<const char16_t*>(s2);
|
||||
const __m128i zero = _mm_setzero_si128();
|
||||
while (n >= 8) {
|
||||
const __m128i byteBlock = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(bytes));
|
||||
const __m128i wideBlock = _mm_loadu_si128(reinterpret_cast<const __m128i*>(wide));
|
||||
const __m128i expanded = _mm_unpacklo_epi8(byteBlock, zero);
|
||||
const uint32_t equalMask = static_cast<uint32_t>(
|
||||
_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<const Char1*>(bytes);
|
||||
s2 = reinterpret_cast<const Char2*>(wide);
|
||||
} else if (sizeof(Char1) == 2 && sizeof(Char2) == 1) {
|
||||
const char16_t* wide = reinterpret_cast<const char16_t*>(s1);
|
||||
const uint8_t* bytes = reinterpret_cast<const uint8_t*>(s2);
|
||||
const __m128i zero = _mm_setzero_si128();
|
||||
while (n >= 8) {
|
||||
const __m128i wideBlock = _mm_loadu_si128(reinterpret_cast<const __m128i*>(wide));
|
||||
const __m128i byteBlock = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(bytes));
|
||||
const __m128i expanded = _mm_unpacklo_epi8(byteBlock, zero);
|
||||
const uint32_t equalMask = static_cast<uint32_t>(
|
||||
_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<const Char1*>(wide);
|
||||
s2 = reinterpret_cast<const Char2*>(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 <typename Char1>
|
|||
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<const uint8_t*>(s1);
|
||||
const uint8_t* right = reinterpret_cast<const uint8_t*>(s2);
|
||||
while (len >= 64) {
|
||||
for (unsigned block = 0; block < 4; block++) {
|
||||
const __m128i leftBlock = _mm_loadu_si128(
|
||||
reinterpret_cast<const __m128i*>(left + block * 16));
|
||||
const __m128i rightBlock = _mm_loadu_si128(
|
||||
reinterpret_cast<const __m128i*>(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<const __m128i*>(left));
|
||||
const __m128i rightBlock = _mm_loadu_si128(reinterpret_cast<const __m128i*>(right));
|
||||
if (_mm_movemask_epi8(_mm_cmpeq_epi8(leftBlock, rightBlock)) != 0xffff)
|
||||
return false;
|
||||
left += 16;
|
||||
right += 16;
|
||||
len -= 16;
|
||||
}
|
||||
s1 = reinterpret_cast<const Char1*>(left);
|
||||
s2 = reinterpret_cast<const Char1*>(right);
|
||||
} else if (sizeof(Char1) == 2) {
|
||||
const char16_t* left = reinterpret_cast<const char16_t*>(s1);
|
||||
const char16_t* right = reinterpret_cast<const char16_t*>(s2);
|
||||
while (len >= 32) {
|
||||
for (unsigned block = 0; block < 4; block++) {
|
||||
const __m128i leftBlock = _mm_loadu_si128(
|
||||
reinterpret_cast<const __m128i*>(left + block * 8));
|
||||
const __m128i rightBlock = _mm_loadu_si128(
|
||||
reinterpret_cast<const __m128i*>(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<const __m128i*>(left));
|
||||
const __m128i rightBlock = _mm_loadu_si128(reinterpret_cast<const __m128i*>(right));
|
||||
if (_mm_movemask_epi8(_mm_cmpeq_epi16(leftBlock, rightBlock)) != 0xffff)
|
||||
return false;
|
||||
left += 8;
|
||||
right += 8;
|
||||
len -= 8;
|
||||
}
|
||||
s1 = reinterpret_cast<const Char1*>(left);
|
||||
s2 = reinterpret_cast<const Char1*>(right);
|
||||
}
|
||||
#endif
|
||||
|
||||
return mozilla::PodEqual(s1, s2, len);
|
||||
}
|
||||
|
||||
|
|
@ -413,45 +259,6 @@ template <typename Char1, typename Char2>
|
|||
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<const uint8_t*>(s1);
|
||||
const char16_t* wide = reinterpret_cast<const char16_t*>(s2);
|
||||
const __m128i zero = _mm_setzero_si128();
|
||||
while (len >= 8) {
|
||||
const __m128i byteBlock = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(bytes));
|
||||
const __m128i wideBlock = _mm_loadu_si128(reinterpret_cast<const __m128i*>(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<const Char1*>(bytes);
|
||||
s2 = reinterpret_cast<const Char2*>(wide);
|
||||
} else if (sizeof(Char1) == 2 && sizeof(Char2) == 1) {
|
||||
const char16_t* wide = reinterpret_cast<const char16_t*>(s1);
|
||||
const uint8_t* bytes = reinterpret_cast<const uint8_t*>(s2);
|
||||
const __m128i zero = _mm_setzero_si128();
|
||||
while (len >= 8) {
|
||||
const __m128i wideBlock = _mm_loadu_si128(reinterpret_cast<const __m128i*>(wide));
|
||||
const __m128i byteBlock = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(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<const Char1*>(wide);
|
||||
s2 = reinterpret_cast<const Char2*>(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<int64_t>(value0));
|
||||
const __m128i bytes1 = _mm_cvtsi64_si128(static_cast<int64_t>(value1));
|
||||
const __m128i bytes2 = _mm_cvtsi64_si128(static_cast<int64_t>(value2));
|
||||
const __m128i bytes3 = _mm_cvtsi64_si128(static_cast<int64_t>(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<int64_t>(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<int64_t>(value0));
|
||||
const __m128i bytes1 = _mm_cvtsi64_si128(static_cast<int64_t>(value1));
|
||||
const __m128i bytes2 = _mm_cvtsi64_si128(static_cast<int64_t>(value2));
|
||||
const __m128i bytes3 = _mm_cvtsi64_si128(static_cast<int64_t>(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<int64_t>(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
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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<uint8_t*>(nsrc->data()), nbytes);
|
||||
mozilla::PodCopy(data, reinterpret_cast<uint8_t*>(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<uint8_t*>(srcRareData), nbytes);
|
||||
mozilla::PodCopy(dstRareData, reinterpret_cast<uint8_t*>(srcRareData), nbytes);
|
||||
nbytesTotal += nbytes;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -656,7 +656,7 @@ ResizeArrayBuffer(JSContext* cx, Handle<ArrayBufferObject*> 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 {
|
||||
|
|
|
|||
|
|
@ -9,12 +9,10 @@
|
|||
#include "mozilla/Sprintf.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <string.h>
|
||||
#include <type_traits>
|
||||
|
||||
#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<unsigned char>(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<const __m128i*>(tbchars.begin().get() + i));
|
||||
const __m128i wide1 = _mm_loadu_si128(
|
||||
reinterpret_cast<const __m128i*>(tbchars.begin().get() + i + 8));
|
||||
const __m128i wide2 = _mm_loadu_si128(
|
||||
reinterpret_cast<const __m128i*>(tbchars.begin().get() + i + 16));
|
||||
const __m128i wide3 = _mm_loadu_si128(
|
||||
reinterpret_cast<const __m128i*>(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<const __m128i*>(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<unsigned char>(tbchars[i]);
|
||||
#else
|
||||
for (size_t i = 0; i < len; ++i)
|
||||
latin1[i] = static_cast<unsigned char>(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<const __m128i*>(src.begin().get() + i));
|
||||
const __m128i bytes1 = _mm_loadl_epi64(
|
||||
reinterpret_cast<const __m128i*>(src.begin().get() + i + 8));
|
||||
const __m128i bytes2 = _mm_loadl_epi64(
|
||||
reinterpret_cast<const __m128i*>(src.begin().get() + i + 16));
|
||||
const __m128i bytes3 = _mm_loadl_epi64(
|
||||
reinterpret_cast<const __m128i*>(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<const __m128i*>(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<Copy, CharT>(cx, src, dst, outlen, &encoding)));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,47 +31,7 @@ FindCharacter(const CharT* chars, size_t length, CharT match)
|
|||
const __m128i needle = sizeof(CharT) == 1
|
||||
? _mm_set1_epi8(static_cast<char>(match))
|
||||
: _mm_set1_epi16(static_cast<short>(match));
|
||||
while (length >= 4 * lanes) {
|
||||
const __m128i block0 = _mm_loadu_si128(
|
||||
reinterpret_cast<const __m128i*>(chars));
|
||||
const uint32_t mask0 = static_cast<uint32_t>(
|
||||
_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<const __m128i*>(chars + lanes));
|
||||
const uint32_t mask1 = static_cast<uint32_t>(
|
||||
_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<const __m128i*>(chars + 2 * lanes));
|
||||
const uint32_t mask2 = static_cast<uint32_t>(
|
||||
_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<const __m128i*>(chars + 3 * lanes));
|
||||
const uint32_t mask3 = static_cast<uint32_t>(
|
||||
_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<const __m128i*>(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 <typename CharT>
|
||||
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<char>(match))
|
||||
: _mm_set1_epi16(static_cast<short>(match));
|
||||
while (length >= 4 * lanes) {
|
||||
end -= 4 * lanes;
|
||||
length -= 4 * lanes;
|
||||
|
||||
const __m128i block3 = _mm_loadu_si128(
|
||||
reinterpret_cast<const __m128i*>(end + 3 * lanes));
|
||||
const uint32_t mask3 = static_cast<uint32_t>(
|
||||
_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<const __m128i*>(end + 2 * lanes));
|
||||
const uint32_t mask2 = static_cast<uint32_t>(
|
||||
_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<const __m128i*>(end + lanes));
|
||||
const uint32_t mask1 = static_cast<uint32_t>(
|
||||
_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<const __m128i*>(end));
|
||||
const uint32_t mask0 = static_cast<uint32_t>(
|
||||
_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<const __m128i*>(end));
|
||||
const __m128i equal = sizeof(CharT) == 1
|
||||
? _mm_cmpeq_epi8(block, needle)
|
||||
: _mm_cmpeq_epi16(block, needle);
|
||||
const uint32_t mask = static_cast<uint32_t>(_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<short>(0xff00));
|
||||
const __m128i zero = _mm_setzero_si128();
|
||||
while (length >= 32) {
|
||||
const __m128i block0 = _mm_loadu_si128(
|
||||
reinterpret_cast<const __m128i*>(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<const __m128i*>(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<const __m128i*>(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<const __m128i*>(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<const __m128i*>(chars));
|
||||
const __m128i fits = _mm_cmpeq_epi16(_mm_and_si128(block, highBytes), zero);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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<Value*>(&elements_[dstStart]), src,
|
||||
count * sizeof(Value));
|
||||
memcpy(reinterpret_cast<Value*>(&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<Value*>(&elements_[dstStart]), src, count * sizeof(Value));
|
||||
memcpy(reinterpret_cast<Value*>(&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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<const CharT> 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<CharT>(nogc) + start, length * sizeof(CharT));
|
||||
mozilla::PodCopy(chars, base->chars<CharT>(nogc) + start, length);
|
||||
chars[length] = 0;
|
||||
return s;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<const __m128i*>(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<CharT>(nogc), n * sizeof(CharT));
|
||||
PodCopy(s, nonInlineChars<CharT>(nogc), n);
|
||||
s[n] = '\0';
|
||||
setNonInlineChars<CharT>(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<char16_t>(nogc), n * sizeof(char16_t));
|
||||
PodCopy(s, nonInlineChars<char16_t>(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<const __m128i*>(src + i));
|
||||
const __m128i wide1 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(src + i + 8));
|
||||
const __m128i wide2 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(src + i + 16));
|
||||
const __m128i wide3 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(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<const __m128i*>(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 <AllowGC allowGC>
|
||||
static MOZ_ALWAYS_INLINE JSInlineString*
|
||||
NewInlineStringDeflated(ExclusiveContext* cx, mozilla::Range<const char16_t> chars)
|
||||
|
|
@ -1219,8 +1170,8 @@ NewInlineStringDeflated(ExclusiveContext* cx, mozilla::Range<const char16_t> 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_<allowGC>(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_<allowGC>(cx, news.get(), n);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -583,9 +583,9 @@ MoveBoxedOrUnboxedDenseElements(JSContext* cx, JSObject* obj, uint32_t dstStart,
|
|||
obj->as<UnboxedArrayObject>().triggerPreBarrier<Type>(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<UnboxedArrayObject>().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))
|
||||
|
|
|
|||
|
|
@ -1895,7 +1895,7 @@ UnboxedPlainObject::fillAfterConvert(ExclusiveContext* cx,
|
|||
Handle<GCVector<Value>> 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)));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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(() => {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ EXTRA_JS_MODULES += [
|
|||
'ExtensionContent.jsm',
|
||||
'ExtensionManagement.jsm',
|
||||
'ExtensionParent.jsm',
|
||||
# 'ExtensionStorage.jsm',
|
||||
'ExtensionUtils.jsm',
|
||||
'LegacyExtensionsUtils.jsm',
|
||||
'MessageChannel.jsm',
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -220,7 +220,6 @@
|
|||
}
|
||||
},
|
||||
"managed": {
|
||||
"unsupported": true,
|
||||
"$ref": "StorageArea",
|
||||
"description": "Items in the <code>managed</code> storage area are set by the domain administrator, and are read-only for the extension; trying to modify this namespace results in an error."
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
});
|
||||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 == "<all_urls>") {
|
||||
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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue