Bug 1865597 - Add error checking when initializing parallel marking and disable on...
[gecko.git] / js / src / frontend / BytecodeEmitter.h
blobb6435390e18d3338c1c095cef09b1b865e6c4247
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 /* JS bytecode generation. */
9 #ifndef frontend_BytecodeEmitter_h
10 #define frontend_BytecodeEmitter_h
12 #include "mozilla/Assertions.h" // MOZ_ASSERT
13 #include "mozilla/Attributes.h" // MOZ_STACK_CLASS, MOZ_ALWAYS_INLINE, MOZ_NEVER_INLINE, MOZ_RAII
14 #include "mozilla/Maybe.h" // mozilla::Maybe, mozilla::Some
15 #include "mozilla/Saturate.h" // mozilla::SaturateUint8
16 #include "mozilla/Span.h" // mozilla::Span
18 #include <stddef.h> // ptrdiff_t
19 #include <stdint.h> // uint16_t, uint32_t
21 #include "frontend/AbstractScopePtr.h" // ScopeIndex
22 #include "frontend/BytecodeSection.h" // BytecodeSection, PerScriptData, GCThingList
23 #include "frontend/DestructuringFlavor.h" // DestructuringFlavor
24 #include "frontend/EitherParser.h" // EitherParser
25 #include "frontend/IteratorKind.h" // IteratorKind
26 #include "frontend/JumpList.h" // JumpList, JumpTarget
27 #include "frontend/NameAnalysisTypes.h" // NameLocation
28 #include "frontend/NameCollections.h" // AtomIndexMap
29 #include "frontend/ParseNode.h" // ParseNode and subclasses
30 #include "frontend/Parser.h" // Parser, PropListType
31 #include "frontend/ParserAtom.h" // TaggedParserAtomIndex, ParserAtom
32 #include "frontend/ScriptIndex.h" // ScriptIndex
33 #include "frontend/SelfHostedIter.h" // SelfHostedIter
34 #include "frontend/SourceNotes.h" // SrcNoteType
35 #include "frontend/ValueUsage.h" // ValueUsage
36 #include "js/AllocPolicy.h" // ReportOutOfMemory
37 #include "js/ColumnNumber.h" // JS::LimitedColumnNumberOneOrigin
38 #include "js/TypeDecls.h" // jsbytecode
39 #include "vm/BuiltinObjectKind.h" // BuiltinObjectKind
40 #include "vm/CheckIsObjectKind.h" // CheckIsObjectKind
41 #include "vm/CompletionKind.h" // CompletionKind
42 #include "vm/FunctionPrefixKind.h" // FunctionPrefixKind
43 #include "vm/GeneratorResumeKind.h" // GeneratorResumeKind
44 #include "vm/Opcodes.h" // JSOp
45 #include "vm/SharedStencil.h" // GCThingIndex, MemberInitializers
46 #include "vm/StencilEnums.h" // TryNoteKind
47 #include "vm/ThrowMsgKind.h" // ThrowMsgKind, ThrowCondition
49 namespace js {
51 class FrontendContext;
53 namespace frontend {
55 class BytecodeOffset;
56 class CallOrNewEmitter;
57 class ClassEmitter;
58 class ElemOpEmitter;
59 class EmitterScope;
60 class ErrorReporter;
61 class FullParseHandler;
62 class NestableControl;
63 class PrivateOpEmitter;
64 class PropertyEmitter;
65 class PropOpEmitter;
66 class OptionalEmitter;
67 class SharedContext;
68 class TDZCheckCache;
69 class TryEmitter;
71 struct TokenPos;
73 enum class ValueIsOnStack { Yes, No };
75 // [SMDOC] Bytecode emission
77 // Bytecode emitter class and helper classes for generating bytecode and related
78 // stencil data from AST generated by JS parser.
81 // BytecodeEmitter
82 // ---------------
84 // BytecodeEmitter receives an AST, and utilizes helper classes to generate the
85 // bytecode sequence, and related stencil data.
87 // BytecodeEmitter can be nested, in order to emit inner non-lazy function
88 // scripts.
91 // Bytecode structures
92 // -------------------
94 // While bytecode is being emitted, it is separated into 2 parts, the prologue
95 // and the main part. The prologue part contains instantiation of the declared
96 // variables, functions, and special names in function. The main part contains
97 // the remaining part of the bytecode.
99 // The generated bytecode is stored into the following 2 classes, before
100 // converting them into stencil data (See ImmutableScriptData and
101 // BytecodeEmitter::createImmutableScriptData):
103 // * BytecodeSection
104 // * PerScriptData
106 // BytecodeSection stores the bytecode sequence and data directly associated
107 // with opcode or index inside the bytecode sequence.
109 // PerScriptData contains data referred from the bytecode, that is mostly the
110 // list of GC things.
113 // Bindings
114 // --------
116 // # Scope and bindings
118 // When emitting AST node that's associated with a given scope, EmitterScope is
119 // allocated to store/cache the bindings information.
121 // This information is used when emitting an opcode that accesses bindings, to
122 // determine where the binding is stored, and how the binding should be
123 // accessed, including which opcode to use and what operand to use for it.
126 // # Temporal Dead Zone (TDZ) check cache
128 // The spec requires TDZ check for all lexical variable access, but emitting
129 // TDZ check for all operation increases the bytecode size and affects the
130 // performance. TDZCheckCache is a cache to optimize away unnecessary TDZ check
131 // operations.
133 // See comments for TDZCheckCache for more details.
136 // Control structures
137 // ------------------
139 // # Jump list
141 // When emitting jump-related bytecode (if-else, break/continue, try-catch),
142 // forward jump is tracked by JumpList class, in order to patch the jump
143 // after the jump target is emitted.
145 // See the comment above JumpList class for mode details.
148 // # Loop and label
150 // Control structure related to break/continue is handled by NestableControl and
151 // its subclasses. Those classes handle jump with labelled and un-labelled
152 // break/continue, stack balancing around them, TDZ check cache for the
153 // loop's basic block, and association between the control and the scope.
156 // Emitter helpers
157 // ---------------
159 // Bytecode sequence or structure specific to certain syntax (e.g. if, for, try)
160 // are handled by emitter helper classes.
162 // Each emitter helper is defined in *Emitter.{cpp,h} in this directory.
164 // Emitter helpers should meet the following requirements:
165 // * helper classes should be ParseNode-agnostic
166 // * helper classes shouldn't contain `JS::Rooted` field, given they can be
167 // held in `mozilla::Maybe` in the consumer or other helper classes
168 // * instantiation (ctor/dtor) of the emitter helper class shouldn't
169 // modify BytecodeEmitter, except for nestable controls
170 // * instantiation (ctor/dtor) of the emitter helper class shouldn't
171 // read BytecodeEmitter field that can change before the first method call.
172 // Such data should be explicitly passed as parameter, or be accessed inside
173 // the method
174 // * methods that emits bytecode should be named `emit*` or `prepareFor*`
175 // * methods and their names shouldn't require the consumer knowing the
176 // details of the bytecode sequence/structure that the helper emits
177 // * implicit branch or scope/control handling should be hidden from the
178 // consumer
179 // * If there are multiple operations between bytecode that the consumer
180 // emits, they should be wrapped into single `emit*` or `prepareFor*`
181 // method
182 // e.g.
183 // // Bad!
184 // helper.emitJumpAroundA();
185 // helper.allocateScopeForA();
186 // ... // emit bytecode for A here
187 // helper.deallocateScopeForA();
188 // helper.emitJumpAroundB();
189 // helper.allocateScopeForB();
190 // ... // emit bytecode for B here
191 // helper.deallocateScopeForB();
192 // helper.emitJumpTarget();
194 // // Good!
195 // helper.prepareForA();
196 // ... // emit bytecode for A here
197 // helper.prepareForB();
198 // ... // emit bytecode for B here
199 // helper.emitEnd();
200 // * helper classes should track state transition and assert it in each
201 // method call, to avoid misuse
202 // * it's recommended to defer receiving parameter until the parameter value
203 // is actually used in the method, instead of receiving and storing them
204 // into instance fields
206 // See comment block above each helper class for more details and example usage.
208 struct MOZ_STACK_CLASS BytecodeEmitter {
209 // Context shared between parsing and bytecode generation.
210 SharedContext* const sc = nullptr;
212 FrontendContext* const fc = nullptr;
214 // Enclosing function or global context.
215 BytecodeEmitter* const parent = nullptr;
217 BytecodeSection bytecodeSection_;
219 static constexpr unsigned LastSrcNoteIsNotLineOnly = unsigned(-1);
221 unsigned lastLineOnlySrcNoteIndex = LastSrcNoteIsNotLineOnly;
223 public:
224 BytecodeSection& bytecodeSection() { return bytecodeSection_; }
225 const BytecodeSection& bytecodeSection() const { return bytecodeSection_; }
227 private:
228 PerScriptData perScriptData_;
230 public:
231 PerScriptData& perScriptData() { return perScriptData_; }
232 const PerScriptData& perScriptData() const { return perScriptData_; }
234 private:
235 // switchToMain sets this to the bytecode offset of the main section.
236 mozilla::Maybe<uint32_t> mainOffset_ = {};
238 // Private storage for parser wrapper. DO NOT REFERENCE INTERNALLY. May not be
239 // initialized.
240 mozilla::Maybe<EitherParser> ep_ = {};
242 const ErrorReporter& errorReporter_;
244 public:
245 CompilationState& compilationState;
247 uint32_t maxFixedSlots = 0; /* maximum number of fixed frame slots so far */
249 // Index into scopeList of the body scope.
250 GCThingIndex bodyScopeIndex = ScopeNote::NoScopeIndex;
252 EmitterScope* varEmitterScope = nullptr;
253 NestableControl* innermostNestableControl = nullptr;
254 EmitterScope* innermostEmitterScope_ = nullptr;
255 TDZCheckCache* innermostTDZCheckCache = nullptr;
257 // When compiling in self-hosted mode, we have special intrinsics that act as
258 // decorators for exported functions. To keeps things simple, we only allow
259 // these to target the last top-level function emitted. This field tracks that
260 // function.
261 FunctionBox* prevSelfHostedTopLevelFunction = nullptr;
263 #ifdef DEBUG
264 bool unstableEmitterScope = false;
266 friend class AutoCheckUnstableEmitterScope;
267 #endif
269 const ErrorReporter& errorReporter() const { return errorReporter_; }
271 ParserAtomsTable& parserAtoms() { return compilationState.parserAtoms; }
272 const ParserAtomsTable& parserAtoms() const {
273 return compilationState.parserAtoms;
276 EmitterScope* innermostEmitterScope() const {
277 MOZ_ASSERT(!unstableEmitterScope);
278 return innermostEmitterScopeNoCheck();
280 EmitterScope* innermostEmitterScopeNoCheck() const {
281 return innermostEmitterScope_;
284 // When parsing internal code such as self-hosted functions or synthetic
285 // class constructors, we do not emit breakpoint and srcnote data since there
286 // is no direcly corresponding user-visible sources.
287 const bool suppressBreakpointsAndSourceNotes = false;
289 // Script contains finally block.
290 bool hasTryFinally = false;
292 enum EmitterMode {
293 Normal,
295 // Emit JSOp::GetIntrinsic instead of JSOp::GetName and assert that
296 // JSOp::GetName and JSOp::*GName don't ever get emitted. See the comment
297 // for the field |selfHostingMode| in Parser.h for details.
298 SelfHosting,
300 // Check the static scope chain of the root function for resolving free
301 // variable accesses in the script.
302 LazyFunction
305 const EmitterMode emitterMode = Normal;
307 mozilla::Maybe<uint32_t> scriptStartOffset = {};
309 // The end location of a function body that is being emitted.
310 mozilla::Maybe<uint32_t> functionBodyEndPos = {};
312 // Jump target just before the final CheckReturn opcode in a derived class
313 // constructor body.
314 JumpList endOfDerivedClassConstructorBody = {};
316 // Jump target just before the final yield in a generator or async function.
317 JumpList finalYields = {};
319 // In order to heuristically determine the size of the allocation if this is a
320 // constructor function, we track expressions which add properties in the
321 // constructor.
322 mozilla::SaturateUint8 propertyAdditionEstimate = {};
325 * Note that BytecodeEmitters are magic: they own the arena "top-of-stack"
326 * space above their tempMark points. This means that you cannot alloc from
327 * tempLifoAlloc and save the pointer beyond the next BytecodeEmitter
328 * destruction.
330 private:
331 // Internal constructor, for delegation use only.
332 BytecodeEmitter(BytecodeEmitter* parent, FrontendContext* fc,
333 SharedContext* sc, const ErrorReporter& errorReporter,
334 CompilationState& compilationState, EmitterMode emitterMode);
336 BytecodeEmitter(BytecodeEmitter* parent, SharedContext* sc);
338 void initFromBodyPosition(TokenPos bodyPosition);
340 public:
341 BytecodeEmitter(FrontendContext* fc, const EitherParser& parser,
342 SharedContext* sc, CompilationState& compilationState,
343 EmitterMode emitterMode = Normal);
345 template <typename Unit>
346 BytecodeEmitter(FrontendContext* fc, Parser<FullParseHandler, Unit>* parser,
347 SharedContext* sc, CompilationState& compilationState,
348 EmitterMode emitterMode = Normal)
349 : BytecodeEmitter(fc, EitherParser(parser), sc, compilationState,
350 emitterMode) {}
352 [[nodiscard]] bool init();
353 [[nodiscard]] bool init(TokenPos bodyPosition);
355 template <typename T>
356 T* findInnermostNestableControl() const;
358 template <typename T, typename Predicate /* (T*) -> bool */>
359 T* findInnermostNestableControl(Predicate predicate) const;
361 NameLocation lookupName(TaggedParserAtomIndex name);
363 // See EmitterScope::lookupPrivate for details around brandLoc
364 void lookupPrivate(TaggedParserAtomIndex name, NameLocation& loc,
365 mozilla::Maybe<NameLocation>& brandLoc);
367 // To implement Annex B and the formal parameter defaults scope semantics
368 // requires accessing names that would otherwise be shadowed. This method
369 // returns the access location of a name that is known to be bound in a
370 // target scope.
371 mozilla::Maybe<NameLocation> locationOfNameBoundInScope(
372 TaggedParserAtomIndex name, EmitterScope* target);
374 // Get the location of a name known to be bound in a given scope,
375 // starting at the source scope.
376 template <typename T>
377 mozilla::Maybe<NameLocation> locationOfNameBoundInScopeType(
378 TaggedParserAtomIndex name, EmitterScope* source);
380 // Get the location of a name known to be bound in the function scope,
381 // starting at the source scope.
382 mozilla::Maybe<NameLocation> locationOfNameBoundInFunctionScope(
383 TaggedParserAtomIndex name) {
384 return locationOfNameBoundInScopeType<FunctionScope>(
385 name, innermostEmitterScope());
388 void setVarEmitterScope(EmitterScope* emitterScope) {
389 MOZ_ASSERT(emitterScope);
390 MOZ_ASSERT(!varEmitterScope);
391 varEmitterScope = emitterScope;
394 AbstractScopePtr outermostScope() const {
395 return perScriptData().gcThingList().firstScope();
397 AbstractScopePtr innermostScope() const;
398 ScopeIndex innermostScopeIndex() const;
400 [[nodiscard]] MOZ_ALWAYS_INLINE bool makeAtomIndex(
401 TaggedParserAtomIndex atom, ParserAtom::Atomize atomize,
402 GCThingIndex* indexp) {
403 MOZ_ASSERT(perScriptData().atomIndices());
404 AtomIndexMap::AddPtr p = perScriptData().atomIndices()->lookupForAdd(atom);
405 if (p) {
406 compilationState.parserAtoms.markAtomize(atom, atomize);
407 *indexp = GCThingIndex(p->value());
408 return true;
411 GCThingIndex index;
412 if (!perScriptData().gcThingList().append(atom, atomize, &index)) {
413 return false;
416 // `atomIndices()` uses uint32_t instead of GCThingIndex, because
417 // GCThingIndex isn't trivial type.
418 if (!perScriptData().atomIndices()->add(p, atom, index.index)) {
419 ReportOutOfMemory(fc);
420 return false;
423 *indexp = index;
424 return true;
427 bool isInLoop();
428 [[nodiscard]] bool checkSingletonContext();
430 bool needsImplicitThis();
432 size_t countThisEnvironmentHops();
433 [[nodiscard]] bool emitThisEnvironmentCallee();
434 [[nodiscard]] bool emitSuperBase();
436 uint32_t mainOffset() const { return *mainOffset_; }
438 bool inPrologue() const { return mainOffset_.isNothing(); }
440 void switchToMain() {
441 MOZ_ASSERT(inPrologue());
442 mainOffset_.emplace(bytecodeSection().code().length());
445 void setFunctionBodyEndPos(uint32_t pos) {
446 functionBodyEndPos = mozilla::Some(pos);
449 void setScriptStartOffsetIfUnset(uint32_t pos) {
450 if (scriptStartOffset.isNothing()) {
451 scriptStartOffset = mozilla::Some(pos);
455 void reportError(ParseNode* pn, unsigned errorNumber, ...);
456 void reportError(uint32_t offset, unsigned errorNumber, ...);
458 // Fill in a ScriptStencil using this BCE data.
459 bool intoScriptStencil(ScriptIndex scriptIndex);
461 // If pn contains a useful expression, return true with *answer set to true.
462 // If pn contains a useless expression, return true with *answer set to
463 // false. Return false on error.
465 // The caller should initialize *answer to false and invoke this function on
466 // an expression statement or similar subtree to decide whether the tree
467 // could produce code that has any side effects. For an expression
468 // statement, we define useless code as code with no side effects, because
469 // the main effect, the value left on the stack after the code executes,
470 // will be discarded by a pop bytecode.
471 [[nodiscard]] bool checkSideEffects(ParseNode* pn, bool* answer);
473 #ifdef DEBUG
474 [[nodiscard]] bool checkStrictOrSloppy(JSOp op);
475 #endif
477 // Add TryNote to the tryNoteList array. The start and end offset are
478 // relative to current section.
479 [[nodiscard]] bool addTryNote(TryNoteKind kind, uint32_t stackDepth,
480 BytecodeOffset start, BytecodeOffset end);
482 // Indicates the emitter should not generate location or debugger source
483 // notes. This lets us avoid generating notes for non-user code.
484 bool skipLocationSrcNotes() const {
485 return inPrologue() || suppressBreakpointsAndSourceNotes;
487 bool skipBreakpointSrcNotes() const {
488 return inPrologue() || suppressBreakpointsAndSourceNotes;
491 // Append a new source note of the given type (and therefore size) to the
492 // notes dynamic array, updating noteCount. Return the new note's index
493 // within the array pointed at by current->notes as outparam.
494 [[nodiscard]] bool newSrcNote(SrcNoteType type, unsigned* indexp = nullptr);
495 [[nodiscard]] bool newSrcNote2(SrcNoteType type, ptrdiff_t operand,
496 unsigned* indexp = nullptr);
497 [[nodiscard]] bool convertLastNewLineToNewLineColumn(
498 JS::LimitedColumnNumberOneOrigin column);
499 [[nodiscard]] bool convertLastSetLineToSetLineColumn(
500 JS::LimitedColumnNumberOneOrigin column);
502 [[nodiscard]] bool newSrcNoteOperand(ptrdiff_t operand);
504 // Control whether emitTree emits a line number note.
505 enum EmitLineNumberNote { EMIT_LINENOTE, SUPPRESS_LINENOTE };
507 // Emit code for the tree rooted at pn.
508 [[nodiscard]] bool emitTree(ParseNode* pn,
509 ValueUsage valueUsage = ValueUsage::WantValue,
510 EmitLineNumberNote emitLineNote = EMIT_LINENOTE);
512 [[nodiscard]] bool emitOptionalTree(
513 ParseNode* pn, OptionalEmitter& oe,
514 ValueUsage valueUsage = ValueUsage::WantValue);
516 [[nodiscard]] bool emitDeclarationInstantiation(ParseNode* body);
518 // Emit global, eval, or module code for tree rooted at body. Always
519 // encompasses the entire source.
520 [[nodiscard]] bool emitScript(ParseNode* body);
522 // Calculate the `nslots` value for ImmutableScriptData constructor parameter.
523 // Fails if it overflows.
524 [[nodiscard]] bool getNslots(uint32_t* nslots);
526 // Emit function code for the tree rooted at body.
527 [[nodiscard]] bool emitFunctionScript(FunctionNode* funNode);
529 [[nodiscard]] bool markStepBreakpoint();
530 [[nodiscard]] bool markSimpleBreakpoint();
531 [[nodiscard]] bool updateLineNumberNotes(uint32_t offset);
532 [[nodiscard]] bool updateSourceCoordNotes(uint32_t offset);
533 [[nodiscard]] bool updateSourceCoordNotesIfNonLiteral(ParseNode* node);
535 JSOp strictifySetNameOp(JSOp op);
537 [[nodiscard]] bool emitCheck(JSOp op, ptrdiff_t delta,
538 BytecodeOffset* offset);
540 // Emit one bytecode.
541 [[nodiscard]] bool emit1(JSOp op);
543 // Emit two bytecodes, an opcode (op) with a byte of immediate operand
544 // (op1).
545 [[nodiscard]] bool emit2(JSOp op, uint8_t op1);
547 // Emit three bytecodes, an opcode with two bytes of immediate operands.
548 [[nodiscard]] bool emit3(JSOp op, jsbytecode op1, jsbytecode op2);
550 // Helper to duplicate one or more stack values. |slotFromTop| is the value's
551 // depth on the JS stack, as measured from the top. |count| is the number of
552 // values to duplicate, in theiro original order.
553 [[nodiscard]] bool emitDupAt(unsigned slotFromTop, unsigned count = 1);
555 // Helper to emit JSOp::Pop or JSOp::PopN.
556 [[nodiscard]] bool emitPopN(unsigned n);
558 // Helper to emit JSOp::Swap or JSOp::Pick.
559 [[nodiscard]] bool emitPickN(uint8_t n);
561 // Helper to emit JSOp::Swap or JSOp::Unpick.
562 [[nodiscard]] bool emitUnpickN(uint8_t n);
564 // Helper to emit JSOp::CheckIsObj.
565 [[nodiscard]] bool emitCheckIsObj(CheckIsObjectKind kind);
567 // Helper to emit JSOp::BuiltinObject.
568 [[nodiscard]] bool emitBuiltinObject(BuiltinObjectKind kind);
570 // Emit a bytecode followed by an uint16 immediate operand stored in
571 // big-endian order.
572 [[nodiscard]] bool emitUint16Operand(JSOp op, uint32_t operand);
574 // Emit a bytecode followed by an uint32 immediate operand.
575 [[nodiscard]] bool emitUint32Operand(JSOp op, uint32_t operand);
577 // Emit (1 + extra) bytecodes, for N bytes of op and its immediate operand.
578 [[nodiscard]] bool emitN(JSOp op, size_t extra,
579 BytecodeOffset* offset = nullptr);
581 [[nodiscard]] bool emitDouble(double dval);
582 [[nodiscard]] bool emitNumberOp(double dval);
584 [[nodiscard]] bool emitBigIntOp(BigIntLiteral* bigint);
586 [[nodiscard]] bool emitThisLiteral(ThisLiteral* pn);
587 [[nodiscard]] bool emitGetFunctionThis(NameNode* thisName);
588 [[nodiscard]] bool emitGetThisForSuperBase(UnaryNode* superBase);
589 [[nodiscard]] bool emitSetThis(BinaryNode* setThisNode);
590 [[nodiscard]] bool emitCheckDerivedClassConstructorReturn();
592 private:
593 [[nodiscard]] bool emitNewTarget();
595 public:
596 [[nodiscard]] bool emitNewTarget(NewTargetNode* pn);
597 [[nodiscard]] bool emitNewTarget(CallNode* pn);
599 // Handle jump opcodes and jump targets.
600 [[nodiscard]] bool emitJumpTargetOp(JSOp op, BytecodeOffset* off);
601 [[nodiscard]] bool emitJumpTarget(JumpTarget* target);
602 [[nodiscard]] bool emitJumpNoFallthrough(JSOp op, JumpList* jump);
603 [[nodiscard]] bool emitJump(JSOp op, JumpList* jump);
604 void patchJumpsToTarget(JumpList jump, JumpTarget target);
605 [[nodiscard]] bool emitJumpTargetAndPatch(JumpList jump);
607 [[nodiscard]] bool emitCall(
608 JSOp op, uint16_t argc,
609 const mozilla::Maybe<uint32_t>& sourceCoordOffset);
610 [[nodiscard]] bool emitCall(JSOp op, uint16_t argc, ParseNode* pn = nullptr);
611 [[nodiscard]] bool emitCallIncDec(UnaryNode* incDec);
613 uint32_t getOffsetForLoop(ParseNode* nextpn);
615 enum class GotoKind { Break, Continue };
616 [[nodiscard]] bool emitGoto(NestableControl* target, GotoKind kind);
618 [[nodiscard]] bool emitGCIndexOp(JSOp op, GCThingIndex index);
620 [[nodiscard]] bool emitAtomOp(JSOp op, TaggedParserAtomIndex atom);
621 [[nodiscard]] bool emitAtomOp(JSOp op, GCThingIndex atomIndex);
623 [[nodiscard]] bool emitStringOp(JSOp op, TaggedParserAtomIndex atom);
624 [[nodiscard]] bool emitStringOp(JSOp op, GCThingIndex atomIndex);
626 [[nodiscard]] bool emitArrayLiteral(ListNode* array);
627 [[nodiscard]] bool emitArray(ListNode* array);
628 [[nodiscard]] bool emitSpreadIntoArray(UnaryNode* elem);
630 [[nodiscard]] bool emitInternedScopeOp(GCThingIndex index, JSOp op);
631 [[nodiscard]] bool emitInternedObjectOp(GCThingIndex index, JSOp op);
632 [[nodiscard]] bool emitRegExp(GCThingIndex index);
634 [[nodiscard]] MOZ_NEVER_INLINE bool emitFunction(FunctionNode* funNode,
635 bool needsProto = false);
636 [[nodiscard]] MOZ_NEVER_INLINE bool emitObject(ListNode* objNode);
638 [[nodiscard]] bool emitHoistedFunctionsInList(ListNode* stmtList);
640 // Can we use the object-literal writer either in singleton-object mode (with
641 // values) or in template mode (field names only, no values) for the property
642 // list?
643 void isPropertyListObjLiteralCompatible(ListNode* obj, bool* withValues,
644 bool* withoutValues);
645 bool isArrayObjLiteralCompatible(ListNode* array);
647 [[nodiscard]] bool emitPropertyList(ListNode* obj, PropertyEmitter& pe,
648 PropListType type);
650 [[nodiscard]] bool emitPropertyListObjLiteral(ListNode* obj, JSOp op,
651 bool useObjLiteralValues);
653 [[nodiscard]] bool emitDestructuringRestExclusionSetObjLiteral(
654 ListNode* pattern);
656 [[nodiscard]] bool emitObjLiteralArray(ListNode* array);
658 // Is a field value JSOp::Object-compatible?
659 [[nodiscard]] bool isRHSObjLiteralCompatible(ParseNode* value);
661 [[nodiscard]] bool emitObjLiteralValue(ObjLiteralWriter& writer,
662 ParseNode* value);
664 mozilla::Maybe<MemberInitializers> setupMemberInitializers(
665 ListNode* classMembers, FieldPlacement placement);
666 [[nodiscard]] bool emitCreateFieldKeys(ListNode* obj,
667 FieldPlacement placement);
668 [[nodiscard]] bool emitCreateMemberInitializers(ClassEmitter& ce,
669 ListNode* obj,
670 FieldPlacement placement
671 #ifdef ENABLE_DECORATORS
673 bool hasHeritage
674 #endif
676 const MemberInitializers& findMemberInitializersForCall();
677 [[nodiscard]] bool emitInitializeInstanceMembers(
678 bool isDerivedClassConstructor);
679 [[nodiscard]] bool emitInitializeStaticFields(ListNode* classMembers);
681 [[nodiscard]] bool emitPrivateMethodInitializers(ClassEmitter& ce,
682 ListNode* obj);
683 [[nodiscard]] bool emitPrivateMethodInitializer(
684 ClassMethod* classMethod, TaggedParserAtomIndex storedMethodAtom);
686 // To catch accidental misuse, emitUint16Operand/emit3 assert that they are
687 // not used to unconditionally emit JSOp::GetLocal. Variable access should
688 // instead be emitted using EmitVarOp. In special cases, when the caller
689 // definitely knows that a given local slot is unaliased, this function may be
690 // used as a non-asserting version of emitUint16Operand.
691 [[nodiscard]] bool emitLocalOp(JSOp op, uint32_t slot);
693 [[nodiscard]] bool emitArgOp(JSOp op, uint16_t slot);
694 [[nodiscard]] bool emitEnvCoordOp(JSOp op, EnvironmentCoordinate ec);
696 [[nodiscard]] bool emitGetNameAtLocation(TaggedParserAtomIndex name,
697 const NameLocation& loc);
698 [[nodiscard]] bool emitGetName(TaggedParserAtomIndex name) {
699 return emitGetNameAtLocation(name, lookupName(name));
701 [[nodiscard]] bool emitGetName(NameNode* name);
702 [[nodiscard]] bool emitGetPrivateName(NameNode* name);
703 [[nodiscard]] bool emitGetPrivateName(TaggedParserAtomIndex name);
705 [[nodiscard]] bool emitTDZCheckIfNeeded(TaggedParserAtomIndex name,
706 const NameLocation& loc,
707 ValueIsOnStack isOnStack);
709 [[nodiscard]] bool emitNameIncDec(UnaryNode* incDec, ValueUsage valueUsage);
711 [[nodiscard]] bool emitDeclarationList(ListNode* declList);
712 [[nodiscard]] bool emitSingleDeclaration(ListNode* declList, NameNode* decl,
713 ParseNode* initializer);
714 [[nodiscard]] bool emitAssignmentRhs(ParseNode* rhs,
715 TaggedParserAtomIndex anonFunctionName);
716 [[nodiscard]] bool emitAssignmentRhs(uint8_t offset);
718 [[nodiscard]] bool emitPrepareIteratorResult();
719 [[nodiscard]] bool emitFinishIteratorResult(bool done);
721 // Convert and add `writer` data to stencil.
722 // Iff it suceeds, `outIndex` out parameter is initialized to the index of the
723 // object in GC things vector.
724 [[nodiscard]] bool addObjLiteralData(ObjLiteralWriter& writer,
725 GCThingIndex* outIndex);
727 [[nodiscard]] bool emitGetDotGeneratorInInnermostScope() {
728 return emitGetDotGeneratorInScope(*innermostEmitterScope());
730 [[nodiscard]] bool emitGetDotGeneratorInScope(EmitterScope& currentScope);
732 [[nodiscard]] bool allocateResumeIndex(BytecodeOffset offset,
733 uint32_t* resumeIndex);
734 [[nodiscard]] bool allocateResumeIndexRange(
735 mozilla::Span<BytecodeOffset> offsets, uint32_t* firstResumeIndex);
737 [[nodiscard]] bool emitInitialYield(UnaryNode* yieldNode);
738 [[nodiscard]] bool emitYield(UnaryNode* yieldNode);
739 [[nodiscard]] bool emitYieldOp(JSOp op);
740 [[nodiscard]] bool emitYieldStar(ParseNode* iter);
741 [[nodiscard]] bool emitAwaitInInnermostScope() {
742 return emitAwaitInScope(*innermostEmitterScope());
744 [[nodiscard]] bool emitAwaitInInnermostScope(UnaryNode* awaitNode);
745 [[nodiscard]] bool emitAwaitInScope(EmitterScope& currentScope);
747 [[nodiscard]] bool emitPushResumeKind(GeneratorResumeKind kind);
749 [[nodiscard]] bool emitPropLHS(PropertyAccess* prop);
750 [[nodiscard]] bool emitPropIncDec(UnaryNode* incDec, ValueUsage valueUsage);
752 [[nodiscard]] bool emitComputedPropertyName(UnaryNode* computedPropName);
754 [[nodiscard]] bool emitObjAndKey(ParseNode* exprOrSuper, ParseNode* key,
755 ElemOpEmitter& eoe);
757 // Emit bytecode to put operands for a JSOp::GetElem/CallElem/SetElem/DelElem
758 // opcode onto the stack in the right order. In the case of SetElem, the
759 // value to be assigned must already be pushed.
760 enum class EmitElemOption { Get, Call, IncDec, CompoundAssign, Ref };
761 [[nodiscard]] bool emitElemOperands(PropertyByValue* elem,
762 EmitElemOption opts);
764 [[nodiscard]] bool emitElemObjAndKey(PropertyByValue* elem, bool isSuper,
765 ElemOpEmitter& eoe);
766 [[nodiscard]] bool emitElemOpBase(JSOp op);
768 [[nodiscard]] bool emitElemIncDec(UnaryNode* incDec, ValueUsage valueUsage);
769 [[nodiscard]] bool emitObjAndPrivateName(PrivateMemberAccess* elem,
770 ElemOpEmitter& eoe);
771 [[nodiscard]] bool emitPrivateIncDec(UnaryNode* incDec,
772 ValueUsage valueUsage);
774 [[nodiscard]] bool emitCatch(BinaryNode* catchClause);
775 [[nodiscard]] bool emitIf(TernaryNode* ifNode);
776 [[nodiscard]] bool emitWith(BinaryNode* withNode);
778 [[nodiscard]] MOZ_NEVER_INLINE bool emitLabeledStatement(
779 const LabeledStatement* labeledStmt);
780 [[nodiscard]] MOZ_NEVER_INLINE bool emitLexicalScope(
781 LexicalScopeNode* lexicalScope);
782 [[nodiscard]] bool emitLexicalScopeBody(
783 ParseNode* body, EmitLineNumberNote emitLineNote = EMIT_LINENOTE);
784 [[nodiscard]] MOZ_NEVER_INLINE bool emitSwitch(SwitchStatement* switchStmt);
785 [[nodiscard]] MOZ_NEVER_INLINE bool emitTry(TryNode* tryNode);
787 [[nodiscard]] bool emitJumpToFinally(JumpList* jump, uint32_t idx);
789 // emitDestructuringLHSRef emits the lhs expression's reference.
790 // If the lhs expression is object property |OBJ.prop|, it emits |OBJ|.
791 // If it's object element |OBJ[ELEM]|, it emits |OBJ| and |ELEM|.
792 // If there's nothing to evaluate for the reference, it emits nothing.
793 // |emitted| parameter receives the number of values pushed onto the stack.
794 [[nodiscard]] bool emitDestructuringLHSRef(ParseNode* target,
795 size_t* emitted);
797 // emitSetOrInitializeDestructuring assumes the lhs expression's reference
798 // and the to-be-destructured value has been pushed on the stack. It emits
799 // code to destructure a single lhs expression (either a name or a compound
800 // []/{} expression).
801 [[nodiscard]] bool emitSetOrInitializeDestructuring(ParseNode* target,
802 DestructuringFlavor flav);
804 // emitDestructuringObjRestExclusionSet emits the property exclusion set
805 // for the rest-property in an object pattern.
806 [[nodiscard]] bool emitDestructuringObjRestExclusionSet(ListNode* pattern);
808 // emitDestructuringOps assumes the to-be-destructured value has been
809 // pushed on the stack and emits code to destructure each part of a [] or
810 // {} lhs expression.
811 [[nodiscard]] bool emitDestructuringOps(ListNode* pattern,
812 DestructuringFlavor flav);
813 [[nodiscard]] bool emitDestructuringOpsArray(ListNode* pattern,
814 DestructuringFlavor flav);
815 [[nodiscard]] bool emitDestructuringOpsObject(ListNode* pattern,
816 DestructuringFlavor flav);
818 enum class CopyOption { Filtered, Unfiltered };
820 // Calls either the |CopyDataProperties| or the
821 // |CopyDataPropertiesUnfiltered| intrinsic function, consumes three (or
822 // two in the latter case) elements from the stack.
823 [[nodiscard]] bool emitCopyDataProperties(CopyOption option);
825 JSOp getIterCallOp(JSOp callOp, SelfHostedIter selfHostedIter);
827 // Push the operands for emit(Async)Iterator onto the stack.
828 [[nodiscard]] bool emitIterable(ParseNode* value,
829 SelfHostedIter selfHostedIter,
830 IteratorKind iterKind = IteratorKind::Sync);
832 // emitIterator expects the iterable to already be on the stack.
833 // It will replace that stack value with the corresponding iterator
834 [[nodiscard]] bool emitIterator(SelfHostedIter selfHostedIter);
836 [[nodiscard]] bool emitAsyncIterator(SelfHostedIter selfHostedIter);
838 // Pops iterator from the top of the stack. Pushes the result of |.next()|
839 // onto the stack.
840 [[nodiscard]] bool emitIteratorNext(
841 const mozilla::Maybe<uint32_t>& callSourceCoordOffset,
842 IteratorKind kind = IteratorKind::Sync,
843 SelfHostedIter selfHostedIter = SelfHostedIter::Deny);
844 [[nodiscard]] bool emitIteratorCloseInScope(
845 EmitterScope& currentScope, IteratorKind iterKind = IteratorKind::Sync,
846 CompletionKind completionKind = CompletionKind::Normal,
847 SelfHostedIter selfHostedIter = SelfHostedIter::Deny);
848 [[nodiscard]] bool emitIteratorCloseInInnermostScope(
849 IteratorKind iterKind = IteratorKind::Sync,
850 CompletionKind completionKind = CompletionKind::Normal,
851 SelfHostedIter selfHostedIter = SelfHostedIter::Deny) {
852 return emitIteratorCloseInScope(*innermostEmitterScope(), iterKind,
853 completionKind, selfHostedIter);
856 template <typename InnerEmitter>
857 [[nodiscard]] bool wrapWithDestructuringTryNote(int32_t iterDepth,
858 InnerEmitter emitter);
860 [[nodiscard]] bool defineHoistedTopLevelFunctions(ParseNode* body);
862 // Check if the value on top of the stack is "undefined". If so, replace
863 // that value on the stack with the value defined by |defaultExpr|.
864 // |pattern| is a lhs node of the default expression. If it's an
865 // identifier and |defaultExpr| is an anonymous function, |SetFunctionName|
866 // is called at compile time.
867 [[nodiscard]] bool emitDefault(ParseNode* defaultExpr, ParseNode* pattern);
869 [[nodiscard]] bool emitAnonymousFunctionWithName(ParseNode* node,
870 TaggedParserAtomIndex name);
872 [[nodiscard]] bool emitAnonymousFunctionWithComputedName(
873 ParseNode* node, FunctionPrefixKind prefixKind);
875 [[nodiscard]] bool setFunName(FunctionBox* fun, TaggedParserAtomIndex name);
876 [[nodiscard]] bool emitInitializer(ParseNode* initializer,
877 ParseNode* pattern);
879 [[nodiscard]] bool emitCallSiteObjectArray(ObjLiteralWriter& writer,
880 ListNode* cookedOrRaw,
881 ParseNode* head, uint32_t count);
882 [[nodiscard]] bool emitCallSiteObject(CallSiteNode* callSiteObj);
883 [[nodiscard]] bool emitTemplateString(ListNode* templateString);
884 [[nodiscard]] bool emitAssignmentOrInit(ParseNodeKind kind, ParseNode* lhs,
885 ParseNode* rhs);
886 [[nodiscard]] bool emitShortCircuitAssignment(AssignmentNode* node);
888 [[nodiscard]] bool emitReturn(UnaryNode* returnNode);
889 [[nodiscard]] bool finishReturn(BytecodeOffset setRvalOffset);
891 [[nodiscard]] bool emitExpressionStatement(UnaryNode* exprStmt);
892 [[nodiscard]] bool emitStatementList(ListNode* stmtList);
894 [[nodiscard]] bool emitDeleteName(UnaryNode* deleteNode);
895 [[nodiscard]] bool emitDeleteProperty(UnaryNode* deleteNode);
896 [[nodiscard]] bool emitDeleteElement(UnaryNode* deleteNode);
897 [[nodiscard]] bool emitDeleteExpression(UnaryNode* deleteNode);
899 // Optional methods which emit Optional Jump Target
900 [[nodiscard]] bool emitOptionalChain(UnaryNode* expr, ValueUsage valueUsage);
901 [[nodiscard]] bool emitCalleeAndThisForOptionalChain(UnaryNode* expr,
902 CallNode* callNode,
903 CallOrNewEmitter& cone);
904 [[nodiscard]] bool emitDeleteOptionalChain(UnaryNode* deleteNode);
906 // Optional methods which emit a shortCircuit jump. They need to be called by
907 // a method which emits an Optional Jump Target, see below.
908 [[nodiscard]] bool emitOptionalDotExpression(PropertyAccessBase* expr,
909 PropOpEmitter& poe, bool isSuper,
910 OptionalEmitter& oe);
911 [[nodiscard]] bool emitOptionalElemExpression(PropertyByValueBase* elem,
912 ElemOpEmitter& eoe,
913 bool isSuper,
914 OptionalEmitter& oe);
915 [[nodiscard]] bool emitOptionalPrivateExpression(
916 PrivateMemberAccessBase* privateExpr, PrivateOpEmitter& xoe,
917 OptionalEmitter& oe);
918 [[nodiscard]] bool emitOptionalCall(CallNode* callNode, OptionalEmitter& oe,
919 ValueUsage valueUsage);
920 [[nodiscard]] bool emitDeletePropertyInOptChain(PropertyAccessBase* propExpr,
921 OptionalEmitter& oe);
922 [[nodiscard]] bool emitDeleteElementInOptChain(PropertyByValueBase* elemExpr,
923 OptionalEmitter& oe);
925 // |op| must be JSOp::Typeof or JSOp::TypeofExpr.
926 [[nodiscard]] bool emitTypeof(UnaryNode* typeofNode, JSOp op);
928 [[nodiscard]] bool emitUnary(UnaryNode* unaryNode);
929 [[nodiscard]] bool emitRightAssociative(ListNode* node);
930 [[nodiscard]] bool emitLeftAssociative(ListNode* node);
931 [[nodiscard]] bool emitPrivateInExpr(ListNode* node);
932 [[nodiscard]] bool emitShortCircuit(ListNode* node, ValueUsage valueUsage);
933 [[nodiscard]] bool emitSequenceExpr(ListNode* node, ValueUsage valueUsage);
935 [[nodiscard]] MOZ_NEVER_INLINE bool emitIncOrDec(UnaryNode* incDec,
936 ValueUsage valueUsage);
938 [[nodiscard]] bool emitConditionalExpression(
939 ConditionalExpression& conditional, ValueUsage valueUsage);
941 [[nodiscard]] ParseNode* getCoordNode(ParseNode* callNode,
942 ParseNode* calleeNode, JSOp op,
943 ListNode* argsList);
945 [[nodiscard]] bool emitArguments(ListNode* argsList, bool isCall,
946 bool isSpread, CallOrNewEmitter& cone);
947 [[nodiscard]] bool emitCallOrNew(CallNode* callNode, ValueUsage valueUsage);
948 [[nodiscard]] bool emitDebugCheckSelfHosted();
949 [[nodiscard]] bool emitSelfHostedCallFunction(CallNode* callNode, JSOp op);
950 [[nodiscard]] bool emitSelfHostedResumeGenerator(CallNode* callNode);
951 [[nodiscard]] bool emitSelfHostedForceInterpreter();
952 [[nodiscard]] bool emitSelfHostedAllowContentIter(CallNode* callNode);
953 [[nodiscard]] bool emitSelfHostedAllowContentIterWith(CallNode* callNode);
954 [[nodiscard]] bool emitSelfHostedAllowContentIterWithNext(CallNode* callNode);
955 [[nodiscard]] bool emitSelfHostedDefineDataProperty(CallNode* callNode);
956 [[nodiscard]] bool emitSelfHostedGetPropertySuper(CallNode* callNode);
957 [[nodiscard]] bool emitSelfHostedHasOwn(CallNode* callNode);
958 [[nodiscard]] bool emitSelfHostedToNumeric(CallNode* callNode);
959 [[nodiscard]] bool emitSelfHostedToString(CallNode* callNode);
960 [[nodiscard]] bool emitSelfHostedIsNullOrUndefined(CallNode* callNode);
961 [[nodiscard]] bool emitSelfHostedIteratorClose(CallNode* callNode);
962 [[nodiscard]] bool emitSelfHostedGetBuiltinConstructor(CallNode* callNode);
963 [[nodiscard]] bool emitSelfHostedGetBuiltinPrototype(CallNode* callNode);
964 [[nodiscard]] bool emitSelfHostedGetBuiltinSymbol(CallNode* callNode);
965 [[nodiscard]] bool emitSelfHostedSetIsInlinableLargeFunction(
966 CallNode* callNode);
967 [[nodiscard]] bool emitSelfHostedSetCanonicalName(CallNode* callNode);
968 [[nodiscard]] bool emitSelfHostedArgumentsLength(CallNode* callNode);
969 [[nodiscard]] bool emitSelfHostedGetArgument(CallNode* callNode);
970 #ifdef DEBUG
971 void assertSelfHostedExpectedTopLevel(ParseNode* node);
972 void assertSelfHostedUnsafeGetReservedSlot(ListNode* argsList);
973 void assertSelfHostedUnsafeSetReservedSlot(ListNode* argsList);
974 #endif
976 [[nodiscard]] bool emitDo(BinaryNode* doNode);
977 [[nodiscard]] bool emitWhile(BinaryNode* whileNode);
979 [[nodiscard]] bool emitFor(
980 ForNode* forNode, const EmitterScope* headLexicalEmitterScope = nullptr);
981 [[nodiscard]] bool emitCStyleFor(ForNode* forNode,
982 const EmitterScope* headLexicalEmitterScope);
983 [[nodiscard]] bool emitForIn(ForNode* forNode,
984 const EmitterScope* headLexicalEmitterScope);
985 [[nodiscard]] bool emitForOf(ForNode* forNode,
986 const EmitterScope* headLexicalEmitterScope);
988 [[nodiscard]] bool emitInitializeForInOrOfTarget(TernaryNode* forHead);
990 [[nodiscard]] bool emitBreak(TaggedParserAtomIndex label);
991 [[nodiscard]] bool emitContinue(TaggedParserAtomIndex label);
993 [[nodiscard]] bool emitFunctionFormalParameters(ParamsBodyNode* paramsBody);
994 [[nodiscard]] bool emitInitializeFunctionSpecialNames();
995 [[nodiscard]] bool emitLexicalInitialization(NameNode* name);
996 [[nodiscard]] bool emitLexicalInitialization(TaggedParserAtomIndex name);
998 // Emit bytecode for the spread operator.
1000 // emitSpread expects some values representing the spread target (an array or
1001 // a tuple), the iterator and it's next() method to be on the stack in that
1002 // order (iterator's next() on the bottom).
1003 // The number of values representing the spread target is
1004 // `spreadeeStackItems`: it's 2 for arrays (one for the array and one for the
1005 // index) and 1 for tuples (the tuple itself).
1006 // Since arrays and tuples use different opcodes to initialize new elements,
1007 // it must be specified using `storeElementOp`.
1008 // When emitSpread() finishes, the stack only contains the values representing
1009 // the spread target.
1010 [[nodiscard]] bool emitSpread(SelfHostedIter selfHostedIter,
1011 int spreadeeStackItems, JSOp storeElementOp);
1012 // This shortcut can be used when spreading into arrays, as it assumes
1013 // `spreadeeStackItems = 2` (|ARRAY INDEX|) and `storeElementOp =
1014 // JSOp::InitElemInc`
1015 [[nodiscard]] bool emitSpread(SelfHostedIter selfHostedIter);
1017 enum class ClassNameKind {
1018 // The class name is defined through its BindingIdentifier, if present.
1019 BindingName,
1021 // The class is anonymous and has a statically inferred name.
1022 InferredName,
1024 // The class is anonymous and has a dynamically computed name.
1025 ComputedName
1028 [[nodiscard]] bool emitClass(
1029 ClassNode* classNode, ClassNameKind nameKind = ClassNameKind::BindingName,
1030 TaggedParserAtomIndex nameForAnonymousClass =
1031 TaggedParserAtomIndex::null());
1033 [[nodiscard]] bool emitSuperElemOperands(
1034 PropertyByValue* elem, EmitElemOption opts = EmitElemOption::Get);
1035 [[nodiscard]] bool emitSuperGetElem(PropertyByValue* elem,
1036 bool isCall = false);
1038 [[nodiscard]] bool emitCalleeAndThis(ParseNode* callee, CallNode* maybeCall,
1039 CallOrNewEmitter& cone);
1041 [[nodiscard]] bool emitOptionalCalleeAndThis(ParseNode* callee,
1042 CallNode* call,
1043 CallOrNewEmitter& cone,
1044 OptionalEmitter& oe);
1046 #ifdef ENABLE_RECORD_TUPLE
1047 [[nodiscard]] bool emitRecordLiteral(ListNode* record);
1048 [[nodiscard]] bool emitTupleLiteral(ListNode* tuple);
1049 #endif
1051 [[nodiscard]] bool emitExportDefault(BinaryNode* exportNode);
1053 [[nodiscard]] bool emitReturnRval() { return emit1(JSOp::RetRval); }
1055 [[nodiscard]] bool emitCheckPrivateField(ThrowCondition throwCondition,
1056 ThrowMsgKind msgKind) {
1057 return emit3(JSOp::CheckPrivateField, uint8_t(throwCondition),
1058 uint8_t(msgKind));
1061 [[nodiscard]] bool emitNewPrivateName(TaggedParserAtomIndex bindingName,
1062 TaggedParserAtomIndex symbolName);
1064 template <class ClassMemberType>
1065 [[nodiscard]] bool emitNewPrivateNames(ListNode* classMembers);
1067 [[nodiscard]] bool emitNewPrivateNames(TaggedParserAtomIndex privateBrandName,
1068 ListNode* classMembers);
1070 [[nodiscard]] js::UniquePtr<ImmutableScriptData> createImmutableScriptData();
1072 private:
1073 [[nodiscard]] SelfHostedIter getSelfHostedIterFor(ParseNode* parseNode);
1075 [[nodiscard]] bool emitSelfHostedGetBuiltinConstructorOrPrototype(
1076 CallNode* callNode, bool isConstructor);
1078 public:
1079 #if defined(DEBUG) || defined(JS_JITSPEW)
1080 void dumpAtom(TaggedParserAtomIndex index) const;
1081 #endif
1084 class MOZ_RAII AutoCheckUnstableEmitterScope {
1085 #ifdef DEBUG
1086 bool prev_;
1087 BytecodeEmitter* bce_;
1088 #endif
1090 public:
1091 AutoCheckUnstableEmitterScope() = delete;
1092 explicit AutoCheckUnstableEmitterScope(BytecodeEmitter* bce)
1093 #ifdef DEBUG
1094 : bce_(bce)
1095 #endif
1097 #ifdef DEBUG
1098 prev_ = bce_->unstableEmitterScope;
1099 bce_->unstableEmitterScope = true;
1100 #endif
1102 ~AutoCheckUnstableEmitterScope() {
1103 #ifdef DEBUG
1104 bce_->unstableEmitterScope = prev_;
1105 #endif
1109 } /* namespace frontend */
1110 } /* namespace js */
1112 #endif /* frontend_BytecodeEmitter_h */