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
51 class FrontendContext
;
56 class CallOrNewEmitter
;
61 class FullParseHandler
;
62 class NestableControl
;
63 class PrivateOpEmitter
;
64 class PropertyEmitter
;
66 class OptionalEmitter
;
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.
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
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):
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.
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
133 // See comments for TDZCheckCache for more details.
136 // Control structures
137 // ------------------
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.
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.
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
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
179 // * If there are multiple operations between bytecode that the consumer
180 // emits, they should be wrapped into single `emit*` or `prepareFor*`
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();
195 // helper.prepareForA();
196 // ... // emit bytecode for A here
197 // helper.prepareForB();
198 // ... // emit bytecode for B here
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
;
224 BytecodeSection
& bytecodeSection() { return bytecodeSection_
; }
225 const BytecodeSection
& bytecodeSection() const { return bytecodeSection_
; }
228 PerScriptData perScriptData_
;
231 PerScriptData
& perScriptData() { return perScriptData_
; }
232 const PerScriptData
& perScriptData() const { return perScriptData_
; }
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
240 mozilla::Maybe
<EitherParser
> ep_
= {};
242 const ErrorReporter
& errorReporter_
;
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
261 FunctionBox
* prevSelfHostedTopLevelFunction
= nullptr;
264 bool unstableEmitterScope
= false;
266 friend class AutoCheckUnstableEmitterScope
;
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;
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.
300 // Check the static scope chain of the root function for resolving free
301 // variable accesses in the script.
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
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
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
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
);
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
,
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
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
);
406 compilationState
.parserAtoms
.markAtomize(atom
, atomize
);
407 *indexp
= GCThingIndex(p
->value());
412 if (!perScriptData().gcThingList().append(atom
, atomize
, &index
)) {
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
);
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
);
474 [[nodiscard
]] bool checkStrictOrSloppy(JSOp op
);
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
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
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();
593 [[nodiscard
]] bool emitNewTarget();
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
643 void isPropertyListObjLiteralCompatible(ListNode
* obj
, bool* withValues
,
644 bool* withoutValues
);
645 bool isArrayObjLiteralCompatible(ListNode
* array
);
647 [[nodiscard
]] bool emitPropertyList(ListNode
* obj
, PropertyEmitter
& pe
,
650 [[nodiscard
]] bool emitPropertyListObjLiteral(ListNode
* obj
, JSOp op
,
651 bool useObjLiteralValues
);
653 [[nodiscard
]] bool emitDestructuringRestExclusionSetObjLiteral(
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
,
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
,
670 FieldPlacement placement
671 #ifdef ENABLE_DECORATORS
676 const MemberInitializers
& findMemberInitializersForCall();
677 [[nodiscard
]] bool emitInitializeInstanceMembers(
678 bool isDerivedClassConstructor
);
679 [[nodiscard
]] bool emitInitializeStaticFields(ListNode
* classMembers
);
681 [[nodiscard
]] bool emitPrivateMethodInitializers(ClassEmitter
& ce
,
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
,
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
,
766 [[nodiscard
]] bool emitElemOpBase(JSOp op
);
768 [[nodiscard
]] bool emitElemIncDec(UnaryNode
* incDec
, ValueUsage valueUsage
);
769 [[nodiscard
]] bool emitObjAndPrivateName(PrivateMemberAccess
* elem
,
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
,
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()|
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
,
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
,
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
,
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
,
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
,
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(
967 [[nodiscard
]] bool emitSelfHostedSetCanonicalName(CallNode
* callNode
);
968 [[nodiscard
]] bool emitSelfHostedArgumentsLength(CallNode
* callNode
);
969 [[nodiscard
]] bool emitSelfHostedGetArgument(CallNode
* callNode
);
971 void assertSelfHostedExpectedTopLevel(ParseNode
* node
);
972 void assertSelfHostedUnsafeGetReservedSlot(ListNode
* argsList
);
973 void assertSelfHostedUnsafeSetReservedSlot(ListNode
* argsList
);
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.
1021 // The class is anonymous and has a statically inferred name.
1024 // The class is anonymous and has a dynamically computed name.
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
,
1043 CallOrNewEmitter
& cone
,
1044 OptionalEmitter
& oe
);
1046 #ifdef ENABLE_RECORD_TUPLE
1047 [[nodiscard
]] bool emitRecordLiteral(ListNode
* record
);
1048 [[nodiscard
]] bool emitTupleLiteral(ListNode
* tuple
);
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
),
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();
1073 [[nodiscard
]] SelfHostedIter
getSelfHostedIterFor(ParseNode
* parseNode
);
1075 [[nodiscard
]] bool emitSelfHostedGetBuiltinConstructorOrPrototype(
1076 CallNode
* callNode
, bool isConstructor
);
1079 #if defined(DEBUG) || defined(JS_JITSPEW)
1080 void dumpAtom(TaggedParserAtomIndex index
) const;
1084 class MOZ_RAII AutoCheckUnstableEmitterScope
{
1087 BytecodeEmitter
* bce_
;
1091 AutoCheckUnstableEmitterScope() = delete;
1092 explicit AutoCheckUnstableEmitterScope(BytecodeEmitter
* bce
)
1098 prev_
= bce_
->unstableEmitterScope
;
1099 bce_
->unstableEmitterScope
= true;
1102 ~AutoCheckUnstableEmitterScope() {
1104 bce_
->unstableEmitterScope
= prev_
;
1109 } /* namespace frontend */
1110 } /* namespace js */
1112 #endif /* frontend_BytecodeEmitter_h */