import changes from `dev' branch of rmottola/Arctic-Fox:

- Bug 1239403 - Add JSFUN_HAS_REST flag to JSFunctionSpec entries for self-hosted builtins with ...rest parameters. r=jandem (72ed527b81)
- Bug 1238548 - Make GCRuntime::setParameter() fallible r=terrence (52a5bd8044)
- Bug 1247679, part 2 - Null check inside TraceCallbackFunc::Trace. r=smaug (ebad38ad73)
- bug 1241453 - switch MaiAtkObject to use AccessibleOrProxy r=davidb (42d09b21da)
- bug 1241453 - switch MaiHyperLink to use AccessibleOrProxy r=davidb (61a1799bc3)
- bug 1241453 - add an AccessibleOrProxy class r=davidb (7882027a59)
- bug 1243077 - add AccessibleOrProxy::IsNull() r=davidb (91bf2962a5)
- bug 1203861 - use strncmp() instead of nsCString.equals() to compare names r=davidb (1a4f043375)
- bug 1243077 - simplify GetRoleCB some r=davidb (37e4ac2e23)
This commit is contained in:
2023-08-07 09:43:14 +08:00
parent cc81aca6b2
commit 6e095708be
18 changed files with 218 additions and 119 deletions
+15 -20
View File
@@ -145,7 +145,7 @@ MaiAtkObject::GetAtkHyperlink()
void
MaiAtkObject::Shutdown()
{
accWrap = 0;
accWrap.SetBits(0);
MaiHyperlink* maiHyperlink =
(MaiHyperlink*)g_object_get_qdata(G_OBJECT(this), quark_mai_hyperlink);
if (maiHyperlink) {
@@ -559,7 +559,7 @@ initializeCB(AtkObject *aAtkObj, gpointer aData)
ATK_OBJECT_CLASS(parent_class)->initialize(aAtkObj, aData);
/* initialize object */
MAI_ATK_OBJECT(aAtkObj)->accWrap = reinterpret_cast<uintptr_t>(aData);
MAI_ATK_OBJECT(aAtkObj)->accWrap.SetBits(reinterpret_cast<uintptr_t>(aData));
}
void
@@ -567,7 +567,7 @@ finalizeCB(GObject *aObj)
{
if (!IS_MAI_OBJECT(aObj))
return;
NS_ASSERTION(MAI_ATK_OBJECT(aObj)->accWrap == 0, "AccWrap NOT null");
NS_ASSERTION(MAI_ATK_OBJECT(aObj)->accWrap.IsNull(), "AccWrap NOT null");
// call parent finalize function
// finalize of GObjectClass will unref the accessible parent if has
@@ -597,7 +597,8 @@ static void
MaybeFireNameChange(AtkObject* aAtkObj, const nsString& aNewName)
{
NS_ConvertUTF16toUTF8 newNameUTF8(aNewName);
if (aAtkObj->name && newNameUTF8.Equals(aAtkObj->name))
if (aAtkObj->name &&
!strncmp(aAtkObj->name, newNameUTF8.get(), newNameUTF8.Length()))
return;
// Below we duplicate the functionality of atk_object_set_name(),
@@ -649,22 +650,17 @@ getRoleCB(AtkObject *aAtkObj)
if (aAtkObj->role != ATK_ROLE_INVALID)
return aAtkObj->role;
AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj);
a11y::role role;
if (!accWrap) {
ProxyAccessible* proxy = GetProxy(aAtkObj);
if (!proxy)
return ATK_ROLE_INVALID;
AccessibleOrProxy acc = GetInternalObj(aAtkObj);
if (acc.IsNull()) {
return ATK_ROLE_INVALID;
}
role = proxy->Role();
} else {
#ifdef DEBUG
if (AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj)) {
NS_ASSERTION(nsAccUtils::IsTextInterfaceSupportCorrect(accWrap),
"Does not support Text interface when it should");
#endif
role = accWrap->Role();
}
#endif
#define ROLE(geckoRole, stringRole, atkRole, macRole, \
msaaRole, ia2Role, nameRule) \
@@ -672,7 +668,7 @@ getRoleCB(AtkObject *aAtkObj)
aAtkObj->role = atkRole; \
break;
switch (role) {
switch (acc.Role()) {
#include "RoleMap.h"
default:
MOZ_CRASH("Unknown role.");
@@ -1064,7 +1060,7 @@ GetAccessibleWrap(AtkObject* aAtkObj)
nullptr);
uintptr_t accWrapPtr = isMAIObject ?
MAI_ATK_OBJECT(aAtkObj)->accWrap :
MAI_ATK_OBJECT(aAtkObj)->accWrap.Bits() :
reinterpret_cast<uintptr_t>(MAI_ATK_SOCKET(aAtkObj)->accWrap);
if (accWrapPtr & IS_PROXY)
return nullptr;
@@ -1088,11 +1084,10 @@ ProxyAccessible*
GetProxy(AtkObject* aObj)
{
if (!aObj || !IS_MAI_OBJECT(aObj) ||
!(MAI_ATK_OBJECT(aObj)->accWrap & IS_PROXY))
!MAI_ATK_OBJECT(aObj)->accWrap.IsProxy())
return nullptr;
return reinterpret_cast<ProxyAccessible*>(MAI_ATK_OBJECT(aObj)->accWrap
& ~IS_PROXY);
return MAI_ATK_OBJECT(aObj)->accWrap.AsProxy();
}
AtkObject*
+2 -1
View File
@@ -11,6 +11,7 @@
#include <glib.h>
#include <glib-object.h>
#include "AccessibleOrProxy.h"
#include "AccessibleWrap.h"
namespace mozilla {
@@ -95,7 +96,7 @@ struct MaiAtkObject
* The AccessibleWrap whose properties and features are exported
* via this object instance.
*/
uintptr_t accWrap;
mozilla::a11y::AccessibleOrProxy accWrap;
/*
* Get the AtkHyperlink for this atk object.
+1 -1
View File
@@ -100,7 +100,7 @@ mai_atk_hyperlink_get_type(void)
return type;
}
MaiHyperlink::MaiHyperlink(uintptr_t aHyperLink) :
MaiHyperlink::MaiHyperlink(AccessibleOrProxy aHyperLink) :
mHyperlink(aHyperLink),
mMaiAtkHyperlink(nullptr)
{
+9 -11
View File
@@ -23,31 +23,29 @@ namespace a11y {
class MaiHyperlink
{
public:
explicit MaiHyperlink(uintptr_t aHyperLink);
explicit MaiHyperlink(AccessibleOrProxy aHyperLink);
~MaiHyperlink();
public:
AtkHyperlink* GetAtkHyperlink() const { return mMaiAtkHyperlink; }
Accessible* GetAccHyperlink()
{
if (!mHyperlink || mHyperlink & IS_PROXY)
if (!mHyperlink.IsAccessible())
return nullptr;
Accessible* link = reinterpret_cast<Accessible*>(mHyperlink);
Accessible* link = mHyperlink.AsAccessible();
if (!link) {
return nullptr;
}
NS_ASSERTION(link->IsLink(), "Why isn't it a link!");
return link;
}
ProxyAccessible* Proxy() const
{
if (!(mHyperlink & IS_PROXY))
return nullptr;
return reinterpret_cast<ProxyAccessible*>(mHyperlink & ~IS_PROXY);
}
ProxyAccessible* Proxy() const { return mHyperlink.AsProxy(); }
protected:
uintptr_t mHyperlink;
AccessibleOrProxy mHyperlink;
AtkHyperlink* mMaiAtkHyperlink;
};
+65
View File
@@ -0,0 +1,65 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_a11y_AccessibleOrProxy_h
#define mozilla_a11y_AccessibleOrProxy_h
#include "mozilla/a11y/Accessible.h"
#include "mozilla/a11y/ProxyAccessible.h"
#include <stdint.h>
namespace mozilla {
namespace a11y {
/**
* This class stores an Accessible* or a ProxyAccessible* in a safe manner
* with size sizeof(void*).
*/
class AccessibleOrProxy
{
public:
MOZ_IMPLICIT AccessibleOrProxy(Accessible* aAcc) :
mBits(reinterpret_cast<uintptr_t>(aAcc)) {}
MOZ_IMPLICIT AccessibleOrProxy(ProxyAccessible* aProxy) :
mBits(reinterpret_cast<uintptr_t>(aProxy) | IS_PROXY) {}
MOZ_IMPLICIT AccessibleOrProxy(decltype(nullptr)) : mBits(0) {}
bool IsProxy() const { return mBits & IS_PROXY; }
ProxyAccessible* AsProxy() const
{
if (IsProxy()) {
return reinterpret_cast<ProxyAccessible*>(mBits & ~IS_PROXY);
}
return nullptr;
}
bool IsAccessible() const { return !IsProxy(); }
Accessible* AsAccessible() const
{
if (IsAccessible()) {
return reinterpret_cast<Accessible*>(mBits);
}
return nullptr;
}
bool IsNull() const { return mBits == 0; }
// XXX these are implementation details that ideally would not be exposed.
uintptr_t Bits() const { return mBits; }
void SetBits(uintptr_t aBits) { mBits = aBits; }
private:
uintptr_t mBits;
static const uintptr_t IS_PROXY = 0x1;
};
}
}
#endif
+38 -34
View File
@@ -321,43 +321,42 @@ MinorGC(JSContext* cx, unsigned argc, Value* vp)
return true;
}
#define FOR_EACH_GC_PARAM(_) \
_("maxBytes", JSGC_MAX_BYTES, true, false) \
_("maxMallocBytes", JSGC_MAX_MALLOC_BYTES, true, false) \
_("gcBytes", JSGC_BYTES, false, false) \
_("gcNumber", JSGC_NUMBER, false, false) \
_("mode", JSGC_MODE, true, true) \
_("unusedChunks", JSGC_UNUSED_CHUNKS, false, false) \
_("totalChunks", JSGC_TOTAL_CHUNKS, false, false) \
_("sliceTimeBudget", JSGC_SLICE_TIME_BUDGET, true, false) \
_("markStackLimit", JSGC_MARK_STACK_LIMIT, true, false) \
_("highFrequencyTimeLimit", JSGC_HIGH_FREQUENCY_TIME_LIMIT, true, false) \
_("highFrequencyLowLimit", JSGC_HIGH_FREQUENCY_LOW_LIMIT, true, false) \
_("highFrequencyHighLimit", JSGC_HIGH_FREQUENCY_HIGH_LIMIT, true, false) \
_("highFrequencyHeapGrowthMax", JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MAX, true, false) \
_("highFrequencyHeapGrowthMin", JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MIN, true, false) \
_("lowFrequencyHeapGrowth", JSGC_LOW_FREQUENCY_HEAP_GROWTH, true, false) \
_("dynamicHeapGrowth", JSGC_DYNAMIC_HEAP_GROWTH, true, true) \
_("dynamicMarkSlice", JSGC_DYNAMIC_MARK_SLICE, true, true) \
_("allocationThreshold", JSGC_ALLOCATION_THRESHOLD, true, false) \
_("decommitThreshold", JSGC_DECOMMIT_THRESHOLD, true, false) \
_("minEmptyChunkCount", JSGC_MIN_EMPTY_CHUNK_COUNT, true, true) \
_("maxEmptyChunkCount", JSGC_MAX_EMPTY_CHUNK_COUNT, true, true) \
_("compactingEnabled", JSGC_COMPACTING_ENABLED, true, true)
#define FOR_EACH_GC_PARAM(_) \
_("maxBytes", JSGC_MAX_BYTES, true) \
_("maxMallocBytes", JSGC_MAX_MALLOC_BYTES, true) \
_("gcBytes", JSGC_BYTES, false) \
_("gcNumber", JSGC_NUMBER, false) \
_("mode", JSGC_MODE, true) \
_("unusedChunks", JSGC_UNUSED_CHUNKS, false) \
_("totalChunks", JSGC_TOTAL_CHUNKS, false) \
_("sliceTimeBudget", JSGC_SLICE_TIME_BUDGET, true) \
_("markStackLimit", JSGC_MARK_STACK_LIMIT, true) \
_("highFrequencyTimeLimit", JSGC_HIGH_FREQUENCY_TIME_LIMIT, true) \
_("highFrequencyLowLimit", JSGC_HIGH_FREQUENCY_LOW_LIMIT, true) \
_("highFrequencyHighLimit", JSGC_HIGH_FREQUENCY_HIGH_LIMIT, true) \
_("highFrequencyHeapGrowthMax", JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MAX, true) \
_("highFrequencyHeapGrowthMin", JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MIN, true) \
_("lowFrequencyHeapGrowth", JSGC_LOW_FREQUENCY_HEAP_GROWTH, true) \
_("dynamicHeapGrowth", JSGC_DYNAMIC_HEAP_GROWTH, true) \
_("dynamicMarkSlice", JSGC_DYNAMIC_MARK_SLICE, true) \
_("allocationThreshold", JSGC_ALLOCATION_THRESHOLD, true) \
_("decommitThreshold", JSGC_DECOMMIT_THRESHOLD, true) \
_("minEmptyChunkCount", JSGC_MIN_EMPTY_CHUNK_COUNT, true) \
_("maxEmptyChunkCount", JSGC_MAX_EMPTY_CHUNK_COUNT, true) \
_("compactingEnabled", JSGC_COMPACTING_ENABLED, true)
static const struct ParamInfo {
const char* name;
JSGCParamKey param;
bool writable;
bool allowZero;
} paramMap[] = {
#define DEFINE_PARAM_INFO(name, key, writable, allowZero) \
{name, key, writable, allowZero},
#define DEFINE_PARAM_INFO(name, key, writable) \
{name, key, writable},
FOR_EACH_GC_PARAM(DEFINE_PARAM_INFO)
#undef DEFINE_PARAM_INFO
};
#define PARAM_NAME_LIST_ENTRY(name, key, writable, allowZero) \
#define PARAM_NAME_LIST_ENTRY(name, key, writable) \
" " name
#define GC_PARAMETER_ARGS_LIST FOR_EACH_GC_PARAM(PARAM_NAME_LIST_ENTRY)
@@ -414,12 +413,6 @@ GCParameter(JSContext* cx, unsigned argc, Value* vp)
}
uint32_t value = floor(d);
if (!info.allowZero && value == 0) {
JS_ReportError(cx, "the second argument must be convertable to uint32_t "
"with non-zero value");
return false;
}
if (param == JSGC_MARK_STACK_LIMIT && JS::IsIncrementalGCInProgress(cx->runtime())) {
JS_ReportError(cx, "attempt to set markStackLimit while a GC is in progress");
return false;
@@ -436,7 +429,18 @@ GCParameter(JSContext* cx, unsigned argc, Value* vp)
}
}
JS_SetGCParameter(cx->runtime(), param, value);
bool ok;
{
JSRuntime* rt = cx->runtime();
AutoLockGC lock(rt);
ok = rt->gc.setParameter(param, value, lock);
}
if (!ok) {
JS_ReportError(cx, "Parameter value out of range");
return false;
}
args.rval().setUndefined();
return true;
}
+2 -2
View File
@@ -231,8 +231,8 @@ const Class js::ScalarTypeDescr::class_ = {
const JSFunctionSpec js::ScalarTypeDescr::typeObjectMethods[] = {
JS_SELF_HOSTED_FN("toSource", "DescrToSource", 0, 0),
{"array", {nullptr, nullptr}, 0, 0, "ArrayShorthand"},
{"equivalent", {nullptr, nullptr}, 1, 0, "TypeDescrEquivalent"},
JS_SELF_HOSTED_FN("array", "ArrayShorthand", 1, JSFUN_HAS_REST),
JS_SELF_HOSTED_FN("equivalent", "TypeDescrEquivalent", 1, 0),
JS_FS_END
};
+4 -4
View File
@@ -154,8 +154,8 @@ class GCSchedulingTunables
/*
* Controls the number of empty chunks reserved for future allocation.
*/
unsigned minEmptyChunkCount_;
unsigned maxEmptyChunkCount_;
uint32_t minEmptyChunkCount_;
uint32_t maxEmptyChunkCount_;
public:
GCSchedulingTunables()
@@ -190,7 +190,7 @@ class GCSchedulingTunables
unsigned minEmptyChunkCount(const AutoLockGC&) const { return minEmptyChunkCount_; }
unsigned maxEmptyChunkCount() const { return maxEmptyChunkCount_; }
void setParameter(JSGCParamKey key, uint32_t value, const AutoLockGC& lock);
bool setParameter(JSGCParamKey key, uint32_t value, const AutoLockGC& lock);
};
/*
@@ -593,7 +593,7 @@ class GCRuntime
void removeRoot(Value* vp);
void setMarkStackLimit(size_t limit, AutoLockGC& lock);
void setParameter(JSGCParamKey key, uint32_t value, AutoLockGC& lock);
bool setParameter(JSGCParamKey key, uint32_t value, AutoLockGC& lock);
uint32_t getParameter(JSGCParamKey key, const AutoLockGC& lock);
bool triggerGC(JS::gcreason::Reason reason);
+2
View File
@@ -0,0 +1,2 @@
// |jit-test| error: Error
gcparam("highFrequencyHeapGrowthMax", 1);
+5 -2
View File
@@ -1460,7 +1460,7 @@ JS_PUBLIC_API(void)
JS_SetGCParameter(JSRuntime* rt, JSGCParamKey key, uint32_t value)
{
AutoLockGC lock(rt);
rt->gc.setParameter(key, value, lock);
MOZ_ALWAYS_TRUE(rt->gc.setParameter(key, value, lock));
}
JS_PUBLIC_API(void)
@@ -3401,7 +3401,10 @@ JS::NewFunctionFromSpec(JSContext* cx, const JSFunctionSpec* fs, HandleId id)
{
return nullptr;
}
return &funVal.toObject().as<JSFunction>();
JSFunction* fun = &funVal.toObject().as<JSFunction>();
if (fs->flags & JSFUN_HAS_REST)
fun->setHasRest();
return fun;
}
RootedAtom atom(cx, IdToFunctionName(cx, id));
+3 -1
View File
@@ -840,7 +840,9 @@ class MOZ_STACK_CLASS SourceBufferHolder final
*/
#define JSFUN_GENERIC_NATIVE 0x800
#define JSFUN_FLAGS_MASK 0xe00 /* | of all the JSFUN_* flags */
#define JSFUN_HAS_REST 0x1000 /* function has ...rest parameter. */
#define JSFUN_FLAGS_MASK 0x1e00 /* | of all the JSFUN_* flags */
/*
* If set, will allow redefining a non-configurable property, but only on a
+1 -1
View File
@@ -1671,7 +1671,7 @@ const JSFunctionSpec js::function_methods[] = {
JS_FN(js_apply_str, fun_apply, 2,0),
JS_FN(js_call_str, fun_call, 1,0),
JS_FN("isGenerator", fun_isGenerator,0,0),
JS_SELF_HOSTED_FN("bind", "FunctionBind", 1,JSPROP_DEFINE_LATE),
JS_SELF_HOSTED_FN("bind", "FunctionBind", 2,JSPROP_DEFINE_LATE|JSFUN_HAS_REST),
JS_FS_END
};
+45 -18
View File
@@ -1293,7 +1293,7 @@ GCRuntime::init(uint32_t maxbytes, uint32_t maxNurseryBytes)
* for default backward API compatibility.
*/
AutoLockGC lock(rt);
tunables.setParameter(JSGC_MAX_BYTES, maxbytes, lock);
MOZ_ALWAYS_TRUE(tunables.setParameter(JSGC_MAX_BYTES, maxbytes, lock));
setMaxMallocBytes(maxbytes);
const char* size = getenv("JSGC_MARK_STACK_LIMIT");
@@ -1401,7 +1401,7 @@ GCRuntime::finishRoots()
FinishPersistentRootedChains(rt->mainThread.roots);
}
void
bool
GCRuntime::setParameter(JSGCParamKey key, uint32_t value, AutoLockGC& lock)
{
switch (key) {
@@ -1420,24 +1420,30 @@ GCRuntime::setParameter(JSGCParamKey key, uint32_t value, AutoLockGC& lock)
decommitThreshold = (uint64_t)value * 1024 * 1024;
break;
case JSGC_MODE:
if (mode != JSGC_MODE_GLOBAL &&
mode != JSGC_MODE_COMPARTMENT &&
mode != JSGC_MODE_INCREMENTAL)
{
return false;
}
mode = JSGCMode(value);
MOZ_ASSERT(mode == JSGC_MODE_GLOBAL ||
mode == JSGC_MODE_COMPARTMENT ||
mode == JSGC_MODE_INCREMENTAL);
break;
case JSGC_COMPACTING_ENABLED:
compactingEnabled = value != 0;
break;
default:
tunables.setParameter(key, value, lock);
if (!tunables.setParameter(key, value, lock))
return false;
for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) {
zone->threshold.updateAfterGC(zone->usage.gcBytes(), GC_NORMAL, tunables,
schedulingState, lock);
}
}
return true;
}
void
bool
GCSchedulingTunables::setParameter(JSGCParamKey key, uint32_t value, const AutoLockGC& lock)
{
switch(key) {
@@ -1447,31 +1453,50 @@ GCSchedulingTunables::setParameter(JSGCParamKey key, uint32_t value, const AutoL
case JSGC_HIGH_FREQUENCY_TIME_LIMIT:
highFrequencyThresholdUsec_ = value * PRMJ_USEC_PER_MSEC;
break;
case JSGC_HIGH_FREQUENCY_LOW_LIMIT:
highFrequencyLowLimitBytes_ = (uint64_t)value * 1024 * 1024;
case JSGC_HIGH_FREQUENCY_LOW_LIMIT: {
uint64_t newLimit = (uint64_t)value * 1024 * 1024;
if (newLimit == UINT64_MAX)
return false;
highFrequencyLowLimitBytes_ = newLimit;
if (highFrequencyLowLimitBytes_ >= highFrequencyHighLimitBytes_)
highFrequencyHighLimitBytes_ = highFrequencyLowLimitBytes_ + 1;
MOZ_ASSERT(highFrequencyHighLimitBytes_ > highFrequencyLowLimitBytes_);
break;
case JSGC_HIGH_FREQUENCY_HIGH_LIMIT:
MOZ_ASSERT(value > 0);
highFrequencyHighLimitBytes_ = (uint64_t)value * 1024 * 1024;
}
case JSGC_HIGH_FREQUENCY_HIGH_LIMIT: {
uint64_t newLimit = (uint64_t)value * 1024 * 1024;
if (newLimit == 0)
return false;
highFrequencyHighLimitBytes_ = newLimit;
if (highFrequencyHighLimitBytes_ <= highFrequencyLowLimitBytes_)
highFrequencyLowLimitBytes_ = highFrequencyHighLimitBytes_ - 1;
MOZ_ASSERT(highFrequencyHighLimitBytes_ > highFrequencyLowLimitBytes_);
break;
case JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MAX:
highFrequencyHeapGrowthMax_ = value / 100.0;
}
case JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MAX: {
double newGrowth = value / 100.0;
if (newGrowth <= 0.85)
return false;
highFrequencyHeapGrowthMax_ = newGrowth;
MOZ_ASSERT(highFrequencyHeapGrowthMax_ / 0.85 > 1.0);
break;
case JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MIN:
highFrequencyHeapGrowthMin_ = value / 100.0;
}
case JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MIN: {
double newGrowth = value / 100.0;
if (newGrowth <= 0.85)
return false;
highFrequencyHeapGrowthMin_ = newGrowth;
MOZ_ASSERT(highFrequencyHeapGrowthMin_ / 0.85 > 1.0);
break;
case JSGC_LOW_FREQUENCY_HEAP_GROWTH:
lowFrequencyHeapGrowth_ = value / 100.0;
}
case JSGC_LOW_FREQUENCY_HEAP_GROWTH: {
double newGrowth = value / 100.0;
if (newGrowth <= 0.9)
return false;
lowFrequencyHeapGrowth_ = newGrowth;
MOZ_ASSERT(lowFrequencyHeapGrowth_ / 0.9 > 1.0);
break;
}
case JSGC_DYNAMIC_HEAP_GROWTH:
dynamicHeapGrowthEnabled_ = value != 0;
break;
@@ -1496,6 +1521,8 @@ GCSchedulingTunables::setParameter(JSGCParamKey key, uint32_t value, const AutoL
default:
MOZ_CRASH("Unknown GC parameter.");
}
return true;
}
uint32_t
+1 -1
View File
@@ -4243,7 +4243,7 @@ static const JSFunctionSpec string_static_methods[] = {
JS_INLINABLE_FN("fromCharCode", js::str_fromCharCode, 1, 0, StringFromCharCode),
JS_SELF_HOSTED_FN("fromCodePoint", "String_static_fromCodePoint", 1,0),
JS_SELF_HOSTED_FN("raw", "String_static_raw", 1,0),
JS_SELF_HOSTED_FN("raw", "String_static_raw", 2,JSFUN_HAS_REST),
JS_SELF_HOSTED_FN("substring", "String_static_substring", 3,0),
JS_SELF_HOSTED_FN("substr", "String_static_substr", 3,0),
JS_SELF_HOSTED_FN("slice", "String_static_slice", 3,0),
+3 -1
View File
@@ -301,7 +301,7 @@ MakeDefaultConstructor(JSContext* cx, JSOp op, JSAtom* atom, HandleObject proto)
RootedFunction ctor(cx);
if (!cx->runtime()->createLazySelfHostedFunctionClone(cx, selfHostedName, name,
/* nargs = */ 0,
/* nargs = */ !!derived,
proto, TenuredObject, &ctor))
{
return nullptr;
@@ -309,6 +309,8 @@ MakeDefaultConstructor(JSContext* cx, JSOp op, JSAtom* atom, HandleObject proto)
ctor->setIsConstructor();
ctor->setIsClassConstructor();
if (derived)
ctor->setHasRest();
MOZ_ASSERT(ctor->infallibleIsDefaultClassConstructor(cx));
+2 -13
View File
@@ -2276,19 +2276,8 @@ JSRuntime::cloneSelfHostedFunctionScript(JSContext* cx, HandlePropertyName name,
return false;
MOZ_ASSERT(!targetFun->isInterpretedLazy());
// ...rest args don't count as formal args, but are included in nargs. We don't,
// however, want to introduce a flag "has rest args" in the declaration of
// self-hosted functions, so we fix up the flag and the nargs value here.
// Since the target function might have been cloned and relazified before,
// this only happens if the target function isn't marked as having rest
// args.
MOZ_ASSERT(sourceFun->nargs() - sourceFun->hasRest() ==
targetFun->nargs() - targetFun->hasRest());
MOZ_ASSERT_IF(targetFun->hasRest(), sourceFun->hasRest());
if (sourceFun->hasRest() && !targetFun->hasRest()) {
targetFun->setHasRest();
targetFun->setArgCount(sourceFun->nargs());
}
MOZ_ASSERT(sourceFun->nargs() == targetFun->nargs());
MOZ_ASSERT(sourceFun->hasRest() == targetFun->hasRest());
// The target function might have been relazified after its flags changed.
targetFun->setFlags(targetFun->flags() | sourceFun->flags());
+18 -6
View File
@@ -58,40 +58,52 @@ void
TraceCallbackFunc::Trace(JS::Heap<JSObject*>* aPtr, const char* aName,
void* aClosure) const
{
mCallback(JS::GCCellPtr(aPtr->get()), aName, aClosure);
if (aPtr->get()) {
mCallback(JS::GCCellPtr(aPtr->get()), aName, aClosure);
}
}
void
TraceCallbackFunc::Trace(JSObject** aPtr, const char* aName,
void* aClosure) const
{
mCallback(JS::GCCellPtr(*aPtr), aName, aClosure);
if (*aPtr) {
mCallback(JS::GCCellPtr(*aPtr), aName, aClosure);
}
}
void
TraceCallbackFunc::Trace(JS::TenuredHeap<JSObject*>* aPtr, const char* aName,
void* aClosure) const
{
mCallback(JS::GCCellPtr(aPtr->getPtr()), aName, aClosure);
if (aPtr->getPtr()) {
mCallback(JS::GCCellPtr(aPtr->getPtr()), aName, aClosure);
}
}
void
TraceCallbackFunc::Trace(JS::Heap<JSFunction*>* aPtr, const char* aName,
void* aClosure) const
{
mCallback(JS::GCCellPtr(aPtr->get()), aName, aClosure);
if (aPtr->get()) {
mCallback(JS::GCCellPtr(aPtr->get()), aName, aClosure);
}
}
void
TraceCallbackFunc::Trace(JS::Heap<JSString*>* aPtr, const char* aName,
void* aClosure) const
{
mCallback(JS::GCCellPtr(aPtr->get()), aName, aClosure);
if (aPtr->get()) {
mCallback(JS::GCCellPtr(aPtr->get()), aName, aClosure);
}
}
void
TraceCallbackFunc::Trace(JS::Heap<JSScript*>* aPtr, const char* aName,
void* aClosure) const
{
mCallback(JS::GCCellPtr(aPtr->get()), aName, aClosure);
if (aPtr->get()) {
mCallback(JS::GCCellPtr(aPtr->get()), aName, aClosure);
}
}
+2 -3
View File
@@ -468,11 +468,10 @@ DowncastCCParticipant(void* aPtr)
NS_CYCLE_COLLECTION_CLASSNAME(_base_class)::Trace(s, aCallbacks, aClosure);
#define NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(_field) \
if (tmp->_field) \
aCallbacks.Trace(&tmp->_field, #_field, aClosure);
aCallbacks.Trace(&tmp->_field, #_field, aClosure);
#define NS_IMPL_CYCLE_COLLECTION_TRACE_JSVAL_MEMBER_CALLBACK(_field) \
aCallbacks.Trace(&tmp->_field, #_field, aClosure);
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(_field)
// NB: The (void)tmp; hack in the TRACE_END macro exists to support
// implementations that don't need to do anything in their Trace method.