зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1569315 - Create FunctionFlags class to allow recycling function flag queries elsewhere r=tcampbell
Differential Revision: https://phabricator.services.mozilla.com/D39773 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
026ae43909
Коммит
f94b0ec315
|
@ -3145,7 +3145,7 @@ bool ASTSerializer::property(ParseNode* pn, MutableHandleValue dst) {
|
|||
bool isShorthand = node->isKind(ParseNodeKind::Shorthand);
|
||||
bool isMethod =
|
||||
valNode->is<FunctionNode>() &&
|
||||
valNode->as<FunctionNode>().funbox()->kind() == JSFunction::Method;
|
||||
valNode->as<FunctionNode>().funbox()->kind() == FunctionFlags::Method;
|
||||
RootedValue key(cx), val(cx);
|
||||
return propertyName(keyNode, &key) && expression(valNode, &val) &&
|
||||
builder.propertyInitializer(key, val, kind, isShorthand, isMethod,
|
||||
|
|
|
@ -166,7 +166,7 @@ JS::Result<FunctionNode*> BinASTParserPerTokenizer<Tok>::parseLazyFunction(
|
|||
// For now, only function declarations and function expression are supported.
|
||||
RootedFunction func(cx_, lazyScript_->functionNonDelazifying());
|
||||
bool isExpr = func->isLambda();
|
||||
MOZ_ASSERT(func->kind() == JSFunction::FunctionKind::NormalFunction);
|
||||
MOZ_ASSERT(func->kind() == FunctionFlags::FunctionKind::NormalFunction);
|
||||
|
||||
// Poison the tokenizer when we leave to ensure that it's not used again by
|
||||
// accident.
|
||||
|
|
|
@ -963,7 +963,7 @@ static bool CompileLazyFunctionImpl(JSContext* cx, Handle<LazyScript*> lazy,
|
|||
}
|
||||
|
||||
FieldInitializers fieldInitializers = FieldInitializers::Invalid();
|
||||
if (fun->kind() == JSFunction::FunctionKind::ClassConstructor) {
|
||||
if (fun->kind() == FunctionFlags::FunctionKind::ClassConstructor) {
|
||||
fieldInitializers = lazy->getFieldInitializers();
|
||||
}
|
||||
|
||||
|
|
|
@ -2530,7 +2530,7 @@ bool BytecodeEmitter::emitFunctionScript(FunctionNode* funNode,
|
|||
parser->errorReporter(), funbox);
|
||||
|
||||
MOZ_ASSERT((fieldInitializers_.valid) ==
|
||||
(funbox->kind() == JSFunction::FunctionKind::ClassConstructor));
|
||||
(funbox->kind() == FunctionFlags::FunctionKind::ClassConstructor));
|
||||
|
||||
setScriptStartOffsetIfUnset(paramsBody->pn_pos.begin);
|
||||
|
||||
|
@ -5696,7 +5696,7 @@ MOZ_NEVER_INLINE bool BytecodeEmitter::emitFunction(
|
|||
RootedFunction fun(cx, funbox->function());
|
||||
|
||||
MOZ_ASSERT((classContentsIfConstructor != nullptr) ==
|
||||
(funbox->kind() == JSFunction::FunctionKind::ClassConstructor));
|
||||
(funbox->kind() == FunctionFlags::FunctionKind::ClassConstructor));
|
||||
|
||||
// [stack]
|
||||
|
||||
|
@ -8130,7 +8130,7 @@ const FieldInitializers& BytecodeEmitter::findFieldInitializersForCall() {
|
|||
for (BytecodeEmitter* current = this; current; current = current->parent) {
|
||||
if (current->sc->isFunctionBox()) {
|
||||
FunctionBox* box = current->sc->asFunctionBox();
|
||||
if (box->kind() == JSFunction::FunctionKind::ClassConstructor) {
|
||||
if (box->kind() == FunctionFlags::FunctionKind::ClassConstructor) {
|
||||
const FieldInitializers& fieldInitializers =
|
||||
current->getFieldInitializers();
|
||||
MOZ_ASSERT(fieldInitializers.valid);
|
||||
|
@ -8142,7 +8142,7 @@ const FieldInitializers& BytecodeEmitter::findFieldInitializersForCall() {
|
|||
for (ScopeIter si(innermostScope()); si; si++) {
|
||||
if (si.scope()->is<FunctionScope>()) {
|
||||
JSFunction* fun = si.scope()->as<FunctionScope>().canonicalFunction();
|
||||
if (fun->kind() == JSFunction::FunctionKind::ClassConstructor) {
|
||||
if (fun->kind() == FunctionFlags::FunctionKind::ClassConstructor) {
|
||||
const FieldInitializers& fieldInitializers =
|
||||
fun->isInterpretedLazy()
|
||||
? fun->lazyScript()->getFieldInitializers()
|
||||
|
|
|
@ -484,7 +484,7 @@ bool FunctionScriptEmitter::prepareForBody() {
|
|||
}
|
||||
}
|
||||
|
||||
if (funbox_->kind() == JSFunction::FunctionKind::ClassConstructor) {
|
||||
if (funbox_->kind() == FunctionFlags::FunctionKind::ClassConstructor) {
|
||||
if (!funbox_->isDerivedClassConstructor()) {
|
||||
if (!bce_->emitInitializeInstanceFields()) {
|
||||
// [stack]
|
||||
|
|
|
@ -506,7 +506,7 @@ bool ParseContext::declareFunctionThis(const UsedNameTracker& usedNames,
|
|||
} else {
|
||||
declareThis = hasUsedFunctionSpecialName(usedNames, dotThis) ||
|
||||
funbox->function()->kind() ==
|
||||
JSFunction::FunctionKind::ClassConstructor;
|
||||
FunctionFlags::FunctionKind::ClassConstructor;
|
||||
}
|
||||
|
||||
if (declareThis) {
|
||||
|
|
|
@ -1982,7 +1982,7 @@ JSFunction* AllocNewFunction(JSContext* cx, HandleAtom atom,
|
|||
RootedFunction fun(cx);
|
||||
|
||||
gc::AllocKind allocKind = gc::AllocKind::FUNCTION;
|
||||
JSFunction::Flags flags;
|
||||
FunctionFlags flags;
|
||||
bool isExtendedUnclonedSelfHostedFunctionName =
|
||||
isSelfHosting && atom && IsExtendedUnclonedSelfHostedFunctionName(atom);
|
||||
MOZ_ASSERT_IF(isExtendedUnclonedSelfHostedFunctionName, !inFunctionBox);
|
||||
|
@ -1991,28 +1991,28 @@ JSFunction* AllocNewFunction(JSContext* cx, HandleAtom atom,
|
|||
case FunctionSyntaxKind::Expression:
|
||||
flags = (generatorKind == GeneratorKind::NotGenerator &&
|
||||
asyncKind == FunctionAsyncKind::SyncFunction
|
||||
? JSFunction::INTERPRETED_LAMBDA
|
||||
: JSFunction::INTERPRETED_LAMBDA_GENERATOR_OR_ASYNC);
|
||||
? FunctionFlags::INTERPRETED_LAMBDA
|
||||
: FunctionFlags::INTERPRETED_LAMBDA_GENERATOR_OR_ASYNC);
|
||||
break;
|
||||
case FunctionSyntaxKind::Arrow:
|
||||
flags = JSFunction::INTERPRETED_LAMBDA_ARROW;
|
||||
flags = FunctionFlags::INTERPRETED_LAMBDA_ARROW;
|
||||
allocKind = gc::AllocKind::FUNCTION_EXTENDED;
|
||||
break;
|
||||
case FunctionSyntaxKind::Method:
|
||||
flags = JSFunction::INTERPRETED_METHOD;
|
||||
flags = FunctionFlags::INTERPRETED_METHOD;
|
||||
allocKind = gc::AllocKind::FUNCTION_EXTENDED;
|
||||
break;
|
||||
case FunctionSyntaxKind::ClassConstructor:
|
||||
case FunctionSyntaxKind::DerivedClassConstructor:
|
||||
flags = JSFunction::INTERPRETED_CLASS_CONSTRUCTOR;
|
||||
flags = FunctionFlags::INTERPRETED_CLASS_CONSTRUCTOR;
|
||||
allocKind = gc::AllocKind::FUNCTION_EXTENDED;
|
||||
break;
|
||||
case FunctionSyntaxKind::Getter:
|
||||
flags = JSFunction::INTERPRETED_GETTER;
|
||||
flags = FunctionFlags::INTERPRETED_GETTER;
|
||||
allocKind = gc::AllocKind::FUNCTION_EXTENDED;
|
||||
break;
|
||||
case FunctionSyntaxKind::Setter:
|
||||
flags = JSFunction::INTERPRETED_SETTER;
|
||||
flags = FunctionFlags::INTERPRETED_SETTER;
|
||||
allocKind = gc::AllocKind::FUNCTION_EXTENDED;
|
||||
break;
|
||||
default:
|
||||
|
@ -2022,8 +2022,8 @@ JSFunction* AllocNewFunction(JSContext* cx, HandleAtom atom,
|
|||
}
|
||||
flags = (generatorKind == GeneratorKind::NotGenerator &&
|
||||
asyncKind == FunctionAsyncKind::SyncFunction
|
||||
? JSFunction::INTERPRETED_NORMAL
|
||||
: JSFunction::INTERPRETED_GENERATOR_OR_ASYNC);
|
||||
? FunctionFlags::INTERPRETED_NORMAL
|
||||
: FunctionFlags::INTERPRETED_GENERATOR_OR_ASYNC);
|
||||
}
|
||||
|
||||
fun = NewFunctionWithProto(cx, nullptr, 0, flags, nullptr, atom, proto,
|
||||
|
|
|
@ -397,7 +397,7 @@ class FunctionBox : public ObjectBox, public SharedContext {
|
|||
bool isInterpreted_ : 1;
|
||||
bool isInterpretedLazy_ : 1;
|
||||
|
||||
JSFunction::FunctionKind kind_;
|
||||
FunctionFlags::FunctionKind kind_;
|
||||
JSAtom* explicitName_;
|
||||
|
||||
uint16_t nargs_;
|
||||
|
@ -545,7 +545,7 @@ class FunctionBox : public ObjectBox, public SharedContext {
|
|||
setIsInterpretedLazy(function()->isInterpretedLazy());
|
||||
}
|
||||
|
||||
JSFunction::FunctionKind kind() { return kind_; }
|
||||
FunctionFlags::FunctionKind kind() { return kind_; }
|
||||
|
||||
JSAtom* explicitName() const { return explicitName_; }
|
||||
|
||||
|
|
|
@ -4460,8 +4460,9 @@ bool BaselineInterpreterCodeGen::emit_JSOP_NEWTARGET() {
|
|||
|
||||
Label notArrow;
|
||||
masm.andPtr(Imm32(uint32_t(CalleeTokenMask)), scratch1);
|
||||
masm.branchFunctionKind(Assembler::NotEqual, JSFunction::FunctionKind::Arrow,
|
||||
scratch1, scratch2, ¬Arrow);
|
||||
masm.branchFunctionKind(Assembler::NotEqual,
|
||||
FunctionFlags::FunctionKind::Arrow, scratch1,
|
||||
scratch2, ¬Arrow);
|
||||
{
|
||||
// Case 2: arrow function.
|
||||
masm.pushValue(
|
||||
|
@ -5741,7 +5742,7 @@ bool BaselineCodeGen<Handler>::emit_JSOP_SUPERFUN() {
|
|||
|
||||
// Use VMCall if not constructor
|
||||
masm.load16ZeroExtend(Address(proto, JSFunction::offsetOfFlags()), scratch);
|
||||
masm.branchTest32(Assembler::Zero, scratch, Imm32(JSFunction::CONSTRUCTOR),
|
||||
masm.branchTest32(Assembler::Zero, scratch, Imm32(FunctionFlags::CONSTRUCTOR),
|
||||
&needVMCall);
|
||||
|
||||
// Valid constructor
|
||||
|
|
|
@ -2678,15 +2678,15 @@ bool CacheIRCompiler::emitLoadFunctionLengthResult() {
|
|||
// If the length was resolved before the length property might be shadowed.
|
||||
masm.branchTest32(
|
||||
Assembler::NonZero, scratch,
|
||||
Imm32(JSFunction::INTERPRETED_LAZY | JSFunction::RESOLVED_LENGTH),
|
||||
Imm32(FunctionFlags::INTERPRETED_LAZY | FunctionFlags::RESOLVED_LENGTH),
|
||||
failure->label());
|
||||
|
||||
Label boundFunction;
|
||||
masm.branchTest32(Assembler::NonZero, scratch, Imm32(JSFunction::BOUND_FUN),
|
||||
&boundFunction);
|
||||
masm.branchTest32(Assembler::NonZero, scratch,
|
||||
Imm32(FunctionFlags::BOUND_FUN), &boundFunction);
|
||||
Label interpreted;
|
||||
masm.branchTest32(Assembler::NonZero, scratch, Imm32(JSFunction::INTERPRETED),
|
||||
&interpreted);
|
||||
masm.branchTest32(Assembler::NonZero, scratch,
|
||||
Imm32(FunctionFlags::INTERPRETED), &interpreted);
|
||||
|
||||
// Load the length of the native function.
|
||||
masm.load16ZeroExtend(Address(obj, JSFunction::offsetOfNargs()), scratch);
|
||||
|
@ -3093,7 +3093,7 @@ bool CacheIRCompiler::emitGuardFunctionIsConstructor() {
|
|||
}
|
||||
|
||||
// Ensure obj is a constructor
|
||||
masm.branchTestFunctionFlags(funcReg, JSFunction::CONSTRUCTOR,
|
||||
masm.branchTestFunctionFlags(funcReg, FunctionFlags::CONSTRUCTOR,
|
||||
Assembler::Zero, failure->label());
|
||||
return true;
|
||||
}
|
||||
|
@ -3107,8 +3107,8 @@ bool CacheIRCompiler::emitGuardNotClassConstructor() {
|
|||
return false;
|
||||
}
|
||||
|
||||
masm.branchFunctionKind(Assembler::Equal, JSFunction::ClassConstructor, fun,
|
||||
scratch, failure->label());
|
||||
masm.branchFunctionKind(Assembler::Equal, FunctionFlags::ClassConstructor,
|
||||
fun, scratch, failure->label());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -3407,7 +3407,7 @@ void CodeGenerator::visitLambda(LLambda* lir) {
|
|||
|
||||
emitLambdaInit(output, envChain, info);
|
||||
|
||||
if (info.flags & JSFunction::EXTENDED) {
|
||||
if (info.flags & FunctionFlags::EXTENDED) {
|
||||
static_assert(FunctionExtended::NUM_EXTENDED_SLOTS == 2,
|
||||
"All slots must be initialized");
|
||||
masm.storeValue(UndefinedValue(),
|
||||
|
@ -3495,7 +3495,7 @@ void CodeGenerator::visitLambdaArrow(LLambdaArrow* lir) {
|
|||
emitLambdaInit(output, envChain, info);
|
||||
|
||||
// Initialize extended slots. Lexical |this| is stored in the first one.
|
||||
MOZ_ASSERT(info.flags & JSFunction::EXTENDED);
|
||||
MOZ_ASSERT(info.flags & FunctionFlags::EXTENDED);
|
||||
static_assert(FunctionExtended::NUM_EXTENDED_SLOTS == 2,
|
||||
"All slots must be initialized");
|
||||
static_assert(FunctionExtended::ARROW_NEWTARGET_SLOT == 0,
|
||||
|
@ -4978,7 +4978,7 @@ void CodeGenerator::visitCallGeneric(LCallGeneric* call) {
|
|||
} else {
|
||||
masm.branchIfFunctionHasNoScript(calleereg, &invoke);
|
||||
}
|
||||
masm.branchFunctionKind(Assembler::Equal, JSFunction::ClassConstructor,
|
||||
masm.branchFunctionKind(Assembler::Equal, FunctionFlags::ClassConstructor,
|
||||
calleereg, objreg, &invoke);
|
||||
}
|
||||
|
||||
|
@ -5422,7 +5422,7 @@ void CodeGenerator::emitApplyGeneric(T* apply) {
|
|||
&invoke);
|
||||
|
||||
// Guard that calleereg is not a class constrcuctor
|
||||
masm.branchFunctionKind(Assembler::Equal, JSFunction::ClassConstructor,
|
||||
masm.branchFunctionKind(Assembler::Equal, FunctionFlags::ClassConstructor,
|
||||
calleereg, objreg, &invoke);
|
||||
|
||||
// Call with an Ion frame or a rectifier frame.
|
||||
|
@ -12724,11 +12724,12 @@ void CodeGenerator::emitIsCallableOrConstructor(Register object,
|
|||
if (mode == Callable) {
|
||||
masm.move32(Imm32(1), output);
|
||||
} else {
|
||||
static_assert(mozilla::IsPowerOfTwo(unsigned(JSFunction::CONSTRUCTOR)),
|
||||
"JSFunction::CONSTRUCTOR has only one bit set");
|
||||
static_assert(mozilla::IsPowerOfTwo(unsigned(FunctionFlags::CONSTRUCTOR)),
|
||||
"FunctionFlags::CONSTRUCTOR has only one bit set");
|
||||
|
||||
masm.load16ZeroExtend(Address(object, JSFunction::offsetOfFlags()), output);
|
||||
masm.rshift32(Imm32(mozilla::FloorLog2(JSFunction::CONSTRUCTOR)), output);
|
||||
masm.rshift32(Imm32(mozilla::FloorLog2(FunctionFlags::CONSTRUCTOR)),
|
||||
output);
|
||||
masm.and32(Imm32(1), output);
|
||||
}
|
||||
masm.jump(&done);
|
||||
|
@ -13668,18 +13669,18 @@ void CodeGenerator::visitFinishBoundFunctionInit(
|
|||
// If the length or name property is resolved, it might be shadowed.
|
||||
masm.branchTest32(
|
||||
Assembler::NonZero, temp1,
|
||||
Imm32(JSFunction::INTERPRETED_LAZY | JSFunction::RESOLVED_NAME |
|
||||
JSFunction::RESOLVED_LENGTH),
|
||||
Imm32(FunctionFlags::INTERPRETED_LAZY | FunctionFlags::RESOLVED_NAME |
|
||||
FunctionFlags::RESOLVED_LENGTH),
|
||||
slowPath);
|
||||
|
||||
Label notBoundTarget, loadName;
|
||||
masm.branchTest32(Assembler::Zero, temp1, Imm32(JSFunction::BOUND_FUN),
|
||||
masm.branchTest32(Assembler::Zero, temp1, Imm32(FunctionFlags::BOUND_FUN),
|
||||
¬BoundTarget);
|
||||
{
|
||||
// Call into the VM if the target's name atom contains the bound
|
||||
// function prefix.
|
||||
masm.branchTest32(Assembler::NonZero, temp1,
|
||||
Imm32(JSFunction::HAS_BOUND_FUNCTION_NAME_PREFIX),
|
||||
Imm32(FunctionFlags::HAS_BOUND_FUNCTION_NAME_PREFIX),
|
||||
slowPath);
|
||||
|
||||
// We also take the slow path when target's length isn't an int32.
|
||||
|
@ -13689,8 +13690,8 @@ void CodeGenerator::visitFinishBoundFunctionInit(
|
|||
// Bound functions reuse HAS_GUESSED_ATOM for
|
||||
// HAS_BOUND_FUNCTION_NAME_PREFIX, so skip the guessed atom check below.
|
||||
static_assert(
|
||||
JSFunction::HAS_BOUND_FUNCTION_NAME_PREFIX ==
|
||||
JSFunction::HAS_GUESSED_ATOM,
|
||||
FunctionFlags::HAS_BOUND_FUNCTION_NAME_PREFIX ==
|
||||
FunctionFlags::HAS_GUESSED_ATOM,
|
||||
"HAS_BOUND_FUNCTION_NAME_PREFIX is shared with HAS_GUESSED_ATOM");
|
||||
masm.jump(&loadName);
|
||||
}
|
||||
|
@ -13698,7 +13699,7 @@ void CodeGenerator::visitFinishBoundFunctionInit(
|
|||
|
||||
Label guessed, hasName;
|
||||
masm.branchTest32(Assembler::NonZero, temp1,
|
||||
Imm32(JSFunction::HAS_GUESSED_ATOM), &guessed);
|
||||
Imm32(FunctionFlags::HAS_GUESSED_ATOM), &guessed);
|
||||
masm.bind(&loadName);
|
||||
masm.loadPtr(Address(target, JSFunction::offsetOfAtom()), temp2);
|
||||
masm.branchTestPtr(Assembler::NonZero, temp2, temp2, &hasName);
|
||||
|
@ -13707,7 +13708,7 @@ void CodeGenerator::visitFinishBoundFunctionInit(
|
|||
|
||||
// Unnamed class expression don't have a name property. To avoid
|
||||
// looking it up from the prototype chain, we take the slow path here.
|
||||
masm.branchFunctionKind(Assembler::Equal, JSFunction::ClassConstructor,
|
||||
masm.branchFunctionKind(Assembler::Equal, FunctionFlags::ClassConstructor,
|
||||
target, temp2, slowPath);
|
||||
|
||||
// An absent name property defaults to the empty string.
|
||||
|
@ -13723,23 +13724,26 @@ void CodeGenerator::visitFinishBoundFunctionInit(
|
|||
// CONSTRUCTOR flag.
|
||||
Label isConstructor, boundFlagsComputed;
|
||||
masm.load16ZeroExtend(Address(bound, JSFunction::offsetOfFlags()), temp2);
|
||||
masm.branchTest32(Assembler::NonZero, temp1, Imm32(JSFunction::CONSTRUCTOR),
|
||||
&isConstructor);
|
||||
masm.branchTest32(Assembler::NonZero, temp1,
|
||||
Imm32(FunctionFlags::CONSTRUCTOR), &isConstructor);
|
||||
{
|
||||
masm.or32(Imm32(JSFunction::BOUND_FUN), temp2);
|
||||
masm.or32(Imm32(FunctionFlags::BOUND_FUN), temp2);
|
||||
masm.jump(&boundFlagsComputed);
|
||||
}
|
||||
masm.bind(&isConstructor);
|
||||
{ masm.or32(Imm32(JSFunction::BOUND_FUN | JSFunction::CONSTRUCTOR), temp2); }
|
||||
{
|
||||
masm.or32(Imm32(FunctionFlags::BOUND_FUN | FunctionFlags::CONSTRUCTOR),
|
||||
temp2);
|
||||
}
|
||||
masm.bind(&boundFlagsComputed);
|
||||
masm.store16(temp2, Address(bound, JSFunction::offsetOfFlags()));
|
||||
|
||||
// Load the target function's length.
|
||||
Label isInterpreted, isBound, lengthLoaded;
|
||||
masm.branchTest32(Assembler::NonZero, temp1, Imm32(JSFunction::BOUND_FUN),
|
||||
masm.branchTest32(Assembler::NonZero, temp1, Imm32(FunctionFlags::BOUND_FUN),
|
||||
&isBound);
|
||||
masm.branchTest32(Assembler::NonZero, temp1, Imm32(JSFunction::INTERPRETED),
|
||||
&isInterpreted);
|
||||
masm.branchTest32(Assembler::NonZero, temp1,
|
||||
Imm32(FunctionFlags::INTERPRETED), &isInterpreted);
|
||||
{
|
||||
// Load the length property of a native function.
|
||||
masm.load16ZeroExtend(Address(target, JSFunction::offsetOfNargs()), temp1);
|
||||
|
|
|
@ -6698,7 +6698,7 @@ struct LambdaFunctionInfo {
|
|||
|
||||
explicit LambdaFunctionInfo(JSFunction* fun)
|
||||
: fun_(fun),
|
||||
flags(fun->flags()),
|
||||
flags(fun->flags().toRaw()),
|
||||
nargs(fun->nargs()),
|
||||
scriptOrLazyScript(fun->hasScript() ? (gc::Cell*)fun->nonLazyScript()
|
||||
: (gc::Cell*)fun->lazyScript()),
|
||||
|
@ -6708,9 +6708,9 @@ struct LambdaFunctionInfo {
|
|||
// right thing. We can't assert this off-thread in CodeGenerator,
|
||||
// because fun->isAsync() accesses the script/lazyScript and can race
|
||||
// with delazification on the main thread.
|
||||
MOZ_ASSERT_IF(flags & JSFunction::EXTENDED, fun->isArrow() ||
|
||||
fun->allowSuperProperty() ||
|
||||
fun->isSelfHostedBuiltin());
|
||||
MOZ_ASSERT_IF(flags & FunctionFlags::EXTENDED,
|
||||
fun->isArrow() || fun->allowSuperProperty() ||
|
||||
fun->isSelfHostedBuiltin());
|
||||
}
|
||||
|
||||
// Be careful when calling this off-thread. Don't call any JSFunction*
|
||||
|
|
|
@ -369,23 +369,23 @@ void MacroAssembler::branchTestFunctionFlags(Register fun, uint32_t flags,
|
|||
void MacroAssembler::branchIfFunctionHasNoJitEntry(Register fun,
|
||||
bool isConstructing,
|
||||
Label* label) {
|
||||
int32_t flags = JSFunction::INTERPRETED | JSFunction::INTERPRETED_LAZY;
|
||||
int32_t flags = FunctionFlags::INTERPRETED | FunctionFlags::INTERPRETED_LAZY;
|
||||
if (!isConstructing) {
|
||||
flags |= JSFunction::WASM_JIT_ENTRY;
|
||||
flags |= FunctionFlags::WASM_JIT_ENTRY;
|
||||
}
|
||||
branchTestFunctionFlags(fun, flags, Assembler::Zero, label);
|
||||
}
|
||||
|
||||
void MacroAssembler::branchIfFunctionHasNoScript(Register fun, Label* label) {
|
||||
int32_t flags = JSFunction::INTERPRETED;
|
||||
int32_t flags = FunctionFlags::INTERPRETED;
|
||||
branchTestFunctionFlags(fun, flags, Assembler::Zero, label);
|
||||
}
|
||||
|
||||
void MacroAssembler::branchIfInterpreted(Register fun, bool isConstructing,
|
||||
Label* label) {
|
||||
int32_t flags = JSFunction::INTERPRETED | JSFunction::INTERPRETED_LAZY;
|
||||
int32_t flags = FunctionFlags::INTERPRETED | FunctionFlags::INTERPRETED_LAZY;
|
||||
if (!isConstructing) {
|
||||
flags |= JSFunction::WASM_JIT_ENTRY;
|
||||
flags |= FunctionFlags::WASM_JIT_ENTRY;
|
||||
}
|
||||
branchTestFunctionFlags(fun, flags, Assembler::NonZero, label);
|
||||
}
|
||||
|
@ -406,7 +406,7 @@ void MacroAssembler::branchIfObjectEmulatesUndefined(Register objReg,
|
|||
}
|
||||
|
||||
void MacroAssembler::branchFunctionKind(Condition cond,
|
||||
JSFunction::FunctionKind kind,
|
||||
FunctionFlags::FunctionKind kind,
|
||||
Register fun, Register scratch,
|
||||
Label* label) {
|
||||
// 16-bit loads are slow and unaligned 32-bit loads may be too so
|
||||
|
@ -414,8 +414,8 @@ void MacroAssembler::branchFunctionKind(Condition cond,
|
|||
MOZ_ASSERT(JSFunction::offsetOfNargs() % sizeof(uint32_t) == 0);
|
||||
MOZ_ASSERT(JSFunction::offsetOfFlags() == JSFunction::offsetOfNargs() + 2);
|
||||
Address address(fun, JSFunction::offsetOfNargs());
|
||||
int32_t mask = IMM32_16ADJ(JSFunction::FUNCTION_KIND_MASK);
|
||||
int32_t bit = IMM32_16ADJ(kind << JSFunction::FUNCTION_KIND_SHIFT);
|
||||
int32_t mask = IMM32_16ADJ(FunctionFlags::FUNCTION_KIND_MASK);
|
||||
int32_t bit = IMM32_16ADJ(kind << FunctionFlags::FUNCTION_KIND_SHIFT);
|
||||
load32(address, scratch);
|
||||
and32(Imm32(mask), scratch);
|
||||
branch32(cond, scratch, Imm32(bit), label);
|
||||
|
|
|
@ -2870,11 +2870,12 @@ void MacroAssembler::branchIfNotInterpretedConstructor(Register fun,
|
|||
Label* label) {
|
||||
// First, ensure it's a scripted function. It is fine if it is still lazy.
|
||||
branchTestFunctionFlags(
|
||||
fun, JSFunction::INTERPRETED | JSFunction::INTERPRETED_LAZY,
|
||||
fun, FunctionFlags::INTERPRETED | FunctionFlags::INTERPRETED_LAZY,
|
||||
Assembler::Zero, label);
|
||||
|
||||
// Check if the CONSTRUCTOR bit is set.
|
||||
branchTestFunctionFlags(fun, JSFunction::CONSTRUCTOR, Assembler::Zero, label);
|
||||
branchTestFunctionFlags(fun, FunctionFlags::CONSTRUCTOR, Assembler::Zero,
|
||||
label);
|
||||
}
|
||||
|
||||
void MacroAssembler::branchTestObjGroupNoSpectreMitigations(
|
||||
|
|
|
@ -1307,8 +1307,9 @@ class MacroAssembler : public MacroAssemblerSpecific {
|
|||
inline void branchIfInterpreted(Register fun, bool isConstructing,
|
||||
Label* label);
|
||||
|
||||
inline void branchFunctionKind(Condition cond, JSFunction::FunctionKind kind,
|
||||
Register fun, Register scratch, Label* label);
|
||||
inline void branchFunctionKind(Condition cond,
|
||||
FunctionFlags::FunctionKind kind, Register fun,
|
||||
Register scratch, Label* label);
|
||||
|
||||
void branchIfNotInterpretedConstructor(Register fun, Register scratch,
|
||||
Label* label);
|
||||
|
|
|
@ -3313,7 +3313,7 @@ static JSObject* CloneFunctionObject(JSContext* cx, HandleObject funobj,
|
|||
// Only allow cloning normal, interpreted functions.
|
||||
RootedFunction fun(cx, &funobj->as<JSFunction>());
|
||||
if (fun->isNative() || fun->isBoundFunction() ||
|
||||
fun->kind() != JSFunction::NormalFunction || fun->isExtended() ||
|
||||
fun->kind() != FunctionFlags::NormalFunction || fun->isExtended() ||
|
||||
fun->isSelfHostedBuiltin()) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
|
||||
JSMSG_CANT_CLONE_OBJECT);
|
||||
|
|
|
@ -582,7 +582,7 @@ JSObject* ErrorObject::createConstructor(JSContext* cx, JSProtoKey key) {
|
|||
}
|
||||
|
||||
ctor = NewFunctionWithProto(
|
||||
cx, Error, 1, JSFunction::NATIVE_CTOR, nullptr, ClassName(key, cx),
|
||||
cx, Error, 1, FunctionFlags::NATIVE_CTOR, nullptr, ClassName(key, cx),
|
||||
proto, gc::AllocKind::FUNCTION_EXTENDED, SingletonObject);
|
||||
}
|
||||
|
||||
|
|
|
@ -45,8 +45,9 @@ bool GlobalObject::initAsyncFunction(JSContext* cx,
|
|||
}
|
||||
HandlePropertyName name = cx->names().AsyncFunction;
|
||||
RootedObject asyncFunction(
|
||||
cx, NewFunctionWithProto(cx, AsyncFunctionConstructor, 1,
|
||||
JSFunction::NATIVE_CTOR, nullptr, name, proto));
|
||||
cx,
|
||||
NewFunctionWithProto(cx, AsyncFunctionConstructor, 1,
|
||||
FunctionFlags::NATIVE_CTOR, nullptr, name, proto));
|
||||
if (!asyncFunction) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -472,7 +472,7 @@ static const JSFunctionSpec async_generator_methods[] = {
|
|||
// 25.3.1 The AsyncGeneratorFunction Constructor
|
||||
RootedObject asyncGenFunction(
|
||||
cx, NewFunctionWithProto(cx, AsyncGeneratorConstructor, 1,
|
||||
JSFunction::NATIVE_CTOR, nullptr, name, proto,
|
||||
FunctionFlags::NATIVE_CTOR, nullptr, name, proto,
|
||||
gc::AllocKind::FUNCTION, SingletonObject));
|
||||
if (!asyncGenFunction) {
|
||||
return false;
|
||||
|
|
|
@ -347,7 +347,7 @@ class FunctionCompiler {
|
|||
|
||||
RootedFunction fun(
|
||||
cx_,
|
||||
NewScriptedFunction(cx_, 0, JSFunction::INTERPRETED_NORMAL,
|
||||
NewScriptedFunction(cx_, 0, FunctionFlags::INTERPRETED_NORMAL,
|
||||
nameIsIdentifier_ ? HandleAtom(nameAtom_) : nullptr,
|
||||
/* proto = */ nullptr, gc::AllocKind::FUNCTION,
|
||||
TenuredObject, enclosingEnv));
|
||||
|
|
|
@ -281,7 +281,7 @@ bool GlobalObject::initGenerators(JSContext* cx, Handle<GlobalObject*> global) {
|
|||
}
|
||||
HandlePropertyName name = cx->names().GeneratorFunction;
|
||||
RootedObject genFunction(
|
||||
cx, NewFunctionWithProto(cx, Generator, 1, JSFunction::NATIVE_CTOR,
|
||||
cx, NewFunctionWithProto(cx, Generator, 1, FunctionFlags::NATIVE_CTOR,
|
||||
nullptr, name, proto, gc::AllocKind::FUNCTION,
|
||||
SingletonObject));
|
||||
if (!genFunction) {
|
||||
|
|
|
@ -139,7 +139,7 @@ inline JSFunction* CloneFunctionObjectIfNotSingleton(
|
|||
fun->atom_.unsafeSet(nullptr);
|
||||
|
||||
if (kind == js::gc::AllocKind::FUNCTION_EXTENDED) {
|
||||
fun->setFlags(JSFunction::EXTENDED);
|
||||
fun->setFlags(FunctionFlags::EXTENDED);
|
||||
for (js::GCPtrValue& extendedSlot : fun->toExtended()->extendedSlots) {
|
||||
extendedSlot.unsafeSet(JS::UndefinedValue());
|
||||
}
|
||||
|
|
|
@ -132,7 +132,7 @@ void js::ThrowTypeErrorBehavior(JSContext* cx) {
|
|||
|
||||
static bool IsSloppyNormalFunction(JSFunction* fun) {
|
||||
// FunctionDeclaration or FunctionExpression in sloppy mode.
|
||||
if (fun->kind() == JSFunction::NormalFunction) {
|
||||
if (fun->kind() == FunctionFlags::NormalFunction) {
|
||||
if (fun->isBuiltin() || fun->isBoundFunction()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -146,7 +146,7 @@ static bool IsSloppyNormalFunction(JSFunction* fun) {
|
|||
}
|
||||
|
||||
// Or asm.js function in sloppy mode.
|
||||
if (fun->kind() == JSFunction::AsmJS) {
|
||||
if (fun->kind() == FunctionFlags::AsmJS) {
|
||||
return !IsAsmJSStrictModeModuleOrFunction(fun);
|
||||
}
|
||||
|
||||
|
@ -582,7 +582,7 @@ XDRResult js::XDRInterpretedFunction(XDRState<mode>* xdr,
|
|||
|
||||
atom = fun->displayAtom();
|
||||
flagsword =
|
||||
(fun->nargs() << 16) | (fun->flags() & ~JSFunction::NO_XDR_FLAGS);
|
||||
(fun->nargs() << 16) | (fun->flags().toRaw() & ~FunctionFlags::NO_XDR_FLAGS);
|
||||
|
||||
// The environment of any function which is not reused will always be
|
||||
// null, it is later defined when a function is cloned or reused to
|
||||
|
@ -618,10 +618,10 @@ XDRResult js::XDRInterpretedFunction(XDRState<mode>* xdr,
|
|||
}
|
||||
|
||||
gc::AllocKind allocKind = gc::AllocKind::FUNCTION;
|
||||
if (uint16_t(flagsword) & JSFunction::EXTENDED) {
|
||||
if (uint16_t(flagsword) & FunctionFlags::EXTENDED) {
|
||||
allocKind = gc::AllocKind::FUNCTION_EXTENDED;
|
||||
}
|
||||
fun = NewFunctionWithProto(cx, nullptr, 0, JSFunction::INTERPRETED,
|
||||
fun = NewFunctionWithProto(cx, nullptr, 0, FunctionFlags::INTERPRETED,
|
||||
/* enclosingDynamicScope = */ nullptr, nullptr,
|
||||
proto, allocKind, TenuredObject);
|
||||
if (!fun) {
|
||||
|
@ -796,7 +796,7 @@ static JSObject* CreateFunctionConstructor(JSContext* cx, JSProtoKey key) {
|
|||
|
||||
RootedObject functionCtor(
|
||||
cx, NewFunctionWithProto(
|
||||
cx, Function, 1, JSFunction::NATIVE_CTOR, nullptr,
|
||||
cx, Function, 1, FunctionFlags::NATIVE_CTOR, nullptr,
|
||||
HandlePropertyName(cx->names().Function), functionProto,
|
||||
gc::AllocKind::FUNCTION, SingletonObject));
|
||||
if (!functionCtor) {
|
||||
|
@ -817,10 +817,10 @@ static JSObject* CreateFunctionPrototype(JSContext* cx, JSProtoKey key) {
|
|||
|
||||
RootedObject objectProto(cx, &self->getPrototype(JSProto_Object).toObject());
|
||||
|
||||
return NewFunctionWithProto(cx, FunctionPrototype, 0, JSFunction::NATIVE_FUN,
|
||||
nullptr, HandlePropertyName(cx->names().empty),
|
||||
objectProto, gc::AllocKind::FUNCTION,
|
||||
SingletonObject);
|
||||
return NewFunctionWithProto(
|
||||
cx, FunctionPrototype, 0, FunctionFlags::NATIVE_FUN, nullptr,
|
||||
HandlePropertyName(cx->names().empty), objectProto,
|
||||
gc::AllocKind::FUNCTION, SingletonObject);
|
||||
}
|
||||
|
||||
JSString* js::FunctionToStringCache::lookup(JSScript* script) const {
|
||||
|
@ -941,8 +941,8 @@ JSString* js::FunctionToString(JSContext* cx, HandleFunction fun,
|
|||
// performance reasons, so only append the name if we're confident it
|
||||
// can be matched as the 'PropertyName' grammar production.
|
||||
if (fun->explicitName() && !fun->isBoundFunction() &&
|
||||
(fun->kind() == JSFunction::NormalFunction ||
|
||||
fun->kind() == JSFunction::ClassConstructor)) {
|
||||
(fun->kind() == FunctionFlags::NormalFunction ||
|
||||
fun->kind() == FunctionFlags::ClassConstructor)) {
|
||||
if (!out.append(' ')) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -1741,8 +1741,8 @@ void JSFunction::maybeRelazify(JSRuntime* rt) {
|
|||
|
||||
JSScript* script = nonLazyScript();
|
||||
|
||||
flags_ &= ~INTERPRETED;
|
||||
flags_ |= INTERPRETED_LAZY;
|
||||
flags_.clearInterpreted();
|
||||
flags_.setInterpretedLazy();
|
||||
LazyScript* lazy = script->maybeLazyScript();
|
||||
if (lazy) {
|
||||
u.scripted.s.lazy_ = lazy;
|
||||
|
@ -1909,10 +1909,10 @@ static bool CreateDynamicFunction(JSContext* cx, const CallArgs& args,
|
|||
|
||||
// Step 30-37 (reordered).
|
||||
RootedObject globalLexical(cx, &global->lexicalEnvironment());
|
||||
JSFunction::Flags flags =
|
||||
FunctionFlags flags =
|
||||
(isGenerator || isAsync)
|
||||
? JSFunction::INTERPRETED_LAMBDA_GENERATOR_OR_ASYNC
|
||||
: JSFunction::INTERPRETED_LAMBDA;
|
||||
? FunctionFlags::INTERPRETED_LAMBDA_GENERATOR_OR_ASYNC
|
||||
: FunctionFlags::INTERPRETED_LAMBDA;
|
||||
gc::AllocKind allocKind = gc::AllocKind::FUNCTION;
|
||||
RootedFunction fun(
|
||||
cx,
|
||||
|
@ -2044,7 +2044,7 @@ bool JSFunction::needsNamedLambdaEnvironment() const {
|
|||
}
|
||||
|
||||
JSFunction* js::NewScriptedFunction(
|
||||
JSContext* cx, unsigned nargs, JSFunction::Flags flags, HandleAtom atom,
|
||||
JSContext* cx, unsigned nargs, FunctionFlags flags, HandleAtom atom,
|
||||
HandleObject proto /* = nullptr */,
|
||||
gc::AllocKind allocKind /* = AllocKind::FUNCTION */,
|
||||
NewObjectKind newKind /* = GenericObject */,
|
||||
|
@ -2081,7 +2081,7 @@ static bool NewFunctionEnvironmentIsWellFormed(JSContext* cx,
|
|||
#endif
|
||||
|
||||
JSFunction* js::NewFunctionWithProto(
|
||||
JSContext* cx, Native native, unsigned nargs, JSFunction::Flags flags,
|
||||
JSContext* cx, Native native, unsigned nargs, FunctionFlags flags,
|
||||
HandleObject enclosingEnv, HandleAtom atom, HandleObject proto,
|
||||
gc::AllocKind allocKind /* = AllocKind::FUNCTION */,
|
||||
NewObjectKind newKind /* = GenericObject */) {
|
||||
|
@ -2097,7 +2097,7 @@ JSFunction* js::NewFunctionWithProto(
|
|||
}
|
||||
|
||||
if (allocKind == gc::AllocKind::FUNCTION_EXTENDED) {
|
||||
flags = JSFunction::Flags(flags | JSFunction::EXTENDED);
|
||||
flags.setIsExtended();
|
||||
}
|
||||
|
||||
/* Initialize all function members. */
|
||||
|
@ -2193,19 +2193,21 @@ static inline JSFunction* NewFunctionClone(JSContext* cx, HandleFunction fun,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
// JSFunction::HAS_INFERRED_NAME can be set at compile-time and at
|
||||
// FunctionFlags::HAS_INFERRED_NAME can be set at compile-time and at
|
||||
// runtime. In the latter case we should actually clear the flag before
|
||||
// cloning the function, but since we can't differentiate between both
|
||||
// cases here, we'll end up with a momentarily incorrect function name.
|
||||
// This will be fixed up in SetFunctionName(), which should happen through
|
||||
// JSOP_SETFUNNAME directly after JSOP_LAMBDA.
|
||||
constexpr uint16_t NonCloneableFlags = JSFunction::EXTENDED |
|
||||
JSFunction::RESOLVED_LENGTH |
|
||||
JSFunction::RESOLVED_NAME;
|
||||
constexpr uint16_t NonCloneableFlags = FunctionFlags::EXTENDED |
|
||||
FunctionFlags::RESOLVED_LENGTH |
|
||||
FunctionFlags::RESOLVED_NAME;
|
||||
|
||||
FunctionFlags flags = fun->flags();
|
||||
flags.clearFlags(NonCloneableFlags);
|
||||
|
||||
uint16_t flags = fun->flags() & ~NonCloneableFlags;
|
||||
if (allocKind == gc::AllocKind::FUNCTION_EXTENDED) {
|
||||
flags |= JSFunction::EXTENDED;
|
||||
flags.setIsExtended();
|
||||
}
|
||||
|
||||
clone->setArgCount(fun->nargs());
|
||||
|
|
|
@ -33,10 +33,8 @@ static const char FunctionConstructorFinalBrace[] = "\n}";
|
|||
|
||||
enum class FunctionPrefixKind { None, Get, Set };
|
||||
|
||||
class JSFunction : public js::NativeObject {
|
||||
class FunctionFlags {
|
||||
public:
|
||||
static const js::Class class_;
|
||||
|
||||
enum FunctionKind {
|
||||
NormalFunction = 0,
|
||||
Arrow, /* ES6 '(args) => body' syntax */
|
||||
|
@ -49,6 +47,7 @@ class JSFunction : public js::NativeObject {
|
|||
FunctionKindLimit
|
||||
};
|
||||
|
||||
// I wish I didn't have to name this enum it makes consumers uglier
|
||||
enum Flags {
|
||||
INTERPRETED = 0x0001, /* function has a JSScript and environment. */
|
||||
CONSTRUCTOR = 0x0002, /* function that can be called as a constructor */
|
||||
|
@ -122,13 +121,198 @@ class JSFunction : public js::NativeObject {
|
|||
CONSTRUCTOR | LAMBDA | SELF_HOSTED | FUNCTION_KIND_MASK
|
||||
};
|
||||
|
||||
uint16_t flags_;
|
||||
|
||||
public:
|
||||
FunctionFlags() : flags_() {
|
||||
static_assert(sizeof(FunctionFlags) == sizeof(flags_),
|
||||
"No extra members allowed is it'll grow JSFunction");
|
||||
static_assert(offsetof(FunctionFlags, flags_) == 0,
|
||||
"Required for JIT flag access");
|
||||
}
|
||||
|
||||
explicit FunctionFlags(uint16_t flags) : flags_(flags) {}
|
||||
MOZ_IMPLICIT FunctionFlags(Flags f) : flags_(f) {}
|
||||
|
||||
static_assert((INTERPRETED | INTERPRETED_LAZY) ==
|
||||
js::JS_FUNCTION_INTERPRETED_BITS,
|
||||
"jsfriendapi.h's JSFunction::INTERPRETED-alike is wrong");
|
||||
"jsfriendapi.h's FunctionFlags::INTERPRETED-alike is wrong");
|
||||
static_assert(((FunctionKindLimit - 1) << FUNCTION_KIND_SHIFT) <=
|
||||
FUNCTION_KIND_MASK,
|
||||
"FunctionKind doesn't fit into flags_");
|
||||
|
||||
uint16_t toRaw() const { return flags_; }
|
||||
|
||||
// For flag combinations the type is int.
|
||||
bool hasFlags(uint16_t flags) const { return flags_ & flags; }
|
||||
void setFlags(uint16_t flags) { flags_ |= flags; }
|
||||
void clearFlags(uint16_t flags) { flags_ &= ~flags; }
|
||||
|
||||
FunctionKind kind() const {
|
||||
return static_cast<FunctionKind>((flags_ & FUNCTION_KIND_MASK) >>
|
||||
FUNCTION_KIND_SHIFT);
|
||||
}
|
||||
|
||||
/* A function can be classified as either native (C++) or interpreted (JS): */
|
||||
bool isInterpreted() const {
|
||||
return hasFlags(INTERPRETED) || hasFlags(INTERPRETED_LAZY);
|
||||
}
|
||||
bool isNative() const { return !isInterpreted(); }
|
||||
|
||||
bool isConstructor() const { return hasFlags(CONSTRUCTOR); }
|
||||
|
||||
/* Possible attributes of a native function: */
|
||||
bool isAsmJSNative() const {
|
||||
MOZ_ASSERT_IF(kind() == AsmJS, isNative());
|
||||
return kind() == AsmJS;
|
||||
}
|
||||
bool isWasm() const {
|
||||
MOZ_ASSERT_IF(kind() == Wasm, isNative());
|
||||
return kind() == Wasm;
|
||||
}
|
||||
bool isWasmWithJitEntry() const {
|
||||
MOZ_ASSERT_IF(hasFlags(WASM_JIT_ENTRY), isWasm());
|
||||
return hasFlags(WASM_JIT_ENTRY);
|
||||
}
|
||||
bool isNativeWithJitEntry() const {
|
||||
MOZ_ASSERT_IF(isWasmWithJitEntry(), isNative());
|
||||
return isWasmWithJitEntry();
|
||||
}
|
||||
bool isBuiltinNative() const {
|
||||
return isNative() && !isAsmJSNative() && !isWasm();
|
||||
}
|
||||
|
||||
/* Possible attributes of an interpreted function: */
|
||||
bool isBoundFunction() const { return hasFlags(BOUND_FUN); }
|
||||
bool hasInferredName() const { return hasFlags(HAS_INFERRED_NAME); }
|
||||
bool hasGuessedAtom() const {
|
||||
static_assert(HAS_GUESSED_ATOM == HAS_BOUND_FUNCTION_NAME_PREFIX,
|
||||
"HAS_GUESSED_ATOM is unused for bound functions");
|
||||
bool hasGuessedAtom = hasFlags(HAS_GUESSED_ATOM);
|
||||
bool boundFun = hasFlags(BOUND_FUN);
|
||||
return hasGuessedAtom && !boundFun;
|
||||
}
|
||||
bool hasBoundFunctionNamePrefix() const {
|
||||
static_assert(
|
||||
HAS_BOUND_FUNCTION_NAME_PREFIX == HAS_GUESSED_ATOM,
|
||||
"HAS_BOUND_FUNCTION_NAME_PREFIX is only used for bound functions");
|
||||
MOZ_ASSERT(isBoundFunction());
|
||||
return hasFlags(HAS_BOUND_FUNCTION_NAME_PREFIX);
|
||||
}
|
||||
bool isLambda() const { return hasFlags(LAMBDA); }
|
||||
bool isInterpretedLazy() const { return hasFlags(INTERPRETED_LAZY); }
|
||||
|
||||
// These methods determine which of the u.scripted.s union arms are active.
|
||||
// For live JSFunctions the pointer values will always be non-null, but due
|
||||
// to partial initialization the GC (and other features that scan the heap
|
||||
// directly) may still return a null pointer.
|
||||
bool hasScript() const { return hasFlags(INTERPRETED); }
|
||||
bool hasLazyScript() const {
|
||||
return isInterpretedLazy() && !isSelfHostedOrIntrinsic();
|
||||
}
|
||||
bool hasSelfHostedLazyScript() const {
|
||||
return isInterpretedLazy() && isSelfHostedOrIntrinsic();
|
||||
}
|
||||
|
||||
// Arrow functions store their lexical new.target in the first extended slot.
|
||||
bool isArrow() const { return kind() == Arrow; }
|
||||
// Every class-constructor is also a method.
|
||||
bool isMethod() const {
|
||||
return kind() == Method || kind() == ClassConstructor;
|
||||
}
|
||||
bool isClassConstructor() const { return kind() == ClassConstructor; }
|
||||
|
||||
bool isGetter() const { return kind() == Getter; }
|
||||
bool isSetter() const { return kind() == Setter; }
|
||||
|
||||
bool allowSuperProperty() const {
|
||||
return isMethod() || isGetter() || isSetter();
|
||||
}
|
||||
|
||||
bool hasResolvedLength() const { return hasFlags(RESOLVED_LENGTH); }
|
||||
bool hasResolvedName() const { return hasFlags(RESOLVED_NAME); }
|
||||
|
||||
bool isSelfHostedOrIntrinsic() const { return hasFlags(SELF_HOSTED); }
|
||||
bool isSelfHostedBuiltin() const {
|
||||
return isSelfHostedOrIntrinsic() && !isNative();
|
||||
}
|
||||
bool isIntrinsic() const { return isSelfHostedOrIntrinsic() && isNative(); }
|
||||
|
||||
void setKind(FunctionKind kind) {
|
||||
this->flags_ &= ~FUNCTION_KIND_MASK;
|
||||
this->flags_ |= static_cast<uint16_t>(kind) << FUNCTION_KIND_SHIFT;
|
||||
}
|
||||
|
||||
// Make the function constructible.
|
||||
void setIsConstructor() {
|
||||
MOZ_ASSERT(!isConstructor());
|
||||
MOZ_ASSERT(isSelfHostedBuiltin());
|
||||
setFlags(CONSTRUCTOR);
|
||||
}
|
||||
|
||||
void setIsClassConstructor() {
|
||||
MOZ_ASSERT(!isClassConstructor());
|
||||
MOZ_ASSERT(isConstructor());
|
||||
|
||||
setKind(ClassConstructor);
|
||||
}
|
||||
|
||||
void clearIsSelfHosted() { clearFlags(SELF_HOSTED); }
|
||||
|
||||
void setIsBoundFunction() {
|
||||
MOZ_ASSERT(!isBoundFunction());
|
||||
setFlags(BOUND_FUN);
|
||||
}
|
||||
|
||||
void setIsSelfHostedBuiltin() {
|
||||
MOZ_ASSERT(isInterpreted());
|
||||
MOZ_ASSERT(!isSelfHostedBuiltin());
|
||||
setFlags(SELF_HOSTED);
|
||||
// Self-hosted functions should not be constructable.
|
||||
clearFlags(CONSTRUCTOR);
|
||||
}
|
||||
void setIsIntrinsic() {
|
||||
MOZ_ASSERT(isNative());
|
||||
MOZ_ASSERT(!isIntrinsic());
|
||||
setFlags(SELF_HOSTED);
|
||||
}
|
||||
|
||||
void setArrow() { setKind(Arrow); }
|
||||
|
||||
void setResolvedLength() { setFlags(RESOLVED_LENGTH); }
|
||||
void setResolvedName() { setFlags(RESOLVED_NAME); }
|
||||
|
||||
// Mark a function as having its 'new' script information cleared.
|
||||
bool wasNewScriptCleared() const { return hasFlags(NEW_SCRIPT_CLEARED); }
|
||||
void setNewScriptCleared() { setFlags(NEW_SCRIPT_CLEARED); }
|
||||
|
||||
void setInferredName() { setFlags(HAS_INFERRED_NAME); }
|
||||
void clearInferredName() { clearFlags(HAS_INFERRED_NAME); }
|
||||
|
||||
void setGuessedAtom() { setFlags(HAS_GUESSED_ATOM); }
|
||||
void clearGuessedAtom() { clearFlags(HAS_GUESSED_ATOM); }
|
||||
|
||||
void setPrefixedBoundFunctionName() {
|
||||
setFlags(HAS_BOUND_FUNCTION_NAME_PREFIX);
|
||||
}
|
||||
|
||||
void setInterpretedLazy() { setFlags(INTERPRETED_LAZY); }
|
||||
void clearInterpretedLazy() { clearFlags(INTERPRETED_LAZY); }
|
||||
void setInterpreted() { setFlags(INTERPRETED); }
|
||||
void clearInterpreted() { clearFlags(INTERPRETED); }
|
||||
|
||||
void setWasmJitEntry() { setFlags(WASM_JIT_ENTRY); }
|
||||
|
||||
bool isExtended() const { return hasFlags(EXTENDED); }
|
||||
void setIsExtended() { setFlags(EXTENDED); }
|
||||
|
||||
bool isNativeConstructor() const { return hasFlags(NATIVE_CTOR); }
|
||||
};
|
||||
|
||||
class JSFunction : public js::NativeObject {
|
||||
public:
|
||||
static const js::Class class_;
|
||||
|
||||
private:
|
||||
/*
|
||||
* number of formal arguments
|
||||
|
@ -142,7 +326,8 @@ class JSFunction : public js::NativeObject {
|
|||
* If any of these flags needs to be accessed in off-thread JIT
|
||||
* compilation, copy it to js::jit::WrappedFunction.
|
||||
*/
|
||||
uint16_t flags_;
|
||||
FunctionFlags flags_;
|
||||
|
||||
union U {
|
||||
class {
|
||||
friend class JSFunction;
|
||||
|
@ -243,95 +428,65 @@ class JSFunction : public js::NativeObject {
|
|||
static constexpr size_t NArgsBits = sizeof(nargs_) * CHAR_BIT;
|
||||
size_t nargs() const { return nargs_; }
|
||||
|
||||
uint16_t flags() const { return flags_; }
|
||||
FunctionFlags flags() { return flags_; }
|
||||
|
||||
FunctionKind kind() const {
|
||||
return static_cast<FunctionKind>((flags_ & FUNCTION_KIND_MASK) >>
|
||||
FUNCTION_KIND_SHIFT);
|
||||
}
|
||||
FunctionFlags::FunctionKind kind() const { return flags_.kind(); }
|
||||
|
||||
/* A function can be classified as either native (C++) or interpreted (JS): */
|
||||
bool isInterpreted() const {
|
||||
return flags() & (INTERPRETED | INTERPRETED_LAZY);
|
||||
}
|
||||
bool isNative() const { return !isInterpreted(); }
|
||||
bool isInterpreted() const { return flags_.isInterpreted(); }
|
||||
bool isNative() const { return flags_.isNative(); }
|
||||
|
||||
bool isConstructor() const { return flags() & CONSTRUCTOR; }
|
||||
bool isConstructor() const { return flags_.isConstructor(); }
|
||||
|
||||
/* Possible attributes of a native function: */
|
||||
bool isAsmJSNative() const {
|
||||
MOZ_ASSERT_IF(kind() == AsmJS, isNative());
|
||||
return kind() == AsmJS;
|
||||
}
|
||||
bool isWasm() const {
|
||||
MOZ_ASSERT_IF(kind() == Wasm, isNative());
|
||||
return kind() == Wasm;
|
||||
}
|
||||
bool isWasmWithJitEntry() const {
|
||||
MOZ_ASSERT_IF(flags() & WASM_JIT_ENTRY, isWasm());
|
||||
return flags() & WASM_JIT_ENTRY;
|
||||
}
|
||||
bool isNativeWithJitEntry() const {
|
||||
MOZ_ASSERT_IF(isWasmWithJitEntry(), isNative());
|
||||
return isWasmWithJitEntry();
|
||||
}
|
||||
bool isBuiltinNative() const {
|
||||
return isNative() && !isAsmJSNative() && !isWasm();
|
||||
}
|
||||
bool isAsmJSNative() const { return flags_.isAsmJSNative(); }
|
||||
|
||||
bool isWasm() const { return flags_.isWasm(); }
|
||||
bool isWasmWithJitEntry() const { return flags_.isWasmWithJitEntry(); }
|
||||
bool isNativeWithJitEntry() const { return flags_.isNativeWithJitEntry(); }
|
||||
bool isBuiltinNative() const { return flags_.isBuiltinNative(); }
|
||||
|
||||
/* Possible attributes of an interpreted function: */
|
||||
bool isBoundFunction() const { return flags() & BOUND_FUN; }
|
||||
bool hasInferredName() const { return flags() & HAS_INFERRED_NAME; }
|
||||
bool hasGuessedAtom() const {
|
||||
static_assert(HAS_GUESSED_ATOM == HAS_BOUND_FUNCTION_NAME_PREFIX,
|
||||
"HAS_GUESSED_ATOM is unused for bound functions");
|
||||
return (flags() & (HAS_GUESSED_ATOM | BOUND_FUN)) == HAS_GUESSED_ATOM;
|
||||
}
|
||||
bool isBoundFunction() const { return flags_.isBoundFunction(); }
|
||||
bool hasInferredName() const { return flags_.hasInferredName(); }
|
||||
bool hasGuessedAtom() const { return flags_.hasGuessedAtom(); }
|
||||
bool hasBoundFunctionNamePrefix() const {
|
||||
static_assert(
|
||||
HAS_BOUND_FUNCTION_NAME_PREFIX == HAS_GUESSED_ATOM,
|
||||
"HAS_BOUND_FUNCTION_NAME_PREFIX is only used for bound functions");
|
||||
MOZ_ASSERT(isBoundFunction());
|
||||
return flags() & HAS_BOUND_FUNCTION_NAME_PREFIX;
|
||||
return flags_.hasBoundFunctionNamePrefix();
|
||||
}
|
||||
bool isLambda() const { return flags() & LAMBDA; }
|
||||
bool isInterpretedLazy() const { return flags() & INTERPRETED_LAZY; }
|
||||
|
||||
bool isLambda() const { return flags_.isLambda(); }
|
||||
bool isInterpretedLazy() const { return flags_.isInterpretedLazy(); }
|
||||
|
||||
// These methods determine which of the u.scripted.s union arms are active.
|
||||
// For live JSFunctions the pointer values will always be non-null, but due
|
||||
// to partial initialization the GC (and other features that scan the heap
|
||||
// directly) may still return a null pointer.
|
||||
bool hasScript() const { return flags() & INTERPRETED; }
|
||||
bool hasLazyScript() const {
|
||||
return isInterpretedLazy() && !isSelfHostedOrIntrinsic();
|
||||
}
|
||||
bool hasScript() const { return flags_.hasScript(); }
|
||||
bool hasLazyScript() const { return flags_.hasLazyScript(); }
|
||||
bool hasSelfHostedLazyScript() const {
|
||||
return isInterpretedLazy() && isSelfHostedOrIntrinsic();
|
||||
return flags_.hasSelfHostedLazyScript();
|
||||
}
|
||||
|
||||
// Arrow functions store their lexical new.target in the first extended slot.
|
||||
bool isArrow() const { return kind() == Arrow; }
|
||||
bool isArrow() const { return flags_.isArrow(); }
|
||||
// Every class-constructor is also a method.
|
||||
bool isMethod() const {
|
||||
return kind() == Method || kind() == ClassConstructor;
|
||||
bool isMethod() const { return flags_.isMethod(); }
|
||||
bool isClassConstructor() const { return flags_.isClassConstructor(); }
|
||||
|
||||
bool isGetter() const { return flags_.isGetter(); }
|
||||
bool isSetter() const { return flags_.isSetter(); }
|
||||
|
||||
bool allowSuperProperty() const { return flags_.allowSuperProperty(); }
|
||||
|
||||
bool hasResolvedLength() const { return flags_.hasResolvedLength(); }
|
||||
bool hasResolvedName() const { return flags_.hasResolvedName(); }
|
||||
|
||||
bool isSelfHostedOrIntrinsic() const {
|
||||
return flags_.isSelfHostedOrIntrinsic();
|
||||
}
|
||||
bool isClassConstructor() const { return kind() == ClassConstructor; }
|
||||
bool isSelfHostedBuiltin() const { return flags_.isSelfHostedBuiltin(); }
|
||||
|
||||
bool isGetter() const { return kind() == Getter; }
|
||||
bool isSetter() const { return kind() == Setter; }
|
||||
|
||||
bool allowSuperProperty() const {
|
||||
return isMethod() || isGetter() || isSetter();
|
||||
}
|
||||
|
||||
bool hasResolvedLength() const { return flags() & RESOLVED_LENGTH; }
|
||||
bool hasResolvedName() const { return flags() & RESOLVED_NAME; }
|
||||
|
||||
bool isSelfHostedOrIntrinsic() const { return flags() & SELF_HOSTED; }
|
||||
bool isSelfHostedBuiltin() const {
|
||||
return isSelfHostedOrIntrinsic() && !isNative();
|
||||
}
|
||||
bool isIntrinsic() const { return isSelfHostedOrIntrinsic() && isNative(); }
|
||||
bool isIntrinsic() const { return flags_.isIntrinsic(); }
|
||||
|
||||
bool hasJitScript() const {
|
||||
if (!hasScript()) {
|
||||
|
@ -364,58 +519,30 @@ class JSFunction : public js::NativeObject {
|
|||
: nonLazyScript()->strict();
|
||||
}
|
||||
|
||||
void setFlags(uint16_t flags) { this->flags_ = flags; }
|
||||
void setKind(FunctionKind kind) {
|
||||
this->flags_ &= ~FUNCTION_KIND_MASK;
|
||||
this->flags_ |= static_cast<uint16_t>(kind) << FUNCTION_KIND_SHIFT;
|
||||
}
|
||||
void setFlags(uint16_t flags) { flags_ = FunctionFlags(flags); }
|
||||
void setFlags(FunctionFlags flags) { flags_ = flags; }
|
||||
void setKind(FunctionFlags::FunctionKind kind) { flags_.setKind(kind); }
|
||||
|
||||
// Make the function constructible.
|
||||
void setIsConstructor() {
|
||||
MOZ_ASSERT(!isConstructor());
|
||||
MOZ_ASSERT(isSelfHostedBuiltin());
|
||||
flags_ |= CONSTRUCTOR;
|
||||
}
|
||||
void setIsConstructor() { flags_.setIsConstructor(); }
|
||||
void setIsClassConstructor() { flags_.setIsClassConstructor(); }
|
||||
|
||||
void setIsClassConstructor() {
|
||||
MOZ_ASSERT(!isClassConstructor());
|
||||
MOZ_ASSERT(isConstructor());
|
||||
|
||||
setKind(ClassConstructor);
|
||||
}
|
||||
|
||||
void clearIsSelfHosted() { flags_ &= ~SELF_HOSTED; }
|
||||
void clearIsSelfHosted() { flags_.clearIsSelfHosted(); }
|
||||
|
||||
// Can be called multiple times by the parser.
|
||||
void setArgCount(uint16_t nargs) { this->nargs_ = nargs; }
|
||||
|
||||
void setIsBoundFunction() {
|
||||
MOZ_ASSERT(!isBoundFunction());
|
||||
flags_ |= BOUND_FUN;
|
||||
}
|
||||
void setIsBoundFunction() { flags_.setIsBoundFunction(); }
|
||||
void setIsSelfHostedBuiltin() { flags_.setIsSelfHostedBuiltin(); }
|
||||
void setIsIntrinsic() { flags_.setIsIntrinsic(); }
|
||||
|
||||
void setIsSelfHostedBuiltin() {
|
||||
MOZ_ASSERT(isInterpreted());
|
||||
MOZ_ASSERT(!isSelfHostedBuiltin());
|
||||
flags_ |= SELF_HOSTED;
|
||||
// Self-hosted functions should not be constructable.
|
||||
flags_ &= ~CONSTRUCTOR;
|
||||
}
|
||||
void setIsIntrinsic() {
|
||||
MOZ_ASSERT(isNative());
|
||||
MOZ_ASSERT(!isIntrinsic());
|
||||
flags_ |= SELF_HOSTED;
|
||||
}
|
||||
|
||||
void setArrow() { setKind(Arrow); }
|
||||
|
||||
void setResolvedLength() { flags_ |= RESOLVED_LENGTH; }
|
||||
|
||||
void setResolvedName() { flags_ |= RESOLVED_NAME; }
|
||||
void setArrow() { flags_.setArrow(); }
|
||||
void setResolvedLength() { flags_.setResolvedLength(); }
|
||||
void setResolvedName() { flags_.setResolvedName(); }
|
||||
|
||||
// Mark a function as having its 'new' script information cleared.
|
||||
bool wasNewScriptCleared() const { return flags_ & NEW_SCRIPT_CLEARED; }
|
||||
void setNewScriptCleared() { flags_ |= NEW_SCRIPT_CLEARED; }
|
||||
bool wasNewScriptCleared() const { return flags_.wasNewScriptCleared(); }
|
||||
void setNewScriptCleared() { flags_.setNewScriptCleared(); }
|
||||
|
||||
static bool getUnresolvedLength(JSContext* cx, js::HandleFunction fun,
|
||||
js::MutableHandleValue v);
|
||||
|
@ -452,13 +579,13 @@ class JSFunction : public js::NativeObject {
|
|||
MOZ_ASSERT(atom);
|
||||
MOZ_ASSERT(!hasGuessedAtom());
|
||||
setAtom(atom);
|
||||
flags_ |= HAS_INFERRED_NAME;
|
||||
flags_.setInferredName();
|
||||
}
|
||||
void clearInferredName() {
|
||||
MOZ_ASSERT(hasInferredName());
|
||||
MOZ_ASSERT(atom_);
|
||||
setAtom(nullptr);
|
||||
flags_ &= ~HAS_INFERRED_NAME;
|
||||
flags_.clearInferredName();
|
||||
}
|
||||
JSAtom* inferredName() const {
|
||||
MOZ_ASSERT(hasInferredName());
|
||||
|
@ -473,20 +600,20 @@ class JSFunction : public js::NativeObject {
|
|||
MOZ_ASSERT(!hasGuessedAtom());
|
||||
MOZ_ASSERT(!isBoundFunction());
|
||||
setAtom(atom);
|
||||
flags_ |= HAS_GUESSED_ATOM;
|
||||
flags_.setGuessedAtom();
|
||||
}
|
||||
void clearGuessedAtom() {
|
||||
MOZ_ASSERT(hasGuessedAtom());
|
||||
MOZ_ASSERT(!isBoundFunction());
|
||||
MOZ_ASSERT(atom_);
|
||||
setAtom(nullptr);
|
||||
flags_ &= ~HAS_GUESSED_ATOM;
|
||||
flags_.clearGuessedAtom();
|
||||
}
|
||||
|
||||
void setPrefixedBoundFunctionName(JSAtom* atom) {
|
||||
MOZ_ASSERT(!hasBoundFunctionNamePrefix());
|
||||
MOZ_ASSERT(atom);
|
||||
flags_ |= HAS_BOUND_FUNCTION_NAME_PREFIX;
|
||||
flags_.setPrefixedBoundFunctionName();
|
||||
setAtom(atom);
|
||||
}
|
||||
|
||||
|
@ -587,8 +714,8 @@ class JSFunction : public js::NativeObject {
|
|||
js::LazyScript::writeBarrierPre(lazyScript());
|
||||
}
|
||||
JSScript* script = existingScriptNonDelazifying();
|
||||
flags_ &= ~INTERPRETED_LAZY;
|
||||
flags_ |= INTERPRETED;
|
||||
flags_.clearInterpretedLazy();
|
||||
flags_.setInterpreted();
|
||||
initScript(script);
|
||||
}
|
||||
return nonLazyScript();
|
||||
|
@ -695,23 +822,23 @@ class JSFunction : public js::NativeObject {
|
|||
lazyScript()->initScript(script);
|
||||
}
|
||||
}
|
||||
flags_ &= ~INTERPRETED_LAZY;
|
||||
flags_ |= INTERPRETED;
|
||||
flags_.clearInterpretedLazy();
|
||||
flags_.setInterpreted();
|
||||
initScript(script);
|
||||
}
|
||||
|
||||
void initLazyScript(js::LazyScript* lazy) {
|
||||
MOZ_ASSERT(isInterpreted());
|
||||
flags_ &= ~INTERPRETED;
|
||||
flags_ |= INTERPRETED_LAZY;
|
||||
flags_.clearInterpreted();
|
||||
flags_.setInterpretedLazy();
|
||||
u.scripted.s.lazy_ = lazy;
|
||||
}
|
||||
|
||||
void initSelfHostLazyScript(js::SelfHostedLazyScript* lazy) {
|
||||
MOZ_ASSERT(isInterpreted());
|
||||
MOZ_ASSERT(isSelfHostedBuiltin());
|
||||
flags_ &= ~INTERPRETED;
|
||||
flags_ |= INTERPRETED_LAZY;
|
||||
flags_.clearInterpreted();
|
||||
flags_.setInterpretedLazy();
|
||||
u.scripted.s.selfHostedLazy_ = lazy;
|
||||
}
|
||||
|
||||
|
@ -762,7 +889,7 @@ class JSFunction : public js::NativeObject {
|
|||
MOZ_ASSERT(*entry);
|
||||
MOZ_ASSERT(isWasm());
|
||||
MOZ_ASSERT(!isWasmWithJitEntry());
|
||||
flags_ |= WASM_JIT_ENTRY;
|
||||
flags_.setWasmJitEntry();
|
||||
u.native.extra.wasmJitEntry_ = entry;
|
||||
MOZ_ASSERT(isWasmWithJitEntry());
|
||||
}
|
||||
|
@ -829,7 +956,7 @@ class JSFunction : public js::NativeObject {
|
|||
|
||||
public:
|
||||
inline bool isExtended() const {
|
||||
bool extended = !!(flags() & EXTENDED);
|
||||
bool extended = flags_.isExtended();
|
||||
MOZ_ASSERT_IF(isTenured(),
|
||||
extended == (asTenured().getAllocKind() ==
|
||||
js::gc::AllocKind::FUNCTION_EXTENDED));
|
||||
|
@ -901,7 +1028,7 @@ extern bool AsyncGeneratorConstructor(JSContext* cx, unsigned argc, Value* vp);
|
|||
// parent.
|
||||
|
||||
extern JSFunction* NewFunctionWithProto(
|
||||
JSContext* cx, JSNative native, unsigned nargs, JSFunction::Flags flags,
|
||||
JSContext* cx, JSNative native, unsigned nargs, FunctionFlags flags,
|
||||
HandleObject enclosingEnv, HandleAtom atom, HandleObject proto,
|
||||
gc::AllocKind allocKind = gc::AllocKind::FUNCTION,
|
||||
NewObjectKind newKind = GenericObject);
|
||||
|
@ -912,7 +1039,7 @@ inline JSFunction* NewNativeFunction(
|
|||
JSContext* cx, JSNative native, unsigned nargs, HandleAtom atom,
|
||||
gc::AllocKind allocKind = gc::AllocKind::FUNCTION,
|
||||
NewObjectKind newKind = SingletonObject,
|
||||
JSFunction::Flags flags = JSFunction::NATIVE_FUN) {
|
||||
FunctionFlags flags = FunctionFlags::NATIVE_FUN) {
|
||||
MOZ_ASSERT(native);
|
||||
return NewFunctionWithProto(cx, native, nargs, flags, nullptr, atom, nullptr,
|
||||
allocKind, newKind);
|
||||
|
@ -924,9 +1051,9 @@ inline JSFunction* NewNativeConstructor(
|
|||
JSContext* cx, JSNative native, unsigned nargs, HandleAtom atom,
|
||||
gc::AllocKind allocKind = gc::AllocKind::FUNCTION,
|
||||
NewObjectKind newKind = SingletonObject,
|
||||
JSFunction::Flags flags = JSFunction::NATIVE_CTOR) {
|
||||
FunctionFlags flags = FunctionFlags::NATIVE_CTOR) {
|
||||
MOZ_ASSERT(native);
|
||||
MOZ_ASSERT(flags & JSFunction::NATIVE_CTOR);
|
||||
MOZ_ASSERT(flags.isNativeConstructor());
|
||||
return NewFunctionWithProto(cx, native, nargs, flags, nullptr, atom, nullptr,
|
||||
allocKind, newKind);
|
||||
}
|
||||
|
@ -935,7 +1062,7 @@ inline JSFunction* NewNativeConstructor(
|
|||
// global will be used. In all cases the parent of the resulting object will be
|
||||
// the global.
|
||||
extern JSFunction* NewScriptedFunction(
|
||||
JSContext* cx, unsigned nargs, JSFunction::Flags flags, HandleAtom atom,
|
||||
JSContext* cx, unsigned nargs, FunctionFlags flags, HandleAtom atom,
|
||||
HandleObject proto = nullptr,
|
||||
gc::AllocKind allocKind = gc::AllocKind::FUNCTION,
|
||||
NewObjectKind newKind = GenericObject, HandleObject enclosingEnv = nullptr);
|
||||
|
|
|
@ -2330,12 +2330,13 @@ JSProtoKey JS::IdentifyStandardInstanceOrPrototype(JSObject* obj) {
|
|||
}
|
||||
|
||||
JSProtoKey JS::IdentifyStandardConstructor(JSObject* obj) {
|
||||
// Note that NATIVE_CTOR does not imply that we are a standard constructor,
|
||||
// but the converse is true (at least until we start having self-hosted
|
||||
// constructors for standard classes). This lets us avoid a costly loop for
|
||||
// many functions (which, depending on the call site, may be the common case).
|
||||
// Note that isNativeConstructor does not imply that we are a standard
|
||||
// constructor, but the converse is true (at least until we start having
|
||||
// self-hosted constructors for standard classes). This lets us avoid a costly
|
||||
// loop for many functions (which, depending on the call site, may be the
|
||||
// common case).
|
||||
if (!obj->is<JSFunction>() ||
|
||||
!(obj->as<JSFunction>().flags() & JSFunction::NATIVE_CTOR)) {
|
||||
!(obj->as<JSFunction>().flags().isNativeConstructor())) {
|
||||
return JSProto_Null;
|
||||
}
|
||||
|
||||
|
|
|
@ -296,7 +296,7 @@ static XDRResult XDRRelazificationInfo(XDRState<mode>* xdr, HandleFunction fun,
|
|||
// relazify scripts with inner functions. See
|
||||
// JSFunction::createScriptForLazilyInterpretedFunction.
|
||||
MOZ_ASSERT(lazy->numInnerFunctions() == 0);
|
||||
if (fun->kind() == JSFunction::FunctionKind::ClassConstructor) {
|
||||
if (fun->kind() == FunctionFlags::FunctionKind::ClassConstructor) {
|
||||
numFieldInitializers =
|
||||
(uint32_t)lazy->getFieldInitializers().numFieldInitializers;
|
||||
} else {
|
||||
|
@ -1253,7 +1253,7 @@ XDRResult js::XDRLazyScript(XDRState<mode>* xdr, HandleScope enclosingScope,
|
|||
lineno = lazy->lineno();
|
||||
column = lazy->column();
|
||||
immutableFlags = lazy->immutableFlags();
|
||||
if (fun->kind() == JSFunction::FunctionKind::ClassConstructor) {
|
||||
if (fun->kind() == FunctionFlags::FunctionKind::ClassConstructor) {
|
||||
numFieldInitializers =
|
||||
(uint32_t)lazy->getFieldInitializers().numFieldInitializers;
|
||||
} else {
|
||||
|
@ -4529,13 +4529,13 @@ static JSObject* CloneInnerInterpretedFunction(
|
|||
}
|
||||
|
||||
gc::AllocKind allocKind = srcFun->getAllocKind();
|
||||
uint16_t flags = srcFun->flags();
|
||||
FunctionFlags flags = srcFun->flags();
|
||||
if (srcFun->isSelfHostedBuiltin()) {
|
||||
// Functions in the self-hosting compartment are only extended in
|
||||
// debug mode. For top-level functions, FUNCTION_EXTENDED gets used by
|
||||
// the cloning algorithm. Do the same for inner functions here.
|
||||
allocKind = gc::AllocKind::FUNCTION_EXTENDED;
|
||||
flags |= JSFunction::Flags::EXTENDED;
|
||||
flags.setIsExtended();
|
||||
}
|
||||
RootedAtom atom(cx, srcFun->displayAtom());
|
||||
if (atom) {
|
||||
|
@ -4543,8 +4543,8 @@ static JSObject* CloneInnerInterpretedFunction(
|
|||
}
|
||||
RootedFunction clone(
|
||||
cx, NewFunctionWithProto(cx, nullptr, srcFun->nargs(),
|
||||
JSFunction::Flags(flags), nullptr, atom,
|
||||
cloneProto, allocKind, TenuredObject));
|
||||
flags, nullptr, atom, cloneProto,
|
||||
allocKind, TenuredObject));
|
||||
if (!clone) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -4791,7 +4791,7 @@ JSScript* js::CloneScriptIntoFunction(
|
|||
}
|
||||
|
||||
// Save flags in case we need to undo the early mutations.
|
||||
const int preservedFlags = fun->flags();
|
||||
const FunctionFlags preservedFlags = fun->flags();
|
||||
RootedScript dst(cx, detail::CopyScript(cx, src, sourceObject, &scopes));
|
||||
if (!dst) {
|
||||
fun->setFlags(preservedFlags);
|
||||
|
|
|
@ -975,7 +975,7 @@ static bool intrinsic_SetCanonicalName(JSContext* cx, unsigned argc,
|
|||
}
|
||||
|
||||
// _SetCanonicalName can only be called on top-level function declarations.
|
||||
MOZ_ASSERT(fun->kind() == JSFunction::NormalFunction);
|
||||
MOZ_ASSERT(fun->kind() == FunctionFlags::NormalFunction);
|
||||
MOZ_ASSERT(!fun->isLambda());
|
||||
|
||||
// It's an error to call _SetCanonicalName multiple times.
|
||||
|
@ -3002,7 +3002,7 @@ static JSObject* CloneObject(JSContext* cx,
|
|||
// Arrow functions use the first extended slot for their lexical |this|
|
||||
// value. And methods use the first extended slot for their home-object.
|
||||
// We only expect to see normal functions here.
|
||||
MOZ_ASSERT(selfHostedFunction->kind() == JSFunction::NormalFunction);
|
||||
MOZ_ASSERT(selfHostedFunction->kind() == FunctionFlags::NormalFunction);
|
||||
js::gc::AllocKind kind = hasName ? gc::AllocKind::FUNCTION_EXTENDED
|
||||
: selfHostedFunction->getAllocKind();
|
||||
|
||||
|
@ -3132,7 +3132,7 @@ bool JSRuntime::createLazySelfHostedFunctionClone(
|
|||
funName = selfHostedFun->explicitName();
|
||||
}
|
||||
|
||||
fun.set(NewScriptedFunction(cx, nargs, JSFunction::INTERPRETED, funName,
|
||||
fun.set(NewScriptedFunction(cx, nargs, FunctionFlags::INTERPRETED, funName,
|
||||
proto, gc::AllocKind::FUNCTION_EXTENDED,
|
||||
newKind));
|
||||
if (!fun) {
|
||||
|
@ -3188,7 +3188,7 @@ bool JSRuntime::cloneSelfHostedFunctionScript(JSContext* cx,
|
|||
MOZ_ASSERT(targetFun->strict(), "Self-hosted builtins must be strict");
|
||||
|
||||
// The target function might have been relazified after its flags changed.
|
||||
targetFun->setFlags(targetFun->flags() | sourceFun->flags());
|
||||
targetFun->setFlags(targetFun->flags().toRaw() | sourceFun->flags().toRaw());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -1217,8 +1217,8 @@ bool FrameIter::matchCallee(JSContext* cx, HandleFunction fun) const {
|
|||
// As we do not know if the calleeTemplate is the real function, or the
|
||||
// template from which it would be cloned, we compare properties which are
|
||||
// stable across the cloning of JSFunctions.
|
||||
if (((currentCallee->flags() ^ fun->flags()) &
|
||||
JSFunction::STABLE_ACROSS_CLONES) != 0 ||
|
||||
if (((currentCallee->flags().toRaw() ^ fun->flags().toRaw()) &
|
||||
FunctionFlags::STABLE_ACROSS_CLONES) != 0 ||
|
||||
currentCallee->nargs() != fun->nargs()) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -353,10 +353,10 @@ class TypedArrayObjectTemplate : public TypedArrayObject {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
JSFunction* fun =
|
||||
NewFunctionWithProto(cx, class_constructor, 3, JSFunction::NATIVE_CTOR,
|
||||
nullptr, ClassName(key, cx), ctorProto,
|
||||
gc::AllocKind::FUNCTION, SingletonObject);
|
||||
JSFunction* fun = NewFunctionWithProto(
|
||||
cx, class_constructor, 3, FunctionFlags::NATIVE_CTOR, nullptr,
|
||||
ClassName(key, cx), ctorProto, gc::AllocKind::FUNCTION,
|
||||
SingletonObject);
|
||||
|
||||
if (fun) {
|
||||
fun->setJitInfo(&jit::JitInfo_TypedArrayConstructor);
|
||||
|
|
|
@ -1433,7 +1433,7 @@ class MOZ_STACK_CLASS JS_HAZ_ROOTED ModuleValidatorShared {
|
|||
MOZ_MUST_USE bool initDummyFunction() {
|
||||
// This flows into FunctionBox, so must be tenured.
|
||||
dummyFunction_ = NewScriptedFunction(
|
||||
cx_, 0, JSFunction::INTERPRETED, nullptr,
|
||||
cx_, 0, FunctionFlags::INTERPRETED, nullptr,
|
||||
/* proto = */ nullptr, gc::AllocKind::FUNCTION, TenuredObject);
|
||||
if (!dummyFunction_) {
|
||||
return false;
|
||||
|
@ -6905,7 +6905,7 @@ static bool HandleInstantiationFailure(JSContext* cx, CallArgs args,
|
|||
}
|
||||
|
||||
RootedFunction fun(
|
||||
cx, NewScriptedFunction(cx, 0, JSFunction::INTERPRETED_NORMAL, name,
|
||||
cx, NewScriptedFunction(cx, 0, FunctionFlags::INTERPRETED_NORMAL, name,
|
||||
/* proto = */ nullptr, gc::AllocKind::FUNCTION,
|
||||
TenuredObject));
|
||||
if (!fun) {
|
||||
|
@ -6982,8 +6982,8 @@ static JSFunction* NewAsmJSModuleFunction(JSContext* cx, JSFunction* origFun,
|
|||
HandleObject moduleObj) {
|
||||
RootedAtom name(cx, origFun->explicitName());
|
||||
|
||||
JSFunction::Flags flags = origFun->isLambda() ? JSFunction::ASMJS_LAMBDA_CTOR
|
||||
: JSFunction::ASMJS_CTOR;
|
||||
FunctionFlags flags = origFun->isLambda() ? FunctionFlags::ASMJS_LAMBDA_CTOR
|
||||
: FunctionFlags::ASMJS_CTOR;
|
||||
JSFunction* moduleFun = NewNativeConstructor(
|
||||
cx, InstantiateAsmJS, origFun->nargs(), name,
|
||||
gc::AllocKind::FUNCTION_EXTENDED, TenuredObject, flags);
|
||||
|
@ -7147,7 +7147,7 @@ bool js::IsAsmJSModule(JSFunction* fun) {
|
|||
}
|
||||
|
||||
bool js::IsAsmJSFunction(JSFunction* fun) {
|
||||
return fun->kind() == JSFunction::AsmJS;
|
||||
return fun->kind() == FunctionFlags::AsmJS;
|
||||
}
|
||||
|
||||
bool js::IsAsmJSStrictModeModuleOrFunction(JSFunction* fun) {
|
||||
|
|
|
@ -1456,7 +1456,7 @@ bool WasmInstanceObject::getExportedFunction(
|
|||
}
|
||||
fun.set(NewNativeConstructor(cx, WasmCall, numArgs, name,
|
||||
gc::AllocKind::FUNCTION_EXTENDED,
|
||||
SingletonObject, JSFunction::ASMJS_CTOR));
|
||||
SingletonObject, FunctionFlags::ASMJS_CTOR));
|
||||
if (!fun) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1471,7 +1471,7 @@ bool WasmInstanceObject::getExportedFunction(
|
|||
|
||||
fun.set(NewNativeFunction(cx, WasmCall, numArgs, name,
|
||||
gc::AllocKind::FUNCTION_EXTENDED, SingletonObject,
|
||||
JSFunction::WASM));
|
||||
FunctionFlags::WASM));
|
||||
if (!fun) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1558,7 +1558,7 @@ WasmFunctionScope* WasmInstanceObject::getFunctionScope(
|
|||
}
|
||||
|
||||
bool wasm::IsWasmExportedFunction(JSFunction* fun) {
|
||||
return fun->kind() == JSFunction::Wasm;
|
||||
return fun->kind() == FunctionFlags::Wasm;
|
||||
}
|
||||
|
||||
bool wasm::CheckFuncRefValue(JSContext* cx, HandleValue v,
|
||||
|
@ -1589,8 +1589,8 @@ Instance& wasm::ExportedFunctionToInstance(JSFunction* fun) {
|
|||
}
|
||||
|
||||
WasmInstanceObject* wasm::ExportedFunctionToInstanceObject(JSFunction* fun) {
|
||||
MOZ_ASSERT(fun->kind() == JSFunction::Wasm ||
|
||||
fun->kind() == JSFunction::AsmJS);
|
||||
MOZ_ASSERT(fun->kind() == FunctionFlags::Wasm ||
|
||||
fun->kind() == FunctionFlags::AsmJS);
|
||||
const Value& v = fun->getExtendedSlot(FunctionExtended::WASM_INSTANCE_SLOT);
|
||||
return &v.toObject().as<WasmInstanceObject>();
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче