mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge inbound to m-c.
This commit is contained in:
commit
ae61dad479
@ -34,6 +34,7 @@
|
||||
#include "JavaScriptChild.h"
|
||||
#include "JavaScriptParent.h"
|
||||
#include "nsDOMLists.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include <algorithm>
|
||||
|
||||
#ifdef ANDROID
|
||||
@ -1009,6 +1010,169 @@ nsFrameMessageManager::Disconnect(bool aRemoveFromParent)
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
struct MessageManagerReferentCount {
|
||||
MessageManagerReferentCount() : strong(0), weakAlive(0), weakDead(0) {}
|
||||
size_t strong;
|
||||
size_t weakAlive;
|
||||
size_t weakDead;
|
||||
nsCOMArray<nsIAtom> suspectMessages;
|
||||
nsDataHashtable<nsPtrHashKey<nsIAtom>, uint32_t> messageCounter;
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class MessageManagerReporter MOZ_FINAL : public nsIMemoryReporter
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIMEMORYREPORTER
|
||||
protected:
|
||||
static const size_t kSuspectReferentCount = 300;
|
||||
void CountReferents(nsFrameMessageManager* aMessageManager,
|
||||
MessageManagerReferentCount* aReferentCount);
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS1(MessageManagerReporter, nsIMemoryReporter)
|
||||
|
||||
void
|
||||
MessageManagerReporter::CountReferents(nsFrameMessageManager* aMessageManager,
|
||||
MessageManagerReferentCount* aReferentCount)
|
||||
{
|
||||
for (uint32_t i = 0; i < aMessageManager->mListeners.Length(); i++) {
|
||||
const nsMessageListenerInfo& listenerInfo = aMessageManager->mListeners[i];
|
||||
|
||||
if (listenerInfo.mWeakListener) {
|
||||
nsCOMPtr<nsISupports> referent =
|
||||
do_QueryReferent(listenerInfo.mWeakListener);
|
||||
if (referent) {
|
||||
aReferentCount->weakAlive++;
|
||||
} else {
|
||||
aReferentCount->weakDead++;
|
||||
}
|
||||
} else {
|
||||
aReferentCount->strong++;
|
||||
}
|
||||
|
||||
uint32_t oldCount = 0;
|
||||
aReferentCount->messageCounter.Get(listenerInfo.mMessage, &oldCount);
|
||||
uint32_t currentCount = oldCount + 1;
|
||||
aReferentCount->messageCounter.Put(listenerInfo.mMessage, currentCount);
|
||||
|
||||
// Keep track of messages that have a suspiciously large
|
||||
// number of referents (symptom of leak).
|
||||
if (currentCount == kSuspectReferentCount) {
|
||||
aReferentCount->suspectMessages.AppendElement(listenerInfo.mMessage);
|
||||
}
|
||||
}
|
||||
|
||||
// Add referent count in child managers because the listeners
|
||||
// participate in messages dispatched from parent message manager.
|
||||
for (uint32_t i = 0; i < aMessageManager->mChildManagers.Length(); i++) {
|
||||
nsRefPtr<nsFrameMessageManager> mm =
|
||||
static_cast<nsFrameMessageManager*>(aMessageManager->mChildManagers[i]);
|
||||
CountReferents(mm, aReferentCount);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MessageManagerReporter::GetName(nsACString& aName)
|
||||
{
|
||||
aName.AssignLiteral("message-manager");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static nsresult
|
||||
ReportReferentCount(const char* aManagerType,
|
||||
const MessageManagerReferentCount& aReferentCount,
|
||||
nsIMemoryReporterCallback* aCb,
|
||||
nsISupports* aClosure)
|
||||
{
|
||||
#define REPORT(_path, _amount, _desc) \
|
||||
do { \
|
||||
nsresult rv; \
|
||||
rv = aCb->Callback(EmptyCString(), _path, \
|
||||
nsIMemoryReporter::KIND_OTHER, \
|
||||
nsIMemoryReporter::UNITS_COUNT, _amount, \
|
||||
_desc, aClosure); \
|
||||
NS_ENSURE_SUCCESS(rv, rv); \
|
||||
} while (0)
|
||||
|
||||
REPORT(nsPrintfCString("message-manager/referent/%s/strong", aManagerType),
|
||||
aReferentCount.strong,
|
||||
nsPrintfCString("The number of strong referents held by the message "
|
||||
"manager in the %s manager.", aManagerType));
|
||||
REPORT(nsPrintfCString("message-manager/referent/%s/weak/alive", aManagerType),
|
||||
aReferentCount.weakAlive,
|
||||
nsPrintfCString("The number of weak referents that are still alive "
|
||||
"held by the message manager in the %s manager.",
|
||||
aManagerType));
|
||||
REPORT(nsPrintfCString("message-manager/referent/%s/weak/dead", aManagerType),
|
||||
aReferentCount.weakDead,
|
||||
nsPrintfCString("The number of weak referents that are dead "
|
||||
"held by the message manager in the %s manager.",
|
||||
aManagerType));
|
||||
|
||||
for (uint32_t i = 0; i < aReferentCount.suspectMessages.Length(); i++) {
|
||||
uint32_t totalReferentCount = 0;
|
||||
aReferentCount.messageCounter.Get(aReferentCount.suspectMessages[i],
|
||||
&totalReferentCount);
|
||||
nsAtomCString suspect(aReferentCount.suspectMessages[i]);
|
||||
REPORT(nsPrintfCString("message-manager-suspect/%s/referent(message=%s)",
|
||||
aManagerType, suspect.get()), totalReferentCount,
|
||||
nsPrintfCString("A message in the %s message manager with a "
|
||||
"suspiciously large number of referents (symptom "
|
||||
"of a leak).", aManagerType));
|
||||
}
|
||||
|
||||
#undef REPORT
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MessageManagerReporter::CollectReports(nsIMemoryReporterCallback* aCb,
|
||||
nsISupports* aClosure)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
if (XRE_GetProcessType() == GeckoProcessType_Default) {
|
||||
nsCOMPtr<nsIMessageBroadcaster> globalmm =
|
||||
do_GetService("@mozilla.org/globalmessagemanager;1");
|
||||
if (globalmm) {
|
||||
nsRefPtr<nsFrameMessageManager> mm =
|
||||
static_cast<nsFrameMessageManager*>(globalmm.get());
|
||||
MessageManagerReferentCount count;
|
||||
CountReferents(mm, &count);
|
||||
rv = ReportReferentCount("global-manager", count, aCb, aClosure);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
|
||||
if (nsFrameMessageManager::sParentProcessManager) {
|
||||
MessageManagerReferentCount count;
|
||||
CountReferents(nsFrameMessageManager::sParentProcessManager, &count);
|
||||
rv = ReportReferentCount("parent-process-manager", count, aCb, aClosure);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
if (nsFrameMessageManager::sChildProcessManager) {
|
||||
MessageManagerReferentCount count;
|
||||
CountReferents(nsFrameMessageManager::sChildProcessManager, &count);
|
||||
rv = ReportReferentCount("child-process-manager", count, aCb, aClosure);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
nsresult
|
||||
NS_NewGlobalMessageManager(nsIMessageBroadcaster** aResult)
|
||||
{
|
||||
@ -1017,6 +1181,7 @@ NS_NewGlobalMessageManager(nsIMessageBroadcaster** aResult)
|
||||
nsFrameMessageManager* mm = new nsFrameMessageManager(nullptr,
|
||||
nullptr,
|
||||
MM_CHROME | MM_GLOBAL | MM_BROADCASTER);
|
||||
NS_RegisterMemoryReporter(new MessageManagerReporter());
|
||||
return CallQueryInterface(mm, aResult);
|
||||
}
|
||||
|
||||
@ -1538,6 +1703,7 @@ NS_NewChildProcessMessageManager(nsISyncMessageSender** aResult)
|
||||
cb = new SameChildProcessMessageManagerCallback();
|
||||
} else {
|
||||
cb = new ChildProcessMessageManagerCallback();
|
||||
NS_RegisterMemoryReporter(new MessageManagerReporter());
|
||||
}
|
||||
nsFrameMessageManager* mm = new nsFrameMessageManager(cb,
|
||||
nullptr,
|
||||
|
@ -32,6 +32,7 @@ class ContentParent;
|
||||
class ContentChild;
|
||||
struct StructuredCloneData;
|
||||
class ClonedMessageData;
|
||||
class MessageManagerReporter;
|
||||
|
||||
namespace ipc {
|
||||
|
||||
@ -143,6 +144,7 @@ class nsFrameMessageManager MOZ_FINAL : public nsIContentFrameMessageManager,
|
||||
public nsIFrameScriptLoader,
|
||||
public nsIProcessChecker
|
||||
{
|
||||
friend class mozilla::dom::MessageManagerReporter;
|
||||
typedef mozilla::dom::StructuredCloneData StructuredCloneData;
|
||||
public:
|
||||
nsFrameMessageManager(mozilla::dom::ipc::MessageManagerCallback* aCallback,
|
||||
|
@ -7,7 +7,6 @@
|
||||
XPIDL_SOURCES += [
|
||||
'nsIContactProperties.idl',
|
||||
'nsIDOMContactManager.idl',
|
||||
'nsIDOMMozContactChangeEvent.idl',
|
||||
]
|
||||
|
||||
XPIDL_MODULE = 'dom_contacts'
|
||||
|
@ -1,24 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsIDOMEvent.idl"
|
||||
|
||||
[scriptable, builtinclass, uuid(7ee758eb-9353-4ade-8715-9953ea512ee2)]
|
||||
interface nsIDOMMozContactChangeEvent : nsIDOMEvent
|
||||
{
|
||||
readonly attribute DOMString contactID;
|
||||
readonly attribute DOMString reason;
|
||||
|
||||
[noscript] void initMozContactChangeEvent(in DOMString aType,
|
||||
in boolean aCanBubble,
|
||||
in boolean aCancelable,
|
||||
in DOMString aContactID,
|
||||
in DOMString aReason);
|
||||
};
|
||||
|
||||
dictionary MozContactChangeEventInit : EventInit
|
||||
{
|
||||
DOMString contactID;
|
||||
DOMString reason;
|
||||
};
|
@ -7,11 +7,11 @@
|
||||
interfaces = [
|
||||
'base',
|
||||
'canvas',
|
||||
'contacts',
|
||||
'core',
|
||||
'html',
|
||||
'events',
|
||||
'devicestorage',
|
||||
'contacts',
|
||||
'settings',
|
||||
'stylesheets',
|
||||
'sidebar',
|
||||
|
@ -4,7 +4,7 @@
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
[Constructor(DOMString type, optional MozContactChangeEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"]
|
||||
[Constructor(DOMString type, optional MozContactChangeEventInit eventInitDict)]
|
||||
interface MozContactChangeEvent : Event
|
||||
{
|
||||
readonly attribute DOMString? contactID;
|
||||
|
@ -476,7 +476,6 @@ WEBIDL_FILES += [
|
||||
'ElementReplaceEvent.webidl',
|
||||
'HashChangeEvent.webidl',
|
||||
'MozApplicationEvent.webidl',
|
||||
'MozContactChangeEvent.webidl',
|
||||
'MozMmsEvent.webidl',
|
||||
'MozSettingsEvent.webidl',
|
||||
'MozSmsEvent.webidl',
|
||||
@ -546,6 +545,7 @@ GENERATED_EVENTS_WEBIDL_FILES = [
|
||||
'DeviceProximityEvent.webidl',
|
||||
'ErrorEvent.webidl',
|
||||
'MediaStreamEvent.webidl',
|
||||
'MozContactChangeEvent.webidl',
|
||||
'MozInterAppMessageEvent.webidl',
|
||||
'RTCDataChannelEvent.webidl',
|
||||
'RTCPeerConnectionIceEvent.webidl',
|
||||
|
@ -132,9 +132,9 @@ JavaScriptChild::fail(JSContext *cx, ReturnStatus *rs)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!toVariant(cx, exn, &rs->get_ReturnException().exn()))
|
||||
return true;
|
||||
|
||||
// If this fails, we still don't want to exit. Just return an invalid
|
||||
// exception.
|
||||
(void) toVariant(cx, exn, &rs->get_ReturnException().exn());
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -377,7 +377,7 @@ JavaScriptChild::AnswerGet(const ObjectId &objId, const ObjectId &receiverId, co
|
||||
if (!convertGeckoStringToId(cx, id, &internedId))
|
||||
return fail(cx, rs);
|
||||
|
||||
JS::Rooted<JS::Value> val(cx);
|
||||
JS::RootedValue val(cx);
|
||||
if (!JS_ForwardGetPropertyTo(cx, obj, internedId, receiver, &val))
|
||||
return fail(cx, rs);
|
||||
|
||||
@ -537,7 +537,7 @@ JavaScriptChild::AnswerCall(const ObjectId &objId, const nsTArray<JSParam> &argv
|
||||
// treat this as the outparam never having been set.
|
||||
for (size_t i = 0; i < vals.length(); i++) {
|
||||
JSVariant variant;
|
||||
if (!toVariant(cx, vals[i], &variant))
|
||||
if (!toVariant(cx, vals.handleAt(i), &variant))
|
||||
return fail(cx, rs);
|
||||
outparams->ReplaceElementAt(i, JSParam(variant));
|
||||
}
|
||||
|
@ -152,7 +152,7 @@ JavaScriptShared::convertGeckoStringToId(JSContext *cx, const nsString &from, JS
|
||||
}
|
||||
|
||||
bool
|
||||
JavaScriptShared::toVariant(JSContext *cx, jsval from, JSVariant *to)
|
||||
JavaScriptShared::toVariant(JSContext *cx, JS::HandleValue from, JSVariant *to)
|
||||
{
|
||||
switch (JS_TypeOfValue(cx, from)) {
|
||||
case JSTYPE_VOID:
|
||||
|
@ -91,7 +91,7 @@ class JavaScriptShared
|
||||
bool Wrap(JSContext *cx, JS::HandleObject aObj, InfallibleTArray<CpowEntry> *outCpows);
|
||||
|
||||
protected:
|
||||
bool toVariant(JSContext *cx, jsval from, JSVariant *to);
|
||||
bool toVariant(JSContext *cx, JS::HandleValue from, JSVariant *to);
|
||||
bool toValue(JSContext *cx, const JSVariant &from, JS::MutableHandleValue to);
|
||||
bool fromDescriptor(JSContext *cx, JS::Handle<JSPropertyDescriptor> desc, PPropertyDescriptor *out);
|
||||
bool toDescriptor(JSContext *cx, const PPropertyDescriptor &in,
|
||||
|
@ -319,46 +319,6 @@ const Class js::NumericTypeClasses[ScalarTypeRepresentation::TYPE_MAX] = {
|
||||
JS_FOR_EACH_SCALAR_TYPE_REPR(BINARYDATA_NUMERIC_CLASSES)
|
||||
};
|
||||
|
||||
template <typename Domain, typename Input>
|
||||
static bool
|
||||
InRange(Input x)
|
||||
{
|
||||
return std::numeric_limits<Domain>::min() <= x &&
|
||||
x <= std::numeric_limits<Domain>::max();
|
||||
}
|
||||
|
||||
template <>
|
||||
bool
|
||||
InRange<float, int>(int x)
|
||||
{
|
||||
return -std::numeric_limits<float>::max() <= x &&
|
||||
x <= std::numeric_limits<float>::max();
|
||||
}
|
||||
|
||||
template <>
|
||||
bool
|
||||
InRange<double, int>(int x)
|
||||
{
|
||||
return -std::numeric_limits<double>::max() <= x &&
|
||||
x <= std::numeric_limits<double>::max();
|
||||
}
|
||||
|
||||
template <>
|
||||
bool
|
||||
InRange<float, double>(double x)
|
||||
{
|
||||
return -std::numeric_limits<float>::max() <= x &&
|
||||
x <= std::numeric_limits<float>::max();
|
||||
}
|
||||
|
||||
template <>
|
||||
bool
|
||||
InRange<double, double>(double x)
|
||||
{
|
||||
return -std::numeric_limits<double>::max() <= x &&
|
||||
x <= std::numeric_limits<double>::max();
|
||||
}
|
||||
|
||||
#define BINARYDATA_TYPE_TO_CLASS(constant_, type_, name_) \
|
||||
template <> \
|
||||
const Class * \
|
||||
|
@ -197,7 +197,7 @@ parser.add_argument('--source', metavar='SOURCE', type=str, nargs='?',
|
||||
help='source code to analyze')
|
||||
parser.add_argument('--upto', metavar='UPTO', type=str, nargs='?',
|
||||
help='last step to execute')
|
||||
parser.add_argument('--jobs', '-j', default=4, metavar='JOBS', type=int,
|
||||
parser.add_argument('--jobs', '-j', default=None, metavar='JOBS', type=int,
|
||||
help='number of simultaneous analyzeRoots.js jobs')
|
||||
parser.add_argument('--list', const=True, nargs='?', type=bool,
|
||||
help='display available steps')
|
||||
|
@ -556,7 +556,10 @@ for (var nameIndex = start; nameIndex <= end; nameIndex++) {
|
||||
var name = xdb.read_key(nameIndex);
|
||||
var functionName = name.readString();
|
||||
var data = xdb.read_entry(name);
|
||||
functionBodies = JSON.parse(data.readString());
|
||||
xdb.free_string(name);
|
||||
var json = data.readString();
|
||||
xdb.free_string(data);
|
||||
functionBodies = JSON.parse(json);
|
||||
|
||||
for (var body of functionBodies)
|
||||
body.suppressed = [];
|
||||
@ -565,7 +568,4 @@ for (var nameIndex = start; nameIndex <= end; nameIndex++) {
|
||||
pbody.suppressed[id] = true;
|
||||
}
|
||||
processBodies(functionName);
|
||||
|
||||
xdb.free_string(name);
|
||||
xdb.free_string(data);
|
||||
}
|
||||
|
@ -24,6 +24,7 @@
|
||||
# and the reports will only reflect the changes since the earlier run.
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use IO::Handle;
|
||||
use File::Basename qw(dirname);
|
||||
use Getopt::Long;
|
||||
@ -193,7 +194,7 @@ sub get_manager_address
|
||||
my $log_data = `cat $log_file`;
|
||||
my ($port) = $log_data =~ /Listening on ([\.\:0-9]*)/
|
||||
or die "no manager found";
|
||||
print OUT "Connecting to manager on port $port\n";
|
||||
print OUT "Connecting to manager on port $port\n" unless $suppress_logs;
|
||||
print "Connecting to manager on port $port.\n";
|
||||
return $1;
|
||||
}
|
||||
@ -310,7 +311,7 @@ sub run_pass
|
||||
|
||||
# collate the worker's output into a single file. make this asynchronous
|
||||
# so we can wait a bit and make sure we get all worker output.
|
||||
defined(my $pid = fork) or die;
|
||||
defined($pid = fork) or die;
|
||||
|
||||
if (!$pid) {
|
||||
sleep(20);
|
||||
|
@ -94,7 +94,7 @@ PushStatementPC(ParseContext<ParseHandler> *pc, StmtInfoPC *stmt, StmtType type)
|
||||
template <>
|
||||
bool
|
||||
ParseContext<FullParseHandler>::define(TokenStream &ts,
|
||||
PropertyName *name, ParseNode *pn, Definition::Kind kind)
|
||||
HandlePropertyName name, ParseNode *pn, Definition::Kind kind)
|
||||
{
|
||||
JS_ASSERT(!pn->isUsed());
|
||||
JS_ASSERT_IF(pn->isDefn(), pn->isPlaceholder());
|
||||
@ -186,7 +186,7 @@ ParseContext<FullParseHandler>::define(TokenStream &ts,
|
||||
|
||||
template <>
|
||||
bool
|
||||
ParseContext<SyntaxParseHandler>::define(TokenStream &ts, PropertyName *name, Node pn,
|
||||
ParseContext<SyntaxParseHandler>::define(TokenStream &ts, HandlePropertyName name, Node pn,
|
||||
Definition::Kind kind)
|
||||
{
|
||||
JS_ASSERT(!decls_.lookupFirst(name));
|
||||
|
@ -167,7 +167,7 @@ struct ParseContext : public GenericParseContext
|
||||
* 'pn' if they are in the scope of 'pn'.
|
||||
* + Pre-existing placeholders in the scope of 'pn' have been removed.
|
||||
*/
|
||||
bool define(TokenStream &ts, PropertyName *name, Node pn, Definition::Kind);
|
||||
bool define(TokenStream &ts, HandlePropertyName name, Node pn, Definition::Kind);
|
||||
|
||||
/*
|
||||
* Let definitions may shadow same-named definitions in enclosing scopes.
|
||||
|
@ -6152,7 +6152,8 @@ CodeGenerator::addGetElementCache(LInstruction *ins, Register obj, ConstantOrReg
|
||||
{
|
||||
switch (gen->info().executionMode()) {
|
||||
case SequentialExecution: {
|
||||
GetElementIC cache(obj, index, output, monitoredResult);
|
||||
RegisterSet liveRegs = ins->safepoint()->liveRegs();
|
||||
GetElementIC cache(liveRegs, obj, index, output, monitoredResult);
|
||||
return addCache(ins, allocateCache(cache));
|
||||
}
|
||||
case ParallelExecution: {
|
||||
|
@ -840,6 +840,7 @@ EmitGetterCall(JSContext *cx, MacroAssembler &masm,
|
||||
Register scratchReg, TypedOrValueRegister output,
|
||||
void *returnAddr)
|
||||
{
|
||||
JS_ASSERT(output.hasValue());
|
||||
// saveLive()
|
||||
MacroAssembler::AfterICSaveLive aic = masm.icSaveLive(liveRegs);
|
||||
|
||||
@ -983,20 +984,24 @@ static bool
|
||||
GenerateCallGetter(JSContext *cx, IonScript *ion, MacroAssembler &masm,
|
||||
IonCache::StubAttacher &attacher, JSObject *obj, PropertyName *name,
|
||||
JSObject *holder, HandleShape shape, RegisterSet &liveRegs, Register object,
|
||||
TypedOrValueRegister output, void *returnAddr)
|
||||
TypedOrValueRegister output, void *returnAddr, Label *failures = NULL)
|
||||
{
|
||||
JS_ASSERT(obj->isNative());
|
||||
// Initial shape check.
|
||||
Label stubFailure;
|
||||
masm.branchPtr(Assembler::NotEqual, Address(object, JSObject::offsetOfShape()),
|
||||
ImmGCPtr(obj->lastProperty()), &stubFailure);
|
||||
|
||||
JS_ASSERT(output.hasValue());
|
||||
|
||||
// Use the passed in label if there was one. Otherwise, we'll have to make our own.
|
||||
Label stubFailure;
|
||||
failures = failures ? failures : &stubFailure;
|
||||
|
||||
// Initial shape check.
|
||||
masm.branchPtr(Assembler::NotEqual, Address(object, JSObject::offsetOfShape()),
|
||||
ImmGCPtr(obj->lastProperty()), failures);
|
||||
|
||||
Register scratchReg = output.valueReg().scratchReg();
|
||||
|
||||
// Note: this may clobber the object register if it's used as scratch.
|
||||
if (obj != holder)
|
||||
GeneratePrototypeGuards(cx, ion, masm, obj, holder, object, scratchReg, &stubFailure);
|
||||
GeneratePrototypeGuards(cx, ion, masm, obj, holder, object, scratchReg, failures);
|
||||
|
||||
// Guard on the holder's shape.
|
||||
Register holderReg = scratchReg;
|
||||
@ -1004,7 +1009,7 @@ GenerateCallGetter(JSContext *cx, IonScript *ion, MacroAssembler &masm,
|
||||
masm.branchPtr(Assembler::NotEqual,
|
||||
Address(holderReg, JSObject::offsetOfShape()),
|
||||
ImmGCPtr(holder->lastProperty()),
|
||||
&stubFailure);
|
||||
failures);
|
||||
|
||||
// Now we're good to go to invoke the native call.
|
||||
if (!EmitGetterCall(cx, masm, attacher, obj, holder, shape, liveRegs, object,
|
||||
@ -1015,7 +1020,7 @@ GenerateCallGetter(JSContext *cx, IonScript *ion, MacroAssembler &masm,
|
||||
attacher.jumpRejoin(masm);
|
||||
|
||||
// Jump to next stub.
|
||||
masm.bind(&stubFailure);
|
||||
masm.bind(failures);
|
||||
attacher.jumpNextStub(masm);
|
||||
|
||||
return true;
|
||||
@ -1120,7 +1125,8 @@ template <class GetPropCache>
|
||||
static GetPropertyIC::NativeGetPropCacheability
|
||||
CanAttachNativeGetProp(typename GetPropCache::Context cx, const GetPropCache &cache,
|
||||
HandleObject obj, HandlePropertyName name,
|
||||
MutableHandleObject holder, MutableHandleShape shape)
|
||||
MutableHandleObject holder, MutableHandleShape shape,
|
||||
bool skipArrayLen = false)
|
||||
{
|
||||
if (!obj || !obj->isNative())
|
||||
return GetPropertyIC::CanAttachNone;
|
||||
@ -1146,7 +1152,10 @@ CanAttachNativeGetProp(typename GetPropCache::Context cx, const GetPropCache &ca
|
||||
return GetPropertyIC::CanAttachReadSlot;
|
||||
}
|
||||
|
||||
if (cx->names().length == name && cache.allowArrayLength(cx, obj) &&
|
||||
// |length| is a non-configurable getter property on ArrayObjects. Any time this
|
||||
// check would have passed, we can install a getter stub instead. Allow people to
|
||||
// make that decision themselves with skipArrayLen
|
||||
if (!skipArrayLen && cx->names().length == name && cache.allowArrayLength(cx, obj) &&
|
||||
IsCacheableArrayLength(cx, obj, name, cache.output()))
|
||||
{
|
||||
// The array length property is non-configurable, which means both that
|
||||
@ -1156,6 +1165,9 @@ CanAttachNativeGetProp(typename GetPropCache::Context cx, const GetPropCache &ca
|
||||
return GetPropertyIC::CanAttachArrayLength;
|
||||
}
|
||||
|
||||
// IonBuilder guarantees that it's impossible to generate a GetPropertyIC with
|
||||
// allowGetters() true and cache.output().hasValue() false. If this isn't true,
|
||||
// we will quickly assert during stub generation.
|
||||
if (cache.allowGetters() &&
|
||||
(IsCacheableGetPropCallNative(obj, holder, shape) ||
|
||||
IsCacheableGetPropCallPropertyOp(obj, holder, shape)))
|
||||
@ -1418,18 +1430,23 @@ GetPropertyIC::tryAttachDOMProxyUnshadowed(JSContext *cx, IonScript *ion, Handle
|
||||
JS_ASSERT(canAttachStub());
|
||||
JS_ASSERT(!*emitted);
|
||||
JS_ASSERT(IsCacheableDOMProxy(obj));
|
||||
JS_ASSERT(output().hasValue());
|
||||
|
||||
RootedObject checkObj(cx, obj->getTaggedProto().toObjectOrNull());
|
||||
RootedObject holder(cx);
|
||||
RootedShape shape(cx);
|
||||
|
||||
NativeGetPropCacheability canCache =
|
||||
CanAttachNativeGetProp(cx, *this, checkObj, name, &holder, &shape);
|
||||
CanAttachNativeGetProp(cx, *this, checkObj, name, &holder, &shape,
|
||||
/* skipArrayLen = */true);
|
||||
JS_ASSERT(canCache != CanAttachArrayLength);
|
||||
|
||||
if (canCache == CanAttachNone)
|
||||
return true;
|
||||
|
||||
// Make sure we observe our invariants if we're gonna deoptimize.
|
||||
if (!holder && (idempotent() || !output().hasValue()))
|
||||
return true;
|
||||
|
||||
*emitted = true;
|
||||
|
||||
if (resetNeeded) {
|
||||
@ -1479,7 +1496,8 @@ GetPropertyIC::tryAttachDOMProxyUnshadowed(JSContext *cx, IonScript *ion, Handle
|
||||
// EmitGetterCall() expects |obj| to be the object the property is
|
||||
// on to do some checks. Since we actually looked at checkObj, and
|
||||
// no extra guards will be generated, we can just pass that instead.
|
||||
JS_ASSERT_IF(canCache != CanAttachCallGetter, canCache == CanAttachArrayLength);
|
||||
JS_ASSERT(canCache == CanAttachCallGetter);
|
||||
JS_ASSERT(!idempotent());
|
||||
if (!EmitGetterCall(cx, masm, attacher, checkObj, holder, shape, liveRegs_,
|
||||
object(), scratchReg, output(), returnAddr))
|
||||
{
|
||||
@ -1489,6 +1507,7 @@ GetPropertyIC::tryAttachDOMProxyUnshadowed(JSContext *cx, IonScript *ion, Handle
|
||||
} else {
|
||||
// Property was not found on the prototype chain. Deoptimize down to
|
||||
// proxy get call
|
||||
JS_ASSERT(!idempotent());
|
||||
if (!EmitCallProxyGet(cx, masm, attacher, name, liveRegs_, object(), output(),
|
||||
returnAddr))
|
||||
{
|
||||
@ -1514,9 +1533,6 @@ GetPropertyIC::tryAttachProxy(JSContext *cx, IonScript *ion, HandleObject obj,
|
||||
if (!obj->is<ProxyObject>())
|
||||
return true;
|
||||
|
||||
if (!output().hasValue())
|
||||
return true;
|
||||
|
||||
// Skim off DOM proxies.
|
||||
if (IsCacheableDOMProxy(obj)) {
|
||||
RootedId id(cx, NameToId(name));
|
||||
@ -1560,6 +1576,9 @@ GetPropertyIC::tryAttachGenericProxy(JSContext *cx, IonScript *ion, HandleObject
|
||||
if (hasGenericProxyStub())
|
||||
return true;
|
||||
|
||||
if (idempotent() || !output().hasValue())
|
||||
return true;
|
||||
|
||||
*emitted = true;
|
||||
|
||||
Label failures;
|
||||
@ -2950,7 +2969,8 @@ GetElementIC::canAttachGetProp(JSObject *obj, const Value &idval, jsid id)
|
||||
|
||||
bool
|
||||
GetElementIC::attachGetProp(JSContext *cx, IonScript *ion, HandleObject obj,
|
||||
const Value &idval, HandlePropertyName name)
|
||||
const Value &idval, HandlePropertyName name,
|
||||
void *returnAddr)
|
||||
{
|
||||
JS_ASSERT(index().reg().hasValue());
|
||||
|
||||
@ -2958,9 +2978,14 @@ GetElementIC::attachGetProp(JSContext *cx, IonScript *ion, HandleObject obj,
|
||||
RootedShape shape(cx);
|
||||
|
||||
GetPropertyIC::NativeGetPropCacheability canCache =
|
||||
CanAttachNativeGetProp(cx, *this, obj, name, &holder, &shape);
|
||||
CanAttachNativeGetProp(cx, *this, obj, name, &holder, &shape,
|
||||
/* skipArrayLen =*/true);
|
||||
|
||||
if (canCache != GetPropertyIC::CanAttachReadSlot) {
|
||||
bool cacheable = canCache == GetPropertyIC::CanAttachReadSlot ||
|
||||
(canCache == GetPropertyIC::CanAttachCallGetter &&
|
||||
output().hasValue());
|
||||
|
||||
if (!cacheable) {
|
||||
IonSpew(IonSpew_InlineCaches, "GETELEM uncacheable property");
|
||||
return true;
|
||||
}
|
||||
@ -2975,8 +3000,19 @@ GetElementIC::attachGetProp(JSContext *cx, IonScript *ion, HandleObject obj,
|
||||
masm.branchTestValue(Assembler::NotEqual, val, idval, &failures);
|
||||
|
||||
RepatchStubAppender attacher(*this);
|
||||
GenerateReadSlot(cx, ion, masm, attacher, obj, holder, shape, object(), output(),
|
||||
&failures);
|
||||
if (canCache == GetPropertyIC::CanAttachReadSlot) {
|
||||
GenerateReadSlot(cx, ion, masm, attacher, obj, holder, shape, object(), output(),
|
||||
&failures);
|
||||
} else {
|
||||
JS_ASSERT(canCache == GetPropertyIC::CanAttachCallGetter);
|
||||
// Set the frame for bailout safety of the OOL call.
|
||||
masm.setFramePushed(ion->frameSize());
|
||||
if (!GenerateCallGetter(cx, ion, masm, attacher, obj, name, holder, shape, liveRegs_,
|
||||
object(), output(), returnAddr, &failures))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return linkAndAttachStub(cx, masm, attacher, ion, "property");
|
||||
}
|
||||
@ -3301,7 +3337,8 @@ bool
|
||||
GetElementIC::update(JSContext *cx, size_t cacheIndex, HandleObject obj,
|
||||
HandleValue idval, MutableHandleValue res)
|
||||
{
|
||||
IonScript *ion = GetTopIonJSScript(cx)->ionScript();
|
||||
void *returnAddr;
|
||||
IonScript *ion = GetTopIonJSScript(cx, &returnAddr)->ionScript();
|
||||
GetElementIC &cache = ion->getCache(cacheIndex).toGetElement();
|
||||
RootedScript script(cx);
|
||||
jsbytecode *pc;
|
||||
@ -3338,7 +3375,7 @@ GetElementIC::update(JSContext *cx, size_t cacheIndex, HandleObject obj,
|
||||
}
|
||||
if (!attachedStub && cache.monitoredResult() && canAttachGetProp(obj, idval, id)) {
|
||||
RootedPropertyName name(cx, JSID_TO_ATOM(id)->asPropertyName());
|
||||
if (!cache.attachGetProp(cx, ion, obj, idval, name))
|
||||
if (!cache.attachGetProp(cx, ion, obj, idval, name, returnAddr))
|
||||
return false;
|
||||
attachedStub = true;
|
||||
}
|
||||
|
@ -705,6 +705,8 @@ class SetPropertyIC : public RepatchIonCache
|
||||
class GetElementIC : public RepatchIonCache
|
||||
{
|
||||
protected:
|
||||
RegisterSet liveRegs_;
|
||||
|
||||
Register object_;
|
||||
ConstantOrRegister index_;
|
||||
TypedOrValueRegister output_;
|
||||
@ -719,9 +721,10 @@ class GetElementIC : public RepatchIonCache
|
||||
static const size_t MAX_FAILED_UPDATES;
|
||||
|
||||
public:
|
||||
GetElementIC(Register object, ConstantOrRegister index,
|
||||
GetElementIC(RegisterSet liveRegs, Register object, ConstantOrRegister index,
|
||||
TypedOrValueRegister output, bool monitoredResult)
|
||||
: object_(object),
|
||||
: liveRegs_(liveRegs),
|
||||
object_(object),
|
||||
index_(index),
|
||||
output_(output),
|
||||
monitoredResult_(monitoredResult),
|
||||
@ -761,7 +764,7 @@ class GetElementIC : public RepatchIonCache
|
||||
|
||||
// Helpers for CanAttachNativeGetProp
|
||||
typedef JSContext * Context;
|
||||
bool allowGetters() const { return false; }
|
||||
bool allowGetters() const { JS_ASSERT(!idempotent()); return true; }
|
||||
bool allowArrayLength(Context, HandleObject) const { return false; }
|
||||
bool canMonitorSingletonUndefinedSlot(HandleObject holder, HandleShape shape) const {
|
||||
return monitoredResult();
|
||||
@ -772,7 +775,8 @@ class GetElementIC : public RepatchIonCache
|
||||
static bool canAttachTypedArrayElement(JSObject *obj, const Value &idval,
|
||||
TypedOrValueRegister output);
|
||||
|
||||
bool attachGetProp(JSContext *cx, IonScript *ion, HandleObject obj, const Value &idval, HandlePropertyName name);
|
||||
bool attachGetProp(JSContext *cx, IonScript *ion, HandleObject obj, const Value &idval,
|
||||
HandlePropertyName name, void *returnAddr);
|
||||
bool attachDenseElement(JSContext *cx, IonScript *ion, JSObject *obj, const Value &idval);
|
||||
bool attachTypedArrayElement(JSContext *cx, IonScript *ion, TypedArrayObject *tarr,
|
||||
const Value &idval);
|
||||
|
@ -616,6 +616,45 @@ JS_IsBuiltinFunctionConstructor(JSFunction *fun)
|
||||
enum InitState { Uninitialized, Running, ShutDown };
|
||||
static InitState jsInitState = Uninitialized;
|
||||
|
||||
#ifdef DEBUG
|
||||
static void
|
||||
CheckMessageNumbering()
|
||||
{
|
||||
// Assert that the numbers associated with the error names in js.msg are
|
||||
// monotonically increasing. It's not a compile-time check, but it's
|
||||
// better than nothing.
|
||||
int errorNumber = 0;
|
||||
# define MSG_DEF(name, number, count, exception, format) \
|
||||
JS_ASSERT(name == errorNumber++);
|
||||
# include "js.msg"
|
||||
# undef MSG_DEF
|
||||
}
|
||||
|
||||
static unsigned
|
||||
MessageParameterCount(const char *format)
|
||||
{
|
||||
unsigned numfmtspecs = 0;
|
||||
for (const char *fmt = format; *fmt != '\0'; fmt++) {
|
||||
if (*fmt == '{' && isdigit(fmt[1]))
|
||||
++numfmtspecs;
|
||||
}
|
||||
return numfmtspecs;
|
||||
}
|
||||
|
||||
static void
|
||||
CheckMessageParameterCounts()
|
||||
{
|
||||
// Assert that each message format has the correct number of braced
|
||||
// parameters.
|
||||
# define MSG_DEF(name, number, count, exception, format) \
|
||||
JS_BEGIN_MACRO \
|
||||
JS_ASSERT(MessageParameterCount(format) == count); \
|
||||
JS_END_MACRO;
|
||||
# include "js.msg"
|
||||
# undef MSG_DEF
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_Init(void)
|
||||
{
|
||||
@ -626,29 +665,9 @@ JS_Init(void)
|
||||
"how do we have live runtimes before JS_Init?");
|
||||
|
||||
#ifdef DEBUG
|
||||
// Assert that the numbers associated with the error names in js.msg are
|
||||
// monotonically increasing. It's not a compile-time check, but it's
|
||||
// better than nothing.
|
||||
int errorNumber = 0;
|
||||
#define MSG_DEF(name, number, count, exception, format) \
|
||||
JS_ASSERT(name == errorNumber++);
|
||||
#include "js.msg"
|
||||
#undef MSG_DEF
|
||||
|
||||
// Assert that each message format has the correct number of braced
|
||||
// parameters.
|
||||
#define MSG_DEF(name, number, count, exception, format) \
|
||||
JS_BEGIN_MACRO \
|
||||
unsigned numfmtspecs = 0; \
|
||||
for (const char *fmt = format; *fmt != '\0'; fmt++) { \
|
||||
if (*fmt == '{' && isdigit(fmt[1])) \
|
||||
++numfmtspecs; \
|
||||
} \
|
||||
JS_ASSERT(count == numfmtspecs); \
|
||||
JS_END_MACRO;
|
||||
#include "js.msg"
|
||||
#undef MSG_DEF
|
||||
#endif /* DEBUG */
|
||||
CheckMessageNumbering();
|
||||
CheckMessageParameterCounts();
|
||||
#endif
|
||||
|
||||
using js::TlsPerThreadData;
|
||||
if (!TlsPerThreadData.initialized() && !TlsPerThreadData.init())
|
||||
|
@ -1086,14 +1086,14 @@ ArrayJoin(JSContext *cx, CallArgs &args)
|
||||
|
||||
// Steps 4 and 5
|
||||
RootedString sepstr(cx, nullptr);
|
||||
JS::Anchor<JSString *> anchor(nullptr);
|
||||
const jschar *sepchars;
|
||||
size_t seplen;
|
||||
if (!Locale && args.hasDefined(0)) {
|
||||
sepstr = ToString<CanGC>(cx, args[0]);
|
||||
if (!sepstr)
|
||||
return false;
|
||||
}
|
||||
const jschar *sepchars;
|
||||
size_t seplen;
|
||||
if (sepstr) {
|
||||
anchor = sepstr;
|
||||
sepchars = sepstr->getChars(cx);
|
||||
if (!sepchars)
|
||||
return false;
|
||||
|
@ -3252,7 +3252,7 @@ proxy_createFunction(JSContext *cx, unsigned argc, Value *vp)
|
||||
RootedObject call(cx, ValueToCallable(cx, vp[3], argc - 2));
|
||||
if (!call)
|
||||
return false;
|
||||
JSObject *construct = nullptr;
|
||||
RootedObject construct(cx, nullptr);
|
||||
if (argc > 2) {
|
||||
construct = ValueToCallable(cx, vp[4], argc - 3);
|
||||
if (!construct)
|
||||
|
@ -593,6 +593,7 @@ js::ExecuteKernel(JSContext *cx, HandleScript script, JSObject &scopeChainArg, c
|
||||
#ifdef DEBUG
|
||||
if (thisv.isObject()) {
|
||||
RootedObject thisObj(cx, &thisv.toObject());
|
||||
AutoSuppressGC nogc(cx);
|
||||
JS_ASSERT(GetOuterObject(cx, thisObj) == thisObj);
|
||||
}
|
||||
#endif
|
||||
|
@ -17,7 +17,6 @@ simple_events = [
|
||||
'PopStateEvent',
|
||||
'HashChangeEvent',
|
||||
'CloseEvent',
|
||||
'MozContactChangeEvent',
|
||||
'DeviceOrientationEvent',
|
||||
'MozApplicationEvent',
|
||||
'SmartCardEvent',
|
||||
|
@ -749,7 +749,7 @@ TEST_F(TransportConduitTest, TestVideoConduitCodecAPI) {
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
// This test can cause intermittent oranges on the builders
|
||||
CHECK_ENVIRONMENT_FLAG("MOZ_WEBRTC_TESTS")
|
||||
CHECK_ENVIRONMENT_FLAG("MOZ_WEBRTC_MEDIACONDUIT_TESTS")
|
||||
|
||||
test_utils = new MtransportTestUtils();
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
|
Loading…
Reference in New Issue
Block a user