Bug 1890750 - Part 1: Include NATIVE_JIT_ENTRY in FunctionFlags::HasJitEntryFlags...
[gecko.git] / js / src / vm / FunctionFlags.h
blobd85b8c408538f85cadebfa1ef75179c240d1fa5a
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=8 sts=2 et sw=2 tw=80:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef vm_FunctionFlags_h
8 #define vm_FunctionFlags_h
10 #include "mozilla/Assertions.h" // MOZ_ASSERT, MOZ_ASSERT_IF
11 #include "mozilla/Attributes.h" // MOZ_IMPLICIT
13 #include <stdint.h> // uint8_t, uint16_t
15 #include "jstypes.h" // JS_PUBLIC_API
17 class JS_PUBLIC_API JSAtom;
19 namespace js {
21 class FunctionFlags {
22 public:
23 // Syntactic characteristics of a function.
24 enum FunctionKind : uint8_t {
25 // Regular function that doesn't match any of the other kinds.
27 // This kind is used by the following scipted functions:
28 // * FunctionDeclaration
29 // * FunctionExpression
30 // * Function created from Function() call or its variants
32 // Also all native functions excluding AsmJS and Wasm use this kind.
33 NormalFunction = 0,
35 // ES6 '(args) => body' syntax.
36 // This kind is used only by scripted function.
37 Arrow,
39 // ES6 MethodDefinition syntax.
40 // This kind is used only by scripted function.
41 Method,
43 // Class constructor syntax, or default constructor.
44 // This kind is used only by scripted function and default constructor.
46 // WARNING: This is independent from Flags::CONSTRUCTOR.
47 ClassConstructor,
49 // Getter and setter syntax in objects or classes, or
50 // native getter and setter created from JSPropertySpec.
51 // This kind is used both by scripted functions and native functions.
52 Getter,
53 Setter,
55 // An asm.js module or exported function.
57 // This kind is used only by scripted function, and used only when the
58 // asm.js module is created.
60 // "use asm" directive itself doesn't necessarily imply this kind.
61 // e.g. arrow function with "use asm" becomes Arrow kind,
63 // See EstablishPreconditions in js/src/wasm/AsmJS.cpp
64 AsmJS,
66 // An exported WebAssembly function.
67 Wasm,
69 FunctionKindLimit
72 enum Flags : uint16_t {
73 // FunctionKind enum value.
74 FUNCTION_KIND_SHIFT = 0,
75 FUNCTION_KIND_MASK = 0x0007,
77 // The AllocKind used was FunctionExtended and extra slots were allocated.
78 // These slots may be used by the engine or the embedding so care must be
79 // taken to avoid conflicts.
81 // This flag is used both by scripted functions and native functions.
82 EXTENDED = 1 << 3,
84 // Set if function is a self-hosted builtin or intrinsic. An 'intrinsic'
85 // here means a native function used inside self-hosted code. In general, a
86 // self-hosted function should appear to script as though it were a native
87 // builtin.
88 SELF_HOSTED = 1 << 4,
90 // An interpreted function has or may-have bytecode and an environment. Only
91 // one of these flags may be used at a time. As a memory optimization, the
92 // SELFHOSTLAZY flag indicates there is no js::BaseScript at all and we must
93 // clone from the self-hosted realm in order to get bytecode.
94 BASESCRIPT = 1 << 5,
95 SELFHOSTLAZY = 1 << 6,
97 // Function may be called as a constructor. This corresponds in the spec as
98 // having a [[Construct]] internal method.
100 // e.g. FunctionDeclaration has this flag, but GeneratorDeclaration doesn't
101 // have this flag.
103 // This flag is used both by scripted functions and native functions.
105 // WARNING: This is independent from FunctionKind::ClassConstructor.
106 CONSTRUCTOR = 1 << 7,
108 // Function is either getter or setter, with "get " or "set " prefix,
109 // but JSFunction::AtomSlot contains unprefixed name, and the function name
110 // is lazily constructed on the first access.
111 LAZY_ACCESSOR_NAME = 1 << 8,
113 // Function comes from a FunctionExpression, ArrowFunction, or Function()
114 // call (not a FunctionDeclaration).
116 // This flag is used only by scripted functions and AsmJS.
117 LAMBDA = 1 << 9,
119 // This Native function has a JIT entry which emulates the
120 // js::BaseScript::jitCodeRaw mechanism. Used for Wasm functions and
121 // TrampolineNative builtins.
122 NATIVE_JIT_ENTRY = 1 << 10,
124 // Function had no explicit name, but a name was set by SetFunctionName at
125 // compile time or SetFunctionName at runtime.
127 // This flag can be used both by scripted functions and native functions.
128 HAS_INFERRED_NAME = 1 << 11,
130 // Function had no explicit name, but a name was guessed for it anyway.
132 // This flag is used only by scripted function.
133 HAS_GUESSED_ATOM = 1 << 12,
135 // The 'length' or 'name property has been resolved. See fun_resolve.
137 // These flags are used both by scripted functions and native functions.
138 RESOLVED_NAME = 1 << 13,
139 RESOLVED_LENGTH = 1 << 14,
141 // This function is kept only for skipping it over during delazification.
143 // This function is inside arrow function's parameter expression, and
144 // parsed twice, once before finding "=>" token, and once after finding
145 // "=>" and rewinding to the beginning of the parameters.
146 // ScriptStencil is created for both case, and the first one is kept only
147 // for delazification, to make sure delazification sees the same sequence
148 // of inner function to skip over.
150 // We call the first one "ghost".
151 // It should be kept lazy, and shouldn't be exposed to debugger.
153 // This flag is used only by scripted functions.
154 GHOST_FUNCTION = 1 << 15,
156 // Shifted form of FunctionKinds.
157 NORMAL_KIND = NormalFunction << FUNCTION_KIND_SHIFT,
158 ASMJS_KIND = AsmJS << FUNCTION_KIND_SHIFT,
159 WASM_KIND = Wasm << FUNCTION_KIND_SHIFT,
160 ARROW_KIND = Arrow << FUNCTION_KIND_SHIFT,
161 METHOD_KIND = Method << FUNCTION_KIND_SHIFT,
162 CLASSCONSTRUCTOR_KIND = ClassConstructor << FUNCTION_KIND_SHIFT,
163 GETTER_KIND = Getter << FUNCTION_KIND_SHIFT,
164 SETTER_KIND = Setter << FUNCTION_KIND_SHIFT,
166 // Derived Flags combinations to use when creating functions.
167 NATIVE_FUN = NORMAL_KIND,
168 NATIVE_CTOR = CONSTRUCTOR | NORMAL_KIND,
169 NATIVE_GETTER_WITH_LAZY_NAME = LAZY_ACCESSOR_NAME | GETTER_KIND,
170 NATIVE_SETTER_WITH_LAZY_NAME = LAZY_ACCESSOR_NAME | SETTER_KIND,
171 ASMJS_CTOR = CONSTRUCTOR | ASMJS_KIND,
172 ASMJS_LAMBDA_CTOR = CONSTRUCTOR | LAMBDA | ASMJS_KIND,
173 WASM = WASM_KIND,
174 INTERPRETED_NORMAL = BASESCRIPT | CONSTRUCTOR | NORMAL_KIND,
175 INTERPRETED_CLASS_CTOR = BASESCRIPT | CONSTRUCTOR | CLASSCONSTRUCTOR_KIND,
176 INTERPRETED_GENERATOR_OR_ASYNC = BASESCRIPT | NORMAL_KIND,
177 INTERPRETED_LAMBDA = BASESCRIPT | LAMBDA | CONSTRUCTOR | NORMAL_KIND,
178 INTERPRETED_LAMBDA_ARROW = BASESCRIPT | LAMBDA | ARROW_KIND,
179 INTERPRETED_LAMBDA_GENERATOR_OR_ASYNC = BASESCRIPT | LAMBDA | NORMAL_KIND,
180 INTERPRETED_GETTER = BASESCRIPT | GETTER_KIND,
181 INTERPRETED_SETTER = BASESCRIPT | SETTER_KIND,
182 INTERPRETED_METHOD = BASESCRIPT | METHOD_KIND,
184 // Flags that XDR ignores. See also: js::BaseScript::MutableFlags.
185 MUTABLE_FLAGS = RESOLVED_NAME | RESOLVED_LENGTH,
187 // Flags preserved when cloning a function.
188 STABLE_ACROSS_CLONES =
189 CONSTRUCTOR | LAMBDA | SELF_HOSTED | FUNCTION_KIND_MASK | GHOST_FUNCTION
192 uint16_t flags_;
194 public:
195 FunctionFlags() : flags_() {
196 static_assert(sizeof(FunctionFlags) == sizeof(flags_),
197 "No extra members allowed is it'll grow JSFunction");
198 static_assert(offsetof(FunctionFlags, flags_) == 0,
199 "Required for JIT flag access");
202 explicit FunctionFlags(uint16_t flags) : flags_(flags) {}
203 MOZ_IMPLICIT FunctionFlags(Flags f) : flags_(f) {}
205 static_assert(((FunctionKindLimit - 1) << FUNCTION_KIND_SHIFT) <=
206 FUNCTION_KIND_MASK,
207 "FunctionKind doesn't fit into flags_");
209 uint16_t toRaw() const { return flags_; }
211 uint16_t stableAcrossClones() const { return flags_ & STABLE_ACROSS_CLONES; }
213 // For flag combinations the type is int.
214 bool hasFlags(uint16_t flags) const { return flags_ & flags; }
215 FunctionFlags& setFlags(uint16_t flags) {
216 flags_ |= flags;
217 return *this;
219 FunctionFlags& clearFlags(uint16_t flags) {
220 flags_ &= ~flags;
221 return *this;
223 FunctionFlags& setFlags(uint16_t flags, bool set) {
224 if (set) {
225 setFlags(flags);
226 } else {
227 clearFlags(flags);
229 return *this;
232 FunctionKind kind() const {
233 return static_cast<FunctionKind>((flags_ & FUNCTION_KIND_MASK) >>
234 FUNCTION_KIND_SHIFT);
237 #ifdef DEBUG
238 void assertFunctionKindIntegrity() {
239 switch (kind()) {
240 case FunctionKind::NormalFunction:
241 MOZ_ASSERT(!hasFlags(LAZY_ACCESSOR_NAME));
242 MOZ_ASSERT(!hasFlags(NATIVE_JIT_ENTRY));
243 break;
245 case FunctionKind::Arrow:
246 MOZ_ASSERT(hasFlags(BASESCRIPT) || hasFlags(SELFHOSTLAZY));
247 MOZ_ASSERT(!hasFlags(CONSTRUCTOR));
248 MOZ_ASSERT(!hasFlags(LAZY_ACCESSOR_NAME));
249 MOZ_ASSERT(hasFlags(LAMBDA));
250 MOZ_ASSERT(!hasFlags(NATIVE_JIT_ENTRY));
251 break;
252 case FunctionKind::Method:
253 MOZ_ASSERT(hasFlags(BASESCRIPT) || hasFlags(SELFHOSTLAZY));
254 MOZ_ASSERT(!hasFlags(CONSTRUCTOR));
255 MOZ_ASSERT(!hasFlags(LAZY_ACCESSOR_NAME));
256 MOZ_ASSERT(!hasFlags(LAMBDA));
257 MOZ_ASSERT(!hasFlags(NATIVE_JIT_ENTRY));
258 break;
259 case FunctionKind::ClassConstructor:
260 MOZ_ASSERT(hasFlags(BASESCRIPT) || hasFlags(SELFHOSTLAZY));
261 MOZ_ASSERT(hasFlags(CONSTRUCTOR));
262 MOZ_ASSERT(!hasFlags(LAZY_ACCESSOR_NAME));
263 MOZ_ASSERT(!hasFlags(LAMBDA));
264 MOZ_ASSERT(!hasFlags(NATIVE_JIT_ENTRY));
265 break;
266 case FunctionKind::Getter:
267 MOZ_ASSERT(!hasFlags(CONSTRUCTOR));
268 MOZ_ASSERT(!hasFlags(LAMBDA));
269 MOZ_ASSERT(!hasFlags(NATIVE_JIT_ENTRY));
270 break;
271 case FunctionKind::Setter:
272 MOZ_ASSERT(!hasFlags(CONSTRUCTOR));
273 MOZ_ASSERT(!hasFlags(LAMBDA));
274 MOZ_ASSERT(!hasFlags(NATIVE_JIT_ENTRY));
275 break;
277 case FunctionKind::AsmJS:
278 MOZ_ASSERT(!hasFlags(BASESCRIPT));
279 MOZ_ASSERT(!hasFlags(SELFHOSTLAZY));
280 MOZ_ASSERT(!hasFlags(LAZY_ACCESSOR_NAME));
281 MOZ_ASSERT(!hasFlags(NATIVE_JIT_ENTRY));
282 break;
283 case FunctionKind::Wasm:
284 MOZ_ASSERT(!hasFlags(BASESCRIPT));
285 MOZ_ASSERT(!hasFlags(SELFHOSTLAZY));
286 MOZ_ASSERT(!hasFlags(CONSTRUCTOR));
287 MOZ_ASSERT(!hasFlags(LAZY_ACCESSOR_NAME));
288 MOZ_ASSERT(!hasFlags(LAMBDA));
289 break;
290 default:
291 break;
294 #endif
296 /* A function can be classified as either native (C++) or interpreted (JS): */
297 bool isInterpreted() const {
298 return hasFlags(BASESCRIPT) || hasFlags(SELFHOSTLAZY);
300 bool isNativeFun() const { return !isInterpreted(); }
302 bool isConstructor() const { return hasFlags(CONSTRUCTOR); }
304 bool isNonBuiltinConstructor() const {
305 // Note: keep this in sync with branchIfNotFunctionIsNonBuiltinCtor in
306 // MacroAssembler.cpp.
307 return hasFlags(BASESCRIPT) && hasFlags(CONSTRUCTOR) &&
308 !hasFlags(SELF_HOSTED);
311 /* Possible attributes of a native function: */
312 bool isAsmJSNative() const {
313 MOZ_ASSERT_IF(kind() == AsmJS, isNativeFun());
314 return kind() == AsmJS;
316 bool isWasm() const {
317 MOZ_ASSERT_IF(kind() == Wasm, isNativeFun());
318 return kind() == Wasm;
320 bool isNativeWithJitEntry() const {
321 MOZ_ASSERT_IF(hasFlags(NATIVE_JIT_ENTRY), isNativeFun());
322 return hasFlags(NATIVE_JIT_ENTRY);
324 bool isWasmWithJitEntry() const { return isWasm() && isNativeWithJitEntry(); }
325 bool isNativeWithoutJitEntry() const {
326 MOZ_ASSERT_IF(!hasJitEntry(), isNativeFun());
327 return !hasJitEntry();
329 bool isBuiltinNative() const {
330 return isNativeFun() && !isAsmJSNative() && !isWasm();
332 bool hasJitEntry() const {
333 return hasBaseScript() || hasSelfHostedLazyScript() ||
334 isNativeWithJitEntry();
337 bool canHaveJitInfo() const {
338 // A native builtin can have a pointer to either its JitEntry or JSJitInfo,
339 // but not both.
340 return isBuiltinNative() && !isNativeWithJitEntry();
343 /* Possible attributes of an interpreted function: */
344 bool hasInferredName() const { return hasFlags(HAS_INFERRED_NAME); }
345 bool hasGuessedAtom() const { return hasFlags(HAS_GUESSED_ATOM); }
346 bool isLambda() const { return hasFlags(LAMBDA); }
348 bool isNamedLambda(bool hasName) const {
349 return hasName && isLambda() && !hasInferredName() && !hasGuessedAtom();
352 // These methods determine which of the u.scripted.s union arms are active.
353 // For live JSFunctions the pointer values will always be non-null, but due
354 // to partial initialization the GC (and other features that scan the heap
355 // directly) may still return a null pointer.
356 bool hasBaseScript() const { return hasFlags(BASESCRIPT); }
357 bool hasSelfHostedLazyScript() const { return hasFlags(SELFHOSTLAZY); }
359 // Arrow functions store their lexical new.target in the first extended slot.
360 bool isArrow() const { return kind() == Arrow; }
361 // Every class-constructor is also a method.
362 bool isMethod() const {
363 return kind() == Method || kind() == ClassConstructor;
365 bool isClassConstructor() const { return kind() == ClassConstructor; }
367 bool isGetter() const { return kind() == Getter; }
368 bool isSetter() const { return kind() == Setter; }
370 bool isAccessorWithLazyName() const { return hasFlags(LAZY_ACCESSOR_NAME); }
372 bool allowSuperProperty() const {
373 return isMethod() || isGetter() || isSetter();
376 bool hasResolvedLength() const { return hasFlags(RESOLVED_LENGTH); }
377 bool hasResolvedName() const { return hasFlags(RESOLVED_NAME); }
379 bool isSelfHostedOrIntrinsic() const { return hasFlags(SELF_HOSTED); }
380 bool isSelfHostedBuiltin() const {
381 return isSelfHostedOrIntrinsic() && !isNativeFun();
383 bool isIntrinsic() const {
384 return isSelfHostedOrIntrinsic() && isNativeFun();
387 FunctionFlags& setKind(FunctionKind kind) {
388 this->flags_ &= ~FUNCTION_KIND_MASK;
389 this->flags_ |= static_cast<uint16_t>(kind) << FUNCTION_KIND_SHIFT;
390 return *this;
393 // Make the function constructible.
394 FunctionFlags& setIsConstructor() {
395 MOZ_ASSERT(!isConstructor());
396 MOZ_ASSERT(isSelfHostedBuiltin());
397 return setFlags(CONSTRUCTOR);
400 FunctionFlags& setIsSelfHostedBuiltin() {
401 MOZ_ASSERT(isInterpreted());
402 MOZ_ASSERT(!isSelfHostedBuiltin());
403 setFlags(SELF_HOSTED);
404 // Self-hosted functions should not be constructable.
405 return clearFlags(CONSTRUCTOR);
407 FunctionFlags& setIsIntrinsic() {
408 MOZ_ASSERT(isNativeFun());
409 MOZ_ASSERT(!isIntrinsic());
410 return setFlags(SELF_HOSTED);
413 FunctionFlags& setResolvedLength() { return setFlags(RESOLVED_LENGTH); }
414 FunctionFlags& setResolvedName() { return setFlags(RESOLVED_NAME); }
416 FunctionFlags& setInferredName() { return setFlags(HAS_INFERRED_NAME); }
418 FunctionFlags& setGuessedAtom() { return setFlags(HAS_GUESSED_ATOM); }
420 FunctionFlags& setSelfHostedLazy() { return setFlags(SELFHOSTLAZY); }
421 FunctionFlags& clearSelfHostedLazy() { return clearFlags(SELFHOSTLAZY); }
422 FunctionFlags& setBaseScript() { return setFlags(BASESCRIPT); }
423 FunctionFlags& clearBaseScript() { return clearFlags(BASESCRIPT); }
425 FunctionFlags& clearLazyAccessorName() {
426 return clearFlags(LAZY_ACCESSOR_NAME);
429 FunctionFlags& setNativeJitEntry() { return setFlags(NATIVE_JIT_ENTRY); }
431 bool isExtended() const { return hasFlags(EXTENDED); }
432 FunctionFlags& setIsExtended() { return setFlags(EXTENDED); }
434 bool isNativeConstructor() const { return hasFlags(NATIVE_CTOR); }
436 FunctionFlags& setIsGhost() { return setFlags(GHOST_FUNCTION); }
437 bool isGhost() const { return hasFlags(GHOST_FUNCTION); }
439 static constexpr uint16_t HasJitEntryFlags() {
440 return BASESCRIPT | SELFHOSTLAZY | NATIVE_JIT_ENTRY;
443 static FunctionFlags clearMutableflags(FunctionFlags flags) {
444 return FunctionFlags(flags.toRaw() & ~FunctionFlags::MUTABLE_FLAGS);
448 } /* namespace js */
450 #endif /* vm_FunctionFlags_h */