Rewrite atomization
This commit is contained in:
parent
60affebbd1
commit
e0a58925d9
|
@ -1283,7 +1283,7 @@ Element::ToggleAttribute(const nsAString& aName,
|
|||
if (aForce.WasPassed() && !aForce.Value()) {
|
||||
return false;
|
||||
}
|
||||
nsCOMPtr<nsIAtom> nameAtom = NS_Atomize(nameToUse);
|
||||
nsCOMPtr<nsIAtom> nameAtom = NS_AtomizeMainThread(nameToUse);
|
||||
if (!nameAtom) {
|
||||
aError.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return false;
|
||||
|
@ -1316,7 +1316,7 @@ Element::SetAttribute(const nsAString& aName,
|
|||
nsAutoString nameToUse;
|
||||
const nsAttrName* name = InternalGetAttrNameFromQName(aName, &nameToUse);
|
||||
if (!name) {
|
||||
nsCOMPtr<nsIAtom> nameAtom = NS_Atomize(nameToUse);
|
||||
nsCOMPtr<nsIAtom> nameAtom = NS_AtomizeMainThread(nameToUse);
|
||||
if (!nameAtom) {
|
||||
aError.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return;
|
||||
|
@ -1398,7 +1398,7 @@ Element::GetAttributeNS(const nsAString& aNamespaceURI,
|
|||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAtom> name = NS_Atomize(aLocalName);
|
||||
nsCOMPtr<nsIAtom> name = NS_AtomizeMainThread(aLocalName);
|
||||
bool hasAttr = GetAttr(nsid, name, aReturn);
|
||||
if (!hasAttr) {
|
||||
SetDOMStringToNull(aReturn);
|
||||
|
@ -1430,7 +1430,7 @@ Element::RemoveAttributeNS(const nsAString& aNamespaceURI,
|
|||
const nsAString& aLocalName,
|
||||
ErrorResult& aError)
|
||||
{
|
||||
nsCOMPtr<nsIAtom> name = NS_Atomize(aLocalName);
|
||||
nsCOMPtr<nsIAtom> name = NS_AtomizeMainThread(aLocalName);
|
||||
int32_t nsid =
|
||||
nsContentUtils::NameSpaceManager()->GetNameSpaceID(aNamespaceURI,
|
||||
nsContentUtils::IsChromeDoc(OwnerDoc()));
|
||||
|
@ -1518,7 +1518,7 @@ Element::HasAttributeNS(const nsAString& aNamespaceURI,
|
|||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAtom> name = NS_Atomize(aLocalName);
|
||||
nsCOMPtr<nsIAtom> name = NS_AtomizeMainThread(aLocalName);
|
||||
return HasAttr(nsid, name);
|
||||
}
|
||||
|
||||
|
|
|
@ -742,7 +742,7 @@ nsAttrValue::GetAsAtom() const
|
|||
{
|
||||
switch (Type()) {
|
||||
case eString:
|
||||
return NS_Atomize(GetStringValue());
|
||||
return NS_AtomizeMainThread(GetStringValue());
|
||||
|
||||
case eAtom:
|
||||
{
|
||||
|
@ -754,7 +754,7 @@ nsAttrValue::GetAsAtom() const
|
|||
{
|
||||
nsAutoString val;
|
||||
ToString(val);
|
||||
return NS_Atomize(val);
|
||||
return NS_AtomizeMainThread(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1267,7 +1267,7 @@ nsAttrValue::ParseAtomArray(const nsAString& aValue)
|
|||
++iter;
|
||||
} while (iter != end && !nsContentUtils::IsHTMLWhitespace(*iter));
|
||||
|
||||
nsCOMPtr<nsIAtom> classAtom = NS_Atomize(Substring(start, iter));
|
||||
nsCOMPtr<nsIAtom> classAtom = NS_AtomizeMainThread(Substring(start, iter));
|
||||
if (!classAtom) {
|
||||
Reset();
|
||||
return;
|
||||
|
@ -1308,7 +1308,7 @@ nsAttrValue::ParseAtomArray(const nsAString& aValue)
|
|||
++iter;
|
||||
} while (iter != end && !nsContentUtils::IsHTMLWhitespace(*iter));
|
||||
|
||||
classAtom = NS_Atomize(Substring(start, iter));
|
||||
classAtom = NS_AtomizeMainThread(Substring(start, iter));
|
||||
|
||||
if (!array->AppendElement(classAtom)) {
|
||||
Reset();
|
||||
|
@ -1757,7 +1757,7 @@ nsAttrValue::SetMiscAtomOrString(const nsAString* aValue)
|
|||
"Empty string?");
|
||||
MiscContainer* cont = GetMiscContainer();
|
||||
if (len <= NS_ATTRVALUE_MAX_STRINGLENGTH_ATOM) {
|
||||
nsCOMPtr<nsIAtom> atom = NS_Atomize(*aValue);
|
||||
nsCOMPtr<nsIAtom> atom = NS_AtomizeMainThread(*aValue);
|
||||
if (atom) {
|
||||
cont->mStringBits =
|
||||
reinterpret_cast<uintptr_t>(atom.forget().take()) | eAtomBase;
|
||||
|
|
|
@ -2947,11 +2947,11 @@ nsContentUtils::SplitQName(const nsIContent* aNamespaceResolver,
|
|||
if (*aNamespace == kNameSpaceID_Unknown)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
*aLocalName = NS_Atomize(Substring(colon + 1, end)).take();
|
||||
*aLocalName = NS_AtomizeMainThread(Substring(colon + 1, end)).take();
|
||||
}
|
||||
else {
|
||||
*aNamespace = kNameSpaceID_None;
|
||||
*aLocalName = NS_Atomize(aQName).take();
|
||||
*aLocalName = NS_AtomizeMainThread(aQName).take();
|
||||
}
|
||||
NS_ENSURE_TRUE(aLocalName, NS_ERROR_OUT_OF_MEMORY);
|
||||
return NS_OK;
|
||||
|
@ -2976,7 +2976,8 @@ nsContentUtils::GetNodeInfoFromQName(const nsAString& aNamespaceURI,
|
|||
const char16_t* end;
|
||||
qName.EndReading(end);
|
||||
|
||||
nsCOMPtr<nsIAtom> prefix = NS_Atomize(Substring(qName.get(), colon));
|
||||
nsCOMPtr<nsIAtom> prefix =
|
||||
NS_AtomizeMainThread(Substring(qName.get(), colon));
|
||||
|
||||
rv = aNodeInfoManager->GetNodeInfo(Substring(colon + 1, end), prefix,
|
||||
nsID, aNodeType, aNodeInfo);
|
||||
|
@ -3036,7 +3037,7 @@ nsContentUtils::SplitExpatName(const char16_t *aExpatName, nsIAtom **aPrefix,
|
|||
nameStart = (uriEnd + 1);
|
||||
if (nameEnd) {
|
||||
const char16_t *prefixStart = nameEnd + 1;
|
||||
*aPrefix = NS_Atomize(Substring(prefixStart, pos)).take();
|
||||
*aPrefix = NS_AtomizeMainThread(Substring(prefixStart, pos)).take();
|
||||
}
|
||||
else {
|
||||
nameEnd = pos;
|
||||
|
@ -3049,7 +3050,7 @@ nsContentUtils::SplitExpatName(const char16_t *aExpatName, nsIAtom **aPrefix,
|
|||
nameEnd = pos;
|
||||
*aPrefix = nullptr;
|
||||
}
|
||||
*aLocalName = NS_Atomize(Substring(nameStart, nameEnd)).take();
|
||||
*aLocalName = NS_AtomizeMainThread(Substring(nameStart, nameEnd)).take();
|
||||
}
|
||||
|
||||
// static
|
||||
|
@ -3887,7 +3888,8 @@ nsContentUtils::GetEventMessageAndAtom(const nsAString& aName,
|
|||
}
|
||||
|
||||
*aEventMessage = eUnidentifiedEvent;
|
||||
nsCOMPtr<nsIAtom> atom = NS_Atomize(NS_LITERAL_STRING("on") + aName);
|
||||
nsCOMPtr<nsIAtom> atom =
|
||||
NS_AtomizeMainThread(NS_LITERAL_STRING("on") + aName);
|
||||
sUserDefinedEvents->AppendObject(atom);
|
||||
mapping.mAtom = atom;
|
||||
mapping.mMessage = eUnidentifiedEvent;
|
||||
|
@ -3920,7 +3922,7 @@ nsContentUtils::GetEventMessageAndAtomForListener(const nsAString& aName,
|
|||
if (mapping.mMaybeSpecialSVGorSMILEvent) {
|
||||
// Try the atom version so that we should get the right message for
|
||||
// SVG/SMIL.
|
||||
atom = NS_Atomize(NS_LITERAL_STRING("on") + aName);
|
||||
atom = NS_AtomizeMainThread(NS_LITERAL_STRING("on") + aName);
|
||||
msg = GetEventMessage(atom);
|
||||
} else {
|
||||
atom = mapping.mAtom;
|
||||
|
|
|
@ -112,7 +112,8 @@ nsNodeInfoManager::nsNodeInfoManager()
|
|||
mNonDocumentNodeInfos(0),
|
||||
mTextNodeInfo(nullptr),
|
||||
mCommentNodeInfo(nullptr),
|
||||
mDocumentNodeInfo(nullptr)
|
||||
mDocumentNodeInfo(nullptr),
|
||||
mRecentlyUsedNodeInfos{}
|
||||
{
|
||||
nsLayoutStatics::AddRef();
|
||||
|
||||
|
@ -232,11 +233,19 @@ nsNodeInfoManager::GetNodeInfo(nsIAtom *aName, nsIAtom *aPrefix,
|
|||
NodeInfo::NodeInfoInner tmpKey(aName, aPrefix, aNamespaceID, aNodeType,
|
||||
aExtraName);
|
||||
|
||||
uint32_t index =
|
||||
GetNodeInfoInnerHashValue(&tmpKey) % RECENTLY_USED_NODEINFOS_SIZE;
|
||||
NodeInfo* ni = mRecentlyUsedNodeInfos[index];
|
||||
if (ni && NodeInfoInnerKeyCompare(&(ni->mInner), &tmpKey)) {
|
||||
RefPtr<NodeInfo> nodeInfo = ni;
|
||||
return nodeInfo.forget();
|
||||
}
|
||||
|
||||
void *node = PL_HashTableLookup(mNodeInfoHash, &tmpKey);
|
||||
|
||||
if (node) {
|
||||
RefPtr<NodeInfo> nodeInfo = static_cast<NodeInfo*>(node);
|
||||
|
||||
mRecentlyUsedNodeInfos[index] = nodeInfo;
|
||||
return nodeInfo.forget();
|
||||
}
|
||||
|
||||
|
@ -254,6 +263,7 @@ nsNodeInfoManager::GetNodeInfo(nsIAtom *aName, nsIAtom *aPrefix,
|
|||
NS_IF_ADDREF(mDocument);
|
||||
}
|
||||
|
||||
mRecentlyUsedNodeInfos[index] = newNodeInfo;
|
||||
return newNodeInfo.forget();
|
||||
}
|
||||
|
||||
|
@ -272,16 +282,26 @@ nsNodeInfoManager::GetNodeInfo(const nsAString& aName, nsIAtom *aPrefix,
|
|||
|
||||
NodeInfo::NodeInfoInner tmpKey(aName, aPrefix, aNamespaceID, aNodeType);
|
||||
|
||||
uint32_t index =
|
||||
GetNodeInfoInnerHashValue(&tmpKey) % RECENTLY_USED_NODEINFOS_SIZE;
|
||||
NodeInfo* ni = mRecentlyUsedNodeInfos[index];
|
||||
if (ni && NodeInfoInnerKeyCompare(&(ni->mInner), &tmpKey)) {
|
||||
RefPtr<NodeInfo> nodeInfo = ni;
|
||||
nodeInfo.forget(aNodeInfo);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void *node = PL_HashTableLookup(mNodeInfoHash, &tmpKey);
|
||||
|
||||
if (node) {
|
||||
RefPtr<NodeInfo> nodeInfo = static_cast<NodeInfo*>(node);
|
||||
mRecentlyUsedNodeInfos[index] = nodeInfo;
|
||||
nodeInfo.forget(aNodeInfo);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAtom> nameAtom = NS_Atomize(aName);
|
||||
nsCOMPtr<nsIAtom> nameAtom = NS_AtomizeMainThread(aName);
|
||||
NS_ENSURE_TRUE(nameAtom, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
RefPtr<NodeInfo> newNodeInfo =
|
||||
|
@ -297,6 +317,7 @@ nsNodeInfoManager::GetNodeInfo(const nsAString& aName, nsIAtom *aPrefix,
|
|||
NS_IF_ADDREF(mDocument);
|
||||
}
|
||||
|
||||
mRecentlyUsedNodeInfos[index] = newNodeInfo;
|
||||
newNodeInfo.forget(aNodeInfo);
|
||||
|
||||
return NS_OK;
|
||||
|
@ -421,6 +442,12 @@ nsNodeInfoManager::RemoveNodeInfo(NodeInfo *aNodeInfo)
|
|||
}
|
||||
}
|
||||
|
||||
uint32_t index =
|
||||
GetNodeInfoInnerHashValue(&aNodeInfo->mInner) % RECENTLY_USED_NODEINFOS_SIZE;
|
||||
if (mRecentlyUsedNodeInfos[index] == aNodeInfo) {
|
||||
mRecentlyUsedNodeInfos[index] = nullptr;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
bool ret =
|
||||
#endif
|
||||
|
|
|
@ -32,6 +32,8 @@ class NodeInfo;
|
|||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#define RECENTLY_USED_NODEINFOS_SIZE 31
|
||||
|
||||
class nsNodeInfoManager final
|
||||
{
|
||||
private:
|
||||
|
@ -137,6 +139,7 @@ private:
|
|||
mozilla::dom::NodeInfo * MOZ_NON_OWNING_REF mCommentNodeInfo; // WEAK to avoid circular ownership
|
||||
mozilla::dom::NodeInfo * MOZ_NON_OWNING_REF mDocumentNodeInfo; // WEAK to avoid circular ownership
|
||||
RefPtr<nsBindingManager> mBindingManager;
|
||||
mozilla::dom::NodeInfo* mRecentlyUsedNodeInfos[RECENTLY_USED_NODEINFOS_SIZE];
|
||||
};
|
||||
|
||||
#endif /* nsNodeInfoManager_h___ */
|
||||
|
|
|
@ -834,7 +834,7 @@ js::atomics_wait(JSContext* cx, unsigned argc, Value* vp)
|
|||
}
|
||||
|
||||
bool
|
||||
js::atomics_wake(JSContext* cx, unsigned argc, Value* vp)
|
||||
js::atomics_notify(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
HandleValue objv = args.get(0);
|
||||
|
@ -874,7 +874,7 @@ js::atomics_wake(JSContext* cx, unsigned argc, Value* vp)
|
|||
iter = iter->lower_pri;
|
||||
if (c->offset != offset || !c->rt->fx.isWaiting())
|
||||
continue;
|
||||
c->rt->fx.wake(FutexRuntime::WakeExplicit);
|
||||
c->rt->fx.notify(FutexRuntime::NotifyExplicit);
|
||||
++woken;
|
||||
--count;
|
||||
} while (count > 0 && iter != waiters);
|
||||
|
@ -950,7 +950,7 @@ js::FutexRuntime::isWaiting()
|
|||
// When a worker is awoken for an interrupt it goes into state
|
||||
// WaitingNotifiedForInterrupt for a short time before it actually
|
||||
// wakes up and goes into WaitingInterrupted. In those states the
|
||||
// worker is still waiting, and if an explicit wake arrives the
|
||||
// worker is still waiting, and if an explicit notify arrives the
|
||||
// worker transitions to Woken. See further comments in
|
||||
// FutexRuntime::wait().
|
||||
return state_ == Waiting || state_ == WaitingInterrupted || state_ == WaitingNotifiedForInterrupt;
|
||||
|
@ -1029,14 +1029,14 @@ js::FutexRuntime::wait(JSContext* cx, js::UniqueLock<js::Mutex>& locked,
|
|||
// should be woken when the interrupt handler returns.
|
||||
// To that end, we flag the thread as interrupted around
|
||||
// the interrupt and check state_ when the interrupt
|
||||
// handler returns. A wake() call that reaches the
|
||||
// handler returns. A notify() call that reaches the
|
||||
// runtime during the interrupt sets state_ to Woken.
|
||||
//
|
||||
// - It is in principle possible for wait() to be
|
||||
// reentered on the same thread/runtime and waiting on the
|
||||
// same location and to yet again be interrupted and enter
|
||||
// the interrupt handler. In this case, it is important
|
||||
// that when another agent wakes waiters, all waiters using
|
||||
// that when another agent notifies waiters, all waiters using
|
||||
// the same runtime on the same location are woken in LIFO
|
||||
// order; FIFO may be the required order, but FIFO would
|
||||
// fail to wake up the innermost call. Interrupts are
|
||||
|
@ -1073,25 +1073,25 @@ finished:
|
|||
}
|
||||
|
||||
void
|
||||
js::FutexRuntime::wake(WakeReason reason)
|
||||
js::FutexRuntime::notify(NotifyReason reason)
|
||||
{
|
||||
MOZ_ASSERT(isWaiting());
|
||||
|
||||
if ((state_ == WaitingInterrupted || state_ == WaitingNotifiedForInterrupt) && reason == WakeExplicit) {
|
||||
if ((state_ == WaitingInterrupted || state_ == WaitingNotifiedForInterrupt) && reason == NotifyExplicit) {
|
||||
state_ = Woken;
|
||||
return;
|
||||
}
|
||||
switch (reason) {
|
||||
case WakeExplicit:
|
||||
case NotifyExplicit:
|
||||
state_ = Woken;
|
||||
break;
|
||||
case WakeForJSInterrupt:
|
||||
case NotifyForJSInterrupt:
|
||||
if (state_ == WaitingNotifiedForInterrupt)
|
||||
return;
|
||||
state_ = WaitingNotifiedForInterrupt;
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("bad WakeReason in FutexRuntime::wake()");
|
||||
MOZ_CRASH("bad NotifyReason in FutexRuntime::notify()");
|
||||
}
|
||||
cond_->notify_all();
|
||||
}
|
||||
|
@ -1108,7 +1108,8 @@ const JSFunctionSpec AtomicsMethods[] = {
|
|||
JS_INLINABLE_FN("xor", atomics_xor, 3,0, AtomicsXor),
|
||||
JS_INLINABLE_FN("isLockFree", atomics_isLockFree, 1,0, AtomicsIsLockFree),
|
||||
JS_FN("wait", atomics_wait, 4,0),
|
||||
JS_FN("wake", atomics_wake, 3,0),
|
||||
JS_FN("notify", atomics_notify, 3,0),
|
||||
JS_FN("wake", atomics_notify, 3,0), //Legacy name
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ MOZ_MUST_USE bool atomics_or(JSContext* cx, unsigned argc, Value* vp);
|
|||
MOZ_MUST_USE bool atomics_xor(JSContext* cx, unsigned argc, Value* vp);
|
||||
MOZ_MUST_USE bool atomics_isLockFree(JSContext* cx, unsigned argc, Value* vp);
|
||||
MOZ_MUST_USE bool atomics_wait(JSContext* cx, unsigned argc, Value* vp);
|
||||
MOZ_MUST_USE bool atomics_wake(JSContext* cx, unsigned argc, Value* vp);
|
||||
MOZ_MUST_USE bool atomics_notify(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
/* asm.js callouts */
|
||||
namespace wasm { class Instance; }
|
||||
|
@ -63,10 +63,10 @@ public:
|
|||
MOZ_MUST_USE bool initInstance();
|
||||
void destroyInstance();
|
||||
|
||||
// Parameters to wake().
|
||||
enum WakeReason {
|
||||
WakeExplicit, // Being asked to wake up by another thread
|
||||
WakeForJSInterrupt // Interrupt requested
|
||||
// Parameters to notify().
|
||||
enum NotifyReason {
|
||||
NotifyExplicit, // Being asked to wake up by another thread
|
||||
NotifyForJSInterrupt // Interrupt requested
|
||||
};
|
||||
|
||||
// Result code from wait().
|
||||
|
@ -83,29 +83,27 @@ public:
|
|||
// times allowed; specify mozilla::Nothing() for an indefinite
|
||||
// wait.
|
||||
//
|
||||
// wait() will not wake up spuriously. It will return true and
|
||||
// set *result to a return code appropriate for
|
||||
// Atomics.wait() on success, and return false on error.
|
||||
// wait() will not wake up spuriously.
|
||||
MOZ_MUST_USE bool wait(JSContext* cx, js::UniqueLock<js::Mutex>& locked,
|
||||
mozilla::Maybe<mozilla::TimeDuration>& timeout, WaitResult* result);
|
||||
|
||||
// Wake the thread represented by this Runtime.
|
||||
// Notify the thread represented by this Runtime.
|
||||
//
|
||||
// The futex lock must be held around this call. (The sleeping
|
||||
// thread will not wake up until the caller of Atomics.wake()
|
||||
// thread will not wake up until the caller of Atomics.notify()
|
||||
// releases the lock.)
|
||||
//
|
||||
// If the thread is not waiting then this method does nothing.
|
||||
//
|
||||
// If the thread is waiting in a call to wait() and the
|
||||
// reason is WakeExplicit then the wait() call will return
|
||||
// reason is NotifyExplicit then the wait() call will return
|
||||
// with Woken.
|
||||
//
|
||||
// If the thread is waiting in a call to wait() and the
|
||||
// reason is WakeForJSInterrupt then the wait() will return
|
||||
// reason is NotifyForJSInterrupt then the wait() will return
|
||||
// with WaitingNotifiedForInterrupt; in the latter case the caller
|
||||
// of wait() must handle the interrupt.
|
||||
void wake(WakeReason reason);
|
||||
void notify(NotifyReason reason);
|
||||
|
||||
bool isWaiting();
|
||||
|
||||
|
@ -128,7 +126,7 @@ public:
|
|||
// interrupt handler
|
||||
WaitingInterrupted, // We are waiting, but have been interrupted
|
||||
// and are running the interrupt handler
|
||||
Woken // Woken by a script call to Atomics.wake
|
||||
Woken // Woken by a script call to Atomics.notify
|
||||
};
|
||||
|
||||
// Condition variable that this runtime will wait on.
|
||||
|
|
|
@ -67,6 +67,8 @@ if (helperThreadCount() === 0) {
|
|||
quit();
|
||||
}
|
||||
|
||||
var mem = new Int32Array(new SharedArrayBuffer(1024));
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
// wait() returns "not-equal" if the value is not the expected one.
|
||||
|
@ -102,7 +104,7 @@ dprint("Sleeping for 2 seconds");
|
|||
sleep(2);
|
||||
dprint("Waking the main thread now");
|
||||
setSharedArrayBuffer(null);
|
||||
assertEq(Atomics.wake(mem, 0, 1), 1); // Can fail spuriously but very unlikely
|
||||
assertEq(Atomics.notify(mem, 0, 1), 1); // Can fail spuriously but very unlikely
|
||||
`);
|
||||
|
||||
var then = Date.now();
|
||||
|
@ -113,14 +115,14 @@ assertEq(getSharedArrayBuffer(), null); // The worker's clearing of the mbx is v
|
|||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
// Test the default argument to atomics.wake()
|
||||
// Test the default argument to atomics.notify()
|
||||
|
||||
setSharedArrayBuffer(mem.buffer);
|
||||
|
||||
evalInWorker(`
|
||||
var mem = new Int32Array(getSharedArrayBuffer());
|
||||
sleep(2); // Probably long enough to avoid a spurious error next
|
||||
assertEq(Atomics.wake(mem, 0), 1); // Last argument to wake should default to +Infinity
|
||||
assertEq(Atomics.notify(mem, 0), 1); // Last argument to wake should default to +Infinity
|
||||
`);
|
||||
|
||||
var then = Date.now();
|
||||
|
|
|
@ -589,7 +589,7 @@ JSRuntime::requestInterrupt(InterruptMode mode)
|
|||
// Atomics.wait().
|
||||
fx.lock();
|
||||
if (fx.isWaiting())
|
||||
fx.wake(FutexRuntime::WakeForJSInterrupt);
|
||||
fx.notify(FutexRuntime::NotifyForJSInterrupt);
|
||||
fx.unlock();
|
||||
InterruptRunningJitCode(this);
|
||||
}
|
||||
|
|
|
@ -1323,12 +1323,7 @@ pref("javascript.options.mem.gc_max_empty_chunk_count", 30);
|
|||
|
||||
pref("javascript.options.showInConsole", false);
|
||||
|
||||
#ifdef RELEASE_OR_BETA
|
||||
// Disabled in Beta and Release for now, see bug 1225406
|
||||
pref("javascript.options.shared_memory", false);
|
||||
#else
|
||||
pref("javascript.options.shared_memory", true);
|
||||
#endif
|
||||
|
||||
pref("javascript.options.throw_on_debuggee_would_run", false);
|
||||
pref("javascript.options.dump_stack_on_debuggee_would_run", false);
|
||||
|
|
|
@ -91,7 +91,7 @@ nsHtml5Portability::releaseString(nsString* str)
|
|||
bool
|
||||
nsHtml5Portability::localEqualsBuffer(nsIAtom* local, char16_t* buf, int32_t offset, int32_t length)
|
||||
{
|
||||
return local->Equals(nsDependentSubstring(buf + offset, buf + offset + length));
|
||||
return local->Equals(buf + offset, length);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -108,7 +108,7 @@ class nsHtml5TreeOperation {
|
|||
}
|
||||
nsAutoString str;
|
||||
aAtom->ToString(str);
|
||||
return NS_Atomize(str);
|
||||
return NS_AtomizeMainThread(str);
|
||||
}
|
||||
|
||||
static nsresult AppendTextToTextNode(const char16_t* aBuffer,
|
||||
|
|
|
@ -325,13 +325,7 @@ AtomTableMatchKey(const PLDHashEntryHdr* aEntry, const void* aKey)
|
|||
nsDependentAtomString(he->mAtom)) == 0;
|
||||
}
|
||||
|
||||
uint32_t length = he->mAtom->GetLength();
|
||||
if (length != k->mLength) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return memcmp(he->mAtom->GetUTF16String(),
|
||||
k->mUTF16String, length * sizeof(char16_t)) == 0;
|
||||
return he->mAtom->Equals(k->mUTF16String, k->mLength);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -364,17 +358,29 @@ static const PLDHashTableOps AtomTableOps = {
|
|||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
#define RECENTLY_USED_MAIN_THREAD_ATOM_CACHE_SIZE 31
|
||||
static nsIAtom*
|
||||
sRecentlyUsedMainThreadAtoms[RECENTLY_USED_MAIN_THREAD_ATOM_CACHE_SIZE] = {};
|
||||
|
||||
void
|
||||
DynamicAtom::GCAtomTable()
|
||||
{
|
||||
MutexAutoLock lock(*gAtomTableLock);
|
||||
GCAtomTableLocked(lock, GCKind::RegularOperation);
|
||||
if (NS_IsMainThread()) {
|
||||
MutexAutoLock lock(*gAtomTableLock);
|
||||
GCAtomTableLocked(lock, GCKind::RegularOperation);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DynamicAtom::GCAtomTableLocked(const MutexAutoLock& aProofOfLock,
|
||||
GCKind aKind)
|
||||
{
|
||||
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
for (uint32_t i = 0; i < RECENTLY_USED_MAIN_THREAD_ATOM_CACHE_SIZE; ++i) {
|
||||
sRecentlyUsedMainThreadAtoms[i] = nullptr;
|
||||
}
|
||||
|
||||
uint32_t removedCount = 0; // Use a non-atomic temporary for cheaper increments.
|
||||
nsAutoCString nonZeroRefcountAtoms;
|
||||
uint32_t nonZeroRefcountAtomsCount = 0;
|
||||
|
@ -712,6 +718,40 @@ NS_Atomize(const nsAString& aUTF16String)
|
|||
return atom.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<nsIAtom>
|
||||
NS_AtomizeMainThread(const nsAString& aUTF16String)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
nsCOMPtr<nsIAtom> retVal;
|
||||
uint32_t hash;
|
||||
AtomTableKey key(aUTF16String.Data(), aUTF16String.Length(), &hash);
|
||||
uint32_t index = hash % RECENTLY_USED_MAIN_THREAD_ATOM_CACHE_SIZE;
|
||||
nsIAtom* atom =
|
||||
sRecentlyUsedMainThreadAtoms[index];
|
||||
if (atom) {
|
||||
uint32_t length = atom->GetLength();
|
||||
if (length == key.mLength &&
|
||||
(memcmp(atom->GetUTF16String(),
|
||||
key.mUTF16String, length * sizeof(char16_t)) == 0)) {
|
||||
retVal = atom;
|
||||
return retVal.forget();
|
||||
}
|
||||
}
|
||||
|
||||
MutexAutoLock lock(*gAtomTableLock);
|
||||
AtomTableEntry* he = static_cast<AtomTableEntry*>(gAtomTable->Add(&key));
|
||||
|
||||
if (he->mAtom) {
|
||||
retVal = he->mAtom;
|
||||
} else {
|
||||
retVal = DynamicAtom::Create(aUTF16String, hash);
|
||||
he->mAtom = retVal;
|
||||
}
|
||||
|
||||
sRecentlyUsedMainThreadAtoms[index] = retVal;
|
||||
return retVal.forget();
|
||||
}
|
||||
|
||||
nsrefcnt
|
||||
NS_GetNumberOfAtoms(void)
|
||||
{
|
||||
|
|
|
@ -37,9 +37,15 @@ interface nsIAtom : nsISupports
|
|||
size_t SizeOfIncludingThis(in MallocSizeOf aMallocSizeOf);
|
||||
|
||||
%{C++
|
||||
// note this is NOT virtual so this won't muck with the vtable!
|
||||
// note these are NOT virtual so they won't muck with the vtable!
|
||||
inline bool Equals(char16ptr_t aString, uint32_t aLength) const
|
||||
{
|
||||
return mLength == aLength &&
|
||||
memcmp(mString, aString, mLength * sizeof(char16_t)) == 0;
|
||||
}
|
||||
|
||||
inline bool Equals(const nsAString& aString) const {
|
||||
return aString.Equals(nsDependentString(mString, mLength));
|
||||
return Equals(aString.BeginReading(), aString.Length());
|
||||
}
|
||||
|
||||
inline bool IsStaticAtom() const {
|
||||
|
@ -119,6 +125,11 @@ extern already_AddRefed<nsIAtom> NS_Atomize(const char16_t* aUTF16String);
|
|||
*/
|
||||
extern already_AddRefed<nsIAtom> NS_Atomize(const nsAString& aUTF16String);
|
||||
|
||||
/**
|
||||
* An optimized version of the method above for the main thread.
|
||||
*/
|
||||
extern already_AddRefed<nsIAtom> NS_AtomizeMainThread(const nsAString& aUTF16String);
|
||||
|
||||
/**
|
||||
* Return a count of the total number of atoms currently
|
||||
* alive in the system.
|
||||
|
|
Loading…
Reference in New Issue