Merge remote-tracking branch 'origin/tracking' into custom

This commit is contained in:
roytam1 2023-07-14 10:22:44 +08:00
commit 56216e737f
17 changed files with 319 additions and 131 deletions

View file

@ -282,7 +282,9 @@ def old_configure_options(*options):
'--with-ios-sdk', '--with-ios-sdk',
'--with-jitreport-granularity', '--with-jitreport-granularity',
'--with-macbundlename-prefix', '--with-macbundlename-prefix',
'--with-macbundle-entitlement',
'--with-macbundle-identity', '--with-macbundle-identity',
'--with-macbundle-type',
'--with-macos-private-frameworks', '--with-macos-private-frameworks',
'--with-macos-sdk', '--with-macos-sdk',
'--with-nspr-cflags', '--with-nspr-cflags',

View file

@ -408,16 +408,16 @@ DOMHighResTimeStamp Performance::ConvertNameToTimestamp(const nsAString& aName,
DOMHighResTimeStamp DOMHighResTimeStamp
Performance::ResolveEndTimeForMeasure( Performance::ResolveEndTimeForMeasure(
const Optional<nsAString>& aEndMark, const Optional<nsAString>& aEndMark,
const PerformanceMeasureOptions* aOptions, const Maybe<const PerformanceMeasureOptions&>& aOptions,
ErrorResult& aRv) ErrorResult& aRv)
{ {
DOMHighResTimeStamp endTime; DOMHighResTimeStamp endTime;
if (aEndMark.WasPassed()) { if (aEndMark.WasPassed()) {
endTime = ConvertMarkToTimestampWithString(aEndMark.Value(), aRv); endTime = ConvertMarkToTimestampWithString(aEndMark.Value(), aRv);
} else if (aOptions != nullptr && aOptions->mEnd.WasPassed()) { } else if (aOptions && aOptions->mEnd.WasPassed()) {
endTime = ConvertMarkToTimestamp(ResolveTimestampAttribute::End, endTime = ConvertMarkToTimestamp(ResolveTimestampAttribute::End,
aOptions->mEnd.Value(), aRv); aOptions->mEnd.Value(), aRv);
} else if (aOptions != nullptr && aOptions->mStart.WasPassed() && } else if (aOptions && aOptions->mStart.WasPassed() &&
aOptions->mDuration.WasPassed()) { aOptions->mDuration.WasPassed()) {
const DOMHighResTimeStamp start = ConvertMarkToTimestamp( const DOMHighResTimeStamp start = ConvertMarkToTimestamp(
ResolveTimestampAttribute::Start, aOptions->mStart.Value(), aRv); ResolveTimestampAttribute::Start, aOptions->mStart.Value(), aRv);
@ -442,16 +442,16 @@ Performance::ResolveEndTimeForMeasure(
DOMHighResTimeStamp DOMHighResTimeStamp
Performance::ResolveStartTimeForMeasure( Performance::ResolveStartTimeForMeasure(
const nsAString* aStartMark, const Maybe<const nsAString&>& aStartMark,
const PerformanceMeasureOptions* aOptions, const Maybe<const PerformanceMeasureOptions&>& aOptions,
ErrorResult& aRv) ErrorResult& aRv)
{ {
DOMHighResTimeStamp startTime; DOMHighResTimeStamp startTime;
if (aOptions != nullptr && aOptions->mStart.WasPassed()) { if (aOptions && aOptions->mStart.WasPassed()) {
startTime = ConvertMarkToTimestamp(ResolveTimestampAttribute::Start, startTime = ConvertMarkToTimestamp(ResolveTimestampAttribute::Start,
aOptions->mStart.Value(), aOptions->mStart.Value(),
aRv); aRv);
} else if (aOptions != nullptr && aOptions->mDuration.WasPassed() && } else if (aOptions && aOptions->mDuration.WasPassed() &&
aOptions->mEnd.WasPassed()) { aOptions->mEnd.WasPassed()) {
const DOMHighResTimeStamp duration = const DOMHighResTimeStamp duration =
ConvertMarkToTimestampWithDOMHighResTimeStamp( ConvertMarkToTimestampWithDOMHighResTimeStamp(
@ -469,7 +469,7 @@ Performance::ResolveStartTimeForMeasure(
} }
startTime = end - duration; startTime = end - duration;
} else if (aStartMark != nullptr) { } else if (aStartMark) {
startTime = ConvertMarkToTimestampWithString(*aStartMark, aRv); startTime = ConvertMarkToTimestampWithString(*aStartMark, aRv);
} else { } else {
startTime = 0; startTime = 0;
@ -485,13 +485,14 @@ Performance::Measure(JSContext* aCx,
const Optional<nsAString>& aEndMark, const Optional<nsAString>& aEndMark,
ErrorResult& aRv) ErrorResult& aRv)
{ {
const PerformanceMeasureOptions* options = nullptr; // Maybe is more readable than using the union type directly.
Maybe<const PerformanceMeasureOptions&> options;
if (aStartOrMeasureOptions.IsPerformanceMeasureOptions()) { if (aStartOrMeasureOptions.IsPerformanceMeasureOptions()) {
options = &aStartOrMeasureOptions.GetAsPerformanceMeasureOptions(); options.emplace(aStartOrMeasureOptions.GetAsPerformanceMeasureOptions());
} }
const bool isOptionsNotEmpty = const bool isOptionsNotEmpty =
(options != nullptr) && options.isSome() &&
(!options->mDetail.isUndefined() || options->mStart.WasPassed() || (!options->mDetail.isUndefined() || options->mStart.WasPassed() ||
options->mEnd.WasPassed() || options->mDuration.WasPassed()); options->mEnd.WasPassed() || options->mDuration.WasPassed());
if (isOptionsNotEmpty) { if (isOptionsNotEmpty) {
@ -518,9 +519,10 @@ Performance::Measure(JSContext* aCx,
return nullptr; return nullptr;
} }
const nsAString* startMark = nullptr; // Convert to Maybe for consistency with options.
Maybe<const nsAString&> startMark;
if (aStartOrMeasureOptions.IsString()) { if (aStartOrMeasureOptions.IsString()) {
startMark = &aStartOrMeasureOptions.GetAsString(); startMark.emplace(aStartOrMeasureOptions.GetAsString());
} }
const DOMHighResTimeStamp startTime = const DOMHighResTimeStamp startTime =
ResolveStartTimeForMeasure(startMark, options, aRv); ResolveStartTimeForMeasure(startMark, options, aRv);
@ -529,7 +531,7 @@ Performance::Measure(JSContext* aCx,
} }
JS::Rooted<JS::Value> detail(aCx); JS::Rooted<JS::Value> detail(aCx);
if (options != nullptr && !options->mDetail.isNullOrUndefined()) { if (options && !options->mDetail.isNullOrUndefined()) {
StructuredSerializeOptions serializeOptions; StructuredSerializeOptions serializeOptions;
JS::Rooted<JS::Value> valueToClone(aCx, options->mDetail); JS::Rooted<JS::Value> valueToClone(aCx, options->mDetail);
nsContentUtils::StructuredClone(aCx, GetParentObject(), valueToClone, nsContentUtils::StructuredClone(aCx, GetParentObject(), valueToClone,

View file

@ -198,11 +198,11 @@ private:
DOMHighResTimeStamp ResolveEndTimeForMeasure( DOMHighResTimeStamp ResolveEndTimeForMeasure(
const Optional<nsAString>& aEndMark, const Optional<nsAString>& aEndMark,
const PerformanceMeasureOptions* aOptions, const Maybe<const PerformanceMeasureOptions&>& aOptions,
ErrorResult& aRv); ErrorResult& aRv);
DOMHighResTimeStamp ResolveStartTimeForMeasure( DOMHighResTimeStamp ResolveStartTimeForMeasure(
const nsAString* aStartMark, const Maybe<const nsAString&>& aStartMark,
const PerformanceMeasureOptions* aOptions, const Maybe<const PerformanceMeasureOptions&>& aOptions,
ErrorResult& aRv); ErrorResult& aRv);
}; };

View file

@ -52,11 +52,6 @@
// stored. // stored.
#define LAZY_FUNCTION_NAME_SLOT 0 #define LAZY_FUNCTION_NAME_SLOT 0
// The extended slot which contains a boolean value that indicates whether
// that the canonical name of the self-hosted builtins is set in self-hosted
// global. This slot is used only in debug build.
#define HAS_SELFHOSTED_CANONICAL_NAME_SLOT 0
// Stores the length for bound functions, so the .length property doesn't need // Stores the length for bound functions, so the .length property doesn't need
// to be resolved eagerly. // to be resolved eagerly.
#define BOUND_FUN_LENGTH_SLOT 1 #define BOUND_FUN_LENGTH_SLOT 1

View file

@ -2809,9 +2809,6 @@ Parser<ParseHandler>::newFunction(HandleAtom atom, FunctionSyntaxKind kind,
gc::AllocKind allocKind = gc::AllocKind::FUNCTION; gc::AllocKind allocKind = gc::AllocKind::FUNCTION;
JSFunction::Flags flags; JSFunction::Flags flags;
#ifdef DEBUG
bool isGlobalSelfHostedBuiltin = false;
#endif
switch (kind) { switch (kind) {
case FunctionSyntaxKind::Expression: case FunctionSyntaxKind::Expression:
flags = (generatorKind == NotGenerator && asyncKind == SyncFunction flags = (generatorKind == NotGenerator && asyncKind == SyncFunction
@ -2848,12 +2845,9 @@ Parser<ParseHandler>::newFunction(HandleAtom atom, FunctionSyntaxKind kind,
break; break;
default: default:
MOZ_ASSERT(kind == FunctionSyntaxKind::Statement); MOZ_ASSERT(kind == FunctionSyntaxKind::Statement);
#ifdef DEBUG
if (options().selfHostingMode && !pc->isFunctionBox()) { if (options().selfHostingMode && !pc->isFunctionBox()) {
isGlobalSelfHostedBuiltin = true;
allocKind = gc::AllocKind::FUNCTION_EXTENDED; allocKind = gc::AllocKind::FUNCTION_EXTENDED;
} }
#endif
flags = (generatorKind == NotGenerator && asyncKind == SyncFunction flags = (generatorKind == NotGenerator && asyncKind == SyncFunction
? JSFunction::INTERPRETED_NORMAL ? JSFunction::INTERPRETED_NORMAL
: JSFunction::INTERPRETED_GENERATOR_OR_ASYNC); : JSFunction::INTERPRETED_GENERATOR_OR_ASYNC);
@ -2869,10 +2863,6 @@ Parser<ParseHandler>::newFunction(HandleAtom atom, FunctionSyntaxKind kind,
return nullptr; return nullptr;
if (options().selfHostingMode) { if (options().selfHostingMode) {
fun->setIsSelfHostedBuiltin(); fun->setIsSelfHostedBuiltin();
#ifdef DEBUG
if (isGlobalSelfHostedBuiltin)
fun->setExtendedSlot(HAS_SELFHOSTED_CANONICAL_NAME_SLOT, BooleanValue(false));
#endif
} }
return fun; return fun;
} }

View file

@ -3530,9 +3530,6 @@ CreateNonSyntacticEnvironmentChain(JSContext* cx, AutoObjectVector& envChain,
static bool static bool
IsFunctionCloneable(HandleFunction fun) IsFunctionCloneable(HandleFunction fun)
{ {
if (!fun->isInterpreted())
return true;
// If a function was compiled with non-global syntactic environments on // If a function was compiled with non-global syntactic environments on
// the environment chain, we could have baked in EnvironmentCoordinates // the environment chain, we could have baked in EnvironmentCoordinates
// into the script. We cannot clone it without breaking the compiler's // into the script. We cannot clone it without breaking the compiler's
@ -3570,6 +3567,11 @@ CloneFunctionObject(JSContext* cx, HandleObject funobj, HandleObject env, Handle
return nullptr; return nullptr;
} }
if (fun->isNative()) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_CANT_CLONE_OBJECT);
return nullptr;
}
if (!IsFunctionCloneable(fun)) { if (!IsFunctionCloneable(fun)) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BAD_CLONE_FUNOBJ_SCOPE); JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BAD_CLONE_FUNOBJ_SCOPE);
return nullptr; return nullptr;
@ -3580,21 +3582,6 @@ CloneFunctionObject(JSContext* cx, HandleObject funobj, HandleObject env, Handle
return nullptr; return nullptr;
} }
if (IsAsmJSModule(fun)) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_CANT_CLONE_OBJECT);
return nullptr;
}
if (IsWrappedAsyncFunction(fun)) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_CANT_CLONE_OBJECT);
return nullptr;
}
if (IsWrappedAsyncGenerator(fun)) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_CANT_CLONE_OBJECT);
return nullptr;
}
if (CanReuseScriptForClone(cx->compartment(), fun, env)) { if (CanReuseScriptForClone(cx->compartment(), fun, env)) {
// If the script is to be reused, either the script can already handle // If the script is to be reused, either the script can already handle
// non-syntactic scopes, or there is only the standard global lexical // non-syntactic scopes, or there is only the standard global lexical

View file

@ -50,6 +50,7 @@
#include "vm/StringBuffer.h" #include "vm/StringBuffer.h"
#include "vm/WrapperObject.h" #include "vm/WrapperObject.h"
#include "vm/Xdr.h" #include "vm/Xdr.h"
#include "wasm/AsmJS.h"
#include "jsscriptinlines.h" #include "jsscriptinlines.h"
@ -1250,7 +1251,7 @@ JSFunction::infallibleIsDefaultClassConstructor(JSContext* cx) const
bool isDefault = false; bool isDefault = false;
if (isInterpretedLazy()) { if (isInterpretedLazy()) {
JSAtom* name = &getExtendedSlot(LAZY_FUNCTION_NAME_SLOT).toString()->asAtom(); JSAtom* name = GetSelfHostedFunctionName(const_cast<JSFunction*>(this));
isDefault = name == cx->names().DefaultDerivedClassConstructor || isDefault = name == cx->names().DefaultDerivedClassConstructor ||
name == cx->names().DefaultBaseClassConstructor; name == cx->names().DefaultBaseClassConstructor;
} else { } else {
@ -1270,7 +1271,7 @@ JSFunction::isDerivedClassConstructor()
// There is only one plausible lazy self-hosted derived // There is only one plausible lazy self-hosted derived
// constructor. // constructor.
if (isSelfHostedBuiltin()) { if (isSelfHostedBuiltin()) {
JSAtom* name = &getExtendedSlot(LAZY_FUNCTION_NAME_SLOT).toString()->asAtom(); JSAtom* name = GetSelfHostedFunctionName(this);
// This function is called from places without access to a // This function is called from places without access to a
// JSContext. Trace some plumbing to get what we want. // JSContext. Trace some plumbing to get what we want.
@ -1529,7 +1530,7 @@ JSFunction::createScriptForLazilyInterpretedFunction(JSContext* cx, HandleFuncti
/* Lazily cloned self-hosted script. */ /* Lazily cloned self-hosted script. */
MOZ_ASSERT(fun->isSelfHostedBuiltin()); MOZ_ASSERT(fun->isSelfHostedBuiltin());
RootedAtom funAtom(cx, &fun->getExtendedSlot(LAZY_FUNCTION_NAME_SLOT).toString()->asAtom()); RootedAtom funAtom(cx, GetSelfHostedFunctionName(fun));
if (!funAtom) if (!funAtom)
return false; return false;
Rooted<PropertyName*> funName(cx, funAtom->asPropertyName()); Rooted<PropertyName*> funName(cx, funAtom->asPropertyName());
@ -1568,9 +1569,7 @@ JSFunction::maybeRelazify(JSRuntime* rt)
return; return;
// To delazify self-hosted builtins we need the name of the function // To delazify self-hosted builtins we need the name of the function
// to clone. This name is stored in the first extended slot. Since // to clone. This name is stored in the first extended slot.
// that slot is sometimes also used for other purposes, make sure it
// contains a string.
if (isSelfHostedBuiltin() && if (isSelfHostedBuiltin() &&
(!isExtended() || !getExtendedSlot(LAZY_FUNCTION_NAME_SLOT).isString())) (!isExtended() || !getExtendedSlot(LAZY_FUNCTION_NAME_SLOT).isString()))
{ {
@ -1588,7 +1587,7 @@ JSFunction::maybeRelazify(JSRuntime* rt)
} else { } else {
MOZ_ASSERT(isSelfHostedBuiltin()); MOZ_ASSERT(isSelfHostedBuiltin());
MOZ_ASSERT(isExtended()); MOZ_ASSERT(isExtended());
MOZ_ASSERT(getExtendedSlot(LAZY_FUNCTION_NAME_SLOT).toString()->isAtom()); MOZ_ASSERT(GetSelfHostedFunctionName(this));
} }
comp->scheduleDelazificationForDebugger(); comp->scheduleDelazificationForDebugger();
@ -2026,6 +2025,8 @@ bool
js::CanReuseScriptForClone(JSCompartment* compartment, HandleFunction fun, js::CanReuseScriptForClone(JSCompartment* compartment, HandleFunction fun,
HandleObject newParent) HandleObject newParent)
{ {
MOZ_ASSERT(fun->isInterpreted());
if (compartment != fun->compartment() || if (compartment != fun->compartment() ||
fun->isSingleton() || fun->isSingleton() ||
ObjectGroup::useSingletonForClone(fun)) ObjectGroup::useSingletonForClone(fun))
@ -2044,12 +2045,11 @@ js::CanReuseScriptForClone(JSCompartment* compartment, HandleFunction fun,
if (IsSyntacticEnvironment(newParent)) if (IsSyntacticEnvironment(newParent))
return true; return true;
// We need to clone the script if we're interpreted and not already marked // We need to clone the script if we're not already marked as having a
// as having a non-syntactic scope. If we're lazy, go ahead and clone the // non-syntactic scope. If we're lazy, go ahead and clone the script; see
// script; see the big comment at the end of CopyScriptInternal for the // the big comment at the end of CopyScriptInternal for the explanation of
// explanation of what's going on there. // what's going on there.
return !fun->isInterpreted() || return fun->hasScript() && fun->nonLazyScript()->hasNonSyntacticScope();
(fun->hasScript() && fun->nonLazyScript()->hasNonSyntacticScope());
} }
static inline JSFunction* static inline JSFunction*
@ -2096,6 +2096,7 @@ js::CloneFunctionReuseScript(JSContext* cx, HandleFunction fun, HandleObject enc
HandleObject proto /* = nullptr */) HandleObject proto /* = nullptr */)
{ {
MOZ_ASSERT(NewFunctionEnvironmentIsWellFormed(cx, enclosingEnv)); MOZ_ASSERT(NewFunctionEnvironmentIsWellFormed(cx, enclosingEnv));
MOZ_ASSERT(fun->isInterpreted());
MOZ_ASSERT(!fun->isBoundFunction()); MOZ_ASSERT(!fun->isBoundFunction());
MOZ_ASSERT(CanReuseScriptForClone(cx->compartment(), fun, enclosingEnv)); MOZ_ASSERT(CanReuseScriptForClone(cx->compartment(), fun, enclosingEnv));
@ -2106,13 +2107,12 @@ js::CloneFunctionReuseScript(JSContext* cx, HandleFunction fun, HandleObject enc
if (fun->hasScript()) { if (fun->hasScript()) {
clone->initScript(fun->nonLazyScript()); clone->initScript(fun->nonLazyScript());
clone->initEnvironment(enclosingEnv); clone->initEnvironment(enclosingEnv);
} else if (fun->isInterpretedLazy()) { } else {
MOZ_ASSERT(fun->isInterpretedLazy());
MOZ_ASSERT(fun->compartment() == clone->compartment()); MOZ_ASSERT(fun->compartment() == clone->compartment());
LazyScript* lazy = fun->lazyScriptOrNull(); LazyScript* lazy = fun->lazyScriptOrNull();
clone->initLazyScript(lazy); clone->initLazyScript(lazy);
clone->initEnvironment(enclosingEnv); clone->initEnvironment(enclosingEnv);
} else {
clone->initNative(fun->native(), fun->jitInfo());
} }
/* /*
@ -2130,25 +2130,19 @@ js::CloneFunctionAndScript(JSContext* cx, HandleFunction fun, HandleObject enclo
HandleObject proto /* = nullptr */) HandleObject proto /* = nullptr */)
{ {
MOZ_ASSERT(NewFunctionEnvironmentIsWellFormed(cx, enclosingEnv)); MOZ_ASSERT(NewFunctionEnvironmentIsWellFormed(cx, enclosingEnv));
MOZ_ASSERT(fun->isInterpreted());
MOZ_ASSERT(!fun->isBoundFunction()); MOZ_ASSERT(!fun->isBoundFunction());
JSScript::AutoDelazify funScript(cx); JSScript::AutoDelazify funScript(cx, fun);
if (fun->isInterpreted()) {
funScript = fun;
if (!funScript) if (!funScript)
return nullptr; return nullptr;
}
RootedFunction clone(cx, NewFunctionClone(cx, fun, SingletonObject, allocKind, proto)); RootedFunction clone(cx, NewFunctionClone(cx, fun, SingletonObject, allocKind, proto));
if (!clone) if (!clone)
return nullptr; return nullptr;
if (fun->hasScript()) {
clone->initScript(nullptr); clone->initScript(nullptr);
clone->initEnvironment(enclosingEnv); clone->initEnvironment(enclosingEnv);
} else {
clone->initNative(fun->native(), fun->jitInfo());
}
/* /*
* Across compartments or if we have to introduce a non-syntactic scope we * Across compartments or if we have to introduce a non-syntactic scope we
@ -2165,7 +2159,6 @@ js::CloneFunctionAndScript(JSContext* cx, HandleFunction fun, HandleObject enclo
newScope->hasOnChain(ScopeKind::NonSyntactic)); newScope->hasOnChain(ScopeKind::NonSyntactic));
#endif #endif
if (clone->isInterpreted()) {
RootedScript script(cx, fun->nonLazyScript()); RootedScript script(cx, fun->nonLazyScript());
MOZ_ASSERT(script->compartment() == fun->compartment()); MOZ_ASSERT(script->compartment() == fun->compartment());
MOZ_ASSERT(cx->compartment() == clone->compartment(), MOZ_ASSERT(cx->compartment() == clone->compartment(),
@ -2175,8 +2168,45 @@ js::CloneFunctionAndScript(JSContext* cx, HandleFunction fun, HandleObject enclo
if (!clonedScript) if (!clonedScript)
return nullptr; return nullptr;
Debugger::onNewScript(cx, clonedScript); Debugger::onNewScript(cx, clonedScript);
return clone;
} }
JSFunction*
js::CloneAsmJSModuleFunction(JSContext* cx, HandleFunction fun)
{
MOZ_ASSERT(fun->isNative());
MOZ_ASSERT(IsAsmJSModule(fun));
MOZ_ASSERT(fun->isExtended());
MOZ_ASSERT(cx->compartment() == fun->compartment());
JSFunction* clone = NewFunctionClone(cx, fun, GenericObject, AllocKind::FUNCTION_EXTENDED,
/* proto = */ nullptr);
if (!clone)
return nullptr;
MOZ_ASSERT(fun->native() == InstantiateAsmJS);
MOZ_ASSERT(!fun->jitInfo());
clone->initNative(InstantiateAsmJS, nullptr);
clone->setGroup(fun->group());
return clone;
}
JSFunction*
js::CloneSelfHostingIntrinsic(JSContext* cx, HandleFunction fun)
{
MOZ_ASSERT(fun->isNative());
MOZ_ASSERT(fun->compartment()->isSelfHosting);
MOZ_ASSERT(!fun->isExtended());
MOZ_ASSERT(cx->compartment() != fun->compartment());
JSFunction* clone = NewFunctionClone(cx, fun, SingletonObject, AllocKind::FUNCTION,
/* proto = */ nullptr);
if (!clone)
return nullptr;
clone->initNative(fun->native(), fun->jitInfo());
return clone; return clone;
} }

View file

@ -824,6 +824,12 @@ CloneFunctionAndScript(JSContext* cx, HandleFunction fun, HandleObject parent,
gc::AllocKind kind = gc::AllocKind::FUNCTION, gc::AllocKind kind = gc::AllocKind::FUNCTION,
HandleObject proto = nullptr); HandleObject proto = nullptr);
extern JSFunction*
CloneAsmJSModuleFunction(JSContext* cx, HandleFunction fun);
extern JSFunction*
CloneSelfHostingIntrinsic(JSContext* cx, HandleFunction fun);
} // namespace js } // namespace js
inline js::FunctionExtended* inline js::FunctionExtended*

View file

@ -4302,7 +4302,13 @@ js::Lambda(JSContext* cx, HandleFunction fun, HandleObject parent)
{ {
MOZ_ASSERT(!fun->isArrow()); MOZ_ASSERT(!fun->isArrow());
RootedObject clone(cx, CloneFunctionObjectIfNotSingleton(cx, fun, parent)); JSFunction* clone;
if (fun->isNative()) {
MOZ_ASSERT(IsAsmJSModule(fun));
clone = CloneAsmJSModuleFunction(cx, fun);
} else {
clone = CloneFunctionObjectIfNotSingleton(cx, fun, parent);
}
if (!clone) if (!clone)
return nullptr; return nullptr;

View file

@ -903,6 +903,22 @@ intrinsic_NewRegExpStringIterator(JSContext* cx, unsigned argc, Value* vp)
return true; return true;
} }
JSAtom*
js::GetSelfHostedFunctionName(JSFunction* fun)
{
Value name = fun->getExtendedSlot(LAZY_FUNCTION_NAME_SLOT);
if (!name.isString()) {
return nullptr;
}
return &name.toString()->asAtom();
}
static void
SetSelfHostedFunctionName(JSFunction* fun, JSAtom* name)
{
fun->setExtendedSlot(LAZY_FUNCTION_NAME_SLOT, StringValue(name));
}
static bool static bool
intrinsic_SetCanonicalName(JSContext* cx, unsigned argc, Value* vp) intrinsic_SetCanonicalName(JSContext* cx, unsigned argc, Value* vp)
{ {
@ -915,10 +931,18 @@ intrinsic_SetCanonicalName(JSContext* cx, unsigned argc, Value* vp)
if (!atom) if (!atom)
return false; return false;
// _SetCanonicalName can only be called on top-level function declarations.
MOZ_ASSERT(fun->kind() == JSFunction::NormalFunction);
MOZ_ASSERT(!fun->isLambda());
// It's an error to call _SetCanonicalName multiple times.
MOZ_ASSERT(!GetSelfHostedFunctionName(fun));
// Set the lazy function name so we can later retrieve the script from the
// self-hosting global.
SetSelfHostedFunctionName(fun, fun->explicitName());
fun->setAtom(atom); fun->setAtom(atom);
#ifdef DEBUG
fun->setExtendedSlot(HAS_SELFHOSTED_CANONICAL_NAME_SLOT, BooleanValue(true));
#endif
args.rval().setUndefined(); args.rval().setUndefined();
return true; return true;
} }
@ -2909,23 +2933,33 @@ CloneObject(JSContext* cx, HandleNativeObject selfHostedObject)
RootedObject clone(cx); RootedObject clone(cx);
if (selfHostedObject->is<JSFunction>()) { if (selfHostedObject->is<JSFunction>()) {
RootedFunction selfHostedFunction(cx, &selfHostedObject->as<JSFunction>()); RootedFunction selfHostedFunction(cx, &selfHostedObject->as<JSFunction>());
bool hasName = selfHostedFunction->explicitName() != nullptr; if (selfHostedFunction->isInterpreted()) {
// Arrow functions use the first extended slot for their lexical |this| value. // Arrow functions use the first extended slot for their lexical |this| value.
MOZ_ASSERT(!selfHostedFunction->isArrow()); // And methods use the first extended slot for their home-object.
js::gc::AllocKind kind = hasName // We only expect to see normal functions here.
? gc::AllocKind::FUNCTION_EXTENDED MOZ_ASSERT(selfHostedFunction->kind() == JSFunction::NormalFunction);
: selfHostedFunction->getAllocKind(); js::gc::AllocKind kind = selfHostedFunction->getAllocKind();
MOZ_ASSERT(!CanReuseScriptForClone(cx->compartment(), selfHostedFunction, cx->global()));
Rooted<LexicalEnvironmentObject*> globalLexical(cx, &cx->global()->lexicalEnvironment()); Handle<GlobalObject*> global = cx->global();
RootedScope emptyGlobalScope(cx, &cx->global()->emptyGlobalScope()); Rooted<LexicalEnvironmentObject*> globalLexical(cx, &global->lexicalEnvironment());
RootedScope emptyGlobalScope(cx, &global->emptyGlobalScope());
MOZ_ASSERT(!CanReuseScriptForClone(cx->compartment(), selfHostedFunction, global));
clone = CloneFunctionAndScript(cx, selfHostedFunction, globalLexical, emptyGlobalScope, clone = CloneFunctionAndScript(cx, selfHostedFunction, globalLexical, emptyGlobalScope,
kind); kind);
// To be able to re-lazify the cloned function, its name in the // To be able to re-lazify the cloned function, its name in the
// self-hosting compartment has to be stored on the clone. // self-hosting compartment has to be stored on the clone. Re-lazification
if (clone && hasName) { // is only possible if this isn't a function expression.
clone->as<JSFunction>().setExtendedSlot(LAZY_FUNCTION_NAME_SLOT, if (clone && !selfHostedFunction->isLambda()) {
StringValue(selfHostedFunction->explicitName())); // If |_SetCanonicalName| was called on the function, the self-hosted
// name is stored in the extended slot.
JSAtom* name = GetSelfHostedFunctionName(selfHostedFunction);
if (!name) {
name = selfHostedFunction->explicitName();
}
SetSelfHostedFunctionName(&clone->as<JSFunction>(), name);
}
} else {
clone = CloneSelfHostingIntrinsic(cx, selfHostedFunction);
} }
} else if (selfHostedObject->is<RegExpObject>()) { } else if (selfHostedObject->is<RegExpObject>()) {
RegExpObject& reobj = selfHostedObject->as<RegExpObject>(); RegExpObject& reobj = selfHostedObject->as<RegExpObject>();
@ -3010,7 +3044,7 @@ JSRuntime::createLazySelfHostedFunctionClone(JSContext* cx, HandlePropertyName s
if (!selfHostedFun->isClassConstructor() && !selfHostedFun->hasGuessedAtom() && if (!selfHostedFun->isClassConstructor() && !selfHostedFun->hasGuessedAtom() &&
selfHostedFun->explicitName() != selfHostedName) selfHostedFun->explicitName() != selfHostedName)
{ {
MOZ_ASSERT(selfHostedFun->getExtendedSlot(HAS_SELFHOSTED_CANONICAL_NAME_SLOT).toBoolean()); MOZ_ASSERT(GetSelfHostedFunctionName(selfHostedFun) == selfHostedName);
funName = selfHostedFun->explicitName(); funName = selfHostedFun->explicitName();
} }
@ -3019,7 +3053,7 @@ JSRuntime::createLazySelfHostedFunctionClone(JSContext* cx, HandlePropertyName s
if (!fun) if (!fun)
return false; return false;
fun->setIsSelfHostedBuiltin(); fun->setIsSelfHostedBuiltin();
fun->setExtendedSlot(LAZY_FUNCTION_NAME_SLOT, StringValue(selfHostedName)); SetSelfHostedFunctionName(fun, selfHostedName);
return true; return true;
} }
@ -3105,7 +3139,7 @@ JSRuntime::assertSelfHostedFunctionHasCanonicalName(JSContext* cx, HandlePropert
#ifdef DEBUG #ifdef DEBUG
JSFunction* selfHostedFun = getUnclonedSelfHostedFunction(cx, name); JSFunction* selfHostedFun = getUnclonedSelfHostedFunction(cx, name);
MOZ_ASSERT(selfHostedFun); MOZ_ASSERT(selfHostedFun);
MOZ_ASSERT(selfHostedFun->getExtendedSlot(HAS_SELFHOSTED_CANONICAL_NAME_SLOT).toBoolean()); MOZ_ASSERT(GetSelfHostedFunctionName(selfHostedFun) == name);
#endif #endif
} }
@ -3127,15 +3161,6 @@ js::IsSelfHostedFunctionWithName(JSFunction* fun, JSAtom* name)
return fun->isSelfHostedBuiltin() && GetSelfHostedFunctionName(fun) == name; return fun->isSelfHostedBuiltin() && GetSelfHostedFunctionName(fun) == name;
} }
JSAtom*
js::GetSelfHostedFunctionName(JSFunction* fun)
{
Value name = fun->getExtendedSlot(LAZY_FUNCTION_NAME_SLOT);
if (!name.isString())
return nullptr;
return &name.toString()->asAtom();
}
static_assert(JSString::MAX_LENGTH <= INT32_MAX, static_assert(JSString::MAX_LENGTH <= INT32_MAX,
"StringIteratorNext in builtin/String.js assumes the stored index " "StringIteratorNext in builtin/String.js assumes the stored index "
"into the string is an Int32Value"); "into the string is an Int32Value");

View file

@ -22,6 +22,19 @@ namespace js {
bool bool
IsSelfHostedFunctionWithName(JSFunction* fun, JSAtom* name); IsSelfHostedFunctionWithName(JSFunction* fun, JSAtom* name);
/*
* Returns the name of the function's binding in the self-hosted global.
*
* This returns a non-null value only when:
* * This is a top level function declaration in the self-hosted global.
* * And either:
* * This function is not cloned and `_SetCanonicalName` has been called to
* set a different function name.
* * This function is cloned.
*
* For functions not cloned and not `_SetCanonicalName`ed, use
* `fun->explicitName()` instead.
*/
JSAtom* JSAtom*
GetSelfHostedFunctionName(JSFunction* fun); GetSelfHostedFunctionName(JSFunction* fun);

View file

@ -8100,8 +8100,8 @@ AsmJSModuleFunctionToModule(JSFunction* fun)
} }
// Implements the semantics of an asm.js module function that has been successfully validated. // Implements the semantics of an asm.js module function that has been successfully validated.
static bool bool
InstantiateAsmJS(JSContext* cx, unsigned argc, JS::Value* vp) js::InstantiateAsmJS(JSContext* cx, unsigned argc, JS::Value* vp)
{ {
CallArgs args = CallArgsFromVp(argc, vp); CallArgs args = CallArgsFromVp(argc, vp);

View file

@ -56,6 +56,9 @@ IsAsmJSFunction(JSFunction* fun);
extern bool extern bool
IsAsmJSStrictModeModuleOrFunction(JSFunction* fun); IsAsmJSStrictModeModuleOrFunction(JSFunction* fun);
extern bool
InstantiateAsmJS(JSContext* cx, unsigned argc, JS::Value* vp);
// asm.js testing natives: // asm.js testing natives:
extern bool extern bool

View file

@ -16,6 +16,7 @@
#include <new> // for placement new #include <new> // for placement new
#include <type_traits> #include <type_traits>
#include <utility>
namespace mozilla { namespace mozilla {
@ -83,7 +84,15 @@ template<class T>
class Maybe class Maybe
{ {
bool mIsSome; bool mIsSome;
AlignedStorage2<T> mStorage;
// To support |Maybe<const Type>| we give |mStorage| the type |T| with any
// const-ness removed. That allows us to |emplace()| an object into
// |mStorage|. Since we treat the contained object as having type |T|
// everywhere else (both internally, and when exposed via public methods) the
// contained object is still treated as const once stored since |const| is
// part of |T|'s type signature.
typedef typename RemoveCV<T>::Type StorageType;
AlignedStorage2<StorageType> mStorage;
public: public:
typedef T ValueType; typedef T ValueType;
@ -453,6 +462,72 @@ public:
} }
}; };
template <typename T>
class Maybe<T&> {
public:
constexpr Maybe() = default;
constexpr MOZ_IMPLICIT Maybe(Nothing) {}
void emplace(T& aRef) { mValue = &aRef; }
/* Methods that check whether this Maybe contains a value */
explicit operator bool() const { return isSome(); }
bool isSome() const { return mValue; }
bool isNothing() const { return !mValue; }
T& ref() const {
MOZ_DIAGNOSTIC_ASSERT(isSome());
return *mValue;
}
T* operator->() const { return &ref(); }
T& operator*() const { return ref(); }
// Deliberately not defining value and ptr accessors, as these may be
// confusing on a reference-typed Maybe.
// XXX Should we define refOr?
void reset() { mValue = nullptr; }
template <typename Func>
Maybe& apply(Func&& aFunc) {
if (isSome()) {
std::forward<Func>(aFunc)(ref());
}
return *this;
}
template <typename Func>
const Maybe& apply(Func&& aFunc) const {
if (isSome()) {
std::forward<Func>(aFunc)(ref());
}
return *this;
}
template <typename Func>
auto map(Func&& aFunc) {
Maybe<decltype(std::forward<Func>(aFunc)(ref()))> val;
if (isSome()) {
val.emplace(std::forward<Func>(aFunc)(ref()));
}
return val;
}
template <typename Func>
auto map(Func&& aFunc) const {
Maybe<decltype(std::forward<Func>(aFunc)(ref()))> val;
if (isSome()) {
val.emplace(std::forward<Func>(aFunc)(ref()));
}
return val;
}
private:
T* mValue = nullptr;
};
/* /*
* Some() creates a Maybe<T> value containing the provided T value. If T has a * Some() creates a Maybe<T> value containing the provided T value. If T has a
* move constructor, it's used to make this as efficient as possible. * move constructor, it's used to make this as efficient as possible.
@ -474,6 +549,13 @@ Some(T&& aValue)
return value; return value;
} }
template <typename T>
Maybe<T&> SomeRef(T& aValue) {
Maybe<T&> value;
value.emplace(aValue);
return value;
}
template<typename T> template<typename T>
Maybe<typename RemoveCV<typename RemoveReference<T>::Type>::Type> Maybe<typename RemoveCV<typename RemoveReference<T>::Type>::Type>
ToMaybe(T* aPtr) ToMaybe(T* aPtr)
@ -492,6 +574,9 @@ ToMaybe(T* aPtr)
template<typename T> bool template<typename T> bool
operator==(const Maybe<T>& aLHS, const Maybe<T>& aRHS) operator==(const Maybe<T>& aLHS, const Maybe<T>& aRHS)
{ {
static_assert(!std::is_reference<T>::value,
"operator== is not defined for Maybe<T&>, compare values or "
"addresses explicitly instead");
if (aLHS.isNothing() != aRHS.isNothing()) { if (aLHS.isNothing() != aRHS.isNothing()) {
return false; return false;
} }

View file

@ -5021,6 +5021,16 @@ fi
AC_DEFINE_UNQUOTED(MOZ_MACBUNDLE_ID,$MOZ_MACBUNDLE_ID) AC_DEFINE_UNQUOTED(MOZ_MACBUNDLE_ID,$MOZ_MACBUNDLE_ID)
AC_SUBST(MOZ_MACBUNDLE_ID) AC_SUBST(MOZ_MACBUNDLE_ID)
dnl ========================================================
dnl = Mac bundle codesign entitlements
dnl ========================================================
MOZ_ARG_WITH_STRING(macbundle-entitlement,
[ --with-macbundle-entitlement=entitlementname
Entitlements to add to the Mac application bundle],
[ MOZ_MACBUNDLE_ENTITLEMENT="$withval"])
AC_SUBST(MOZ_MACBUNDLE_ENTITLEMENT)
dnl ======================================================== dnl ========================================================
dnl = Mac bundle codesign identity dnl = Mac bundle codesign identity
dnl ======================================================== dnl ========================================================
@ -5031,6 +5041,17 @@ MOZ_ARG_WITH_STRING(macbundle-identity,
AC_SUBST(MOZ_MACBUNDLE_IDENTITY) AC_SUBST(MOZ_MACBUNDLE_IDENTITY)
dnl ========================================================
dnl = Mac bundle DMG type
dnl ========================================================
MOZ_ARG_WITH_STRING(macbundle-type,
[ --with-macbundle-type=hybrid
Method to use to create the DMG],
[ MOZ_MACBUNDLE_TYPE="$withval"])
AC_SUBST(MOZ_MACBUNDLE_TYPE)
dnl ======================================================== dnl ========================================================
dnl = Child Process Name for IPC dnl = Child Process Name for IPC
dnl ======================================================== dnl ========================================================

View file

@ -44,19 +44,25 @@ def set_folder_icon(dir):
def create_dmg_from_staged(stagedir, output_dmg, tmpdir, volume_name): def create_dmg_from_staged(stagedir, output_dmg, tmpdir, volume_name):
'Given a prepared directory stagedir, produce a DMG at output_dmg.' 'Given a prepared directory stagedir, produce a DMG at output_dmg.'
import buildconfig
if not is_linux: if not is_linux:
# Running on OS X # Running on OS X
hybrid = os.path.join(tmpdir, 'hybrid.dmg') hybrid = os.path.join(tmpdir, 'hybrid.dmg')
subprocess.check_call(['hdiutil', 'create', hdiutiloptions = ['create', '-fs', 'HFS+',
'-fs', 'HFS+',
'-volname', volume_name, '-volname', volume_name,
'-srcfolder', stagedir, '-srcfolder', stagedir,
'-ov', hybrid]) '-ov', hybrid]
if buildconfig.substs['MOZ_MACBUNDLE_TYPE'] == 'hybrid':
hdiutiloptions = ['makehybrid', '-hfs',
'-hfs-volume-name', volume_name,
'-hfs-openfolder', stagedir,
'-ov', stagedir,
'-o', hybrid]
subprocess.check_call(['hdiutil'] + hdiutiloptions)
subprocess.check_call(['hdiutil', 'convert', '-format', 'UDBZ', subprocess.check_call(['hdiutil', 'convert', '-format', 'UDBZ',
'-imagekey', 'bzip2-level=9', '-imagekey', 'bzip2-level=9',
'-ov', hybrid, '-o', output_dmg]) '-ov', hybrid, '-o', output_dmg])
else: else:
import buildconfig
uncompressed = os.path.join(tmpdir, 'uncompressed.dmg') uncompressed = os.path.join(tmpdir, 'uncompressed.dmg')
subprocess.check_call([ subprocess.check_call([
buildconfig.substs['GENISOIMAGE'], buildconfig.substs['GENISOIMAGE'],
@ -123,15 +129,28 @@ def create_dmg(source_directory, output_dmg, volume_name, extra_files):
identity = buildconfig.substs['MOZ_MACBUNDLE_IDENTITY'] identity = buildconfig.substs['MOZ_MACBUNDLE_IDENTITY']
if identity != '': if identity != '':
dylibs = [] dylibs = []
entitlements = []
appbundle = os.path.join(stagedir, buildconfig.substs['MOZ_MACBUNDLE_NAME']) appbundle = os.path.join(stagedir, buildconfig.substs['MOZ_MACBUNDLE_NAME'])
# If the -bin file is in Resources add it to the dylibs as well # If the -bin file is in Resources add it to the dylibs as well
resourcebin = os.path.join(appbundle, 'Contents/Resources/' + buildconfig.substs['MOZ_APP_NAME'] + '-bin') resourcebin = os.path.join(appbundle, 'Contents/Resources/' + buildconfig.substs['MOZ_APP_NAME'] + '-bin')
if os.path.isfile(resourcebin): if os.path.isfile(resourcebin):
dylibs.append(resourcebin) dylibs.append(resourcebin)
# Create a list of dylibs in Contents/Resources that won't get signed by --deep # Create a list of dylibs in Contents/Resources that won't get signed by --deep
for root, dirnames, filenames in os.walk('Contents/Resources/'): for root, dirnames, filenames in os.walk(os.path.join(appbundle,'Contents/Resources/')):
for filename in fnmatch.filter(filenames, '*.dylib'): for filename in fnmatch.filter(filenames, '*.dylib'):
dylibs.append(os.path.join(root, filename)) dylibs.append(os.path.join(root, filename))
# Select default entitlements based on whether debug is enabled
entitlement = os.path.abspath(os.path.join(os.getcwd(), '../../platform/security/mac/production.entitlements.xml')) entitlement = os.path.abspath(os.path.join(os.getcwd(), '../../platform/security/mac/production.entitlements.xml'))
subprocess.check_call(['codesign', '--deep', '--timestamp', '--options', 'runtime', '--entitlements', entitlement, '-s', identity] + dylibs + [appbundle]) if buildconfig.substs['MOZ_DEBUG']:
entitlement = os.path.abspath(os.path.join(os.getcwd(), '../../platform/security/mac/developer.entitlements.xml'))
# Check to see if the entitlements are disabled or overrided by mozconfig
entitlementname = buildconfig.substs['MOZ_MACBUNDLE_ENTITLEMENT']
if entitlementname != '':
if os.path.isfile(entitlementname):
entitlement = entitlementname
if entitlementname != 'none':
if os.path.isfile(entitlement):
entitlements = ['--entitlements', entitlement]
# Call the codesign tool
subprocess.check_call(['codesign', '--deep', '--timestamp', '--options', 'runtime'] + entitlements + [ '-s', identity] + dylibs + [appbundle])
create_dmg_from_staged(stagedir, output_dmg, tmpdir, volume_name) create_dmg_from_staged(stagedir, output_dmg, tmpdir, volume_name)

View file

@ -4,7 +4,9 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "PoisonIOInterposer.h" #include "PoisonIOInterposer.h"
#ifndef __aarch64__
#include "mach_override.h" #include "mach_override.h"
#endif
#include "mozilla/ArrayUtils.h" #include "mozilla/ArrayUtils.h"
#include "mozilla/Assertions.h" #include "mozilla/Assertions.h"
@ -360,9 +362,11 @@ InitPoisonIOInterposer()
if (!d->Function) { if (!d->Function) {
continue; continue;
} }
#ifndef __aarch64__
DebugOnly<mach_error_t> t = mach_override_ptr(d->Function, d->Wrapper, DebugOnly<mach_error_t> t = mach_override_ptr(d->Function, d->Wrapper,
&d->Buffer); &d->Buffer);
MOZ_ASSERT(t == err_none); MOZ_ASSERT(t == err_none);
#endif
} }
} }