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:
Matthew Gaudet 2019-07-31 19:30:27 +00:00
Родитель 026ae43909
Коммит f94b0ec315
31 изменённых файлов: 408 добавлений и 270 удалений

Просмотреть файл

@ -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, &notArrow);
masm.branchFunctionKind(Assembler::NotEqual,
FunctionFlags::FunctionKind::Arrow, scratch1,
scratch2, &notArrow);
{
// 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),
&notBoundTarget);
{
// 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>();
}