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/. */ 6 7 /* JS bytecode generation. */ 8 9 #ifndef frontend_BytecodeEmitter_h 10 #define frontend_BytecodeEmitter_h 11 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/Span.h" // mozilla::Span 16 #include "mozilla/Vector.h" // mozilla::Vector 17 18 #include <functional> // std::function 19 #include <stddef.h> // ptrdiff_t 20 #include <stdint.h> // uint16_t, uint32_t 21 22 #include "jsapi.h" // CompletionKind 23 24 #include "frontend/AbstractScopePtr.h" // ScopeIndex 25 #include "frontend/BCEParserHandle.h" // BCEParserHandle 26 #include "frontend/BytecodeControlStructures.h" // NestableControl 27 #include "frontend/BytecodeOffset.h" // BytecodeOffset 28 #include "frontend/BytecodeSection.h" // BytecodeSection, PerScriptData, CGScopeList 29 #include "frontend/DestructuringFlavor.h" // DestructuringFlavor 30 #include "frontend/EitherParser.h" // EitherParser 31 #include "frontend/ErrorReporter.h" // ErrorReporter 32 #include "frontend/FullParseHandler.h" // FullParseHandler 33 #include "frontend/IteratorKind.h" // IteratorKind 34 #include "frontend/JumpList.h" // JumpList, JumpTarget 35 #include "frontend/NameAnalysisTypes.h" // NameLocation 36 #include "frontend/NameCollections.h" // AtomIndexMap 37 #include "frontend/ParseNode.h" // ParseNode and subclasses 38 #include "frontend/Parser.h" // Parser, PropListType 39 #include "frontend/ParserAtom.h" // TaggedParserAtomIndex 40 #include "frontend/PrivateOpEmitter.h" // PrivateOpEmitter 41 #include "frontend/ScriptIndex.h" // ScriptIndex 42 #include "frontend/SharedContext.h" // SharedContext, TopLevelFunction 43 #include "frontend/SourceNotes.h" // SrcNoteType 44 #include "frontend/TokenStream.h" // TokenPos 45 #include "frontend/ValueUsage.h" // ValueUsage 46 #include "js/RootingAPI.h" // JS::Rooted, JS::Handle 47 #include "js/TypeDecls.h" // jsbytecode 48 #include "vm/BuiltinObjectKind.h" // BuiltinObjectKind 49 #include "vm/BytecodeUtil.h" // JSOp 50 #include "vm/CheckIsObjectKind.h" // CheckIsObjectKind 51 #include "vm/FunctionPrefixKind.h" // FunctionPrefixKind 52 #include "vm/GeneratorResumeKind.h" // GeneratorResumeKind 53 #include "vm/JSFunction.h" // JSFunction 54 #include "vm/JSScript.h" // JSScript, BaseScript, MemberInitializers 55 #include "vm/Runtime.h" // ReportOutOfMemory 56 #include "vm/SharedStencil.h" // GCThingIndex 57 #include "vm/StencilEnums.h" // TryNoteKind 58 #include "vm/StringType.h" // JSAtom 59 #include "vm/ThrowMsgKind.h" // ThrowMsgKind, ThrowCondition 60 61 namespace js { 62 namespace frontend { 63 64 class CallOrNewEmitter; 65 class ClassEmitter; 66 class ElemOpEmitter; 67 class EmitterScope; 68 class NestableControl; 69 class PropertyEmitter; 70 class PropOpEmitter; 71 class OptionalEmitter; 72 class TDZCheckCache; 73 class TryEmitter; 74 class ScriptStencil; 75 76 enum class ValueIsOnStack { Yes, No }; 77 78 // [SMDOC] Bytecode emission 79 // 80 // Bytecode emitter class and helper classes for generating bytecode and related 81 // stencil data from AST generated by JS parser. 82 // 83 // 84 // BytecodeEmitter 85 // --------------- 86 // 87 // BytecodeEmitter receives an AST, and utilizes helper classes to generate the 88 // bytecode sequence, and related stencil data. 89 // 90 // BytecodeEmitter can be nested, in order to emit inner non-lazy function 91 // scripts. 92 // 93 // 94 // Bytecode structures 95 // ------------------- 96 // 97 // While bytecode is being emitted, it is separated into 2 parts, the prologue 98 // and the main part. The prologue part contains instantiation of the declared 99 // variables, functions, and special names in function. The main part contains 100 // the remaining part of the bytecode. 101 // 102 // The generated bytecode is stored into the following 2 classes, before 103 // converting them into stencil data (See ImmutableScriptData and 104 // BytecodeEmitter::createImmutableScriptData): 105 // 106 // * BytecodeSection 107 // * PerScriptData 108 // 109 // BytecodeSection stores the bytecode sequence and data directly associated 110 // with opcode or index inside the bytecode sequence. 111 // 112 // PerScriptData contains data referred from the bytecode, that is mostly the 113 // list of GC things. 114 // 115 // 116 // Bindings 117 // -------- 118 // 119 // # Scope and bindings 120 // 121 // When emitting AST node that's associated with a given scope, EmitterScope is 122 // allocated to store/cache the bindings information. 123 // 124 // This information is used when emitting an opcode that accesses bindings, to 125 // determine where the binding is stored, and how the binding should be 126 // accessed, including which opcode to use and what operand to use for it. 127 // 128 // 129 // # Temporal Dead Zone (TDZ) check cache 130 // 131 // The spec requires TDZ check for all lexical variable access, but emitting 132 // TDZ check for all operation increases the bytecode size and affects the 133 // performance. TDZCheckCache is a cache to optimize away unnecessary TDZ check 134 // operations. 135 // 136 // See comments for TDZCheckCache for more details. 137 // 138 // 139 // Control structures 140 // ------------------ 141 // 142 // # Jump list 143 // 144 // When emitting jump-related bytecode (if-else, break/continue, try-catch), 145 // forward jump is tracked by JumpList class, in order to patch the jump 146 // after the jump target is emitted. 147 // 148 // See the comment above JumpList class for mode details. 149 // 150 // 151 // # Loop and label 152 // 153 // Control structure related to break/continue is handled by NestableControl and 154 // its subclasses. Those classes handle jump with labelled and un-labelled 155 // break/continue, stack balancing around them, TDZ check cache for the 156 // loop's basic block, and association between the control and the scope. 157 // 158 // 159 // Emitter helpers 160 // --------------- 161 // 162 // Bytecode sequence or structure specific to certain syntax (e.g. if, for, try) 163 // are handled by emitter helper classes. 164 // 165 // Each emitter helper is defined in *Emitter.{cpp,h} in this directory. 166 // 167 // Emitter helpers should meet the following requirements: 168 // * helper classes should be ParseNode-agnostic 169 // * helper classes shouldn't contain `JS::Rooted` field, given they can be 170 // held in `mozilla::Maybe` in the consumer or other helper classes 171 // * instantiation (ctor/dtor) of the emitter helper class shouldn't 172 // modify BytecodeEmitter, except for nestable controls 173 // * instantiation (ctor/dtor) of the emitter helper class shouldn't 174 // read BytecodeEmitter field that can change before the first method call. 175 // Such data should be explicitly passed as parameter, or be accessed inside 176 // the method 177 // * methods that emits bytecode should be named `emit*` or `prepareFor*` 178 // * methods and their names shouldn't require the consumer knowing the 179 // details of the bytecode sequence/structure that the helper emits 180 // * implicit branch or scope/control handling should be hidden from the 181 // consumer 182 // * If there are multiple operations between bytecode that the consumer 183 // emits, they should be wrapped into single `emit*` or `prepareFor*` 184 // method 185 // e.g. 186 // // Bad! 187 // helper.emitJumpAroundA(); 188 // helper.allocateScopeForA(); 189 // ... // emit bytecode for A here 190 // helper.deallocateScopeForA(); 191 // helper.emitJumpAroundB(); 192 // helper.allocateScopeForB(); 193 // ... // emit bytecode for B here 194 // helper.deallocateScopeForB(); 195 // helper.emitJumpTarget(); 196 // 197 // // Good! 198 // helper.prepareForA(); 199 // ... // emit bytecode for A here 200 // helper.prepareForB(); 201 // ... // emit bytecode for B here 202 // helper.emitEnd(); 203 // * helper classes should track state transition and assert it in each 204 // method call, to avoid misuse 205 // * parameters related to source code offset should use `mozilla::Maybe`, 206 // to support the case that there's no position information 207 // * it's recommended to defer receiving parameter until the parameter value 208 // is actually used in the method, instead of receiving and storing them 209 // into instance fields 210 // 211 // See comment block above each helper class for more details and example usage. 212 213 struct MOZ_STACK_CLASS BytecodeEmitter { 214 // Context shared between parsing and bytecode generation. 215 SharedContext* const sc = nullptr; 216 217 JSContext* const cx = nullptr; 218 219 // Enclosing function or global context. 220 BytecodeEmitter* const parent = nullptr; 221 222 BytecodeSection bytecodeSection_; 223 224 public: bytecodeSectionBytecodeEmitter225 BytecodeSection& bytecodeSection() { return bytecodeSection_; } bytecodeSectionBytecodeEmitter226 const BytecodeSection& bytecodeSection() const { return bytecodeSection_; } 227 228 private: 229 PerScriptData perScriptData_; 230 231 public: perScriptDataBytecodeEmitter232 PerScriptData& perScriptData() { return perScriptData_; } perScriptDataBytecodeEmitter233 const PerScriptData& perScriptData() const { return perScriptData_; } 234 235 private: 236 // switchToMain sets this to the bytecode offset of the main section. 237 mozilla::Maybe<uint32_t> mainOffset_ = {}; 238 239 public: 240 // Private storage for parser wrapper. DO NOT REFERENCE INTERNALLY. May not be 241 // initialized. Use |parser| instead. 242 mozilla::Maybe<EitherParser> ep_ = {}; 243 BCEParserHandle* parser = nullptr; 244 245 CompilationState& compilationState; 246 247 uint32_t maxFixedSlots = 0; /* maximum number of fixed frame slots so far */ 248 249 // Index into scopeList of the body scope. 250 GCThingIndex bodyScopeIndex = ScopeNote::NoScopeIndex; 251 252 EmitterScope* varEmitterScope = nullptr; 253 NestableControl* innermostNestableControl = nullptr; 254 EmitterScope* innermostEmitterScope_ = nullptr; 255 TDZCheckCache* innermostTDZCheckCache = nullptr; 256 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; 262 263 #ifdef DEBUG 264 bool unstableEmitterScope = false; 265 266 friend class AutoCheckUnstableEmitterScope; 267 #endif 268 parserAtomsBytecodeEmitter269 ParserAtomsTable& parserAtoms() { return compilationState.parserAtoms; } parserAtomsBytecodeEmitter270 const ParserAtomsTable& parserAtoms() const { 271 return compilationState.parserAtoms; 272 } 273 innermostEmitterScopeBytecodeEmitter274 EmitterScope* innermostEmitterScope() const { 275 MOZ_ASSERT(!unstableEmitterScope); 276 return innermostEmitterScopeNoCheck(); 277 } innermostEmitterScopeNoCheckBytecodeEmitter278 EmitterScope* innermostEmitterScopeNoCheck() const { 279 return innermostEmitterScope_; 280 } 281 282 // When parsing internal code such as self-hosted functions or synthetic 283 // class constructors, we do not emit breakpoint and srcnote data since there 284 // is no direcly corresponding user-visible sources. 285 const bool suppressBreakpointsAndSourceNotes = false; 286 287 // Script contains finally block. 288 bool hasTryFinally = false; 289 290 enum EmitterMode { 291 Normal, 292 293 // Emit JSOp::GetIntrinsic instead of JSOp::GetName and assert that 294 // JSOp::GetName and JSOp::*GName don't ever get emitted. See the comment 295 // for the field |selfHostingMode| in Parser.h for details. 296 SelfHosting, 297 298 // Check the static scope chain of the root function for resolving free 299 // variable accesses in the script. 300 LazyFunction 301 }; 302 303 const EmitterMode emitterMode = Normal; 304 305 mozilla::Maybe<uint32_t> scriptStartOffset = {}; 306 307 // The end location of a function body that is being emitted. 308 mozilla::Maybe<uint32_t> functionBodyEndPos = {}; 309 310 /* 311 * Note that BytecodeEmitters are magic: they own the arena "top-of-stack" 312 * space above their tempMark points. This means that you cannot alloc from 313 * tempLifoAlloc and save the pointer beyond the next BytecodeEmitter 314 * destruction. 315 */ 316 private: 317 // Internal constructor, for delegation use only. 318 BytecodeEmitter(BytecodeEmitter* parent, SharedContext* sc, 319 CompilationState& compilationState, EmitterMode emitterMode); 320 321 void initFromBodyPosition(TokenPos bodyPosition); 322 323 /* 324 * Helper for reporting that we have insufficient args. pluralizer 325 * should be "s" if requiredArgs is anything other than "1" and "" 326 * if requiredArgs is "1". 327 */ 328 void reportNeedMoreArgsError(ParseNode* pn, const char* errorName, 329 const char* requiredArgs, const char* pluralizer, 330 const ListNode* argsList); 331 332 public: 333 BytecodeEmitter(BytecodeEmitter* parent, BCEParserHandle* handle, 334 SharedContext* sc, CompilationState& compilationState, 335 EmitterMode emitterMode = Normal); 336 337 BytecodeEmitter(BytecodeEmitter* parent, const EitherParser& parser, 338 SharedContext* sc, CompilationState& compilationState, 339 EmitterMode emitterMode = Normal); 340 341 template <typename Unit> 342 BytecodeEmitter(BytecodeEmitter* parent, 343 Parser<FullParseHandler, Unit>* parser, SharedContext* sc, 344 CompilationState& compilationState, 345 EmitterMode emitterMode = Normal) BytecodeEmitterBytecodeEmitter346 : BytecodeEmitter(parent, EitherParser(parser), sc, compilationState, 347 emitterMode) {} 348 349 [[nodiscard]] bool init(); 350 [[nodiscard]] bool init(TokenPos bodyPosition); 351 352 template <typename T> 353 T* findInnermostNestableControl() const; 354 355 template <typename T, typename Predicate /* (T*) -> bool */> 356 T* findInnermostNestableControl(Predicate predicate) const; 357 358 NameLocation lookupName(TaggedParserAtomIndex name); 359 360 // See EmitterScope::lookupPrivate for details around brandLoc 361 bool lookupPrivate(TaggedParserAtomIndex name, NameLocation& loc, 362 mozilla::Maybe<NameLocation>& brandLoc); 363 364 // To implement Annex B and the formal parameter defaults scope semantics 365 // requires accessing names that would otherwise be shadowed. This method 366 // returns the access location of a name that is known to be bound in a 367 // target scope. 368 mozilla::Maybe<NameLocation> locationOfNameBoundInScope( 369 TaggedParserAtomIndex name, EmitterScope* target); 370 371 // Get the location of a name known to be bound in a given scope, 372 // starting at the source scope. 373 template <typename T> 374 mozilla::Maybe<NameLocation> locationOfNameBoundInScopeType( 375 TaggedParserAtomIndex name, EmitterScope* source); 376 377 // Get the location of a name known to be bound in the function scope, 378 // starting at the source scope. locationOfNameBoundInFunctionScopeBytecodeEmitter379 mozilla::Maybe<NameLocation> locationOfNameBoundInFunctionScope( 380 TaggedParserAtomIndex name) { 381 return locationOfNameBoundInScopeType<FunctionScope>( 382 name, innermostEmitterScope()); 383 } 384 setVarEmitterScopeBytecodeEmitter385 void setVarEmitterScope(EmitterScope* emitterScope) { 386 MOZ_ASSERT(emitterScope); 387 MOZ_ASSERT(!varEmitterScope); 388 varEmitterScope = emitterScope; 389 } 390 outermostScopeBytecodeEmitter391 AbstractScopePtr outermostScope() const { 392 return perScriptData().gcThingList().firstScope(); 393 } 394 AbstractScopePtr innermostScope() const; 395 ScopeIndex innermostScopeIndex() const; 396 makeAtomIndexBytecodeEmitter397 [[nodiscard]] MOZ_ALWAYS_INLINE bool makeAtomIndex(TaggedParserAtomIndex atom, 398 GCThingIndex* indexp) { 399 MOZ_ASSERT(perScriptData().atomIndices()); 400 AtomIndexMap::AddPtr p = perScriptData().atomIndices()->lookupForAdd(atom); 401 if (p) { 402 *indexp = GCThingIndex(p->value()); 403 return true; 404 } 405 406 GCThingIndex index; 407 if (!perScriptData().gcThingList().append(atom, &index)) { 408 return false; 409 } 410 411 // `atomIndices()` uses uint32_t instead of GCThingIndex, because 412 // GCThingIndex isn't trivial type. 413 if (!perScriptData().atomIndices()->add(p, atom, index.index)) { 414 ReportOutOfMemory(cx); 415 return false; 416 } 417 418 *indexp = index; 419 return true; 420 } 421 422 bool isInLoop(); 423 [[nodiscard]] bool checkSingletonContext(); 424 425 bool needsImplicitThis(); 426 427 size_t countThisEnvironmentHops(); 428 [[nodiscard]] bool emitThisEnvironmentCallee(); 429 [[nodiscard]] bool emitSuperBase(); 430 mainOffsetBytecodeEmitter431 uint32_t mainOffset() const { return *mainOffset_; } 432 inPrologueBytecodeEmitter433 bool inPrologue() const { return mainOffset_.isNothing(); } 434 switchToMainBytecodeEmitter435 void switchToMain() { 436 MOZ_ASSERT(inPrologue()); 437 mainOffset_.emplace(bytecodeSection().code().length()); 438 } 439 setFunctionBodyEndPosBytecodeEmitter440 void setFunctionBodyEndPos(uint32_t pos) { 441 functionBodyEndPos = mozilla::Some(pos); 442 } 443 setScriptStartOffsetIfUnsetBytecodeEmitter444 void setScriptStartOffsetIfUnset(uint32_t pos) { 445 if (scriptStartOffset.isNothing()) { 446 scriptStartOffset = mozilla::Some(pos); 447 } 448 } 449 450 void reportError(ParseNode* pn, unsigned errorNumber, ...); 451 void reportError(const mozilla::Maybe<uint32_t>& maybeOffset, 452 unsigned errorNumber, ...); 453 454 // Fill in a ScriptStencil using this BCE data. 455 bool intoScriptStencil(ScriptIndex scriptIndex); 456 457 // If pn contains a useful expression, return true with *answer set to true. 458 // If pn contains a useless expression, return true with *answer set to 459 // false. Return false on error. 460 // 461 // The caller should initialize *answer to false and invoke this function on 462 // an expression statement or similar subtree to decide whether the tree 463 // could produce code that has any side effects. For an expression 464 // statement, we define useless code as code with no side effects, because 465 // the main effect, the value left on the stack after the code executes, 466 // will be discarded by a pop bytecode. 467 [[nodiscard]] bool checkSideEffects(ParseNode* pn, bool* answer); 468 469 #ifdef DEBUG 470 [[nodiscard]] bool checkStrictOrSloppy(JSOp op); 471 #endif 472 473 // Add TryNote to the tryNoteList array. The start and end offset are 474 // relative to current section. 475 [[nodiscard]] bool addTryNote(TryNoteKind kind, uint32_t stackDepth, 476 BytecodeOffset start, BytecodeOffset end); 477 478 // Indicates the emitter should not generate location or debugger source 479 // notes. This lets us avoid generating notes for non-user code. skipLocationSrcNotesBytecodeEmitter480 bool skipLocationSrcNotes() const { 481 return inPrologue() || suppressBreakpointsAndSourceNotes; 482 } skipBreakpointSrcNotesBytecodeEmitter483 bool skipBreakpointSrcNotes() const { 484 return inPrologue() || suppressBreakpointsAndSourceNotes; 485 } 486 487 // Append a new source note of the given type (and therefore size) to the 488 // notes dynamic array, updating noteCount. Return the new note's index 489 // within the array pointed at by current->notes as outparam. 490 [[nodiscard]] bool newSrcNote(SrcNoteType type, unsigned* indexp = nullptr); 491 [[nodiscard]] bool newSrcNote2(SrcNoteType type, ptrdiff_t operand, 492 unsigned* indexp = nullptr); 493 494 [[nodiscard]] bool newSrcNoteOperand(ptrdiff_t operand); 495 496 // Control whether emitTree emits a line number note. 497 enum EmitLineNumberNote { EMIT_LINENOTE, SUPPRESS_LINENOTE }; 498 499 // Emit code for the tree rooted at pn. 500 [[nodiscard]] bool emitTree(ParseNode* pn, 501 ValueUsage valueUsage = ValueUsage::WantValue, 502 EmitLineNumberNote emitLineNote = EMIT_LINENOTE); 503 504 [[nodiscard]] bool emitOptionalTree( 505 ParseNode* pn, OptionalEmitter& oe, 506 ValueUsage valueUsage = ValueUsage::WantValue); 507 508 [[nodiscard]] bool emitDeclarationInstantiation(ParseNode* body); 509 510 // Emit global, eval, or module code for tree rooted at body. Always 511 // encompasses the entire source. 512 [[nodiscard]] bool emitScript(ParseNode* body); 513 514 // Calculate the `nslots` value for BCEScriptStencil constructor parameter. 515 // Fails if it overflows. 516 [[nodiscard]] bool getNslots(uint32_t* nslots); 517 518 // Emit function code for the tree rooted at body. 519 [[nodiscard]] bool emitFunctionScript(FunctionNode* funNode); 520 521 [[nodiscard]] bool markStepBreakpoint(); 522 [[nodiscard]] bool markSimpleBreakpoint(); 523 [[nodiscard]] bool updateLineNumberNotes(uint32_t offset); 524 [[nodiscard]] bool updateSourceCoordNotes(uint32_t offset); 525 526 JSOp strictifySetNameOp(JSOp op); 527 528 [[nodiscard]] bool emitCheck(JSOp op, ptrdiff_t delta, 529 BytecodeOffset* offset); 530 531 // Emit one bytecode. 532 [[nodiscard]] bool emit1(JSOp op); 533 534 // Emit two bytecodes, an opcode (op) with a byte of immediate operand 535 // (op1). 536 [[nodiscard]] bool emit2(JSOp op, uint8_t op1); 537 538 // Emit three bytecodes, an opcode with two bytes of immediate operands. 539 [[nodiscard]] bool emit3(JSOp op, jsbytecode op1, jsbytecode op2); 540 541 // Helper to duplicate one or more stack values. |slotFromTop| is the value's 542 // depth on the JS stack, as measured from the top. |count| is the number of 543 // values to duplicate, in theiro original order. 544 [[nodiscard]] bool emitDupAt(unsigned slotFromTop, unsigned count = 1); 545 546 // Helper to emit JSOp::Pop or JSOp::PopN. 547 [[nodiscard]] bool emitPopN(unsigned n); 548 549 // Helper to emit JSOp::Swap or JSOp::Pick. 550 [[nodiscard]] bool emitPickN(uint8_t n); 551 552 // Helper to emit JSOp::Swap or JSOp::Unpick. 553 [[nodiscard]] bool emitUnpickN(uint8_t n); 554 555 // Helper to emit JSOp::CheckIsObj. 556 [[nodiscard]] bool emitCheckIsObj(CheckIsObjectKind kind); 557 558 // Helper to emit JSOp::BuiltinObject. 559 [[nodiscard]] bool emitBuiltinObject(BuiltinObjectKind kind); 560 561 // Push whether the value atop of the stack is non-undefined and non-null. 562 [[nodiscard]] bool emitPushNotUndefinedOrNull(); 563 564 // Emit a bytecode followed by an uint16 immediate operand stored in 565 // big-endian order. 566 [[nodiscard]] bool emitUint16Operand(JSOp op, uint32_t operand); 567 568 // Emit a bytecode followed by an uint32 immediate operand. 569 [[nodiscard]] bool emitUint32Operand(JSOp op, uint32_t operand); 570 571 // Emit (1 + extra) bytecodes, for N bytes of op and its immediate operand. 572 [[nodiscard]] bool emitN(JSOp op, size_t extra, 573 BytecodeOffset* offset = nullptr); 574 575 [[nodiscard]] bool emitDouble(double dval); 576 [[nodiscard]] bool emitNumberOp(double dval); 577 578 [[nodiscard]] bool emitBigIntOp(BigIntLiteral* bigint); 579 580 [[nodiscard]] bool emitThisLiteral(ThisLiteral* pn); 581 [[nodiscard]] bool emitGetFunctionThis(NameNode* thisName); 582 [[nodiscard]] bool emitGetFunctionThis( 583 const mozilla::Maybe<uint32_t>& offset); 584 [[nodiscard]] bool emitGetThisForSuperBase(UnaryNode* superBase); 585 [[nodiscard]] bool emitSetThis(BinaryNode* setThisNode); 586 [[nodiscard]] bool emitCheckDerivedClassConstructorReturn(); 587 588 // Handle jump opcodes and jump targets. 589 [[nodiscard]] bool emitJumpTargetOp(JSOp op, BytecodeOffset* off); 590 [[nodiscard]] bool emitJumpTarget(JumpTarget* target); 591 [[nodiscard]] bool emitJumpNoFallthrough(JSOp op, JumpList* jump); 592 [[nodiscard]] bool emitJump(JSOp op, JumpList* jump); 593 void patchJumpsToTarget(JumpList jump, JumpTarget target); 594 [[nodiscard]] bool emitJumpTargetAndPatch(JumpList jump); 595 596 [[nodiscard]] bool emitCall( 597 JSOp op, uint16_t argc, 598 const mozilla::Maybe<uint32_t>& sourceCoordOffset); 599 [[nodiscard]] bool emitCall(JSOp op, uint16_t argc, ParseNode* pn = nullptr); 600 [[nodiscard]] bool emitCallIncDec(UnaryNode* incDec); 601 602 mozilla::Maybe<uint32_t> getOffsetForLoop(ParseNode* nextpn); 603 604 enum class GotoKind { Break, Continue }; 605 [[nodiscard]] bool emitGoto(NestableControl* target, JumpList* jumplist, 606 GotoKind kind); 607 608 [[nodiscard]] bool emitGCIndexOp(JSOp op, GCThingIndex index); 609 610 [[nodiscard]] bool emitAtomOp(JSOp op, TaggedParserAtomIndex atom); 611 [[nodiscard]] bool emitAtomOp(JSOp op, GCThingIndex atomIndex); 612 613 [[nodiscard]] bool emitArrayLiteral(ListNode* array); 614 [[nodiscard]] bool emitArray(ParseNode* arrayHead, uint32_t count); 615 616 [[nodiscard]] bool emitInternedScopeOp(GCThingIndex index, JSOp op); 617 [[nodiscard]] bool emitInternedObjectOp(GCThingIndex index, JSOp op); 618 [[nodiscard]] bool emitObjectPairOp(GCThingIndex index1, GCThingIndex index2, 619 JSOp op); 620 [[nodiscard]] bool emitRegExp(GCThingIndex index); 621 622 [[nodiscard]] MOZ_NEVER_INLINE bool emitFunction(FunctionNode* funNode, 623 bool needsProto = false); 624 [[nodiscard]] MOZ_NEVER_INLINE bool emitObject(ListNode* objNode); 625 626 [[nodiscard]] bool emitHoistedFunctionsInList(ListNode* stmtList); 627 628 // Can we use the object-literal writer either in singleton-object mode (with 629 // values) or in template mode (field names only, no values) for the property 630 // list? 631 void isPropertyListObjLiteralCompatible(ListNode* obj, bool* withValues, 632 bool* withoutValues); 633 bool isArrayObjLiteralCompatible(ParseNode* arrayHead); 634 635 [[nodiscard]] bool emitPropertyList(ListNode* obj, PropertyEmitter& pe, 636 PropListType type); 637 638 [[nodiscard]] bool emitPropertyListObjLiteral(ListNode* obj, 639 ObjLiteralFlags flags, 640 bool useObjLiteralValues); 641 642 [[nodiscard]] bool emitDestructuringRestExclusionSetObjLiteral( 643 ListNode* pattern); 644 645 [[nodiscard]] bool emitObjLiteralArray(ParseNode* arrayHead); 646 647 // Is a field value OBJLITERAL-compatible? 648 [[nodiscard]] bool isRHSObjLiteralCompatible(ParseNode* value); 649 650 [[nodiscard]] bool emitObjLiteralValue(ObjLiteralWriter& writer, 651 ParseNode* value); 652 653 mozilla::Maybe<MemberInitializers> setupMemberInitializers( 654 ListNode* classMembers, FieldPlacement placement); 655 [[nodiscard]] bool emitCreateFieldKeys(ListNode* obj, 656 FieldPlacement placement); 657 [[nodiscard]] bool emitCreateMemberInitializers(ClassEmitter& ce, 658 ListNode* obj, 659 FieldPlacement placement); 660 const MemberInitializers& findMemberInitializersForCall(); 661 [[nodiscard]] bool emitInitializeInstanceMembers(); 662 [[nodiscard]] bool emitInitializeStaticFields(ListNode* classMembers); 663 664 [[nodiscard]] bool emitPrivateMethodInitializers(ClassEmitter& ce, 665 ListNode* obj); 666 [[nodiscard]] bool emitPrivateMethodInitializer( 667 ClassEmitter& ce, ParseNode* prop, ParseNode* propName, 668 TaggedParserAtomIndex storedMethodAtom, AccessorType accessorType); 669 670 // To catch accidental misuse, emitUint16Operand/emit3 assert that they are 671 // not used to unconditionally emit JSOp::GetLocal. Variable access should 672 // instead be emitted using EmitVarOp. In special cases, when the caller 673 // definitely knows that a given local slot is unaliased, this function may be 674 // used as a non-asserting version of emitUint16Operand. 675 [[nodiscard]] bool emitLocalOp(JSOp op, uint32_t slot); 676 677 [[nodiscard]] bool emitArgOp(JSOp op, uint16_t slot); 678 [[nodiscard]] bool emitEnvCoordOp(JSOp op, EnvironmentCoordinate ec); 679 680 [[nodiscard]] bool emitGetNameAtLocation(TaggedParserAtomIndex name, 681 const NameLocation& loc); emitGetNameBytecodeEmitter682 [[nodiscard]] bool emitGetName(TaggedParserAtomIndex name) { 683 return emitGetNameAtLocation(name, lookupName(name)); 684 } 685 [[nodiscard]] bool emitGetName(NameNode* name); 686 [[nodiscard]] bool emitGetPrivateName(NameNode* name); 687 [[nodiscard]] bool emitGetPrivateName(TaggedParserAtomIndex name); 688 689 [[nodiscard]] bool emitTDZCheckIfNeeded(TaggedParserAtomIndex name, 690 const NameLocation& loc, 691 ValueIsOnStack isOnStack); 692 693 [[nodiscard]] bool emitNameIncDec(UnaryNode* incDec); 694 695 [[nodiscard]] bool emitDeclarationList(ListNode* declList); 696 [[nodiscard]] bool emitSingleDeclaration(ListNode* declList, NameNode* decl, 697 ParseNode* initializer); 698 [[nodiscard]] bool emitAssignmentRhs(ParseNode* rhs, 699 TaggedParserAtomIndex anonFunctionName); 700 [[nodiscard]] bool emitAssignmentRhs(uint8_t offset); 701 702 [[nodiscard]] bool emitPrepareIteratorResult(); 703 [[nodiscard]] bool emitFinishIteratorResult(bool done); 704 [[nodiscard]] bool iteratorResultShape(GCThingIndex* outShape); 705 706 // Convert and add `writer` data to stencil. 707 // Iff it suceeds, `outIndex` out parameter is initialized to the index of the 708 // object in GC things vector. 709 [[nodiscard]] bool addObjLiteralData(ObjLiteralWriter& writer, 710 GCThingIndex* outIndex); 711 emitGetDotGeneratorInInnermostScopeBytecodeEmitter712 [[nodiscard]] bool emitGetDotGeneratorInInnermostScope() { 713 return emitGetDotGeneratorInScope(*innermostEmitterScope()); 714 } 715 [[nodiscard]] bool emitGetDotGeneratorInScope(EmitterScope& currentScope); 716 717 [[nodiscard]] bool allocateResumeIndex(BytecodeOffset offset, 718 uint32_t* resumeIndex); 719 [[nodiscard]] bool allocateResumeIndexRange( 720 mozilla::Span<BytecodeOffset> offsets, uint32_t* firstResumeIndex); 721 722 [[nodiscard]] bool emitInitialYield(UnaryNode* yieldNode); 723 [[nodiscard]] bool emitYield(UnaryNode* yieldNode); 724 [[nodiscard]] bool emitYieldOp(JSOp op); 725 [[nodiscard]] bool emitYieldStar(ParseNode* iter); emitAwaitInInnermostScopeBytecodeEmitter726 [[nodiscard]] bool emitAwaitInInnermostScope() { 727 return emitAwaitInScope(*innermostEmitterScope()); 728 } 729 [[nodiscard]] bool emitAwaitInInnermostScope(UnaryNode* awaitNode); 730 [[nodiscard]] bool emitAwaitInScope(EmitterScope& currentScope); 731 732 [[nodiscard]] bool emitPushResumeKind(GeneratorResumeKind kind); 733 734 [[nodiscard]] bool emitPropLHS(PropertyAccess* prop); 735 [[nodiscard]] bool emitPropIncDec(UnaryNode* incDec); 736 737 [[nodiscard]] bool emitComputedPropertyName(UnaryNode* computedPropName); 738 739 [[nodiscard]] bool emitObjAndKey(ParseNode* exprOrSuper, ParseNode* key, 740 ElemOpEmitter& eoe); 741 742 // Emit bytecode to put operands for a JSOp::GetElem/CallElem/SetElem/DelElem 743 // opcode onto the stack in the right order. In the case of SetElem, the 744 // value to be assigned must already be pushed. 745 enum class EmitElemOption { Get, Call, IncDec, CompoundAssign, Ref }; 746 [[nodiscard]] bool emitElemOperands(PropertyByValue* elem, 747 EmitElemOption opts); 748 749 [[nodiscard]] bool emitElemObjAndKey(PropertyByValue* elem, bool isSuper, 750 ElemOpEmitter& eoe); 751 [[nodiscard]] bool emitElemOpBase(JSOp op); 752 753 [[nodiscard]] bool emitElemIncDec(UnaryNode* incDec); 754 [[nodiscard]] bool emitObjAndPrivateName(PrivateMemberAccess* elem, 755 ElemOpEmitter& eoe); 756 [[nodiscard]] bool emitPrivateIncDec(UnaryNode* incDec); 757 758 [[nodiscard]] bool emitCatch(BinaryNode* catchClause); 759 [[nodiscard]] bool emitIf(TernaryNode* ifNode); 760 [[nodiscard]] bool emitWith(BinaryNode* withNode); 761 762 [[nodiscard]] MOZ_NEVER_INLINE bool emitLabeledStatement( 763 const LabeledStatement* labeledStmt); 764 [[nodiscard]] MOZ_NEVER_INLINE bool emitLexicalScope( 765 LexicalScopeNode* lexicalScope); 766 [[nodiscard]] bool emitLexicalScopeBody( 767 ParseNode* body, EmitLineNumberNote emitLineNote = EMIT_LINENOTE); 768 [[nodiscard]] MOZ_NEVER_INLINE bool emitSwitch(SwitchStatement* switchStmt); 769 [[nodiscard]] MOZ_NEVER_INLINE bool emitTry(TryNode* tryNode); 770 771 [[nodiscard]] bool emitGoSub(JumpList* jump); 772 773 // emitDestructuringLHSRef emits the lhs expression's reference. 774 // If the lhs expression is object property |OBJ.prop|, it emits |OBJ|. 775 // If it's object element |OBJ[ELEM]|, it emits |OBJ| and |ELEM|. 776 // If there's nothing to evaluate for the reference, it emits nothing. 777 // |emitted| parameter receives the number of values pushed onto the stack. 778 [[nodiscard]] bool emitDestructuringLHSRef(ParseNode* target, 779 size_t* emitted); 780 781 // emitSetOrInitializeDestructuring assumes the lhs expression's reference 782 // and the to-be-destructured value has been pushed on the stack. It emits 783 // code to destructure a single lhs expression (either a name or a compound 784 // []/{} expression). 785 [[nodiscard]] bool emitSetOrInitializeDestructuring(ParseNode* target, 786 DestructuringFlavor flav); 787 788 // emitDestructuringObjRestExclusionSet emits the property exclusion set 789 // for the rest-property in an object pattern. 790 [[nodiscard]] bool emitDestructuringObjRestExclusionSet(ListNode* pattern); 791 792 // emitDestructuringOps assumes the to-be-destructured value has been 793 // pushed on the stack and emits code to destructure each part of a [] or 794 // {} lhs expression. 795 [[nodiscard]] bool emitDestructuringOps(ListNode* pattern, 796 DestructuringFlavor flav); 797 [[nodiscard]] bool emitDestructuringOpsArray(ListNode* pattern, 798 DestructuringFlavor flav); 799 [[nodiscard]] bool emitDestructuringOpsObject(ListNode* pattern, 800 DestructuringFlavor flav); 801 802 enum class CopyOption { Filtered, Unfiltered }; 803 804 // Calls either the |CopyDataProperties| or the 805 // |CopyDataPropertiesUnfiltered| intrinsic function, consumes three (or 806 // two in the latter case) elements from the stack. 807 [[nodiscard]] bool emitCopyDataProperties(CopyOption option); 808 809 // emitIterator expects the iterable to already be on the stack. 810 // It will replace that stack value with the corresponding iterator 811 [[nodiscard]] bool emitIterator(); 812 813 [[nodiscard]] bool emitAsyncIterator(); 814 815 // Pops iterator from the top of the stack. Pushes the result of |.next()| 816 // onto the stack. 817 [[nodiscard]] bool emitIteratorNext( 818 const mozilla::Maybe<uint32_t>& callSourceCoordOffset, 819 IteratorKind kind = IteratorKind::Sync, bool allowSelfHosted = false); 820 [[nodiscard]] bool emitIteratorCloseInScope( 821 EmitterScope& currentScope, IteratorKind iterKind = IteratorKind::Sync, 822 CompletionKind completionKind = CompletionKind::Normal, 823 bool allowSelfHosted = false); 824 [[nodiscard]] bool emitIteratorCloseInInnermostScope( 825 IteratorKind iterKind = IteratorKind::Sync, 826 CompletionKind completionKind = CompletionKind::Normal, 827 bool allowSelfHosted = false) { 828 return emitIteratorCloseInScope(*innermostEmitterScope(), iterKind, 829 completionKind, allowSelfHosted); 830 } 831 832 template <typename InnerEmitter> 833 [[nodiscard]] bool wrapWithDestructuringTryNote(int32_t iterDepth, 834 InnerEmitter emitter); 835 836 [[nodiscard]] bool defineHoistedTopLevelFunctions(ParseNode* body); 837 838 // Check if the value on top of the stack is "undefined". If so, replace 839 // that value on the stack with the value defined by |defaultExpr|. 840 // |pattern| is a lhs node of the default expression. If it's an 841 // identifier and |defaultExpr| is an anonymous function, |SetFunctionName| 842 // is called at compile time. 843 [[nodiscard]] bool emitDefault(ParseNode* defaultExpr, ParseNode* pattern); 844 845 [[nodiscard]] bool emitAnonymousFunctionWithName(ParseNode* node, 846 TaggedParserAtomIndex name); 847 848 [[nodiscard]] bool emitAnonymousFunctionWithComputedName( 849 ParseNode* node, FunctionPrefixKind prefixKind); 850 851 [[nodiscard]] bool setFunName(FunctionBox* fun, TaggedParserAtomIndex name); 852 [[nodiscard]] bool emitInitializer(ParseNode* initializer, 853 ParseNode* pattern); 854 855 [[nodiscard]] bool emitCallSiteObjectArray(ListNode* cookedOrRaw, 856 GCThingIndex* outArrayIndex); 857 [[nodiscard]] bool emitCallSiteObject(CallSiteNode* callSiteObj); 858 [[nodiscard]] bool emitTemplateString(ListNode* templateString); 859 [[nodiscard]] bool emitAssignmentOrInit(ParseNodeKind kind, ParseNode* lhs, 860 ParseNode* rhs); 861 [[nodiscard]] bool emitShortCircuitAssignment(AssignmentNode* node); 862 863 [[nodiscard]] bool emitReturn(UnaryNode* returnNode); 864 [[nodiscard]] bool emitExpressionStatement(UnaryNode* exprStmt); 865 [[nodiscard]] bool emitStatementList(ListNode* stmtList); 866 867 [[nodiscard]] bool emitDeleteName(UnaryNode* deleteNode); 868 [[nodiscard]] bool emitDeleteProperty(UnaryNode* deleteNode); 869 [[nodiscard]] bool emitDeleteElement(UnaryNode* deleteNode); 870 [[nodiscard]] bool emitDeleteExpression(UnaryNode* deleteNode); 871 872 // Optional methods which emit Optional Jump Target 873 [[nodiscard]] bool emitOptionalChain(UnaryNode* expr, ValueUsage valueUsage); 874 [[nodiscard]] bool emitCalleeAndThisForOptionalChain(UnaryNode* expr, 875 CallNode* callNode, 876 CallOrNewEmitter& cone); 877 [[nodiscard]] bool emitDeleteOptionalChain(UnaryNode* deleteNode); 878 879 // Optional methods which emit a shortCircuit jump. They need to be called by 880 // a method which emits an Optional Jump Target, see below. 881 [[nodiscard]] bool emitOptionalDotExpression(PropertyAccessBase* expr, 882 PropOpEmitter& poe, bool isSuper, 883 OptionalEmitter& oe); 884 [[nodiscard]] bool emitOptionalElemExpression(PropertyByValueBase* elem, 885 ElemOpEmitter& eoe, 886 bool isSuper, 887 OptionalEmitter& oe); 888 [[nodiscard]] bool emitOptionalPrivateExpression( 889 PrivateMemberAccessBase* privateExpr, PrivateOpEmitter& xoe, 890 OptionalEmitter& oe); 891 [[nodiscard]] bool emitOptionalCall(CallNode* callNode, OptionalEmitter& oe, 892 ValueUsage valueUsage); 893 [[nodiscard]] bool emitDeletePropertyInOptChain(PropertyAccessBase* propExpr, 894 OptionalEmitter& oe); 895 [[nodiscard]] bool emitDeleteElementInOptChain(PropertyByValueBase* elemExpr, 896 OptionalEmitter& oe); 897 898 // |op| must be JSOp::Typeof or JSOp::TypeofExpr. 899 [[nodiscard]] bool emitTypeof(UnaryNode* typeofNode, JSOp op); 900 901 [[nodiscard]] bool emitUnary(UnaryNode* unaryNode); 902 [[nodiscard]] bool emitRightAssociative(ListNode* node); 903 [[nodiscard]] bool emitLeftAssociative(ListNode* node); 904 [[nodiscard]] bool emitPrivateInExpr(ListNode* node); 905 [[nodiscard]] bool emitShortCircuit(ListNode* node); 906 [[nodiscard]] bool emitSequenceExpr( 907 ListNode* node, ValueUsage valueUsage = ValueUsage::WantValue); 908 909 [[nodiscard]] MOZ_NEVER_INLINE bool emitIncOrDec(UnaryNode* incDec); 910 911 [[nodiscard]] bool emitConditionalExpression( 912 ConditionalExpression& conditional, 913 ValueUsage valueUsage = ValueUsage::WantValue); 914 915 bool isOptimizableSpreadArgument(ParseNode* expr); 916 917 [[nodiscard]] ParseNode* getCoordNode(ParseNode* callNode, 918 ParseNode* calleeNode, JSOp op, 919 ListNode* argsList); 920 921 [[nodiscard]] bool emitArguments(ListNode* argsList, bool isCall, 922 bool isSpread, CallOrNewEmitter& cone); 923 [[nodiscard]] bool emitCallOrNew( 924 CallNode* callNode, ValueUsage valueUsage = ValueUsage::WantValue); 925 [[nodiscard]] bool emitSelfHostedCallFunction(CallNode* callNode); 926 [[nodiscard]] bool emitSelfHostedResumeGenerator(BinaryNode* callNode); 927 [[nodiscard]] bool emitSelfHostedForceInterpreter(); 928 [[nodiscard]] bool emitSelfHostedAllowContentIter(BinaryNode* callNode); 929 [[nodiscard]] bool emitSelfHostedDefineDataProperty(BinaryNode* callNode); 930 [[nodiscard]] bool emitSelfHostedGetPropertySuper(BinaryNode* callNode); 931 [[nodiscard]] bool emitSelfHostedHasOwn(BinaryNode* callNode); 932 [[nodiscard]] bool emitSelfHostedToNumeric(BinaryNode* callNode); 933 [[nodiscard]] bool emitSelfHostedToString(BinaryNode* callNode); 934 [[nodiscard]] bool emitSelfHostedGetBuiltinConstructor(BinaryNode* callNode); 935 [[nodiscard]] bool emitSelfHostedGetBuiltinPrototype(BinaryNode* callNode); 936 [[nodiscard]] bool emitSelfHostedGetBuiltinSymbol(BinaryNode* callNode); 937 [[nodiscard]] bool emitSelfHostedSetIsInlinableLargeFunction( 938 BinaryNode* callNode); 939 [[nodiscard]] bool emitSelfHostedSetCanonicalName(BinaryNode* callNode); 940 #ifdef DEBUG 941 [[nodiscard]] bool checkSelfHostedExpectedTopLevel(BinaryNode* callNode, 942 ParseNode* node); 943 [[nodiscard]] bool checkSelfHostedUnsafeGetReservedSlot(BinaryNode* callNode); 944 [[nodiscard]] bool checkSelfHostedUnsafeSetReservedSlot(BinaryNode* callNode); 945 #endif 946 947 [[nodiscard]] bool emitDo(BinaryNode* doNode); 948 [[nodiscard]] bool emitWhile(BinaryNode* whileNode); 949 950 [[nodiscard]] bool emitFor( 951 ForNode* forNode, const EmitterScope* headLexicalEmitterScope = nullptr); 952 [[nodiscard]] bool emitCStyleFor(ForNode* forNode, 953 const EmitterScope* headLexicalEmitterScope); 954 [[nodiscard]] bool emitForIn(ForNode* forNode, 955 const EmitterScope* headLexicalEmitterScope); 956 [[nodiscard]] bool emitForOf(ForNode* forNode, 957 const EmitterScope* headLexicalEmitterScope); 958 959 [[nodiscard]] bool emitInitializeForInOrOfTarget(TernaryNode* forHead); 960 961 [[nodiscard]] bool emitBreak(TaggedParserAtomIndex label); 962 [[nodiscard]] bool emitContinue(TaggedParserAtomIndex label); 963 964 [[nodiscard]] bool emitFunctionFormalParameters(ListNode* paramsBody); 965 [[nodiscard]] bool emitInitializeFunctionSpecialNames(); 966 [[nodiscard]] bool emitLexicalInitialization(NameNode* name); 967 [[nodiscard]] bool emitLexicalInitialization(TaggedParserAtomIndex name); 968 969 // Emit bytecode for the spread operator. 970 // 971 // emitSpread expects the current index (I) of the array, the array itself 972 // and the iterator to be on the stack in that order (iterator on the bottom). 973 // It will pop the iterator and I, then iterate over the iterator by calling 974 // |.next()| and put the results into the I-th element of array with 975 // incrementing I, then push the result I (it will be original I + 976 // iteration count). The stack after iteration will look like |ARRAY INDEX|. 977 [[nodiscard]] bool emitSpread(bool allowSelfHosted = false); 978 979 enum class ClassNameKind { 980 // The class name is defined through its BindingIdentifier, if present. 981 BindingName, 982 983 // The class is anonymous and has a statically inferred name. 984 InferredName, 985 986 // The class is anonymous and has a dynamically computed name. 987 ComputedName 988 }; 989 990 [[nodiscard]] bool emitClass( 991 ClassNode* classNode, ClassNameKind nameKind = ClassNameKind::BindingName, 992 TaggedParserAtomIndex nameForAnonymousClass = 993 TaggedParserAtomIndex::null()); 994 995 [[nodiscard]] bool emitSuperElemOperands( 996 PropertyByValue* elem, EmitElemOption opts = EmitElemOption::Get); 997 [[nodiscard]] bool emitSuperGetElem(PropertyByValue* elem, 998 bool isCall = false); 999 1000 [[nodiscard]] bool emitCalleeAndThis(ParseNode* callee, ParseNode* call, 1001 CallOrNewEmitter& cone); 1002 1003 [[nodiscard]] bool emitOptionalCalleeAndThis(ParseNode* callee, 1004 CallNode* call, 1005 CallOrNewEmitter& cone, 1006 OptionalEmitter& oe); 1007 1008 [[nodiscard]] bool emitExportDefault(BinaryNode* exportNode); 1009 emitReturnRvalBytecodeEmitter1010 [[nodiscard]] bool emitReturnRval() { return emit1(JSOp::RetRval); } 1011 emitCheckPrivateFieldBytecodeEmitter1012 [[nodiscard]] bool emitCheckPrivateField(ThrowCondition throwCondition, 1013 ThrowMsgKind msgKind) { 1014 return emit3(JSOp::CheckPrivateField, uint8_t(throwCondition), 1015 uint8_t(msgKind)); 1016 } 1017 1018 [[nodiscard]] bool emitNewPrivateName(TaggedParserAtomIndex bindingName, 1019 TaggedParserAtomIndex symbolName); 1020 1021 template <class ClassMemberType> 1022 [[nodiscard]] bool emitNewPrivateNames(ListNode* classMembers); 1023 1024 [[nodiscard]] bool emitNewPrivateNames(TaggedParserAtomIndex privateBrandName, 1025 ListNode* classMembers); 1026 1027 [[nodiscard]] js::UniquePtr<ImmutableScriptData> createImmutableScriptData( 1028 JSContext* cx); 1029 1030 private: 1031 [[nodiscard]] bool allowSelfHostedIter(ParseNode* parseNode); 1032 1033 [[nodiscard]] bool emitSelfHostedGetBuiltinConstructorOrPrototype( 1034 BinaryNode* callNode, bool isConstructor); 1035 1036 public: 1037 #if defined(DEBUG) || defined(JS_JITSPEW) 1038 void dumpAtom(TaggedParserAtomIndex index) const; 1039 #endif 1040 }; 1041 1042 class MOZ_RAII AutoCheckUnstableEmitterScope { 1043 #ifdef DEBUG 1044 bool prev_; 1045 BytecodeEmitter* bce_; 1046 #endif 1047 1048 public: 1049 AutoCheckUnstableEmitterScope() = delete; AutoCheckUnstableEmitterScope(BytecodeEmitter * bce)1050 explicit AutoCheckUnstableEmitterScope(BytecodeEmitter* bce) 1051 #ifdef DEBUG 1052 : bce_(bce) 1053 #endif 1054 { 1055 #ifdef DEBUG 1056 prev_ = bce_->unstableEmitterScope; 1057 bce_->unstableEmitterScope = true; 1058 #endif 1059 } ~AutoCheckUnstableEmitterScope()1060 ~AutoCheckUnstableEmitterScope() { 1061 #ifdef DEBUG 1062 bce_->unstableEmitterScope = prev_; 1063 #endif 1064 } 1065 }; 1066 1067 } /* namespace frontend */ 1068 } /* namespace js */ 1069 1070 #endif /* frontend_BytecodeEmitter_h */ 1071