BytecodeEmitter.cpp (396503B)
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 /* 8 * JS bytecode generation. 9 */ 10 11 #include "frontend/BytecodeEmitter.h" 12 13 #include "mozilla/Casting.h" // mozilla::AssertedCast 14 #include "mozilla/DebugOnly.h" // mozilla::DebugOnly 15 #include "mozilla/FloatingPoint.h" // mozilla::NumberEqualsInt32, mozilla::NumberIsInt32 16 #include "mozilla/HashTable.h" // mozilla::HashSet 17 #include "mozilla/Maybe.h" // mozilla::{Maybe,Nothing,Some} 18 #include "mozilla/Saturate.h" 19 #include "mozilla/Variant.h" // mozilla::AsVariant 20 21 #include <algorithm> 22 #include <iterator> 23 #include <string.h> 24 25 #include "jstypes.h" // JS_BIT 26 27 #include "frontend/AbstractScopePtr.h" // ScopeIndex 28 #include "frontend/BytecodeControlStructures.h" // NestableControl, BreakableControl, LabelControl, LoopControl, TryFinallyControl 29 #include "frontend/CallOrNewEmitter.h" // CallOrNewEmitter 30 #include "frontend/CForEmitter.h" // CForEmitter 31 #include "frontend/DecoratorEmitter.h" // DecoratorEmitter 32 #include "frontend/DefaultEmitter.h" // DefaultEmitter 33 #include "frontend/DoWhileEmitter.h" // DoWhileEmitter 34 #include "frontend/ElemOpEmitter.h" // ElemOpEmitter 35 #include "frontend/EmitterScope.h" // EmitterScope 36 #include "frontend/ExpressionStatementEmitter.h" // ExpressionStatementEmitter 37 #include "frontend/ForInEmitter.h" // ForInEmitter 38 #include "frontend/ForOfEmitter.h" // ForOfEmitter 39 #include "frontend/FunctionEmitter.h" // FunctionEmitter, FunctionScriptEmitter, FunctionParamsEmitter 40 #include "frontend/IfEmitter.h" // IfEmitter, InternalIfEmitter, CondEmitter 41 #include "frontend/LabelEmitter.h" // LabelEmitter 42 #include "frontend/LexicalScopeEmitter.h" // LexicalScopeEmitter 43 #include "frontend/ModuleSharedContext.h" // ModuleSharedContext 44 #include "frontend/NameAnalysisTypes.h" // PrivateNameKind 45 #include "frontend/NameFunctions.h" // NameFunctions 46 #include "frontend/NameOpEmitter.h" // NameOpEmitter 47 #include "frontend/ObjectEmitter.h" // PropertyEmitter, ObjectEmitter, ClassEmitter 48 #include "frontend/OptionalEmitter.h" // OptionalEmitter 49 #include "frontend/ParseContext.h" // ParseContext::Scope 50 #include "frontend/ParseNode.h" // ParseNodeKind, ParseNode and subclasses 51 #include "frontend/Parser.h" // Parser 52 #include "frontend/ParserAtom.h" // ParserAtomsTable, ParserAtom 53 #include "frontend/PrivateOpEmitter.h" // PrivateOpEmitter 54 #include "frontend/PropOpEmitter.h" // PropOpEmitter 55 #include "frontend/SourceNotes.h" // SrcNote, SrcNoteType, SrcNoteWriter 56 #include "frontend/SwitchEmitter.h" // SwitchEmitter 57 #include "frontend/TaggedParserAtomIndexHasher.h" // TaggedParserAtomIndexHasher 58 #include "frontend/TDZCheckCache.h" // TDZCheckCache 59 #include "frontend/TryEmitter.h" // TryEmitter 60 #include "frontend/UsingEmitter.h" // UsingEmitter 61 #include "frontend/WhileEmitter.h" // WhileEmitter 62 #include "js/ColumnNumber.h" // JS::LimitedColumnNumberOneOrigin, JS::ColumnNumberOffset 63 #include "js/friend/ErrorMessages.h" // JSMSG_* 64 #include "js/friend/StackLimits.h" // AutoCheckRecursionLimit 65 #include "util/StringBuilder.h" // StringBuilder 66 #include "vm/BytecodeUtil.h" // JOF_*, IsArgOp, IsLocalOp, SET_UINT24, SET_ICINDEX, BytecodeFallsThrough, BytecodeIsJumpTarget 67 #include "vm/CompletionKind.h" // CompletionKind 68 #include "vm/ConstantCompareOperand.h" // ConstantCompareOperand 69 #include "vm/FunctionPrefixKind.h" // FunctionPrefixKind 70 #include "vm/GeneratorObject.h" // AbstractGeneratorObject 71 #include "vm/Opcodes.h" // JSOp, JSOpLength_* 72 #include "vm/PropMap.h" // SharedPropMap::MaxPropsForNonDictionary 73 #include "vm/Scope.h" // GetScopeDataTrailingNames 74 #include "vm/SharedStencil.h" // ScopeNote 75 #include "vm/ThrowMsgKind.h" // ThrowMsgKind 76 #include "vm/TypeofEqOperand.h" // TypeofEqOperand 77 78 using namespace js; 79 using namespace js::frontend; 80 81 using mozilla::AssertedCast; 82 using mozilla::AsVariant; 83 using mozilla::DebugOnly; 84 using mozilla::Maybe; 85 using mozilla::Nothing; 86 using mozilla::NumberEqualsInt32; 87 using mozilla::NumberIsInt32; 88 using mozilla::Some; 89 90 static bool ParseNodeRequiresSpecialLineNumberNotes(ParseNode* pn) { 91 // The few node types listed below are exceptions to the usual 92 // location-source-note-emitting code in BytecodeEmitter::emitTree(). 93 // Single-line `while` loops and C-style `for` loops require careful 94 // handling to avoid strange stepping behavior. 95 // Functions usually shouldn't have location information (bug 1431202). 96 97 ParseNodeKind kind = pn->getKind(); 98 return kind == ParseNodeKind::WhileStmt || kind == ParseNodeKind::ForStmt || 99 kind == ParseNodeKind::Function; 100 } 101 102 static bool NeedsFieldInitializer(ParseNode* member, bool inStaticContext) { 103 // For the purposes of bytecode emission, StaticClassBlocks are treated as if 104 // they were static initializers. 105 return (member->is<StaticClassBlock>() && inStaticContext) || 106 (member->is<ClassField>() && 107 member->as<ClassField>().isStatic() == inStaticContext); 108 } 109 110 static bool NeedsAccessorInitializer(ParseNode* member, bool isStatic) { 111 if (isStatic) { 112 return false; 113 } 114 return member->is<ClassMethod>() && 115 member->as<ClassMethod>().name().isKind(ParseNodeKind::PrivateName) && 116 !member->as<ClassMethod>().isStatic() && 117 member->as<ClassMethod>().accessorType() != AccessorType::None; 118 } 119 120 static bool ShouldSuppressBreakpointsAndSourceNotes( 121 SharedContext* sc, BytecodeEmitter::EmitterMode emitterMode) { 122 // Suppress for all self-hosting code. 123 if (emitterMode == BytecodeEmitter::EmitterMode::SelfHosting) { 124 return true; 125 } 126 127 // Suppress for synthesized class constructors. 128 if (sc->isFunctionBox()) { 129 FunctionBox* funbox = sc->asFunctionBox(); 130 return funbox->isSyntheticFunction() && funbox->isClassConstructor(); 131 } 132 133 return false; 134 } 135 136 BytecodeEmitter::BytecodeEmitter(BytecodeEmitter* parent, FrontendContext* fc, 137 SharedContext* sc, 138 const ErrorReporter& errorReporter, 139 CompilationState& compilationState, 140 EmitterMode emitterMode) 141 : sc(sc), 142 fc(fc), 143 parent(parent), 144 bytecodeSection_(fc, sc->extent().lineno, 145 JS::LimitedColumnNumberOneOrigin(sc->extent().column)), 146 perScriptData_(fc, compilationState), 147 errorReporter_(errorReporter), 148 compilationState(compilationState), 149 suppressBreakpointsAndSourceNotes( 150 ShouldSuppressBreakpointsAndSourceNotes(sc, emitterMode)), 151 emitterMode(emitterMode) { 152 MOZ_ASSERT_IF(parent, fc == parent->fc); 153 } 154 155 BytecodeEmitter::BytecodeEmitter(BytecodeEmitter* parent, SharedContext* sc) 156 : BytecodeEmitter(parent, parent->fc, sc, parent->errorReporter_, 157 parent->compilationState, parent->emitterMode) {} 158 159 BytecodeEmitter::BytecodeEmitter(FrontendContext* fc, 160 const EitherParser& parser, SharedContext* sc, 161 CompilationState& compilationState, 162 EmitterMode emitterMode) 163 : BytecodeEmitter(nullptr, fc, sc, parser.errorReporter(), compilationState, 164 emitterMode) { 165 ep_.emplace(parser); 166 } 167 168 void BytecodeEmitter::initFromBodyPosition(TokenPos bodyPosition) { 169 setScriptStartOffsetIfUnset(bodyPosition.begin); 170 setFunctionBodyEndPos(bodyPosition.end); 171 } 172 173 bool BytecodeEmitter::init() { 174 if (!parent) { 175 if (!compilationState.prepareSharedDataStorage(fc)) { 176 return false; 177 } 178 } 179 return perScriptData_.init(fc); 180 } 181 182 bool BytecodeEmitter::init(TokenPos bodyPosition) { 183 initFromBodyPosition(bodyPosition); 184 return init(); 185 } 186 187 template <typename T> 188 T* BytecodeEmitter::findInnermostNestableControl() const { 189 return NestableControl::findNearest<T>(innermostNestableControl); 190 } 191 192 template <typename T, typename Predicate /* (T*) -> bool */> 193 T* BytecodeEmitter::findInnermostNestableControl(Predicate predicate) const { 194 return NestableControl::findNearest<T>(innermostNestableControl, predicate); 195 } 196 197 NameLocation BytecodeEmitter::lookupName(TaggedParserAtomIndex name) { 198 return innermostEmitterScope()->lookup(this, name); 199 } 200 201 void BytecodeEmitter::lookupPrivate(TaggedParserAtomIndex name, 202 NameLocation& loc, 203 Maybe<NameLocation>& brandLoc) { 204 innermostEmitterScope()->lookupPrivate(this, name, loc, brandLoc); 205 } 206 207 Maybe<NameLocation> BytecodeEmitter::locationOfNameBoundInScope( 208 TaggedParserAtomIndex name, EmitterScope* target) { 209 return innermostEmitterScope()->locationBoundInScope(name, target); 210 } 211 212 template <typename T> 213 Maybe<NameLocation> BytecodeEmitter::locationOfNameBoundInScopeType( 214 TaggedParserAtomIndex name, EmitterScope* source) { 215 EmitterScope* aScope = source; 216 while (!aScope->scope(this).is<T>()) { 217 aScope = aScope->enclosingInFrame(); 218 } 219 return source->locationBoundInScope(name, aScope); 220 } 221 222 bool BytecodeEmitter::markStepBreakpoint() { 223 if (skipBreakpointSrcNotes()) { 224 return true; 225 } 226 227 if (!newSrcNote(SrcNoteType::BreakpointStepSep)) { 228 return false; 229 } 230 231 // We track the location of the most recent separator for use in 232 // markSimpleBreakpoint. Note that this means that the position must already 233 // be set before markStepBreakpoint is called. 234 bytecodeSection().updateSeparatorPosition(); 235 236 return true; 237 } 238 239 bool BytecodeEmitter::markSimpleBreakpoint() { 240 if (skipBreakpointSrcNotes()) { 241 return true; 242 } 243 244 // If a breakable call ends up being the same location as the most recent 245 // expression start, we need to skip marking it breakable in order to avoid 246 // having two breakpoints with the same line/column position. 247 // Note: This assumes that the position for the call has already been set. 248 if (!bytecodeSection().isDuplicateLocation()) { 249 if (!newSrcNote(SrcNoteType::Breakpoint)) { 250 return false; 251 } 252 } 253 254 return true; 255 } 256 257 bool BytecodeEmitter::emitCheck(JSOp op, ptrdiff_t delta, 258 BytecodeOffset* offset) { 259 size_t oldLength = bytecodeSection().code().length(); 260 *offset = BytecodeOffset(oldLength); 261 262 size_t newLength = oldLength + size_t(delta); 263 if (MOZ_UNLIKELY(newLength > MaxBytecodeLength)) { 264 ReportAllocationOverflow(fc); 265 return false; 266 } 267 268 if (!bytecodeSection().code().growByUninitialized(delta)) { 269 return false; 270 } 271 272 if (BytecodeOpHasIC(op)) { 273 // Even if every bytecode op is a JOF_IC op and the function has ARGC_LIMIT 274 // arguments, numICEntries cannot overflow. 275 static_assert(MaxBytecodeLength + 1 /* this */ + ARGC_LIMIT <= UINT32_MAX, 276 "numICEntries must not overflow"); 277 bytecodeSection().incrementNumICEntries(); 278 } 279 280 return true; 281 } 282 283 #ifdef DEBUG 284 bool BytecodeEmitter::checkStrictOrSloppy(JSOp op) const { 285 if (IsCheckStrictOp(op) && !sc->strict()) { 286 return false; 287 } 288 if (IsCheckSloppyOp(op) && sc->strict()) { 289 return false; 290 } 291 return true; 292 } 293 #endif 294 295 bool BytecodeEmitter::emit1(JSOp op) { 296 MOZ_ASSERT(checkStrictOrSloppy(op)); 297 MOZ_ASSERT(GetOpLength(op) == 1); 298 299 BytecodeOffset offset; 300 if (!emitCheck(op, 1, &offset)) { 301 return false; 302 } 303 304 jsbytecode* code = bytecodeSection().code(offset); 305 code[0] = jsbytecode(op); 306 bytecodeSection().updateDepth(op, offset); 307 return true; 308 } 309 310 bool BytecodeEmitter::emit2(JSOp op, uint8_t op1) { 311 MOZ_ASSERT(checkStrictOrSloppy(op)); 312 MOZ_ASSERT(GetOpLength(op) == 2); 313 314 BytecodeOffset offset; 315 if (!emitCheck(op, 2, &offset)) { 316 return false; 317 } 318 319 jsbytecode* code = bytecodeSection().code(offset); 320 code[0] = jsbytecode(op); 321 code[1] = jsbytecode(op1); 322 bytecodeSection().updateDepth(op, offset); 323 return true; 324 } 325 326 bool BytecodeEmitter::emit3(JSOp op, jsbytecode op1, jsbytecode op2) { 327 MOZ_ASSERT(checkStrictOrSloppy(op)); 328 MOZ_ASSERT(GetOpLength(op) == 3); 329 330 /* These should filter through emitVarOp. */ 331 MOZ_ASSERT(!IsArgOp(op)); 332 MOZ_ASSERT(!IsLocalOp(op)); 333 334 BytecodeOffset offset; 335 if (!emitCheck(op, 3, &offset)) { 336 return false; 337 } 338 339 jsbytecode* code = bytecodeSection().code(offset); 340 code[0] = jsbytecode(op); 341 code[1] = op1; 342 code[2] = op2; 343 bytecodeSection().updateDepth(op, offset); 344 return true; 345 } 346 347 bool BytecodeEmitter::emitN(JSOp op, size_t extra, BytecodeOffset* offset) { 348 MOZ_ASSERT(checkStrictOrSloppy(op)); 349 ptrdiff_t length = 1 + ptrdiff_t(extra); 350 351 BytecodeOffset off; 352 if (!emitCheck(op, length, &off)) { 353 return false; 354 } 355 356 jsbytecode* code = bytecodeSection().code(off); 357 code[0] = jsbytecode(op); 358 /* The remaining |extra| bytes are set by the caller */ 359 360 /* 361 * Don't updateDepth if op's use-count comes from the immediate 362 * operand yet to be stored in the extra bytes after op. 363 */ 364 if (CodeSpec(op).nuses >= 0) { 365 bytecodeSection().updateDepth(op, off); 366 } 367 368 if (offset) { 369 *offset = off; 370 } 371 return true; 372 } 373 374 bool BytecodeEmitter::emitJumpTargetOp(JSOp op, BytecodeOffset* off) { 375 MOZ_ASSERT(BytecodeIsJumpTarget(op)); 376 377 // Record the current IC-entry index at start of this op. 378 uint32_t numEntries = bytecodeSection().numICEntries(); 379 380 size_t n = GetOpLength(op) - 1; 381 MOZ_ASSERT(GetOpLength(op) >= 1 + ICINDEX_LEN); 382 383 if (!emitN(op, n, off)) { 384 return false; 385 } 386 387 SET_ICINDEX(bytecodeSection().code(*off), numEntries); 388 return true; 389 } 390 391 bool BytecodeEmitter::emitJumpTarget(JumpTarget* target) { 392 BytecodeOffset off = bytecodeSection().offset(); 393 394 // Alias consecutive jump targets. 395 if (bytecodeSection().lastTargetOffset().valid() && 396 off == bytecodeSection().lastTargetOffset() + 397 BytecodeOffsetDiff(JSOpLength_JumpTarget)) { 398 target->offset = bytecodeSection().lastTargetOffset(); 399 return true; 400 } 401 402 target->offset = off; 403 bytecodeSection().setLastTargetOffset(off); 404 405 BytecodeOffset opOff; 406 return emitJumpTargetOp(JSOp::JumpTarget, &opOff); 407 } 408 409 bool BytecodeEmitter::emitJumpNoFallthrough(JSOp op, JumpList* jump) { 410 BytecodeOffset offset; 411 if (!emitCheck(op, 5, &offset)) { 412 return false; 413 } 414 415 jsbytecode* code = bytecodeSection().code(offset); 416 code[0] = jsbytecode(op); 417 MOZ_ASSERT(!jump->offset.valid() || 418 (0 <= jump->offset.value() && jump->offset < offset)); 419 jump->push(bytecodeSection().code(BytecodeOffset(0)), offset); 420 bytecodeSection().updateDepth(op, offset); 421 return true; 422 } 423 424 bool BytecodeEmitter::emitJump(JSOp op, JumpList* jump) { 425 if (!emitJumpNoFallthrough(op, jump)) { 426 return false; 427 } 428 if (BytecodeFallsThrough(op)) { 429 JumpTarget fallthrough; 430 if (!emitJumpTarget(&fallthrough)) { 431 return false; 432 } 433 } 434 return true; 435 } 436 437 void BytecodeEmitter::patchJumpsToTarget(JumpList jump, JumpTarget target) { 438 MOZ_ASSERT( 439 !jump.offset.valid() || 440 (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset())); 441 MOZ_ASSERT(0 <= target.offset.value() && 442 target.offset <= bytecodeSection().offset()); 443 MOZ_ASSERT_IF( 444 jump.offset.valid() && 445 target.offset + BytecodeOffsetDiff(4) <= bytecodeSection().offset(), 446 BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))); 447 jump.patchAll(bytecodeSection().code(BytecodeOffset(0)), target); 448 } 449 450 bool BytecodeEmitter::emitJumpTargetAndPatch(JumpList jump) { 451 if (!jump.offset.valid()) { 452 return true; 453 } 454 JumpTarget target; 455 if (!emitJumpTarget(&target)) { 456 return false; 457 } 458 patchJumpsToTarget(jump, target); 459 return true; 460 } 461 462 bool BytecodeEmitter::emitCall(JSOp op, uint16_t argc, 463 const Maybe<uint32_t>& sourceCoordOffset) { 464 if (sourceCoordOffset.isSome()) { 465 if (!updateSourceCoordNotes(*sourceCoordOffset)) { 466 return false; 467 } 468 } 469 return emit3(op, ARGC_LO(argc), ARGC_HI(argc)); 470 } 471 472 bool BytecodeEmitter::emitCall(JSOp op, uint16_t argc, ParseNode* pn) { 473 return emitCall(op, argc, pn ? Some(pn->pn_pos.begin) : Nothing()); 474 } 475 476 bool BytecodeEmitter::emitDupAt(unsigned slotFromTop, unsigned count) { 477 MOZ_ASSERT(slotFromTop < unsigned(bytecodeSection().stackDepth())); 478 MOZ_ASSERT(slotFromTop + 1 >= count); 479 480 if (slotFromTop == 0 && count == 1) { 481 return emit1(JSOp::Dup); 482 } 483 484 if (slotFromTop == 1 && count == 2) { 485 return emit1(JSOp::Dup2); 486 } 487 488 if (slotFromTop >= Bit(24)) { 489 reportError(nullptr, JSMSG_TOO_MANY_LOCALS); 490 return false; 491 } 492 493 for (unsigned i = 0; i < count; i++) { 494 BytecodeOffset off; 495 if (!emitN(JSOp::DupAt, 3, &off)) { 496 return false; 497 } 498 499 jsbytecode* pc = bytecodeSection().code(off); 500 SET_UINT24(pc, slotFromTop); 501 } 502 503 return true; 504 } 505 506 bool BytecodeEmitter::emitPopN(unsigned n) { 507 MOZ_ASSERT(n != 0); 508 509 if (n == 1) { 510 return emit1(JSOp::Pop); 511 } 512 513 // 2 JSOp::Pop instructions (2 bytes) are shorter than JSOp::PopN (3 bytes). 514 if (n == 2) { 515 return emit1(JSOp::Pop) && emit1(JSOp::Pop); 516 } 517 518 return emitUint16Operand(JSOp::PopN, n); 519 } 520 521 bool BytecodeEmitter::emitPickN(uint8_t n) { 522 MOZ_ASSERT(n != 0); 523 524 if (n == 1) { 525 return emit1(JSOp::Swap); 526 } 527 528 return emit2(JSOp::Pick, n); 529 } 530 531 bool BytecodeEmitter::emitUnpickN(uint8_t n) { 532 MOZ_ASSERT(n != 0); 533 534 if (n == 1) { 535 return emit1(JSOp::Swap); 536 } 537 538 return emit2(JSOp::Unpick, n); 539 } 540 541 bool BytecodeEmitter::emitCheckIsObj(CheckIsObjectKind kind) { 542 return emit2(JSOp::CheckIsObj, uint8_t(kind)); 543 } 544 545 bool BytecodeEmitter::emitBuiltinObject(BuiltinObjectKind kind) { 546 return emit2(JSOp::BuiltinObject, uint8_t(kind)); 547 } 548 549 /* Updates line number notes, not column notes. */ 550 bool BytecodeEmitter::updateLineNumberNotes(uint32_t offset) { 551 if (skipLocationSrcNotes()) { 552 return true; 553 } 554 555 const ErrorReporter& er = errorReporter(); 556 std::optional<bool> onThisLineStatus = 557 er.isOnThisLine(offset, bytecodeSection().currentLine()); 558 if (!onThisLineStatus.has_value()) { 559 er.errorNoOffset(JSMSG_OUT_OF_MEMORY); 560 return false; 561 } 562 563 bool onThisLine = *onThisLineStatus; 564 565 if (!onThisLine) { 566 unsigned line = er.lineAt(offset); 567 unsigned delta = line - bytecodeSection().currentLine(); 568 569 // If we use a `SetLine` note below, we want it to be relative to the 570 // scripts initial line number for better chance of sharing. 571 unsigned initialLine = sc->extent().lineno; 572 MOZ_ASSERT(line >= initialLine); 573 574 /* 575 * Encode any change in the current source line number by using 576 * either several SrcNoteType::NewLine notes or just one 577 * SrcNoteType::SetLine note, whichever consumes less space. 578 * 579 * NB: We handle backward line number deltas (possible with for 580 * loops where the update part is emitted after the body, but its 581 * line number is <= any line number in the body) here by letting 582 * unsigned delta_ wrap to a very large number, which triggers a 583 * SrcNoteType::SetLine. 584 */ 585 bytecodeSection().setCurrentLine(line, offset); 586 if (delta >= SrcNote::SetLine::lengthFor(line, initialLine)) { 587 if (!newSrcNote2(SrcNoteType::SetLine, 588 SrcNote::SetLine::toOperand(line, initialLine))) { 589 return false; 590 } 591 } else { 592 do { 593 if (!newSrcNote(SrcNoteType::NewLine)) { 594 return false; 595 } 596 } while (--delta != 0); 597 } 598 599 bytecodeSection().updateSeparatorPositionIfPresent(); 600 } 601 return true; 602 } 603 604 /* Updates the line number and column number information in the source notes. */ 605 bool BytecodeEmitter::updateSourceCoordNotes(uint32_t offset) { 606 if (skipLocationSrcNotes()) { 607 return true; 608 } 609 610 if (!updateLineNumberNotes(offset)) { 611 return false; 612 } 613 614 JS::LimitedColumnNumberOneOrigin columnIndex = 615 errorReporter().columnAt(offset); 616 617 // Assert colspan is always representable. 618 static_assert((0 - ptrdiff_t(JS::LimitedColumnNumberOneOrigin::Limit)) >= 619 SrcNote::ColSpan::MinColSpan); 620 static_assert((ptrdiff_t(JS::LimitedColumnNumberOneOrigin::Limit) - 0) <= 621 SrcNote::ColSpan::MaxColSpan); 622 623 JS::ColumnNumberOffset colspan = columnIndex - bytecodeSection().lastColumn(); 624 625 if (colspan != JS::ColumnNumberOffset::zero()) { 626 if (lastLineOnlySrcNoteIndex != LastSrcNoteIsNotLineOnly) { 627 MOZ_ASSERT(bytecodeSection().lastColumn() == 628 JS::LimitedColumnNumberOneOrigin()); 629 630 const SrcNotesVector& notes = bytecodeSection().notes(); 631 SrcNoteType type = notes[lastLineOnlySrcNoteIndex].type(); 632 if (type == SrcNoteType::NewLine) { 633 if (!convertLastNewLineToNewLineColumn(columnIndex)) { 634 return false; 635 } 636 } else { 637 MOZ_ASSERT(type == SrcNoteType::SetLine); 638 if (!convertLastSetLineToSetLineColumn(columnIndex)) { 639 return false; 640 } 641 } 642 } else { 643 if (!newSrcNote2(SrcNoteType::ColSpan, 644 SrcNote::ColSpan::toOperand(colspan))) { 645 return false; 646 } 647 } 648 bytecodeSection().setLastColumn(columnIndex, offset); 649 bytecodeSection().updateSeparatorPositionIfPresent(); 650 } 651 return true; 652 } 653 654 bool BytecodeEmitter::updateSourceCoordNotesIfNonLiteral(ParseNode* node) { 655 if (node->isLiteral()) { 656 return true; 657 } 658 return updateSourceCoordNotes(node->pn_pos.begin); 659 } 660 661 uint32_t BytecodeEmitter::getOffsetForLoop(ParseNode* nextpn) const { 662 // Try to give the JSOp::LoopHead the same line number as the next 663 // instruction. nextpn is often a block, in which case the next instruction 664 // typically comes from the first statement inside. 665 if (nextpn->is<LexicalScopeNode>()) { 666 nextpn = nextpn->as<LexicalScopeNode>().scopeBody(); 667 } 668 if (nextpn->isKind(ParseNodeKind::StatementList)) { 669 if (ParseNode* firstStatement = nextpn->as<ListNode>().head()) { 670 nextpn = firstStatement; 671 } 672 } 673 674 return nextpn->pn_pos.begin; 675 } 676 677 bool BytecodeEmitter::emitUint16Operand(JSOp op, uint32_t operand) { 678 MOZ_ASSERT(operand <= UINT16_MAX); 679 if (!emit3(op, UINT16_LO(operand), UINT16_HI(operand))) { 680 return false; 681 } 682 return true; 683 } 684 685 bool BytecodeEmitter::emitUint32Operand(JSOp op, uint32_t operand) { 686 BytecodeOffset off; 687 if (!emitN(op, 4, &off)) { 688 return false; 689 } 690 SET_UINT32(bytecodeSection().code(off), operand); 691 return true; 692 } 693 694 bool BytecodeEmitter::emitGoto(NestableControl* target, GotoKind kind) { 695 NonLocalExitControl nle(this, kind == GotoKind::Continue 696 ? NonLocalExitKind::Continue 697 : NonLocalExitKind::Break); 698 return nle.emitNonLocalJump(target); 699 } 700 701 AbstractScopePtr BytecodeEmitter::innermostScope() const { 702 return innermostEmitterScope()->scope(this); 703 } 704 705 ScopeIndex BytecodeEmitter::innermostScopeIndex() const { 706 return *innermostEmitterScope()->scopeIndex(this); 707 } 708 709 bool BytecodeEmitter::emitGCIndexOp(JSOp op, GCThingIndex index) { 710 MOZ_ASSERT(checkStrictOrSloppy(op)); 711 712 constexpr size_t OpLength = 1 + GCTHING_INDEX_LEN; 713 MOZ_ASSERT(GetOpLength(op) == OpLength); 714 715 BytecodeOffset offset; 716 if (!emitCheck(op, OpLength, &offset)) { 717 return false; 718 } 719 720 jsbytecode* code = bytecodeSection().code(offset); 721 code[0] = jsbytecode(op); 722 SET_GCTHING_INDEX(code, index); 723 bytecodeSection().updateDepth(op, offset); 724 return true; 725 } 726 727 bool BytecodeEmitter::emitAtomOp(JSOp op, TaggedParserAtomIndex atom) { 728 MOZ_ASSERT(atom); 729 730 // .generator lookups should be emitted as JSOp::GetAliasedVar instead of 731 // JSOp::GetName etc, to bypass |with| objects on the scope chain. 732 // It's safe to emit .this lookups though because |with| objects skip 733 // those. 734 MOZ_ASSERT_IF(op == JSOp::GetName || op == JSOp::GetGName, 735 atom != TaggedParserAtomIndex::WellKnown::dot_generator_()); 736 737 GCThingIndex index; 738 if (!makeAtomIndex(atom, ParserAtom::Atomize::Yes, &index)) { 739 return false; 740 } 741 742 return emitAtomOp(op, index); 743 } 744 745 bool BytecodeEmitter::emitAtomOp(JSOp op, GCThingIndex atomIndex) { 746 MOZ_ASSERT(JOF_OPTYPE(op) == JOF_ATOM); 747 #ifdef DEBUG 748 auto atom = perScriptData().gcThingList().getAtom(atomIndex); 749 MOZ_ASSERT(compilationState.parserAtoms.isInstantiatedAsJSAtom(atom)); 750 #endif 751 return emitGCIndexOp(op, atomIndex); 752 } 753 754 bool BytecodeEmitter::emitStringOp(JSOp op, TaggedParserAtomIndex atom) { 755 MOZ_ASSERT(atom); 756 GCThingIndex index; 757 if (!makeAtomIndex(atom, ParserAtom::Atomize::No, &index)) { 758 return false; 759 } 760 761 return emitStringOp(op, index); 762 } 763 764 bool BytecodeEmitter::emitStringOp(JSOp op, GCThingIndex atomIndex) { 765 MOZ_ASSERT(JOF_OPTYPE(op) == JOF_STRING); 766 return emitGCIndexOp(op, atomIndex); 767 } 768 769 bool BytecodeEmitter::emitInternedScopeOp(GCThingIndex index, JSOp op) { 770 MOZ_ASSERT(JOF_OPTYPE(op) == JOF_SCOPE); 771 MOZ_ASSERT(index < perScriptData().gcThingList().length()); 772 return emitGCIndexOp(op, index); 773 } 774 775 bool BytecodeEmitter::emitInternedObjectOp(GCThingIndex index, JSOp op) { 776 MOZ_ASSERT(JOF_OPTYPE(op) == JOF_OBJECT); 777 MOZ_ASSERT(index < perScriptData().gcThingList().length()); 778 return emitGCIndexOp(op, index); 779 } 780 781 bool BytecodeEmitter::emitRegExp(GCThingIndex index) { 782 return emitGCIndexOp(JSOp::RegExp, index); 783 } 784 785 bool BytecodeEmitter::emitLocalOp(JSOp op, uint32_t slot) { 786 MOZ_ASSERT(JOF_OPTYPE(op) != JOF_ENVCOORD); 787 MOZ_ASSERT(IsLocalOp(op)); 788 789 BytecodeOffset off; 790 if (!emitN(op, LOCALNO_LEN, &off)) { 791 return false; 792 } 793 794 SET_LOCALNO(bytecodeSection().code(off), slot); 795 return true; 796 } 797 798 bool BytecodeEmitter::emitArgOp(JSOp op, uint16_t slot) { 799 MOZ_ASSERT(IsArgOp(op)); 800 BytecodeOffset off; 801 if (!emitN(op, ARGNO_LEN, &off)) { 802 return false; 803 } 804 805 SET_ARGNO(bytecodeSection().code(off), slot); 806 return true; 807 } 808 809 bool BytecodeEmitter::emitEnvCoordOp(JSOp op, EnvironmentCoordinate ec) { 810 MOZ_ASSERT(JOF_OPTYPE(op) == JOF_ENVCOORD || 811 JOF_OPTYPE(op) == JOF_DEBUGCOORD); 812 813 constexpr size_t N = ENVCOORD_HOPS_LEN + ENVCOORD_SLOT_LEN; 814 MOZ_ASSERT(GetOpLength(op) == 1 + N); 815 816 BytecodeOffset off; 817 if (!emitN(op, N, &off)) { 818 return false; 819 } 820 821 jsbytecode* pc = bytecodeSection().code(off); 822 SET_ENVCOORD_HOPS(pc, ec.hops()); 823 pc += ENVCOORD_HOPS_LEN; 824 SET_ENVCOORD_SLOT(pc, ec.slot()); 825 pc += ENVCOORD_SLOT_LEN; 826 return true; 827 } 828 829 bool BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer) const { 830 AutoCheckRecursionLimit recursion(fc); 831 if (!recursion.check(fc)) { 832 return false; 833 } 834 835 restart: 836 837 switch (pn->getKind()) { 838 // Trivial cases with no side effects. 839 case ParseNodeKind::EmptyStmt: 840 case ParseNodeKind::TrueExpr: 841 case ParseNodeKind::FalseExpr: 842 case ParseNodeKind::NullExpr: 843 case ParseNodeKind::RawUndefinedExpr: 844 case ParseNodeKind::Elision: 845 case ParseNodeKind::Generator: 846 MOZ_ASSERT(pn->is<NullaryNode>()); 847 *answer = false; 848 return true; 849 850 case ParseNodeKind::ObjectPropertyName: 851 case ParseNodeKind::PrivateName: // no side effects, unlike 852 // ParseNodeKind::Name 853 case ParseNodeKind::StringExpr: 854 case ParseNodeKind::TemplateStringExpr: 855 MOZ_ASSERT(pn->is<NameNode>()); 856 *answer = false; 857 return true; 858 859 case ParseNodeKind::RegExpExpr: 860 MOZ_ASSERT(pn->is<RegExpLiteral>()); 861 *answer = false; 862 return true; 863 864 case ParseNodeKind::NumberExpr: 865 MOZ_ASSERT(pn->is<NumericLiteral>()); 866 *answer = false; 867 return true; 868 869 case ParseNodeKind::BigIntExpr: 870 MOZ_ASSERT(pn->is<BigIntLiteral>()); 871 *answer = false; 872 return true; 873 874 // |this| can throw in derived class constructors, including nested arrow 875 // functions or eval. 876 case ParseNodeKind::ThisExpr: 877 MOZ_ASSERT(pn->is<UnaryNode>()); 878 *answer = sc->needsThisTDZChecks(); 879 return true; 880 881 // |new.target| doesn't have any side-effects. 882 case ParseNodeKind::NewTargetExpr: { 883 MOZ_ASSERT(pn->is<NewTargetNode>()); 884 *answer = false; 885 return true; 886 } 887 888 // Trivial binary nodes with more token pos holders. 889 case ParseNodeKind::ImportMetaExpr: { 890 MOZ_ASSERT(pn->as<BinaryNode>().left()->isKind(ParseNodeKind::PosHolder)); 891 MOZ_ASSERT( 892 pn->as<BinaryNode>().right()->isKind(ParseNodeKind::PosHolder)); 893 *answer = false; 894 return true; 895 } 896 897 case ParseNodeKind::BreakStmt: 898 MOZ_ASSERT(pn->is<BreakStatement>()); 899 *answer = true; 900 return true; 901 902 case ParseNodeKind::ContinueStmt: 903 MOZ_ASSERT(pn->is<ContinueStatement>()); 904 *answer = true; 905 return true; 906 907 case ParseNodeKind::DebuggerStmt: 908 MOZ_ASSERT(pn->is<DebuggerStatement>()); 909 *answer = true; 910 return true; 911 912 // Watch out for getters! 913 case ParseNodeKind::OptionalDotExpr: 914 case ParseNodeKind::DotExpr: 915 case ParseNodeKind::ArgumentsLength: 916 MOZ_ASSERT(pn->is<BinaryNode>()); 917 *answer = true; 918 return true; 919 920 // Unary cases with side effects only if the child has them. 921 case ParseNodeKind::TypeOfExpr: 922 case ParseNodeKind::VoidExpr: 923 case ParseNodeKind::NotExpr: 924 return checkSideEffects(pn->as<UnaryNode>().kid(), answer); 925 926 // Even if the name expression is effect-free, performing ToPropertyKey on 927 // it might not be effect-free: 928 // 929 // RegExp.prototype.toString = () => { throw 42; }; 930 // ({ [/regex/]: 0 }); // ToPropertyKey(/regex/) throws 42 931 // 932 // function Q() { 933 // ({ [new.target]: 0 }); 934 // } 935 // Q.toString = () => { throw 17; }; 936 // new Q; // new.target will be Q, ToPropertyKey(Q) throws 17 937 case ParseNodeKind::ComputedName: 938 MOZ_ASSERT(pn->is<UnaryNode>()); 939 *answer = true; 940 return true; 941 942 // Looking up or evaluating the associated name could throw. 943 case ParseNodeKind::TypeOfNameExpr: 944 MOZ_ASSERT(pn->is<UnaryNode>()); 945 *answer = true; 946 return true; 947 948 // This unary case has side effects on the enclosing object, sure. But 949 // that's not the question this function answers: it's whether the 950 // operation may have a side effect on something *other* than the result 951 // of the overall operation in which it's embedded. The answer to that 952 // is no, because an object literal having a mutated prototype only 953 // produces a value, without affecting anything else. 954 case ParseNodeKind::MutateProto: 955 return checkSideEffects(pn->as<UnaryNode>().kid(), answer); 956 957 // Unary cases with obvious side effects. 958 case ParseNodeKind::PreIncrementExpr: 959 case ParseNodeKind::PostIncrementExpr: 960 case ParseNodeKind::PreDecrementExpr: 961 case ParseNodeKind::PostDecrementExpr: 962 case ParseNodeKind::ThrowStmt: 963 MOZ_ASSERT(pn->is<UnaryNode>()); 964 *answer = true; 965 return true; 966 967 // These might invoke valueOf/toString, even with a subexpression without 968 // side effects! Consider |+{ valueOf: null, toString: null }|. 969 case ParseNodeKind::BitNotExpr: 970 case ParseNodeKind::PosExpr: 971 case ParseNodeKind::NegExpr: 972 MOZ_ASSERT(pn->is<UnaryNode>()); 973 *answer = true; 974 return true; 975 976 // This invokes the (user-controllable) iterator protocol. 977 case ParseNodeKind::Spread: 978 MOZ_ASSERT(pn->is<UnaryNode>()); 979 *answer = true; 980 return true; 981 982 case ParseNodeKind::InitialYield: 983 case ParseNodeKind::YieldStarExpr: 984 case ParseNodeKind::YieldExpr: 985 case ParseNodeKind::AwaitExpr: 986 MOZ_ASSERT(pn->is<UnaryNode>()); 987 *answer = true; 988 return true; 989 990 // Deletion generally has side effects, even if isolated cases have none. 991 case ParseNodeKind::DeleteNameExpr: 992 case ParseNodeKind::DeletePropExpr: 993 case ParseNodeKind::DeleteElemExpr: 994 case ParseNodeKind::DeleteOptionalChainExpr: 995 MOZ_ASSERT(pn->is<UnaryNode>()); 996 *answer = true; 997 return true; 998 999 // Deletion of a non-Reference expression has side effects only through 1000 // evaluating the expression. 1001 case ParseNodeKind::DeleteExpr: { 1002 ParseNode* expr = pn->as<UnaryNode>().kid(); 1003 return checkSideEffects(expr, answer); 1004 } 1005 1006 case ParseNodeKind::ExpressionStmt: 1007 return checkSideEffects(pn->as<UnaryNode>().kid(), answer); 1008 1009 // Binary cases with obvious side effects. 1010 case ParseNodeKind::InitExpr: 1011 *answer = true; 1012 return true; 1013 1014 case ParseNodeKind::AssignExpr: 1015 case ParseNodeKind::AddAssignExpr: 1016 case ParseNodeKind::SubAssignExpr: 1017 case ParseNodeKind::CoalesceAssignExpr: 1018 case ParseNodeKind::OrAssignExpr: 1019 case ParseNodeKind::AndAssignExpr: 1020 case ParseNodeKind::BitOrAssignExpr: 1021 case ParseNodeKind::BitXorAssignExpr: 1022 case ParseNodeKind::BitAndAssignExpr: 1023 case ParseNodeKind::LshAssignExpr: 1024 case ParseNodeKind::RshAssignExpr: 1025 case ParseNodeKind::UrshAssignExpr: 1026 case ParseNodeKind::MulAssignExpr: 1027 case ParseNodeKind::DivAssignExpr: 1028 case ParseNodeKind::ModAssignExpr: 1029 case ParseNodeKind::PowAssignExpr: 1030 MOZ_ASSERT(pn->is<AssignmentNode>()); 1031 *answer = true; 1032 return true; 1033 1034 case ParseNodeKind::SetThis: 1035 MOZ_ASSERT(pn->is<BinaryNode>()); 1036 *answer = true; 1037 return true; 1038 1039 case ParseNodeKind::StatementList: 1040 // Strict equality operations and short circuit operators are well-behaved 1041 // and perform no conversions. 1042 case ParseNodeKind::CoalesceExpr: 1043 case ParseNodeKind::OrExpr: 1044 case ParseNodeKind::AndExpr: 1045 case ParseNodeKind::StrictEqExpr: 1046 case ParseNodeKind::StrictNeExpr: 1047 // Any subexpression of a comma expression could be effectful. 1048 case ParseNodeKind::CommaExpr: 1049 MOZ_ASSERT(!pn->as<ListNode>().empty()); 1050 [[fallthrough]]; 1051 // Subcomponents of a literal may be effectful. 1052 case ParseNodeKind::ArrayExpr: 1053 case ParseNodeKind::ObjectExpr: 1054 for (ParseNode* item : pn->as<ListNode>().contents()) { 1055 if (!checkSideEffects(item, answer)) { 1056 return false; 1057 } 1058 if (*answer) { 1059 return true; 1060 } 1061 } 1062 return true; 1063 1064 #ifdef ENABLE_DECORATORS 1065 case ParseNodeKind::DecoratorList: 1066 MOZ_CRASH("Decorators are not supported yet"); 1067 #endif 1068 1069 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT 1070 case ParseNodeKind::UsingDecl: 1071 case ParseNodeKind::AwaitUsingDecl: 1072 MOZ_CRASH("Using declarations are not supported yet"); 1073 #endif 1074 1075 // Most other binary operations (parsed as lists in SpiderMonkey) may 1076 // perform conversions triggering side effects. Math operations perform 1077 // ToNumber and may fail invoking invalid user-defined toString/valueOf: 1078 // |5 < { toString: null }|. |instanceof| throws if provided a 1079 // non-object constructor: |null instanceof null|. |in| throws if given 1080 // a non-object RHS: |5 in null|. 1081 case ParseNodeKind::BitOrExpr: 1082 case ParseNodeKind::BitXorExpr: 1083 case ParseNodeKind::BitAndExpr: 1084 case ParseNodeKind::EqExpr: 1085 case ParseNodeKind::NeExpr: 1086 case ParseNodeKind::LtExpr: 1087 case ParseNodeKind::LeExpr: 1088 case ParseNodeKind::GtExpr: 1089 case ParseNodeKind::GeExpr: 1090 case ParseNodeKind::InstanceOfExpr: 1091 case ParseNodeKind::InExpr: 1092 case ParseNodeKind::PrivateInExpr: 1093 case ParseNodeKind::LshExpr: 1094 case ParseNodeKind::RshExpr: 1095 case ParseNodeKind::UrshExpr: 1096 case ParseNodeKind::AddExpr: 1097 case ParseNodeKind::SubExpr: 1098 case ParseNodeKind::MulExpr: 1099 case ParseNodeKind::DivExpr: 1100 case ParseNodeKind::ModExpr: 1101 case ParseNodeKind::PowExpr: 1102 MOZ_ASSERT(pn->as<ListNode>().count() >= 2); 1103 *answer = true; 1104 return true; 1105 1106 case ParseNodeKind::PropertyDefinition: 1107 case ParseNodeKind::Case: { 1108 BinaryNode* node = &pn->as<BinaryNode>(); 1109 if (!checkSideEffects(node->left(), answer)) { 1110 return false; 1111 } 1112 if (*answer) { 1113 return true; 1114 } 1115 return checkSideEffects(node->right(), answer); 1116 } 1117 1118 // More getters. 1119 case ParseNodeKind::ElemExpr: 1120 case ParseNodeKind::OptionalElemExpr: 1121 MOZ_ASSERT(pn->is<BinaryNode>()); 1122 *answer = true; 1123 return true; 1124 1125 // Throws if the operand is not of the right class. Can also call a private 1126 // getter. 1127 case ParseNodeKind::PrivateMemberExpr: 1128 case ParseNodeKind::OptionalPrivateMemberExpr: 1129 *answer = true; 1130 return true; 1131 1132 // These affect visible names in this code, or in other code. 1133 case ParseNodeKind::ImportDecl: 1134 case ParseNodeKind::ExportFromStmt: 1135 case ParseNodeKind::ExportDefaultStmt: 1136 MOZ_ASSERT(pn->is<BinaryNode>()); 1137 *answer = true; 1138 return true; 1139 1140 // Likewise. 1141 case ParseNodeKind::ExportStmt: 1142 MOZ_ASSERT(pn->is<UnaryNode>()); 1143 *answer = true; 1144 return true; 1145 1146 case ParseNodeKind::CallImportExpr: 1147 case ParseNodeKind::CallImportSpec: 1148 MOZ_ASSERT(pn->is<BinaryNode>()); 1149 *answer = true; 1150 return true; 1151 1152 // Every part of a loop might be effect-free, but looping infinitely *is* 1153 // an effect. (Language lawyer trivia: C++ says threads can be assumed 1154 // to exit or have side effects, C++14 [intro.multithread]p27, so a C++ 1155 // implementation's equivalent of the below could set |*answer = false;| 1156 // if all loop sub-nodes set |*answer = false|!) 1157 case ParseNodeKind::DoWhileStmt: 1158 case ParseNodeKind::WhileStmt: 1159 case ParseNodeKind::ForStmt: 1160 MOZ_ASSERT(pn->is<BinaryNode>()); 1161 *answer = true; 1162 return true; 1163 1164 // Declarations affect the name set of the relevant scope. 1165 case ParseNodeKind::VarStmt: 1166 case ParseNodeKind::ConstDecl: 1167 case ParseNodeKind::LetDecl: 1168 MOZ_ASSERT(pn->is<ListNode>()); 1169 *answer = true; 1170 return true; 1171 1172 case ParseNodeKind::IfStmt: 1173 case ParseNodeKind::ConditionalExpr: { 1174 TernaryNode* node = &pn->as<TernaryNode>(); 1175 if (!checkSideEffects(node->kid1(), answer)) { 1176 return false; 1177 } 1178 if (*answer) { 1179 return true; 1180 } 1181 if (!checkSideEffects(node->kid2(), answer)) { 1182 return false; 1183 } 1184 if (*answer) { 1185 return true; 1186 } 1187 if ((pn = node->kid3())) { 1188 goto restart; 1189 } 1190 return true; 1191 } 1192 1193 // Function calls can invoke non-local code. 1194 case ParseNodeKind::NewExpr: 1195 case ParseNodeKind::CallExpr: 1196 case ParseNodeKind::OptionalCallExpr: 1197 case ParseNodeKind::TaggedTemplateExpr: 1198 case ParseNodeKind::SuperCallExpr: 1199 MOZ_ASSERT(pn->is<BinaryNode>()); 1200 *answer = true; 1201 return true; 1202 1203 // Function arg lists can contain arbitrary expressions. Technically 1204 // this only causes side-effects if one of the arguments does, but since 1205 // the call being made will always trigger side-effects, it isn't needed. 1206 case ParseNodeKind::Arguments: 1207 MOZ_ASSERT(pn->is<ListNode>()); 1208 *answer = true; 1209 return true; 1210 1211 case ParseNodeKind::OptionalChain: 1212 MOZ_ASSERT(pn->is<UnaryNode>()); 1213 *answer = true; 1214 return true; 1215 1216 // Classes typically introduce names. Even if no name is introduced, 1217 // the heritage and/or class body (through computed property names) 1218 // usually have effects. 1219 case ParseNodeKind::ClassDecl: 1220 MOZ_ASSERT(pn->is<ClassNode>()); 1221 *answer = true; 1222 return true; 1223 1224 // |with| calls |ToObject| on its expression and so throws if that value 1225 // is null/undefined. 1226 case ParseNodeKind::WithStmt: 1227 MOZ_ASSERT(pn->is<BinaryNode>()); 1228 *answer = true; 1229 return true; 1230 1231 case ParseNodeKind::ReturnStmt: 1232 MOZ_ASSERT(pn->is<BinaryNode>()); 1233 *answer = true; 1234 return true; 1235 1236 case ParseNodeKind::Name: 1237 MOZ_ASSERT(pn->is<NameNode>()); 1238 *answer = true; 1239 return true; 1240 1241 // Shorthands could trigger getters: the |x| in the object literal in 1242 // |with ({ get x() { throw 42; } }) ({ x });|, for example, triggers 1243 // one. (Of course, it isn't necessary to use |with| for a shorthand to 1244 // trigger a getter.) 1245 case ParseNodeKind::Shorthand: 1246 MOZ_ASSERT(pn->is<BinaryNode>()); 1247 *answer = true; 1248 return true; 1249 1250 case ParseNodeKind::Function: 1251 MOZ_ASSERT(pn->is<FunctionNode>()); 1252 /* 1253 * A named function, contrary to ES3, is no longer effectful, because 1254 * we bind its name lexically (using JSOp::Callee) instead of creating 1255 * an Object instance and binding a readonly, permanent property in it 1256 * (the object and binding can be detected and hijacked or captured). 1257 * This is a bug fix to ES3; it is fixed in ES3.1 drafts. 1258 */ 1259 *answer = false; 1260 return true; 1261 1262 case ParseNodeKind::Module: 1263 *answer = false; 1264 return true; 1265 1266 case ParseNodeKind::TryStmt: { 1267 TryNode* tryNode = &pn->as<TryNode>(); 1268 if (!checkSideEffects(tryNode->body(), answer)) { 1269 return false; 1270 } 1271 if (*answer) { 1272 return true; 1273 } 1274 if (LexicalScopeNode* catchScope = tryNode->catchScope()) { 1275 if (!checkSideEffects(catchScope, answer)) { 1276 return false; 1277 } 1278 if (*answer) { 1279 return true; 1280 } 1281 } 1282 if (ParseNode* finallyBlock = tryNode->finallyBlock()) { 1283 if (!checkSideEffects(finallyBlock, answer)) { 1284 return false; 1285 } 1286 } 1287 return true; 1288 } 1289 1290 case ParseNodeKind::Catch: { 1291 BinaryNode* catchClause = &pn->as<BinaryNode>(); 1292 if (ParseNode* name = catchClause->left()) { 1293 if (!checkSideEffects(name, answer)) { 1294 return false; 1295 } 1296 if (*answer) { 1297 return true; 1298 } 1299 } 1300 return checkSideEffects(catchClause->right(), answer); 1301 } 1302 1303 case ParseNodeKind::SwitchStmt: { 1304 SwitchStatement* switchStmt = &pn->as<SwitchStatement>(); 1305 if (!checkSideEffects(&switchStmt->discriminant(), answer)) { 1306 return false; 1307 } 1308 return *answer || 1309 checkSideEffects(&switchStmt->lexicalForCaseList(), answer); 1310 } 1311 1312 case ParseNodeKind::LabelStmt: 1313 return checkSideEffects(pn->as<LabeledStatement>().statement(), answer); 1314 1315 case ParseNodeKind::LexicalScope: 1316 return checkSideEffects(pn->as<LexicalScopeNode>().scopeBody(), answer); 1317 1318 // We could methodically check every interpolated expression, but it's 1319 // probably not worth the trouble. Treat template strings as effect-free 1320 // only if they don't contain any substitutions. 1321 case ParseNodeKind::TemplateStringListExpr: { 1322 ListNode* list = &pn->as<ListNode>(); 1323 MOZ_ASSERT(!list->empty()); 1324 MOZ_ASSERT((list->count() % 2) == 1, 1325 "template strings must alternate template and substitution " 1326 "parts"); 1327 *answer = list->count() > 1; 1328 return true; 1329 } 1330 1331 // This should be unreachable but is left as-is for now. 1332 case ParseNodeKind::ParamsBody: 1333 *answer = true; 1334 return true; 1335 1336 case ParseNodeKind::ForIn: // by ParseNodeKind::For 1337 case ParseNodeKind::ForOf: // by ParseNodeKind::For 1338 case ParseNodeKind::ForHead: // by ParseNodeKind::For 1339 case ParseNodeKind::DefaultConstructor: // by ParseNodeKind::ClassDecl 1340 case ParseNodeKind::ClassBodyScope: // by ParseNodeKind::ClassDecl 1341 case ParseNodeKind::ClassMethod: // by ParseNodeKind::ClassDecl 1342 case ParseNodeKind::ClassField: // by ParseNodeKind::ClassDecl 1343 case ParseNodeKind::ClassNames: // by ParseNodeKind::ClassDecl 1344 case ParseNodeKind::StaticClassBlock: // by ParseNodeKind::ClassDecl 1345 case ParseNodeKind::ClassMemberList: // by ParseNodeKind::ClassDecl 1346 case ParseNodeKind::ImportSpecList: // by ParseNodeKind::Import 1347 case ParseNodeKind::ImportSpec: // by ParseNodeKind::Import 1348 case ParseNodeKind::ImportNamespaceSpec: // by ParseNodeKind::Import 1349 case ParseNodeKind::ImportAttribute: // by ParseNodeKind::Import 1350 case ParseNodeKind::ImportAttributeList: // by ParseNodeKind::Import 1351 case ParseNodeKind::ImportModuleRequest: // by ParseNodeKind::Import 1352 case ParseNodeKind::ExportBatchSpecStmt: // by ParseNodeKind::Export 1353 case ParseNodeKind::ExportSpecList: // by ParseNodeKind::Export 1354 case ParseNodeKind::ExportSpec: // by ParseNodeKind::Export 1355 case ParseNodeKind::ExportNamespaceSpec: // by ParseNodeKind::Export 1356 case ParseNodeKind::CallSiteObj: // by ParseNodeKind::TaggedTemplate 1357 case ParseNodeKind::PosHolder: // by ParseNodeKind::NewTarget 1358 case ParseNodeKind::SuperBase: // by ParseNodeKind::Elem and others 1359 case ParseNodeKind::PropertyNameExpr: // by ParseNodeKind::Dot 1360 MOZ_CRASH("handled by parent nodes"); 1361 1362 case ParseNodeKind::LastUnused: 1363 case ParseNodeKind::Limit: 1364 MOZ_CRASH("invalid node kind"); 1365 } 1366 1367 MOZ_CRASH( 1368 "invalid, unenumerated ParseNodeKind value encountered in " 1369 "BytecodeEmitter::checkSideEffects"); 1370 } 1371 1372 bool BytecodeEmitter::isInLoop() const { 1373 return findInnermostNestableControl<LoopControl>(); 1374 } 1375 1376 bool BytecodeEmitter::checkSingletonContext() const { 1377 MOZ_ASSERT_IF(sc->treatAsRunOnce(), sc->isTopLevelContext()); 1378 return sc->treatAsRunOnce() && !isInLoop(); 1379 } 1380 1381 bool BytecodeEmitter::needsImplicitThis() const { 1382 // Short-circuit if there is an enclosing 'with' scope. 1383 if (sc->inWith()) { 1384 return true; 1385 } 1386 1387 // Otherwise see if the current point is under a 'with'. 1388 for (EmitterScope* es = innermostEmitterScope(); es; 1389 es = es->enclosingInFrame()) { 1390 if (es->scope(this).kind() == ScopeKind::With) { 1391 return true; 1392 } 1393 } 1394 1395 return false; 1396 } 1397 1398 size_t BytecodeEmitter::countThisEnvironmentHops() const { 1399 unsigned numHops = 0; 1400 1401 for (const auto* current = this; current; current = current->parent) { 1402 for (EmitterScope* es = current->innermostEmitterScope(); es; 1403 es = es->enclosingInFrame()) { 1404 if (es->scope(current).is<FunctionScope>()) { 1405 if (!es->scope(current).isArrow()) { 1406 // The Parser is responsible for marking the environment as either 1407 // closed-over or used-by-eval which ensure that is must exist. 1408 MOZ_ASSERT(es->scope(current).hasEnvironment()); 1409 return numHops; 1410 } 1411 } 1412 if (es->scope(current).hasEnvironment()) { 1413 numHops++; 1414 } 1415 } 1416 } 1417 1418 // The "this" environment exists outside of the compilation, but the 1419 // `ScopeContext` recorded the number of additional hops needed, so add 1420 // those in now. 1421 MOZ_ASSERT(sc->allowSuperProperty()); 1422 numHops += compilationState.scopeContext.enclosingThisEnvironmentHops; 1423 return numHops; 1424 } 1425 1426 bool BytecodeEmitter::emitThisEnvironmentCallee() { 1427 // Get the innermost enclosing function that has a |this| binding. 1428 1429 // Directly load callee from the frame if possible. 1430 if (sc->isFunctionBox() && !sc->asFunctionBox()->isArrow()) { 1431 return emit1(JSOp::Callee); 1432 } 1433 1434 // We have to load the callee from the environment chain. 1435 size_t numHops = countThisEnvironmentHops(); 1436 1437 static_assert( 1438 ENVCOORD_HOPS_LIMIT - 1 <= UINT16_MAX, 1439 "JSOp::EnvCallee operand size should match ENVCOORD_HOPS_LIMIT"); 1440 1441 MOZ_ASSERT(numHops < ENVCOORD_HOPS_LIMIT - 1); 1442 1443 return emitUint16Operand(JSOp::EnvCallee, numHops); 1444 } 1445 1446 bool BytecodeEmitter::emitSuperBase() { 1447 if (!emitThisEnvironmentCallee()) { 1448 return false; 1449 } 1450 1451 return emit1(JSOp::SuperBase); 1452 } 1453 1454 void BytecodeEmitter::reportError(ParseNode* pn, unsigned errorNumber, 1455 ...) const { 1456 uint32_t offset = pn ? pn->pn_pos.begin : *scriptStartOffset; 1457 1458 va_list args; 1459 va_start(args, errorNumber); 1460 1461 errorReporter().errorWithNotesAtVA(nullptr, AsVariant(offset), errorNumber, 1462 &args); 1463 1464 va_end(args); 1465 } 1466 1467 void BytecodeEmitter::reportError(uint32_t offset, unsigned errorNumber, 1468 ...) const { 1469 va_list args; 1470 va_start(args, errorNumber); 1471 1472 errorReporter().errorWithNotesAtVA(nullptr, AsVariant(offset), errorNumber, 1473 &args); 1474 1475 va_end(args); 1476 } 1477 1478 bool BytecodeEmitter::addObjLiteralData(ObjLiteralWriter& writer, 1479 GCThingIndex* outIndex) { 1480 if (!writer.checkForDuplicatedNames(fc)) { 1481 return false; 1482 } 1483 1484 size_t len = writer.getCode().size(); 1485 auto* code = compilationState.alloc.newArrayUninitialized<uint8_t>(len); 1486 if (!code) { 1487 js::ReportOutOfMemory(fc); 1488 return false; 1489 } 1490 memcpy(code, writer.getCode().data(), len); 1491 1492 ObjLiteralIndex objIndex(compilationState.objLiteralData.length()); 1493 if (uint32_t(objIndex) >= TaggedScriptThingIndex::IndexLimit) { 1494 ReportAllocationOverflow(fc); 1495 return false; 1496 } 1497 if (!compilationState.objLiteralData.emplaceBack(code, len, writer.getKind(), 1498 writer.getFlags(), 1499 writer.getPropertyCount())) { 1500 js::ReportOutOfMemory(fc); 1501 return false; 1502 } 1503 1504 return perScriptData().gcThingList().append(objIndex, outIndex); 1505 } 1506 1507 bool BytecodeEmitter::emitPrepareIteratorResult() { 1508 constexpr JSOp op = JSOp::NewObject; 1509 1510 ObjLiteralWriter writer; 1511 writer.beginShape(op); 1512 1513 writer.setPropNameNoDuplicateCheck(parserAtoms(), 1514 TaggedParserAtomIndex::WellKnown::value()); 1515 if (!writer.propWithUndefinedValue(fc)) { 1516 return false; 1517 } 1518 writer.setPropNameNoDuplicateCheck(parserAtoms(), 1519 TaggedParserAtomIndex::WellKnown::done()); 1520 if (!writer.propWithUndefinedValue(fc)) { 1521 return false; 1522 } 1523 1524 GCThingIndex shape; 1525 if (!addObjLiteralData(writer, &shape)) { 1526 return false; 1527 } 1528 1529 return emitGCIndexOp(op, shape); 1530 } 1531 1532 bool BytecodeEmitter::emitFinishIteratorResult(bool done) { 1533 if (!emitAtomOp(JSOp::InitProp, TaggedParserAtomIndex::WellKnown::value())) { 1534 return false; 1535 } 1536 if (!emit1(done ? JSOp::True : JSOp::False)) { 1537 return false; 1538 } 1539 if (!emitAtomOp(JSOp::InitProp, TaggedParserAtomIndex::WellKnown::done())) { 1540 return false; 1541 } 1542 return true; 1543 } 1544 1545 bool BytecodeEmitter::emitGetNameAtLocation(TaggedParserAtomIndex name, 1546 const NameLocation& loc) { 1547 NameOpEmitter noe(this, name, loc, NameOpEmitter::Kind::Get); 1548 if (!noe.emitGet()) { 1549 return false; 1550 } 1551 1552 return true; 1553 } 1554 1555 bool BytecodeEmitter::emitGetName(NameNode* name) { 1556 MOZ_ASSERT(name->isKind(ParseNodeKind::Name)); 1557 1558 return emitGetName(name->name()); 1559 } 1560 1561 bool BytecodeEmitter::emitGetPrivateName(NameNode* name) { 1562 MOZ_ASSERT(name->isKind(ParseNodeKind::PrivateName)); 1563 return emitGetPrivateName(name->name()); 1564 } 1565 1566 bool BytecodeEmitter::emitGetPrivateName(TaggedParserAtomIndex nameAtom) { 1567 // The parser ensures the private name is present on the environment chain, 1568 // but its location can be Dynamic or Global when emitting debugger 1569 // eval-in-frame code. 1570 NameLocation location = lookupName(nameAtom); 1571 MOZ_ASSERT(location.kind() == NameLocation::Kind::FrameSlot || 1572 location.kind() == NameLocation::Kind::EnvironmentCoordinate || 1573 location.kind() == NameLocation::Kind::Dynamic || 1574 location.kind() == NameLocation::Kind::Global); 1575 1576 return emitGetNameAtLocation(nameAtom, location); 1577 } 1578 1579 bool BytecodeEmitter::emitTDZCheckIfNeeded(TaggedParserAtomIndex name, 1580 const NameLocation& loc, 1581 ValueIsOnStack isOnStack) { 1582 // Dynamic accesses have TDZ checks built into their VM code and should 1583 // never emit explicit TDZ checks. 1584 MOZ_ASSERT(loc.hasKnownSlot()); 1585 MOZ_ASSERT(loc.isLexical() || loc.isPrivateMethod() || loc.isSynthetic()); 1586 1587 // Private names are implemented as lexical bindings, but it's just an 1588 // implementation detail. Per spec there's no TDZ check when using them. 1589 if (parserAtoms().isPrivateName(name)) { 1590 return true; 1591 } 1592 1593 Maybe<MaybeCheckTDZ> check = 1594 innermostTDZCheckCache->needsTDZCheck(this, name); 1595 if (!check) { 1596 return false; 1597 } 1598 1599 // We've already emitted a check in this basic block. 1600 if (*check == DontCheckTDZ) { 1601 return true; 1602 } 1603 1604 // If the value is not on the stack, we have to load it first. 1605 if (isOnStack == ValueIsOnStack::No) { 1606 if (loc.kind() == NameLocation::Kind::FrameSlot) { 1607 if (!emitLocalOp(JSOp::GetLocal, loc.frameSlot())) { 1608 return false; 1609 } 1610 } else { 1611 if (!emitEnvCoordOp(JSOp::GetAliasedVar, loc.environmentCoordinate())) { 1612 return false; 1613 } 1614 } 1615 } 1616 1617 // Emit the lexical check. 1618 if (loc.kind() == NameLocation::Kind::FrameSlot) { 1619 if (!emitLocalOp(JSOp::CheckLexical, loc.frameSlot())) { 1620 return false; 1621 } 1622 } else { 1623 if (!emitEnvCoordOp(JSOp::CheckAliasedLexical, 1624 loc.environmentCoordinate())) { 1625 return false; 1626 } 1627 } 1628 1629 // Pop the value if needed. 1630 if (isOnStack == ValueIsOnStack::No) { 1631 if (!emit1(JSOp::Pop)) { 1632 return false; 1633 } 1634 } 1635 1636 return innermostTDZCheckCache->noteTDZCheck(this, name, DontCheckTDZ); 1637 } 1638 1639 bool BytecodeEmitter::emitPropLHS(PropertyAccess* prop) { 1640 MOZ_ASSERT(!prop->isSuper()); 1641 1642 ParseNode* expr = &prop->expression(); 1643 1644 if (!expr->is<PropertyAccess>() || expr->as<PropertyAccess>().isSuper()) { 1645 // The non-optimized case. 1646 return emitTree(expr); 1647 } 1648 1649 // If the object operand is also a dotted property reference, reverse the 1650 // list linked via expression() temporarily so we can iterate over it from 1651 // the bottom up (reversing again as we go), to avoid excessive recursion. 1652 PropertyAccess* pndot = &expr->as<PropertyAccess>(); 1653 ParseNode* pnup = nullptr; 1654 ParseNode* pndown; 1655 for (;;) { 1656 // Reverse pndot->expression() to point up, not down. 1657 pndown = &pndot->expression(); 1658 pndot->setExpression(pnup); 1659 if (!pndown->is<PropertyAccess>() || 1660 pndown->as<PropertyAccess>().isSuper()) { 1661 break; 1662 } 1663 pnup = pndot; 1664 pndot = &pndown->as<PropertyAccess>(); 1665 } 1666 1667 // pndown is a primary expression, not a dotted property reference. 1668 if (!emitTree(pndown)) { 1669 return false; 1670 } 1671 1672 while (true) { 1673 // Walk back up the list, emitting annotated name ops. 1674 if (!emitAtomOp(JSOp::GetProp, pndot->key().atom())) { 1675 return false; 1676 } 1677 1678 // Reverse the pndot->expression() link again. 1679 pnup = pndot->maybeExpression(); 1680 pndot->setExpression(pndown); 1681 pndown = pndot; 1682 if (!pnup) { 1683 break; 1684 } 1685 pndot = &pnup->as<PropertyAccess>(); 1686 } 1687 return true; 1688 } 1689 1690 bool BytecodeEmitter::emitPropIncDec(UnaryNode* incDec, ValueUsage valueUsage) { 1691 PropertyAccess* prop = &incDec->kid()->as<PropertyAccess>(); 1692 bool isSuper = prop->isSuper(); 1693 ParseNodeKind kind = incDec->getKind(); 1694 PropOpEmitter poe( 1695 this, 1696 kind == ParseNodeKind::PostIncrementExpr 1697 ? PropOpEmitter::Kind::PostIncrement 1698 : kind == ParseNodeKind::PreIncrementExpr 1699 ? PropOpEmitter::Kind::PreIncrement 1700 : kind == ParseNodeKind::PostDecrementExpr 1701 ? PropOpEmitter::Kind::PostDecrement 1702 : PropOpEmitter::Kind::PreDecrement, 1703 isSuper ? PropOpEmitter::ObjKind::Super : PropOpEmitter::ObjKind::Other); 1704 if (!poe.prepareForObj()) { 1705 return false; 1706 } 1707 if (isSuper) { 1708 UnaryNode* base = &prop->expression().as<UnaryNode>(); 1709 if (!emitGetThisForSuperBase(base)) { 1710 // [stack] THIS 1711 return false; 1712 } 1713 } else { 1714 if (!emitPropLHS(prop)) { 1715 // [stack] OBJ 1716 return false; 1717 } 1718 } 1719 if (!poe.emitIncDec(prop->key().atom(), valueUsage)) { 1720 // [stack] RESULT 1721 return false; 1722 } 1723 1724 return true; 1725 } 1726 1727 bool BytecodeEmitter::emitNameIncDec(UnaryNode* incDec, ValueUsage valueUsage) { 1728 MOZ_ASSERT(incDec->kid()->isKind(ParseNodeKind::Name)); 1729 1730 ParseNodeKind kind = incDec->getKind(); 1731 NameNode* name = &incDec->kid()->as<NameNode>(); 1732 NameOpEmitter noe(this, name->atom(), 1733 kind == ParseNodeKind::PostIncrementExpr 1734 ? NameOpEmitter::Kind::PostIncrement 1735 : kind == ParseNodeKind::PreIncrementExpr 1736 ? NameOpEmitter::Kind::PreIncrement 1737 : kind == ParseNodeKind::PostDecrementExpr 1738 ? NameOpEmitter::Kind::PostDecrement 1739 : NameOpEmitter::Kind::PreDecrement); 1740 if (!noe.emitIncDec(valueUsage)) { 1741 return false; 1742 } 1743 1744 return true; 1745 } 1746 1747 bool BytecodeEmitter::emitElemObjAndKey(PropertyByValue* elem, 1748 ElemOpEmitter& eoe) { 1749 ParseNode* exprOrSuper = &elem->expression(); 1750 ParseNode* key = &elem->key(); 1751 1752 if (!eoe.prepareForObj()) { 1753 // [stack] 1754 return false; 1755 } 1756 1757 if (elem->isSuper()) { 1758 auto* base = &exprOrSuper->as<UnaryNode>(); 1759 if (!emitGetThisForSuperBase(base)) { 1760 // [stack] THIS 1761 return false; 1762 } 1763 } else { 1764 if (!emitTree(exprOrSuper)) { 1765 // [stack] OBJ 1766 return false; 1767 } 1768 } 1769 1770 if (!eoe.prepareForKey()) { 1771 // [stack] # if Super 1772 // [stack] THIS? THIS 1773 // [stack] # otherwise 1774 // [stack] OBJ? OBJ 1775 return false; 1776 } 1777 1778 if (!emitTree(key)) { 1779 // [stack] # if Super 1780 // [stack] THIS? THIS KEY 1781 // [stack] # otherwise 1782 // [stack] OBJ? OBJ KEY 1783 return false; 1784 } 1785 1786 return true; 1787 } 1788 1789 bool BytecodeEmitter::emitElemOpBase(JSOp op) { 1790 if (!emit1(op)) { 1791 return false; 1792 } 1793 1794 return true; 1795 } 1796 1797 static ElemOpEmitter::Kind ConvertIncDecKind(ParseNodeKind kind) { 1798 switch (kind) { 1799 case ParseNodeKind::PostIncrementExpr: 1800 return ElemOpEmitter::Kind::PostIncrement; 1801 case ParseNodeKind::PreIncrementExpr: 1802 return ElemOpEmitter::Kind::PreIncrement; 1803 case ParseNodeKind::PostDecrementExpr: 1804 return ElemOpEmitter::Kind::PostDecrement; 1805 case ParseNodeKind::PreDecrementExpr: 1806 return ElemOpEmitter::Kind::PreDecrement; 1807 default: 1808 MOZ_CRASH("unexpected inc/dec node kind"); 1809 } 1810 } 1811 1812 static PrivateOpEmitter::Kind PrivateConvertIncDecKind(ParseNodeKind kind) { 1813 switch (kind) { 1814 case ParseNodeKind::PostIncrementExpr: 1815 return PrivateOpEmitter::Kind::PostIncrement; 1816 case ParseNodeKind::PreIncrementExpr: 1817 return PrivateOpEmitter::Kind::PreIncrement; 1818 case ParseNodeKind::PostDecrementExpr: 1819 return PrivateOpEmitter::Kind::PostDecrement; 1820 case ParseNodeKind::PreDecrementExpr: 1821 return PrivateOpEmitter::Kind::PreDecrement; 1822 default: 1823 MOZ_CRASH("unexpected inc/dec node kind"); 1824 } 1825 } 1826 1827 bool BytecodeEmitter::emitElemIncDec(UnaryNode* incDec, ValueUsage valueUsage) { 1828 PropertyByValue* elemExpr = &incDec->kid()->as<PropertyByValue>(); 1829 bool isSuper = elemExpr->isSuper(); 1830 MOZ_ASSERT(!elemExpr->key().isKind(ParseNodeKind::PrivateName)); 1831 ParseNodeKind kind = incDec->getKind(); 1832 ElemOpEmitter eoe( 1833 this, ConvertIncDecKind(kind), 1834 isSuper ? ElemOpEmitter::ObjKind::Super : ElemOpEmitter::ObjKind::Other); 1835 if (!emitElemObjAndKey(elemExpr, eoe)) { 1836 // [stack] # if Super 1837 // [stack] THIS KEY 1838 // [stack] # otherwise 1839 // [stack] OBJ KEY 1840 return false; 1841 } 1842 if (!eoe.emitIncDec(valueUsage)) { 1843 // [stack] RESULT 1844 return false; 1845 } 1846 1847 return true; 1848 } 1849 1850 bool BytecodeEmitter::emitCallIncDec(UnaryNode* incDec) { 1851 MOZ_ASSERT(incDec->isKind(ParseNodeKind::PreIncrementExpr) || 1852 incDec->isKind(ParseNodeKind::PostIncrementExpr) || 1853 incDec->isKind(ParseNodeKind::PreDecrementExpr) || 1854 incDec->isKind(ParseNodeKind::PostDecrementExpr)); 1855 1856 ParseNode* call = incDec->kid(); 1857 MOZ_ASSERT(call->isKind(ParseNodeKind::CallExpr)); 1858 if (!emitTree(call)) { 1859 // [stack] CALLRESULT 1860 return false; 1861 } 1862 1863 // The increment/decrement has no side effects, so proceed to throw for 1864 // invalid assignment target. 1865 return emit2(JSOp::ThrowMsg, uint8_t(ThrowMsgKind::AssignToCall)); 1866 } 1867 1868 bool BytecodeEmitter::emitPrivateIncDec(UnaryNode* incDec, 1869 ValueUsage valueUsage) { 1870 PrivateMemberAccess* privateExpr = &incDec->kid()->as<PrivateMemberAccess>(); 1871 ParseNodeKind kind = incDec->getKind(); 1872 PrivateOpEmitter xoe(this, PrivateConvertIncDecKind(kind), 1873 privateExpr->privateName().name()); 1874 if (!emitTree(&privateExpr->expression())) { 1875 // [stack] OBJ 1876 return false; 1877 } 1878 if (!xoe.emitReference()) { 1879 // [stack] OBJ NAME 1880 return false; 1881 } 1882 if (!xoe.emitIncDec(valueUsage)) { 1883 // [stack] RESULT 1884 return false; 1885 } 1886 1887 return true; 1888 } 1889 1890 bool BytecodeEmitter::emitDouble(double d) { 1891 BytecodeOffset offset; 1892 if (!emitCheck(JSOp::Double, 9, &offset)) { 1893 return false; 1894 } 1895 1896 jsbytecode* code = bytecodeSection().code(offset); 1897 code[0] = jsbytecode(JSOp::Double); 1898 SET_INLINE_VALUE(code, DoubleValue(d)); 1899 bytecodeSection().updateDepth(JSOp::Double, offset); 1900 return true; 1901 } 1902 1903 bool BytecodeEmitter::emitNumberOp(double dval) { 1904 int32_t ival; 1905 if (NumberIsInt32(dval, &ival)) { 1906 if (ival == 0) { 1907 return emit1(JSOp::Zero); 1908 } 1909 if (ival == 1) { 1910 return emit1(JSOp::One); 1911 } 1912 if ((int)(int8_t)ival == ival) { 1913 return emit2(JSOp::Int8, uint8_t(int8_t(ival))); 1914 } 1915 1916 uint32_t u = uint32_t(ival); 1917 if (u < Bit(16)) { 1918 if (!emitUint16Operand(JSOp::Uint16, u)) { 1919 return false; 1920 } 1921 } else if (u < Bit(24)) { 1922 BytecodeOffset off; 1923 if (!emitN(JSOp::Uint24, 3, &off)) { 1924 return false; 1925 } 1926 SET_UINT24(bytecodeSection().code(off), u); 1927 } else { 1928 BytecodeOffset off; 1929 if (!emitN(JSOp::Int32, 4, &off)) { 1930 return false; 1931 } 1932 SET_INT32(bytecodeSection().code(off), ival); 1933 } 1934 return true; 1935 } 1936 1937 return emitDouble(dval); 1938 } 1939 1940 /* 1941 * Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. 1942 * LLVM is deciding to inline this function which uses a lot of stack space 1943 * into emitTree which is recursive and uses relatively little stack space. 1944 */ 1945 MOZ_NEVER_INLINE bool BytecodeEmitter::emitSwitch(SwitchStatement* switchStmt) { 1946 LexicalScopeNode& lexical = switchStmt->lexicalForCaseList(); 1947 MOZ_ASSERT(lexical.isKind(ParseNodeKind::LexicalScope)); 1948 ListNode* cases = &lexical.scopeBody()->as<ListNode>(); 1949 MOZ_ASSERT(cases->isKind(ParseNodeKind::StatementList)); 1950 1951 SwitchEmitter se(this); 1952 if (!se.emitDiscriminant(switchStmt->discriminant().pn_pos.begin)) { 1953 return false; 1954 } 1955 1956 if (!markStepBreakpoint()) { 1957 return false; 1958 } 1959 if (!emitTree(&switchStmt->discriminant())) { 1960 return false; 1961 } 1962 1963 // Enter the scope before pushing the switch BreakableControl since all 1964 // breaks are under this scope. 1965 1966 if (!lexical.isEmptyScope()) { 1967 if (!se.emitLexical(lexical.scopeBindings())) { 1968 return false; 1969 } 1970 1971 // A switch statement may contain hoisted functions inside its 1972 // cases. The hasTopLevelFunctionDeclarations flag is propagated from the 1973 // StatementList bodies of the cases to the case list. 1974 if (cases->hasTopLevelFunctionDeclarations()) { 1975 for (ParseNode* item : cases->contents()) { 1976 CaseClause* caseClause = &item->as<CaseClause>(); 1977 ListNode* statements = caseClause->statementList(); 1978 if (statements->hasTopLevelFunctionDeclarations()) { 1979 if (!emitHoistedFunctionsInList(statements)) { 1980 return false; 1981 } 1982 } 1983 } 1984 } 1985 } else { 1986 MOZ_ASSERT(!cases->hasTopLevelFunctionDeclarations()); 1987 } 1988 1989 SwitchEmitter::TableGenerator tableGen(this); 1990 uint32_t caseCount = cases->count() - (switchStmt->hasDefault() ? 1 : 0); 1991 if (caseCount == 0) { 1992 tableGen.finish(0); 1993 } else { 1994 for (ParseNode* item : cases->contents()) { 1995 CaseClause* caseClause = &item->as<CaseClause>(); 1996 if (caseClause->isDefault()) { 1997 continue; 1998 } 1999 2000 ParseNode* caseValue = caseClause->caseExpression(); 2001 2002 if (caseValue->getKind() != ParseNodeKind::NumberExpr) { 2003 tableGen.setInvalid(); 2004 break; 2005 } 2006 2007 int32_t i; 2008 if (!NumberEqualsInt32(caseValue->as<NumericLiteral>().value(), &i)) { 2009 tableGen.setInvalid(); 2010 break; 2011 } 2012 2013 if (!tableGen.addNumber(i)) { 2014 return false; 2015 } 2016 } 2017 2018 tableGen.finish(caseCount); 2019 } 2020 2021 if (!se.validateCaseCount(caseCount)) { 2022 return false; 2023 } 2024 2025 bool isTableSwitch = tableGen.isValid(); 2026 if (isTableSwitch) { 2027 if (!se.emitTable(tableGen)) { 2028 return false; 2029 } 2030 } else { 2031 if (!se.emitCond()) { 2032 return false; 2033 } 2034 2035 // Emit code for evaluating cases and jumping to case statements. 2036 for (ParseNode* item : cases->contents()) { 2037 CaseClause* caseClause = &item->as<CaseClause>(); 2038 if (caseClause->isDefault()) { 2039 continue; 2040 } 2041 2042 if (!se.prepareForCaseValue()) { 2043 return false; 2044 } 2045 2046 ParseNode* caseValue = caseClause->caseExpression(); 2047 // If the expression is a literal, suppress line number emission so 2048 // that debugging works more naturally. 2049 if (!emitTree( 2050 caseValue, ValueUsage::WantValue, 2051 caseValue->isLiteral() ? SUPPRESS_LINENOTE : EMIT_LINENOTE)) { 2052 return false; 2053 } 2054 2055 if (!se.emitCaseJump()) { 2056 return false; 2057 } 2058 } 2059 } 2060 2061 // Emit code for each case's statements. 2062 for (ParseNode* item : cases->contents()) { 2063 CaseClause* caseClause = &item->as<CaseClause>(); 2064 if (caseClause->isDefault()) { 2065 if (!se.emitDefaultBody()) { 2066 return false; 2067 } 2068 } else { 2069 if (isTableSwitch) { 2070 ParseNode* caseValue = caseClause->caseExpression(); 2071 MOZ_ASSERT(caseValue->isKind(ParseNodeKind::NumberExpr)); 2072 2073 NumericLiteral* literal = &caseValue->as<NumericLiteral>(); 2074 #ifdef DEBUG 2075 // Use NumberEqualsInt32 here because switches compare using 2076 // strict equality, which will equate -0 and +0. In contrast 2077 // NumberIsInt32 would return false for -0. 2078 int32_t v; 2079 MOZ_ASSERT(mozilla::NumberEqualsInt32(literal->value(), &v)); 2080 #endif 2081 int32_t i = int32_t(literal->value()); 2082 2083 if (!se.emitCaseBody(i, tableGen)) { 2084 return false; 2085 } 2086 } else { 2087 if (!se.emitCaseBody()) { 2088 return false; 2089 } 2090 } 2091 } 2092 2093 if (!emitTree(caseClause->statementList())) { 2094 return false; 2095 } 2096 } 2097 2098 if (!se.emitEnd()) { 2099 return false; 2100 } 2101 2102 return true; 2103 } 2104 2105 bool BytecodeEmitter::allocateResumeIndex(BytecodeOffset offset, 2106 uint32_t* resumeIndex) { 2107 static constexpr uint32_t MaxResumeIndex = BitMask(24); 2108 2109 static_assert( 2110 MaxResumeIndex < uint32_t(AbstractGeneratorObject::RESUME_INDEX_RUNNING), 2111 "resumeIndex should not include magic AbstractGeneratorObject " 2112 "resumeIndex values"); 2113 static_assert( 2114 MaxResumeIndex <= INT32_MAX / sizeof(uintptr_t), 2115 "resumeIndex * sizeof(uintptr_t) must fit in an int32. JIT code relies " 2116 "on this when loading resume entries from BaselineScript"); 2117 2118 *resumeIndex = bytecodeSection().resumeOffsetList().length(); 2119 if (*resumeIndex > MaxResumeIndex) { 2120 reportError(nullptr, JSMSG_TOO_MANY_RESUME_INDEXES); 2121 return false; 2122 } 2123 2124 return bytecodeSection().resumeOffsetList().append(offset.value()); 2125 } 2126 2127 bool BytecodeEmitter::allocateResumeIndexRange( 2128 mozilla::Span<BytecodeOffset> offsets, uint32_t* firstResumeIndex) { 2129 *firstResumeIndex = 0; 2130 2131 for (size_t i = 0, len = offsets.size(); i < len; i++) { 2132 uint32_t resumeIndex; 2133 if (!allocateResumeIndex(offsets[i], &resumeIndex)) { 2134 return false; 2135 } 2136 if (i == 0) { 2137 *firstResumeIndex = resumeIndex; 2138 } 2139 } 2140 2141 return true; 2142 } 2143 2144 bool BytecodeEmitter::emitYieldOp(JSOp op) { 2145 // ParseContext::Scope::setOwnStackSlotCount should check the fixed slot 2146 // for the following, and it should prevent using fixed slot if there are 2147 // too many bindings: 2148 // * generator or asyn function 2149 // * module code after top-level await 2150 MOZ_ASSERT(innermostEmitterScopeNoCheck()->frameSlotEnd() <= 2151 ParseContext::Scope::FixedSlotLimit); 2152 2153 if (op == JSOp::FinalYieldRval) { 2154 return emit1(JSOp::FinalYieldRval); 2155 } 2156 2157 MOZ_ASSERT(op == JSOp::InitialYield || op == JSOp::Yield || 2158 op == JSOp::Await); 2159 2160 BytecodeOffset off; 2161 if (!emitN(op, 3, &off)) { 2162 return false; 2163 } 2164 2165 // InitialYield is always the first yield node. 2166 MOZ_ASSERT_IF(op == JSOp::InitialYield, bytecodeSection().numYields() == 0); 2167 2168 if (op == JSOp::InitialYield || op == JSOp::Yield) { 2169 bytecodeSection().addNumYields(); 2170 } 2171 2172 uint32_t resumeIndex; 2173 if (!allocateResumeIndex(bytecodeSection().offset(), &resumeIndex)) { 2174 return false; 2175 } 2176 2177 // InitialYield is the first resumable instruction. 2178 MOZ_ASSERT_IF( 2179 op == JSOp::InitialYield, 2180 resumeIndex == AbstractGeneratorObject::RESUME_INDEX_INITIAL_YIELD); 2181 2182 SET_RESUMEINDEX(bytecodeSection().code(off), resumeIndex); 2183 2184 BytecodeOffset unusedOffset; 2185 return emitJumpTargetOp(JSOp::AfterYield, &unusedOffset); 2186 } 2187 2188 bool BytecodeEmitter::emitPushResumeKind(GeneratorResumeKind kind) { 2189 return emit2(JSOp::ResumeKind, uint8_t(kind)); 2190 } 2191 2192 bool BytecodeEmitter::emitSetThis(BinaryNode* setThisNode) { 2193 // ParseNodeKind::SetThis is used to update |this| after a super() call 2194 // in a derived class constructor. 2195 2196 MOZ_ASSERT(setThisNode->isKind(ParseNodeKind::SetThis)); 2197 MOZ_ASSERT(setThisNode->left()->isKind(ParseNodeKind::Name)); 2198 2199 auto name = setThisNode->left()->as<NameNode>().name(); 2200 2201 // The 'this' binding is not lexical, but due to super() semantics this 2202 // initialization needs to be treated as a lexical one. 2203 NameLocation loc = lookupName(name); 2204 NameLocation lexicalLoc; 2205 if (loc.kind() == NameLocation::Kind::FrameSlot) { 2206 lexicalLoc = NameLocation::FrameSlot(BindingKind::Let, loc.frameSlot()); 2207 } else if (loc.kind() == NameLocation::Kind::EnvironmentCoordinate) { 2208 EnvironmentCoordinate coord = loc.environmentCoordinate(); 2209 uint16_t hops = AssertedCast<uint16_t>(coord.hops()); 2210 lexicalLoc = NameLocation::EnvironmentCoordinate(BindingKind::Let, hops, 2211 coord.slot()); 2212 } else { 2213 MOZ_ASSERT(loc.kind() == NameLocation::Kind::Dynamic); 2214 lexicalLoc = loc; 2215 } 2216 2217 NameOpEmitter noe(this, name, lexicalLoc, NameOpEmitter::Kind::Initialize); 2218 if (!noe.prepareForRhs()) { 2219 // [stack] 2220 return false; 2221 } 2222 2223 // Emit the new |this| value. 2224 if (!emitTree(setThisNode->right())) { 2225 // [stack] NEWTHIS 2226 return false; 2227 } 2228 2229 // Get the original |this| and throw if we already initialized 2230 // it. Do *not* use the NameLocation argument, as that's the special 2231 // lexical location below to deal with super() semantics. 2232 if (!emitGetName(name)) { 2233 // [stack] NEWTHIS THIS 2234 return false; 2235 } 2236 if (!emit1(JSOp::CheckThisReinit)) { 2237 // [stack] NEWTHIS THIS 2238 return false; 2239 } 2240 if (!emit1(JSOp::Pop)) { 2241 // [stack] NEWTHIS 2242 return false; 2243 } 2244 if (!noe.emitAssignment()) { 2245 // [stack] NEWTHIS 2246 return false; 2247 } 2248 2249 if (!emitInitializeInstanceMembers(true)) { 2250 return false; 2251 } 2252 2253 return true; 2254 } 2255 2256 bool BytecodeEmitter::defineHoistedTopLevelFunctions(ParseNode* body) { 2257 MOZ_ASSERT(inPrologue()); 2258 MOZ_ASSERT(sc->isGlobalContext() || (sc->isEvalContext() && !sc->strict())); 2259 MOZ_ASSERT(body->is<LexicalScopeNode>() || body->is<ListNode>()); 2260 2261 if (body->is<LexicalScopeNode>()) { 2262 body = body->as<LexicalScopeNode>().scopeBody(); 2263 MOZ_ASSERT(body->is<ListNode>()); 2264 } 2265 2266 if (!body->as<ListNode>().hasTopLevelFunctionDeclarations()) { 2267 return true; 2268 } 2269 2270 return emitHoistedFunctionsInList(&body->as<ListNode>()); 2271 } 2272 2273 // For Global and sloppy-Eval scripts, this performs most of the steps of the 2274 // spec's [GlobalDeclarationInstantiation] and [EvalDeclarationInstantiation] 2275 // operations. 2276 // 2277 // Note that while strict-Eval is handled in the same part of the spec, it never 2278 // fails for global-redeclaration checks so those scripts initialize directly in 2279 // their bytecode. 2280 bool BytecodeEmitter::emitDeclarationInstantiation(ParseNode* body) { 2281 if (sc->isModuleContext()) { 2282 // ES Modules have dedicated variable and lexial environments and therefore 2283 // do not have to perform redeclaration checks. We initialize their bindings 2284 // elsewhere in bytecode. 2285 return true; 2286 } 2287 2288 if (sc->isEvalContext() && sc->strict()) { 2289 // Strict Eval has a dedicated variables (and lexical) environment and 2290 // therefore does not have to perform redeclaration checks. We initialize 2291 // their bindings elsewhere in the bytecode. 2292 return true; 2293 } 2294 2295 // If we have no variables bindings, then we are done! 2296 if (sc->isGlobalContext()) { 2297 if (!sc->asGlobalContext()->bindings) { 2298 return true; 2299 } 2300 } else { 2301 MOZ_ASSERT(sc->isEvalContext()); 2302 2303 if (!sc->asEvalContext()->bindings) { 2304 return true; 2305 } 2306 } 2307 2308 #if DEBUG 2309 // There should be no emitted functions yet. 2310 for (const auto& thing : perScriptData().gcThingList().objects()) { 2311 MOZ_ASSERT(thing.isEmptyGlobalScope() || thing.isScope()); 2312 } 2313 #endif 2314 2315 // Emit the hoisted functions to gc-things list. There is no bytecode 2316 // generated yet to bind them. 2317 if (!defineHoistedTopLevelFunctions(body)) { 2318 return false; 2319 } 2320 2321 // Save the last GCThingIndex emitted. The hoisted functions are contained in 2322 // the gc-things list up until this point. This set of gc-things also contain 2323 // initial scopes (of which there must be at least one). 2324 MOZ_ASSERT(perScriptData().gcThingList().length() > 0); 2325 GCThingIndex lastFun = 2326 GCThingIndex(perScriptData().gcThingList().length() - 1); 2327 2328 #if DEBUG 2329 for (const auto& thing : perScriptData().gcThingList().objects()) { 2330 MOZ_ASSERT(thing.isEmptyGlobalScope() || thing.isScope() || 2331 thing.isFunction()); 2332 } 2333 #endif 2334 2335 // Check for declaration conflicts and initialize the bindings. 2336 // NOTE: The self-hosting top-level script should not populate the builtins 2337 // directly on the GlobalObject (and instead uses JSOp::GetIntrinsic for 2338 // lookups). 2339 if (emitterMode == BytecodeEmitter::EmitterMode::Normal) { 2340 if (!emitGCIndexOp(JSOp::GlobalOrEvalDeclInstantiation, lastFun)) { 2341 return false; 2342 } 2343 } 2344 2345 return true; 2346 } 2347 2348 bool BytecodeEmitter::emitScript(ParseNode* body) { 2349 setScriptStartOffsetIfUnset(body->pn_pos.begin); 2350 2351 MOZ_ASSERT(inPrologue()); 2352 2353 TDZCheckCache tdzCache(this); 2354 EmitterScope emitterScope(this); 2355 Maybe<AsyncEmitter> topLevelAwait; 2356 if (sc->isGlobalContext()) { 2357 if (!emitterScope.enterGlobal(this, sc->asGlobalContext())) { 2358 return false; 2359 } 2360 } else if (sc->isEvalContext()) { 2361 if (!emitterScope.enterEval(this, sc->asEvalContext())) { 2362 return false; 2363 } 2364 } else { 2365 MOZ_ASSERT(sc->isModuleContext()); 2366 if (!emitterScope.enterModule(this, sc->asModuleContext())) { 2367 return false; 2368 } 2369 if (sc->asModuleContext()->isAsync()) { 2370 topLevelAwait.emplace(this); 2371 } 2372 } 2373 2374 setFunctionBodyEndPos(body->pn_pos.end); 2375 2376 bool isSloppyEval = sc->isEvalContext() && !sc->strict(); 2377 if (isSloppyEval && body->is<LexicalScopeNode>() && 2378 !body->as<LexicalScopeNode>().isEmptyScope()) { 2379 // Sloppy eval scripts may emit hoisted functions bindings with a 2380 // `JSOp::GlobalOrEvalDeclInstantiation` opcode below. If this eval needs a 2381 // top-level lexical environment, we must ensure that environment is created 2382 // before those functions are created and bound. 2383 // 2384 // This differs from the global-script case below because the global-lexical 2385 // environment exists outside the script itself. In the case of strict eval 2386 // scripts, the `emitterScope` above is already sufficient. 2387 EmitterScope lexicalEmitterScope(this); 2388 LexicalScopeNode* scope = &body->as<LexicalScopeNode>(); 2389 2390 if (!lexicalEmitterScope.enterLexical(this, ScopeKind::Lexical, 2391 scope->scopeBindings())) { 2392 return false; 2393 } 2394 2395 if (!emitDeclarationInstantiation(scope->scopeBody())) { 2396 return false; 2397 } 2398 2399 switchToMain(); 2400 2401 ParseNode* scopeBody = scope->scopeBody(); 2402 if (!emitLexicalScopeBody(scopeBody)) { 2403 return false; 2404 } 2405 2406 if (!updateSourceCoordNotes(scopeBody->pn_pos.end)) { 2407 return false; 2408 } 2409 2410 if (!lexicalEmitterScope.leave(this)) { 2411 return false; 2412 } 2413 } else { 2414 if (!emitDeclarationInstantiation(body)) { 2415 return false; 2416 } 2417 if (topLevelAwait) { 2418 if (!topLevelAwait->prepareForModule()) { 2419 return false; 2420 } 2421 } 2422 2423 switchToMain(); 2424 2425 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT 2426 if (!emitterScope.prepareForModuleDisposableScopeBody(this)) { 2427 return false; 2428 } 2429 #endif 2430 2431 if (topLevelAwait) { 2432 if (!topLevelAwait->prepareForBody()) { 2433 return false; 2434 } 2435 } 2436 2437 if (!emitTree(body)) { 2438 // [stack] 2439 return false; 2440 } 2441 2442 if (!updateSourceCoordNotes(body->pn_pos.end)) { 2443 return false; 2444 } 2445 } 2446 2447 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT 2448 if (!emitterScope.emitModuleDisposableScopeBodyEnd(this)) { 2449 return false; 2450 } 2451 #endif 2452 2453 if (topLevelAwait) { 2454 if (!topLevelAwait->emitEndModule()) { 2455 return false; 2456 } 2457 } 2458 2459 if (!markSimpleBreakpoint()) { 2460 return false; 2461 } 2462 2463 if (!emitReturnRval()) { 2464 return false; 2465 } 2466 2467 if (!emitterScope.leave(this)) { 2468 return false; 2469 } 2470 2471 if (!NameFunctions(fc, parserAtoms(), body)) { 2472 return false; 2473 } 2474 2475 // Create a Stencil and convert it into a JSScript. 2476 return intoScriptStencil(CompilationStencil::TopLevelIndex); 2477 } 2478 2479 js::UniquePtr<ImmutableScriptData> 2480 BytecodeEmitter::createImmutableScriptData() { 2481 uint32_t nslots; 2482 if (!getNslots(&nslots)) { 2483 return nullptr; 2484 } 2485 2486 bool isFunction = sc->isFunctionBox(); 2487 uint16_t funLength = isFunction ? sc->asFunctionBox()->length() : 0; 2488 2489 mozilla::SaturateUint8 propertyCountEstimate = propertyAdditionEstimate; 2490 2491 // Add fields to the property count estimate. 2492 if (isFunction && sc->asFunctionBox()->useMemberInitializers()) { 2493 propertyCountEstimate += 2494 sc->asFunctionBox()->memberInitializers().numMemberInitializers; 2495 } 2496 2497 return ImmutableScriptData::new_( 2498 fc, mainOffset(), maxFixedSlots, nslots, bodyScopeIndex, 2499 bytecodeSection().numICEntries(), isFunction, funLength, 2500 propertyCountEstimate.value(), bytecodeSection().code(), 2501 bytecodeSection().notes(), bytecodeSection().resumeOffsetList().span(), 2502 bytecodeSection().scopeNoteList().span(), 2503 bytecodeSection().tryNoteList().span()); 2504 } 2505 2506 #if defined(ENABLE_DECORATORS) || defined(ENABLE_EXPLICIT_RESOURCE_MANAGEMENT) 2507 bool BytecodeEmitter::emitCheckIsCallable() { 2508 // This emits code to check if the value at the top of the stack is 2509 // callable. The value is left on the stack. 2510 // [stack] VAL 2511 if (!emitAtomOp(JSOp::GetIntrinsic, 2512 TaggedParserAtomIndex::WellKnown::IsCallable())) { 2513 // [stack] VAL ISCALLABLE 2514 return false; 2515 } 2516 if (!emit1(JSOp::Undefined)) { 2517 // [stack] VAL ISCALLABLE UNDEFINED 2518 return false; 2519 } 2520 if (!emitDupAt(2)) { 2521 // [stack] VAL ISCALLABLE UNDEFINED VAL 2522 return false; 2523 } 2524 return emitCall(JSOp::Call, 1); 2525 // [stack] VAL ISCALLABLE_RESULT 2526 } 2527 #endif 2528 2529 bool BytecodeEmitter::getNslots(uint32_t* nslots) const { 2530 uint64_t nslots64 = 2531 maxFixedSlots + static_cast<uint64_t>(bytecodeSection().maxStackDepth()); 2532 if (nslots64 > UINT32_MAX) { 2533 reportError(nullptr, JSMSG_NEED_DIET, "script"); 2534 return false; 2535 } 2536 *nslots = nslots64; 2537 return true; 2538 } 2539 2540 bool BytecodeEmitter::emitFunctionScript(FunctionNode* funNode) { 2541 MOZ_ASSERT(inPrologue()); 2542 ParamsBodyNode* paramsBody = funNode->body(); 2543 FunctionBox* funbox = sc->asFunctionBox(); 2544 2545 setScriptStartOffsetIfUnset(paramsBody->pn_pos.begin); 2546 2547 // [stack] 2548 2549 FunctionScriptEmitter fse(this, funbox, Some(paramsBody->pn_pos.begin), 2550 Some(paramsBody->pn_pos.end)); 2551 if (!fse.prepareForParameters()) { 2552 // [stack] 2553 return false; 2554 } 2555 2556 if (!emitFunctionFormalParameters(paramsBody)) { 2557 // [stack] 2558 return false; 2559 } 2560 2561 if (!fse.prepareForBody()) { 2562 // [stack] 2563 return false; 2564 } 2565 2566 if (!emitTree(paramsBody->body())) { 2567 // [stack] 2568 return false; 2569 } 2570 2571 if (!fse.emitEndBody()) { 2572 // [stack] 2573 return false; 2574 } 2575 2576 if (funbox->index() == CompilationStencil::TopLevelIndex) { 2577 if (!NameFunctions(fc, parserAtoms(), funNode)) { 2578 return false; 2579 } 2580 } 2581 2582 return fse.intoStencil(); 2583 } 2584 2585 class js::frontend::DestructuringLHSRef { 2586 struct None { 2587 size_t numReferenceSlots() const { return 0; } 2588 }; 2589 2590 mozilla::Variant<None, NameOpEmitter, PropOpEmitter, ElemOpEmitter, 2591 PrivateOpEmitter> 2592 emitter_ = AsVariant(None{}); 2593 2594 public: 2595 template <typename T> 2596 void from(T&& emitter) { 2597 emitter_.emplace<T>(std::forward<T>(emitter)); 2598 } 2599 2600 template <typename T> 2601 T& emitter() { 2602 return emitter_.as<T>(); 2603 } 2604 2605 /** 2606 * Return the number of values pushed onto the stack. 2607 */ 2608 size_t numReferenceSlots() const { 2609 return emitter_.match([](auto& e) { return e.numReferenceSlots(); }); 2610 } 2611 }; 2612 2613 bool BytecodeEmitter::emitDestructuringLHSRef(ParseNode* target, 2614 DestructuringFlavor flav, 2615 DestructuringLHSRef& lref) { 2616 #ifdef DEBUG 2617 int depth = bytecodeSection().stackDepth(); 2618 #endif 2619 2620 switch (target->getKind()) { 2621 case ParseNodeKind::ArrayExpr: 2622 case ParseNodeKind::ObjectExpr: 2623 // No need to recurse into ParseNodeKind::Array and ParseNodeKind::Object 2624 // subpatterns here, since emitSetOrInitializeDestructuring does the 2625 // recursion when setting or initializing the value. 2626 break; 2627 2628 case ParseNodeKind::Name: { 2629 auto* name = &target->as<NameNode>(); 2630 NameOpEmitter noe(this, name->atom(), 2631 flav == DestructuringFlavor::Assignment 2632 ? NameOpEmitter::Kind::SimpleAssignment 2633 : NameOpEmitter::Kind::Initialize); 2634 if (!noe.prepareForRhs()) { 2635 return false; 2636 } 2637 2638 lref.from(std::move(noe)); 2639 return true; 2640 } 2641 2642 case ParseNodeKind::ArgumentsLength: 2643 case ParseNodeKind::DotExpr: { 2644 PropertyAccess* prop = &target->as<PropertyAccess>(); 2645 bool isSuper = prop->isSuper(); 2646 PropOpEmitter poe(this, PropOpEmitter::Kind::SimpleAssignment, 2647 isSuper ? PropOpEmitter::ObjKind::Super 2648 : PropOpEmitter::ObjKind::Other); 2649 if (!poe.prepareForObj()) { 2650 return false; 2651 } 2652 if (isSuper) { 2653 UnaryNode* base = &prop->expression().as<UnaryNode>(); 2654 if (!emitGetThisForSuperBase(base)) { 2655 // [stack] THIS SUPERBASE 2656 return false; 2657 } 2658 } else { 2659 if (!emitTree(&prop->expression())) { 2660 // [stack] OBJ 2661 return false; 2662 } 2663 } 2664 if (!poe.prepareForRhs()) { 2665 // [stack] # if Super 2666 // [stack] THIS SUPERBASE 2667 // [stack] # otherwise 2668 // [stack] OBJ 2669 return false; 2670 } 2671 2672 lref.from(std::move(poe)); 2673 break; 2674 } 2675 2676 case ParseNodeKind::ElemExpr: { 2677 PropertyByValue* elem = &target->as<PropertyByValue>(); 2678 bool isSuper = elem->isSuper(); 2679 MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName)); 2680 ElemOpEmitter eoe(this, ElemOpEmitter::Kind::SimpleAssignment, 2681 isSuper ? ElemOpEmitter::ObjKind::Super 2682 : ElemOpEmitter::ObjKind::Other); 2683 if (!emitElemObjAndKey(elem, eoe)) { 2684 // [stack] # if Super 2685 // [stack] THIS KEY 2686 // [stack] # otherwise 2687 // [stack] OBJ KEY 2688 return false; 2689 } 2690 if (!eoe.prepareForRhs()) { 2691 // [stack] # if Super 2692 // [stack] THIS KEY SUPERBASE 2693 // [stack] # otherwise 2694 // [stack] OBJ KEY 2695 return false; 2696 } 2697 2698 lref.from(std::move(eoe)); 2699 break; 2700 } 2701 2702 case ParseNodeKind::PrivateMemberExpr: { 2703 PrivateMemberAccess* privateExpr = &target->as<PrivateMemberAccess>(); 2704 PrivateOpEmitter xoe(this, PrivateOpEmitter::Kind::SimpleAssignment, 2705 privateExpr->privateName().name()); 2706 if (!emitTree(&privateExpr->expression())) { 2707 // [stack] OBJ 2708 return false; 2709 } 2710 if (!xoe.emitReference()) { 2711 // [stack] OBJ NAME 2712 return false; 2713 } 2714 2715 lref.from(std::move(xoe)); 2716 break; 2717 } 2718 2719 case ParseNodeKind::CallExpr: 2720 MOZ_ASSERT_UNREACHABLE( 2721 "Parser::reportIfNotValidSimpleAssignmentTarget " 2722 "rejects function calls as assignment " 2723 "targets in destructuring assignments"); 2724 break; 2725 2726 default: 2727 MOZ_CRASH("emitDestructuringLHSRef: bad lhs kind"); 2728 } 2729 2730 MOZ_ASSERT(bytecodeSection().stackDepth() == 2731 depth + int(lref.numReferenceSlots())); 2732 2733 return true; 2734 } 2735 2736 bool BytecodeEmitter::emitSetOrInitializeDestructuring( 2737 ParseNode* target, DestructuringFlavor flav, DestructuringLHSRef& lref) { 2738 // Now emit the lvalue opcode sequence. If the lvalue is a nested 2739 // destructuring initialiser-form, call ourselves to handle it, then pop 2740 // the matched value. Otherwise emit an lvalue bytecode sequence followed 2741 // by an assignment op. 2742 2743 switch (target->getKind()) { 2744 case ParseNodeKind::ArrayExpr: 2745 case ParseNodeKind::ObjectExpr: 2746 if (!emitDestructuringOps(&target->as<ListNode>(), flav, 2747 SelfHostedIter::Deny)) { 2748 return false; 2749 } 2750 // emitDestructuringOps leaves the assigned (to-be-destructured) value on 2751 // top of the stack. 2752 break; 2753 2754 case ParseNodeKind::Name: { 2755 // The environment is already pushed by emitDestructuringLHSRef. 2756 // [stack] ENV? VAL 2757 auto& noe = lref.emitter<NameOpEmitter>(); 2758 2759 if (!noe.emitAssignment()) { 2760 // [stack] VAL 2761 return false; 2762 } 2763 break; 2764 } 2765 2766 case ParseNodeKind::ArgumentsLength: 2767 case ParseNodeKind::DotExpr: { 2768 // The reference is already pushed by emitDestructuringLHSRef. 2769 // [stack] # if Super 2770 // [stack] THIS SUPERBASE VAL 2771 // [stack] # otherwise 2772 // [stack] OBJ VAL 2773 auto& poe = lref.emitter<PropOpEmitter>(); 2774 auto* prop = &target->as<PropertyAccess>(); 2775 2776 if (!poe.emitAssignment(prop->key().atom())) { 2777 // [stack] # VAL 2778 return false; 2779 } 2780 break; 2781 } 2782 2783 case ParseNodeKind::ElemExpr: { 2784 // The reference is already pushed by emitDestructuringLHSRef. 2785 // [stack] # if Super 2786 // [stack] THIS KEY SUPERBASE VAL 2787 // [stack] # otherwise 2788 // [stack] OBJ KEY VAL 2789 auto& eoe = lref.emitter<ElemOpEmitter>(); 2790 2791 if (!eoe.emitAssignment()) { 2792 // [stack] VAL 2793 return false; 2794 } 2795 break; 2796 } 2797 2798 case ParseNodeKind::PrivateMemberExpr: { 2799 // The reference is already pushed by emitDestructuringLHSRef. 2800 // [stack] OBJ NAME VAL 2801 auto& xoe = lref.emitter<PrivateOpEmitter>(); 2802 2803 if (!xoe.emitAssignment()) { 2804 // [stack] VAL 2805 return false; 2806 } 2807 break; 2808 } 2809 2810 case ParseNodeKind::CallExpr: 2811 MOZ_ASSERT_UNREACHABLE( 2812 "Parser::reportIfNotValidSimpleAssignmentTarget " 2813 "rejects function calls as assignment " 2814 "targets in destructuring assignments"); 2815 break; 2816 2817 default: 2818 MOZ_CRASH("emitSetOrInitializeDestructuring: bad lhs kind"); 2819 } 2820 2821 // Pop the assigned value. 2822 if (!emit1(JSOp::Pop)) { 2823 // [stack] # empty 2824 return false; 2825 } 2826 2827 return true; 2828 } 2829 2830 JSOp BytecodeEmitter::getIterCallOp(JSOp callOp, 2831 SelfHostedIter selfHostedIter) const { 2832 if (emitterMode == BytecodeEmitter::SelfHosting) { 2833 MOZ_ASSERT(selfHostedIter != SelfHostedIter::Deny); 2834 2835 switch (callOp) { 2836 case JSOp::Call: 2837 return JSOp::CallContent; 2838 case JSOp::CallIter: 2839 return JSOp::CallContentIter; 2840 default: 2841 MOZ_CRASH("Unknown iterator call op"); 2842 } 2843 } 2844 2845 return callOp; 2846 } 2847 2848 bool BytecodeEmitter::emitIteratorNext( 2849 const Maybe<uint32_t>& callSourceCoordOffset, IteratorKind iterKind, 2850 SelfHostedIter selfHostedIter) { 2851 MOZ_ASSERT(selfHostedIter != SelfHostedIter::Deny || 2852 emitterMode != BytecodeEmitter::SelfHosting, 2853 ".next() iteration is prohibited in self-hosted code because it" 2854 "can run user-modifiable iteration code"); 2855 2856 // [stack] ... NEXT ITER 2857 MOZ_ASSERT(bytecodeSection().stackDepth() >= 2); 2858 2859 if (!emitCall(getIterCallOp(JSOp::Call, selfHostedIter), 0, 2860 callSourceCoordOffset)) { 2861 // [stack] ... RESULT 2862 return false; 2863 } 2864 2865 if (iterKind == IteratorKind::Async) { 2866 if (!emitAwaitInInnermostScope()) { 2867 // [stack] ... RESULT 2868 return false; 2869 } 2870 } 2871 2872 if (!emitCheckIsObj(CheckIsObjectKind::IteratorNext)) { 2873 // [stack] ... RESULT 2874 return false; 2875 } 2876 return true; 2877 } 2878 2879 bool BytecodeEmitter::emitIteratorCloseInScope(EmitterScope& currentScope, 2880 IteratorKind iterKind, 2881 CompletionKind completionKind, 2882 SelfHostedIter selfHostedIter) { 2883 MOZ_ASSERT(selfHostedIter != SelfHostedIter::Deny || 2884 emitterMode != BytecodeEmitter::SelfHosting, 2885 ".close() on iterators is prohibited in self-hosted code because " 2886 "it can run user-modifiable iteration code"); 2887 2888 if (iterKind == IteratorKind::Sync) { 2889 return emit2(JSOp::CloseIter, uint8_t(completionKind)); 2890 } 2891 2892 // Generate inline logic corresponding to IteratorClose (ES2021 7.4.6) and 2893 // AsyncIteratorClose (ES2021 7.4.7). Steps numbers apply to both operations. 2894 // 2895 // Callers need to ensure that the iterator object is at the top of the 2896 // stack. 2897 2898 // For non-Throw completions, we emit the equivalent of: 2899 // 2900 // var returnMethod = GetMethod(iterator, "return"); 2901 // if (returnMethod !== undefined) { 2902 // var innerResult = [Await] Call(returnMethod, iterator); 2903 // CheckIsObj(innerResult); 2904 // } 2905 // 2906 // Whereas for Throw completions, we emit: 2907 // 2908 // try { 2909 // var returnMethod = GetMethod(iterator, "return"); 2910 // if (returnMethod !== undefined) { 2911 // [Await] Call(returnMethod, iterator); 2912 // } 2913 // } catch {} 2914 2915 Maybe<TryEmitter> tryCatch; 2916 2917 if (completionKind == CompletionKind::Throw) { 2918 tryCatch.emplace(this, TryEmitter::Kind::TryCatch, 2919 TryEmitter::ControlKind::NonSyntactic); 2920 2921 if (!tryCatch->emitTry()) { 2922 // [stack] ... ITER 2923 return false; 2924 } 2925 } 2926 2927 if (!emit1(JSOp::Dup)) { 2928 // [stack] ... ITER ITER 2929 return false; 2930 } 2931 2932 // Steps 1-2 are assertions, step 3 is implicit. 2933 2934 // Step 4. 2935 // 2936 // Get the "return" method. 2937 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::return_())) { 2938 // [stack] ... ITER RET 2939 return false; 2940 } 2941 2942 // Step 5. 2943 // 2944 // Do nothing if "return" is undefined or null. 2945 InternalIfEmitter ifReturnMethodIsDefined(this); 2946 if (!emit1(JSOp::IsNullOrUndefined)) { 2947 // [stack] ... ITER RET NULL-OR-UNDEF 2948 return false; 2949 } 2950 2951 if (!ifReturnMethodIsDefined.emitThenElse( 2952 IfEmitter::ConditionKind::Negative)) { 2953 // [stack] ... ITER RET 2954 return false; 2955 } 2956 2957 // Steps 5.c, 7. 2958 // 2959 // Call the "return" method. 2960 if (!emit1(JSOp::Swap)) { 2961 // [stack] ... RET ITER 2962 return false; 2963 } 2964 2965 if (!emitCall(getIterCallOp(JSOp::Call, selfHostedIter), 0)) { 2966 // [stack] ... RESULT 2967 return false; 2968 } 2969 2970 // 7.4.7 AsyncIteratorClose, step 5.d. 2971 if (iterKind == IteratorKind::Async) { 2972 if (completionKind != CompletionKind::Throw) { 2973 // Await clobbers rval, so save the current rval. 2974 if (!emit1(JSOp::GetRval)) { 2975 // [stack] ... RESULT RVAL 2976 return false; 2977 } 2978 if (!emit1(JSOp::Swap)) { 2979 // [stack] ... RVAL RESULT 2980 return false; 2981 } 2982 } 2983 2984 if (!emitAwaitInScope(currentScope)) { 2985 // [stack] ... RVAL? RESULT 2986 return false; 2987 } 2988 2989 if (completionKind != CompletionKind::Throw) { 2990 if (!emit1(JSOp::Swap)) { 2991 // [stack] ... RESULT RVAL 2992 return false; 2993 } 2994 if (!emit1(JSOp::SetRval)) { 2995 // [stack] ... RESULT 2996 return false; 2997 } 2998 } 2999 } 3000 3001 // Step 6 (Handled in caller). 3002 3003 // Step 8. 3004 if (completionKind != CompletionKind::Throw) { 3005 // Check that the "return" result is an object. 3006 if (!emitCheckIsObj(CheckIsObjectKind::IteratorReturn)) { 3007 // [stack] ... RESULT 3008 return false; 3009 } 3010 } 3011 3012 if (!ifReturnMethodIsDefined.emitElse()) { 3013 // [stack] ... ITER RET 3014 return false; 3015 } 3016 3017 if (!emit1(JSOp::Pop)) { 3018 // [stack] ... ITER 3019 return false; 3020 } 3021 3022 if (!ifReturnMethodIsDefined.emitEnd()) { 3023 return false; 3024 } 3025 3026 if (completionKind == CompletionKind::Throw) { 3027 if (!tryCatch->emitCatch()) { 3028 // [stack] ... ITER EXC 3029 return false; 3030 } 3031 3032 // Just ignore the exception thrown by call and await. 3033 if (!emit1(JSOp::Pop)) { 3034 // [stack] ... ITER 3035 return false; 3036 } 3037 3038 if (!tryCatch->emitEnd()) { 3039 // [stack] ... ITER 3040 return false; 3041 } 3042 } 3043 3044 // Step 9 (Handled in caller). 3045 3046 return emit1(JSOp::Pop); 3047 // [stack] ... 3048 } 3049 3050 template <typename InnerEmitter> 3051 bool BytecodeEmitter::wrapWithDestructuringTryNote(int32_t iterDepth, 3052 InnerEmitter emitter) { 3053 MOZ_ASSERT(bytecodeSection().stackDepth() >= iterDepth); 3054 3055 // Pad a nop at the beginning of the bytecode covered by the trynote so 3056 // that when unwinding environments, we may unwind to the scope 3057 // corresponding to the pc *before* the start, in case the first bytecode 3058 // emitted by |emitter| is the start of an inner scope. See comment above 3059 // UnwindEnvironmentToTryPc. 3060 if (!emit1(JSOp::TryDestructuring)) { 3061 return false; 3062 } 3063 3064 BytecodeOffset start = bytecodeSection().offset(); 3065 if (!emitter(this)) { 3066 return false; 3067 } 3068 BytecodeOffset end = bytecodeSection().offset(); 3069 if (start != end) { 3070 return addTryNote(TryNoteKind::Destructuring, iterDepth, start, end); 3071 } 3072 return true; 3073 } 3074 3075 bool BytecodeEmitter::emitDefault(ParseNode* defaultExpr, ParseNode* pattern) { 3076 // [stack] VALUE 3077 3078 DefaultEmitter de(this); 3079 if (!de.prepareForDefault()) { 3080 // [stack] 3081 return false; 3082 } 3083 if (!emitInitializer(defaultExpr, pattern)) { 3084 // [stack] DEFAULTVALUE 3085 return false; 3086 } 3087 if (!de.emitEnd()) { 3088 // [stack] VALUE/DEFAULTVALUE 3089 return false; 3090 } 3091 return true; 3092 } 3093 3094 bool BytecodeEmitter::emitAnonymousFunctionWithName( 3095 ParseNode* node, TaggedParserAtomIndex name) { 3096 MOZ_ASSERT(node->isDirectRHSAnonFunction()); 3097 3098 if (node->is<FunctionNode>()) { 3099 // Function doesn't have 'name' property at this point. 3100 // Set function's name at compile time. 3101 setFunName(node->as<FunctionNode>().funbox(), name); 3102 3103 return emitTree(node); 3104 } 3105 3106 MOZ_ASSERT(node->is<ClassNode>()); 3107 3108 return emitClass(&node->as<ClassNode>(), ClassNameKind::InferredName, name); 3109 } 3110 3111 bool BytecodeEmitter::emitAnonymousFunctionWithComputedName( 3112 ParseNode* node, FunctionPrefixKind prefixKind) { 3113 MOZ_ASSERT(node->isDirectRHSAnonFunction()); 3114 3115 if (node->is<FunctionNode>()) { 3116 if (!emitTree(node)) { 3117 // [stack] NAME FUN 3118 return false; 3119 } 3120 if (!emitDupAt(1)) { 3121 // [stack] NAME FUN NAME 3122 return false; 3123 } 3124 if (!emit2(JSOp::SetFunName, uint8_t(prefixKind))) { 3125 // [stack] NAME FUN 3126 return false; 3127 } 3128 return true; 3129 } 3130 3131 MOZ_ASSERT(node->is<ClassNode>()); 3132 MOZ_ASSERT(prefixKind == FunctionPrefixKind::None); 3133 3134 return emitClass(&node->as<ClassNode>(), ClassNameKind::ComputedName); 3135 } 3136 3137 void BytecodeEmitter::setFunName(FunctionBox* funbox, 3138 TaggedParserAtomIndex name) const { 3139 // The inferred name may already be set if this function is an interpreted 3140 // lazy function and we OOM'ed after we set the inferred name the first 3141 // time. 3142 if (funbox->hasInferredName()) { 3143 MOZ_ASSERT(!funbox->emitBytecode); 3144 MOZ_ASSERT(funbox->displayAtom() == name); 3145 } else { 3146 funbox->setInferredName(name); 3147 } 3148 } 3149 3150 bool BytecodeEmitter::emitInitializer(ParseNode* initializer, 3151 ParseNode* pattern) { 3152 if (initializer->isDirectRHSAnonFunction()) { 3153 MOZ_ASSERT(!pattern->isInParens()); 3154 auto name = pattern->as<NameNode>().name(); 3155 if (!emitAnonymousFunctionWithName(initializer, name)) { 3156 return false; 3157 } 3158 } else { 3159 if (!emitTree(initializer)) { 3160 return false; 3161 } 3162 } 3163 3164 return true; 3165 } 3166 3167 bool BytecodeEmitter::emitDestructuringOpsArray(ListNode* pattern, 3168 DestructuringFlavor flav, 3169 SelfHostedIter selfHostedIter) { 3170 MOZ_ASSERT(pattern->isKind(ParseNodeKind::ArrayExpr)); 3171 MOZ_ASSERT(bytecodeSection().stackDepth() != 0); 3172 3173 // Here's pseudo code for |let [a, b, , c=y, ...d] = x;| 3174 // 3175 // Lines that are annotated "covered by trynote" mean that upon throwing 3176 // an exception, IteratorClose is called on iter only if done is false. 3177 // 3178 // let x, y; 3179 // let a, b, c, d; 3180 // let iter, next, lref, result, done, value; // stack values 3181 // 3182 // // NOTE: the fast path for this example is not applicable, because of 3183 // // the spread and the assignment |c=y|, but it is documented here for a 3184 // // simpler example, |let [a,b] = x;| 3185 // // 3186 // // if (IsOptimizableArray(x)) { 3187 // // a = x[0]; 3188 // // b = x[1]; 3189 // // goto end: // (skip everything below) 3190 // // } 3191 // 3192 // iter = x[Symbol.iterator](); 3193 // next = iter.next; 3194 // 3195 // // ==== emitted by loop for a ==== 3196 // lref = GetReference(a); // covered by trynote 3197 // 3198 // result = Call(next, iter); 3199 // done = result.done; 3200 // 3201 // if (done) 3202 // value = undefined; 3203 // else 3204 // value = result.value; 3205 // 3206 // SetOrInitialize(lref, value); // covered by trynote 3207 // 3208 // // ==== emitted by loop for b ==== 3209 // lref = GetReference(b); // covered by trynote 3210 // 3211 // if (done) { 3212 // value = undefined; 3213 // } else { 3214 // result = Call(next, iter); 3215 // done = result.done; 3216 // if (done) 3217 // value = undefined; 3218 // else 3219 // value = result.value; 3220 // } 3221 // 3222 // SetOrInitialize(lref, value); // covered by trynote 3223 // 3224 // // ==== emitted by loop for elision ==== 3225 // if (done) { 3226 // value = undefined; 3227 // } else { 3228 // result = Call(next, iter); 3229 // done = result.done; 3230 // if (done) 3231 // value = undefined; 3232 // else 3233 // value = result.value; 3234 // } 3235 // 3236 // // ==== emitted by loop for c ==== 3237 // lref = GetReference(c); // covered by trynote 3238 // 3239 // if (done) { 3240 // value = undefined; 3241 // } else { 3242 // result = Call(next, iter); 3243 // done = result.done; 3244 // if (done) 3245 // value = undefined; 3246 // else 3247 // value = result.value; 3248 // } 3249 // 3250 // if (value === undefined) 3251 // value = y; // covered by trynote 3252 // 3253 // SetOrInitialize(lref, value); // covered by trynote 3254 // 3255 // // ==== emitted by loop for d ==== 3256 // lref = GetReference(d); // covered by trynote 3257 // 3258 // if (done) 3259 // value = []; 3260 // else 3261 // value = [...iter]; 3262 // 3263 // SetOrInitialize(lref, value); // covered by trynote 3264 // 3265 // // === emitted after loop === 3266 // if (!done) 3267 // IteratorClose(iter); 3268 // 3269 // end: 3270 3271 bool isEligibleForArrayOptimizations = true; 3272 for (ParseNode* member : pattern->contents()) { 3273 switch (member->getKind()) { 3274 case ParseNodeKind::Elision: 3275 break; 3276 case ParseNodeKind::Name: { 3277 auto name = member->as<NameNode>().name(); 3278 NameLocation loc = lookupName(name); 3279 if (loc.kind() != NameLocation::Kind::ArgumentSlot && 3280 loc.kind() != NameLocation::Kind::FrameSlot && 3281 loc.kind() != NameLocation::Kind::EnvironmentCoordinate) { 3282 isEligibleForArrayOptimizations = false; 3283 } 3284 break; 3285 } 3286 default: 3287 // Unfortunately we can't handle any recursive destructuring, 3288 // because we can't guarantee that the recursed-into parts 3289 // won't run code which invalidates our constraints. We also 3290 // cannot handle ParseNodeKind::AssignExpr for similar reasons. 3291 isEligibleForArrayOptimizations = false; 3292 break; 3293 } 3294 if (!isEligibleForArrayOptimizations) { 3295 break; 3296 } 3297 } 3298 3299 // Use an iterator to destructure the RHS, instead of index lookup. We 3300 // must leave the *original* value on the stack. 3301 if (!emit1(JSOp::Dup)) { 3302 // [stack] ... OBJ OBJ 3303 return false; 3304 } 3305 3306 Maybe<InternalIfEmitter> ifArrayOptimizable; 3307 3308 if (isEligibleForArrayOptimizations) { 3309 ifArrayOptimizable.emplace( 3310 this, BranchEmitterBase::LexicalKind::MayContainLexicalAccessInBranch); 3311 3312 if (!emit1(JSOp::Dup)) { 3313 // [stack] OBJ OBJ 3314 return false; 3315 } 3316 3317 if (!emit1(JSOp::OptimizeGetIterator)) { 3318 // [stack] OBJ OBJ IS_OPTIMIZABLE 3319 return false; 3320 } 3321 3322 if (!ifArrayOptimizable->emitThenElse()) { 3323 // [stack] OBJ OBJ 3324 return false; 3325 } 3326 3327 if (!emitAtomOp(JSOp::GetProp, 3328 TaggedParserAtomIndex::WellKnown::length())) { 3329 // [stack] OBJ LENGTH 3330 return false; 3331 } 3332 3333 if (!emit1(JSOp::Swap)) { 3334 // [stack] LENGTH OBJ 3335 return false; 3336 } 3337 3338 uint32_t idx = 0; 3339 for (ParseNode* member : pattern->contents()) { 3340 if (member->isKind(ParseNodeKind::Elision)) { 3341 idx += 1; 3342 continue; 3343 } 3344 MOZ_ASSERT(member->isKind(ParseNodeKind::Name)); 3345 3346 if (!emit1(JSOp::Dup)) { 3347 // [stack] LENGTH OBJ OBJ 3348 return false; 3349 } 3350 3351 if (!emitNumberOp(idx)) { 3352 // [stack] LENGTH OBJ OBJ IDX 3353 return false; 3354 } 3355 3356 if (!emit1(JSOp::Dup)) { 3357 // [stack] LENGTH OBJ OBJ IDX IDX 3358 return false; 3359 } 3360 3361 if (!emitDupAt(4)) { 3362 // [stack] LENGTH OBJ OBJ IDX IDX LENGTH 3363 return false; 3364 } 3365 3366 if (!emit1(JSOp::Lt)) { 3367 // [stack] LENGTH OBJ OBJ IDX IS_IN_DENSE_BOUNDS 3368 return false; 3369 } 3370 3371 InternalIfEmitter isInDenseBounds(this); 3372 if (!isInDenseBounds.emitThenElse()) { 3373 // [stack] LENGTH OBJ OBJ IDX 3374 return false; 3375 } 3376 3377 if (!emit1(JSOp::GetElem)) { 3378 // [stack] LENGTH OBJ VALUE 3379 return false; 3380 } 3381 3382 if (!isInDenseBounds.emitElse()) { 3383 // [stack] LENGTH OBJ OBJ IDX 3384 return false; 3385 } 3386 3387 if (!emitPopN(2)) { 3388 // [stack] LENGTH OBJ 3389 return false; 3390 } 3391 3392 if (!emit1(JSOp::Undefined)) { 3393 // [stack] LENGTH OBJ UNDEFINED 3394 return false; 3395 } 3396 3397 if (!isInDenseBounds.emitEnd()) { 3398 // [stack] LENGTH OBJ VALUE|UNDEFINED 3399 return false; 3400 } 3401 3402 DestructuringLHSRef lref; 3403 if (!emitDestructuringLHSRef(member, flav, lref)) { 3404 // [stack] LENGTH OBJ 3405 return false; 3406 } 3407 3408 if (!emitSetOrInitializeDestructuring(member, flav, lref)) { 3409 // [stack] LENGTH OBJ 3410 return false; 3411 } 3412 3413 idx += 1; 3414 } 3415 3416 if (!emit1(JSOp::Swap)) { 3417 // [stack] OBJ LENGTH 3418 return false; 3419 } 3420 3421 if (!emit1(JSOp::Pop)) { 3422 // [stack] OBJ 3423 return false; 3424 } 3425 3426 if (!ifArrayOptimizable->emitElse()) { 3427 // [stack] OBJ OBJ 3428 return false; 3429 } 3430 } 3431 3432 if (!emitIterator(selfHostedIter)) { 3433 // [stack] ... OBJ NEXT ITER 3434 return false; 3435 } 3436 3437 // For an empty pattern [], call IteratorClose unconditionally. Nothing 3438 // else needs to be done. 3439 if (!pattern->head()) { 3440 if (!emit1(JSOp::Swap)) { 3441 // [stack] ... OBJ ITER NEXT 3442 return false; 3443 } 3444 if (!emit1(JSOp::Pop)) { 3445 // [stack] ... OBJ ITER 3446 return false; 3447 } 3448 3449 if (!emitIteratorCloseInInnermostScope( 3450 IteratorKind::Sync, CompletionKind::Normal, selfHostedIter)) { 3451 // [stack] ... OBJ 3452 return false; 3453 } 3454 3455 if (ifArrayOptimizable.isSome()) { 3456 if (!ifArrayOptimizable->emitEnd()) { 3457 // [stack] OBJ 3458 return false; 3459 } 3460 } 3461 3462 return true; 3463 } 3464 3465 // Push an initial FALSE value for DONE. 3466 if (!emit1(JSOp::False)) { 3467 // [stack] ... OBJ NEXT ITER FALSE 3468 return false; 3469 } 3470 3471 // TryNoteKind::Destructuring expects the iterator and the done value 3472 // to be the second to top and the top of the stack, respectively. 3473 // IteratorClose is called upon exception only if done is false. 3474 int32_t tryNoteDepth = bytecodeSection().stackDepth(); 3475 3476 for (ParseNode* member : pattern->contents()) { 3477 bool isFirst = member == pattern->head(); 3478 DebugOnly<bool> hasNext = !!member->pn_next; 3479 3480 ParseNode* subpattern; 3481 if (member->isKind(ParseNodeKind::Spread)) { 3482 subpattern = member->as<UnaryNode>().kid(); 3483 3484 MOZ_ASSERT(!subpattern->isKind(ParseNodeKind::AssignExpr)); 3485 } else { 3486 subpattern = member; 3487 } 3488 3489 ParseNode* lhsPattern = subpattern; 3490 ParseNode* pndefault = nullptr; 3491 if (subpattern->isKind(ParseNodeKind::AssignExpr)) { 3492 lhsPattern = subpattern->as<AssignmentNode>().left(); 3493 pndefault = subpattern->as<AssignmentNode>().right(); 3494 } 3495 3496 // Spec requires LHS reference to be evaluated first. 3497 DestructuringLHSRef lref; 3498 bool isElision = lhsPattern->isKind(ParseNodeKind::Elision); 3499 if (!isElision) { 3500 auto emitLHSRef = [lhsPattern, flav, &lref](BytecodeEmitter* bce) { 3501 return bce->emitDestructuringLHSRef(lhsPattern, flav, lref); 3502 // [stack] ... OBJ NEXT ITER DONE LREF* 3503 }; 3504 if (!wrapWithDestructuringTryNote(tryNoteDepth, emitLHSRef)) { 3505 return false; 3506 } 3507 } 3508 3509 // Number of stack slots emitted for the LHS reference. 3510 size_t emitted = lref.numReferenceSlots(); 3511 3512 // Pick the DONE value to the top of the stack. 3513 if (emitted) { 3514 if (!emitPickN(emitted)) { 3515 // [stack] ... OBJ NEXT ITER LREF* DONE 3516 return false; 3517 } 3518 } 3519 3520 if (isFirst) { 3521 // If this element is the first, DONE is always FALSE, so pop it. 3522 // 3523 // Non-first elements should emit if-else depending on the 3524 // member pattern, below. 3525 if (!emit1(JSOp::Pop)) { 3526 // [stack] ... OBJ NEXT ITER LREF* 3527 return false; 3528 } 3529 } 3530 3531 if (member->isKind(ParseNodeKind::Spread)) { 3532 InternalIfEmitter ifThenElse(this); 3533 if (!isFirst) { 3534 // If spread is not the first element of the pattern, 3535 // iterator can already be completed. 3536 // [stack] ... OBJ NEXT ITER LREF* DONE 3537 3538 if (!ifThenElse.emitThenElse()) { 3539 // [stack] ... OBJ NEXT ITER LREF* 3540 return false; 3541 } 3542 3543 if (!emitUint32Operand(JSOp::NewArray, 0)) { 3544 // [stack] ... OBJ NEXT ITER LREF* ARRAY 3545 return false; 3546 } 3547 if (!ifThenElse.emitElse()) { 3548 // [stack] ... OBJ NEXT ITER LREF* 3549 return false; 3550 } 3551 } 3552 3553 // If iterator is not completed, create a new array with the rest 3554 // of the iterator. 3555 if (!emitDupAt(emitted + 1, 2)) { 3556 // [stack] ... OBJ NEXT ITER LREF* NEXT ITER 3557 return false; 3558 } 3559 if (!emitUint32Operand(JSOp::NewArray, 0)) { 3560 // [stack] ... OBJ NEXT ITER LREF* NEXT ITER ARRAY 3561 return false; 3562 } 3563 if (!emitNumberOp(0)) { 3564 // [stack] ... OBJ NEXT ITER LREF* NEXT ITER ARRAY INDEX 3565 return false; 3566 } 3567 if (!emitSpread(SelfHostedIter::Deny)) { 3568 // [stack] ... OBJ NEXT ITER LREF* ARRAY INDEX 3569 return false; 3570 } 3571 if (!emit1(JSOp::Pop)) { 3572 // [stack] ... OBJ NEXT ITER LREF* ARRAY 3573 return false; 3574 } 3575 3576 if (!isFirst) { 3577 if (!ifThenElse.emitEnd()) { 3578 return false; 3579 } 3580 MOZ_ASSERT(ifThenElse.pushed() == 1); 3581 } 3582 3583 // At this point the iterator is done. Unpick a TRUE value for DONE above 3584 // ITER. 3585 if (!emit1(JSOp::True)) { 3586 // [stack] ... OBJ NEXT ITER LREF* ARRAY TRUE 3587 return false; 3588 } 3589 if (!emitUnpickN(emitted + 1)) { 3590 // [stack] ... OBJ NEXT ITER TRUE LREF* ARRAY 3591 return false; 3592 } 3593 3594 auto emitAssignment = [lhsPattern, flav, &lref](BytecodeEmitter* bce) { 3595 return bce->emitSetOrInitializeDestructuring(lhsPattern, flav, lref); 3596 // [stack] ... OBJ NEXT ITER TRUE 3597 }; 3598 if (!wrapWithDestructuringTryNote(tryNoteDepth, emitAssignment)) { 3599 return false; 3600 } 3601 3602 MOZ_ASSERT(!hasNext); 3603 break; 3604 } 3605 3606 InternalIfEmitter ifAlreadyDone(this); 3607 if (!isFirst) { 3608 // [stack] ... OBJ NEXT ITER LREF* DONE 3609 3610 if (!ifAlreadyDone.emitThenElse()) { 3611 // [stack] ... OBJ NEXT ITER LREF* 3612 return false; 3613 } 3614 3615 if (!emit1(JSOp::Undefined)) { 3616 // [stack] ... OBJ NEXT ITER LREF* UNDEF 3617 return false; 3618 } 3619 if (!emit1(JSOp::NopDestructuring)) { 3620 // [stack] ... OBJ NEXT ITER LREF* UNDEF 3621 return false; 3622 } 3623 3624 // The iterator is done. Unpick a TRUE value for DONE above ITER. 3625 if (!emit1(JSOp::True)) { 3626 // [stack] ... OBJ NEXT ITER LREF* UNDEF TRUE 3627 return false; 3628 } 3629 if (!emitUnpickN(emitted + 1)) { 3630 // [stack] ... OBJ NEXT ITER TRUE LREF* UNDEF 3631 return false; 3632 } 3633 3634 if (!ifAlreadyDone.emitElse()) { 3635 // [stack] ... OBJ NEXT ITER LREF* 3636 return false; 3637 } 3638 } 3639 3640 if (!emitDupAt(emitted + 1, 2)) { 3641 // [stack] ... OBJ NEXT ITER LREF* NEXT 3642 return false; 3643 } 3644 if (!emitIteratorNext(Some(pattern->pn_pos.begin), IteratorKind::Sync, 3645 selfHostedIter)) { 3646 // [stack] ... OBJ NEXT ITER LREF* RESULT 3647 return false; 3648 } 3649 if (!emit1(JSOp::Dup)) { 3650 // [stack] ... OBJ NEXT ITER LREF* RESULT RESULT 3651 return false; 3652 } 3653 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::done())) { 3654 // [stack] ... OBJ NEXT ITER LREF* RESULT DONE 3655 return false; 3656 } 3657 3658 if (!emit1(JSOp::Dup)) { 3659 // [stack] ... OBJ NEXT ITER LREF* RESULT DONE DONE 3660 return false; 3661 } 3662 if (!emitUnpickN(emitted + 2)) { 3663 // [stack] ... OBJ NEXT ITER DONE LREF* RESULT DONE 3664 return false; 3665 } 3666 3667 InternalIfEmitter ifDone(this); 3668 if (!ifDone.emitThenElse()) { 3669 // [stack] ... OBJ NEXT ITER DONE LREF* RESULT 3670 return false; 3671 } 3672 3673 if (!emit1(JSOp::Pop)) { 3674 // [stack] ... OBJ NEXT ITER DONE LREF* 3675 return false; 3676 } 3677 if (!emit1(JSOp::Undefined)) { 3678 // [stack] ... OBJ NEXT ITER DONE LREF* UNDEF 3679 return false; 3680 } 3681 if (!emit1(JSOp::NopDestructuring)) { 3682 // [stack] ... OBJ NEXT ITER DONE LREF* UNDEF 3683 return false; 3684 } 3685 3686 if (!ifDone.emitElse()) { 3687 // [stack] ... OBJ NEXT ITER DONE LREF* RESULT 3688 return false; 3689 } 3690 3691 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::value())) { 3692 // [stack] ... OBJ NEXT ITER DONE LREF* VALUE 3693 return false; 3694 } 3695 3696 if (!ifDone.emitEnd()) { 3697 return false; 3698 } 3699 MOZ_ASSERT(ifDone.pushed() == 0); 3700 3701 if (!isFirst) { 3702 if (!ifAlreadyDone.emitEnd()) { 3703 return false; 3704 } 3705 MOZ_ASSERT(ifAlreadyDone.pushed() == 2); 3706 } 3707 3708 if (pndefault) { 3709 auto emitDefault = [pndefault, lhsPattern](BytecodeEmitter* bce) { 3710 return bce->emitDefault(pndefault, lhsPattern); 3711 // [stack] ... OBJ NEXT ITER DONE LREF* VALUE 3712 }; 3713 3714 if (!wrapWithDestructuringTryNote(tryNoteDepth, emitDefault)) { 3715 return false; 3716 } 3717 } 3718 3719 if (!isElision) { 3720 auto emitAssignment = [lhsPattern, flav, &lref](BytecodeEmitter* bce) { 3721 return bce->emitSetOrInitializeDestructuring(lhsPattern, flav, lref); 3722 // [stack] ... OBJ NEXT ITER DONE 3723 }; 3724 3725 if (!wrapWithDestructuringTryNote(tryNoteDepth, emitAssignment)) { 3726 return false; 3727 } 3728 } else { 3729 if (!emit1(JSOp::Pop)) { 3730 // [stack] ... OBJ NEXT ITER DONE 3731 return false; 3732 } 3733 } 3734 } 3735 3736 // The last DONE value is on top of the stack. If not DONE, call 3737 // IteratorClose. 3738 // [stack] ... OBJ NEXT ITER DONE 3739 3740 InternalIfEmitter ifDone(this); 3741 if (!ifDone.emitThenElse()) { 3742 // [stack] ... OBJ NEXT ITER 3743 return false; 3744 } 3745 if (!emitPopN(2)) { 3746 // [stack] ... OBJ 3747 return false; 3748 } 3749 if (!ifDone.emitElse()) { 3750 // [stack] ... OBJ NEXT ITER 3751 return false; 3752 } 3753 if (!emit1(JSOp::Swap)) { 3754 // [stack] ... OBJ ITER NEXT 3755 return false; 3756 } 3757 if (!emit1(JSOp::Pop)) { 3758 // [stack] ... OBJ ITER 3759 return false; 3760 } 3761 if (!emitIteratorCloseInInnermostScope( 3762 IteratorKind::Sync, CompletionKind::Normal, selfHostedIter)) { 3763 // [stack] ... OBJ 3764 return false; 3765 } 3766 if (!ifDone.emitEnd()) { 3767 return false; 3768 } 3769 3770 if (ifArrayOptimizable.isSome()) { 3771 if (!ifArrayOptimizable->emitEnd()) { 3772 // [stack] OBJ 3773 return false; 3774 } 3775 } 3776 3777 return true; 3778 } 3779 3780 bool BytecodeEmitter::emitComputedPropertyName(UnaryNode* computedPropName) { 3781 MOZ_ASSERT(computedPropName->isKind(ParseNodeKind::ComputedName)); 3782 return emitTree(computedPropName->kid()) && emit1(JSOp::ToPropertyKey); 3783 } 3784 3785 bool BytecodeEmitter::emitDestructuringOpsObject(ListNode* pattern, 3786 DestructuringFlavor flav) { 3787 MOZ_ASSERT(pattern->isKind(ParseNodeKind::ObjectExpr)); 3788 3789 // [stack] ... RHS 3790 MOZ_ASSERT(bytecodeSection().stackDepth() > 0); 3791 3792 if (!emit1(JSOp::CheckObjCoercible)) { 3793 // [stack] ... RHS 3794 return false; 3795 } 3796 3797 // To understand why we chose '4', please see the discussion on Bug 1948959. 3798 const uint8_t estimatedRestSize = 4; 3799 3800 bool needsRestPropertyExcludedSet = 3801 pattern->count() > 1 && pattern->last()->isKind(ParseNodeKind::Spread); 3802 if (needsRestPropertyExcludedSet) { 3803 if (!emitDestructuringObjRestExclusionSet(pattern, estimatedRestSize)) { 3804 // [stack] ... RHS SET 3805 return false; 3806 } 3807 3808 if (!emit1(JSOp::Swap)) { 3809 // [stack] ... SET RHS 3810 return false; 3811 } 3812 } 3813 3814 for (ParseNode* member : pattern->contents()) { 3815 ParseNode* subpattern; 3816 bool hasKeyOnStack = false; 3817 if (member->isKind(ParseNodeKind::MutateProto) || 3818 member->isKind(ParseNodeKind::Spread)) { 3819 subpattern = member->as<UnaryNode>().kid(); 3820 3821 MOZ_ASSERT_IF(member->isKind(ParseNodeKind::Spread), 3822 !subpattern->isKind(ParseNodeKind::AssignExpr)); 3823 } else { 3824 MOZ_ASSERT(member->isKind(ParseNodeKind::PropertyDefinition) || 3825 member->isKind(ParseNodeKind::Shorthand)); 3826 subpattern = member->as<BinaryNode>().right(); 3827 3828 // Computed property names are evaluated before the subpattern. 3829 ParseNode* key = member->as<BinaryNode>().left(); 3830 if (key->isKind(ParseNodeKind::ComputedName)) { 3831 if (!emitComputedPropertyName(&key->as<UnaryNode>())) { 3832 // [stack] ... SET? RHS KEY 3833 return false; 3834 } 3835 hasKeyOnStack = true; 3836 } 3837 } 3838 3839 ParseNode* lhs = subpattern; 3840 ParseNode* pndefault = nullptr; 3841 if (subpattern->isKind(ParseNodeKind::AssignExpr)) { 3842 lhs = subpattern->as<AssignmentNode>().left(); 3843 pndefault = subpattern->as<AssignmentNode>().right(); 3844 } 3845 3846 // Spec requires LHS reference to be evaluated first. 3847 DestructuringLHSRef lref; 3848 if (!emitDestructuringLHSRef(lhs, flav, lref)) { 3849 // [stack] ... SET? RHS KEY? LREF* 3850 return false; 3851 } 3852 3853 // Number of stack slots emitted for the LHS reference. 3854 size_t emitted = lref.numReferenceSlots(); 3855 3856 // Duplicate the value being destructured to use as a reference base. 3857 if (!emitDupAt(emitted + hasKeyOnStack)) { 3858 // [stack] ... SET? RHS KEY? LREF* RHS 3859 return false; 3860 } 3861 3862 if (member->isKind(ParseNodeKind::Spread)) { 3863 if (!updateSourceCoordNotes(member->pn_pos.begin)) { 3864 return false; 3865 } 3866 3867 if (!emit2(JSOp::NewInit, estimatedRestSize)) { 3868 // [stack] ... SET? RHS LREF* RHS TARGET 3869 return false; 3870 } 3871 if (!emit1(JSOp::Dup)) { 3872 // [stack] ... SET? RHS LREF* RHS TARGET TARGET 3873 return false; 3874 } 3875 if (!emit2(JSOp::Pick, 2)) { 3876 // [stack] ... SET? RHS LREF* TARGET TARGET RHS 3877 return false; 3878 } 3879 3880 if (needsRestPropertyExcludedSet) { 3881 if (!emit2(JSOp::Pick, emitted + 4)) { 3882 // [stack] ... RHS LREF* TARGET TARGET RHS SET 3883 return false; 3884 } 3885 } 3886 3887 CopyOption option = needsRestPropertyExcludedSet ? CopyOption::Filtered 3888 : CopyOption::Unfiltered; 3889 if (!emitCopyDataProperties(option)) { 3890 // [stack] ... RHS LREF* TARGET 3891 return false; 3892 } 3893 3894 // Destructure TARGET per this member's lhs. 3895 if (!emitSetOrInitializeDestructuring(lhs, flav, lref)) { 3896 // [stack] ... RHS 3897 return false; 3898 } 3899 3900 MOZ_ASSERT(member == pattern->last(), "Rest property is always last"); 3901 break; 3902 } 3903 3904 // Now push the property value currently being matched, which is the value 3905 // of the current property name "label" on the left of a colon in the object 3906 // initialiser. 3907 if (member->isKind(ParseNodeKind::MutateProto)) { 3908 if (!emitAtomOp(JSOp::GetProp, 3909 TaggedParserAtomIndex::WellKnown::proto_())) { 3910 // [stack] ... SET? RHS LREF* PROP 3911 return false; 3912 } 3913 } else { 3914 MOZ_ASSERT(member->isKind(ParseNodeKind::PropertyDefinition) || 3915 member->isKind(ParseNodeKind::Shorthand)); 3916 3917 ParseNode* key = member->as<BinaryNode>().left(); 3918 if (key->isKind(ParseNodeKind::ObjectPropertyName) || 3919 key->isKind(ParseNodeKind::StringExpr)) { 3920 if (!emitAtomOp(JSOp::GetProp, key->as<NameNode>().atom())) { 3921 // [stack] ... SET? RHS LREF* PROP 3922 return false; 3923 } 3924 } else { 3925 if (key->isKind(ParseNodeKind::NumberExpr)) { 3926 if (!emitNumberOp(key->as<NumericLiteral>().value())) { 3927 // [stack]... SET? RHS LREF* RHS KEY 3928 return false; 3929 } 3930 } else { 3931 // Otherwise this is a computed property name. BigInt keys are parsed 3932 // as (synthetic) computed property names, too. 3933 MOZ_ASSERT(key->isKind(ParseNodeKind::ComputedName)); 3934 MOZ_ASSERT(hasKeyOnStack); 3935 3936 if (!emit2(JSOp::Pick, emitted + 1)) { 3937 // [stack] ... SET? RHS LREF* RHS KEY 3938 return false; 3939 } 3940 3941 // Add the computed property key to the exclusion set. 3942 if (needsRestPropertyExcludedSet) { 3943 if (!emitDupAt(emitted + 3)) { 3944 // [stack] ... SET RHS LREF* RHS KEY SET 3945 return false; 3946 } 3947 if (!emitDupAt(1)) { 3948 // [stack] ... SET RHS LREF* RHS KEY SET KEY 3949 return false; 3950 } 3951 if (!emit1(JSOp::Undefined)) { 3952 // [stack] ... SET RHS LREF* RHS KEY SET KEY UNDEFINED 3953 return false; 3954 } 3955 if (!emit1(JSOp::InitElem)) { 3956 // [stack] ... SET RHS LREF* RHS KEY SET 3957 return false; 3958 } 3959 if (!emit1(JSOp::Pop)) { 3960 // [stack] ... SET RHS LREF* RHS KEY 3961 return false; 3962 } 3963 } 3964 } 3965 3966 // Get the property value. 3967 if (!emitElemOpBase(JSOp::GetElem)) { 3968 // [stack] ... SET? RHS LREF* PROP 3969 return false; 3970 } 3971 } 3972 } 3973 3974 if (pndefault) { 3975 if (!emitDefault(pndefault, lhs)) { 3976 // [stack] ... SET? RHS LREF* VALUE 3977 return false; 3978 } 3979 } 3980 3981 // Destructure PROP per this member's lhs. 3982 if (!emitSetOrInitializeDestructuring(lhs, flav, lref)) { 3983 // [stack] ... SET? RHS 3984 return false; 3985 } 3986 } 3987 3988 return true; 3989 } 3990 3991 static bool IsDestructuringRestExclusionSetObjLiteralCompatible( 3992 ListNode* pattern) { 3993 uint32_t propCount = 0; 3994 for (ParseNode* member : pattern->contents()) { 3995 if (member->isKind(ParseNodeKind::Spread)) { 3996 MOZ_ASSERT(!member->pn_next, "unexpected trailing element after spread"); 3997 break; 3998 } 3999 4000 propCount++; 4001 4002 if (member->isKind(ParseNodeKind::MutateProto)) { 4003 continue; 4004 } 4005 4006 ParseNode* key = member->as<BinaryNode>().left(); 4007 if (key->isKind(ParseNodeKind::ObjectPropertyName) || 4008 key->isKind(ParseNodeKind::StringExpr)) { 4009 continue; 4010 } 4011 4012 // Number and BigInt keys aren't yet supported. Computed property names need 4013 // to be added dynamically. 4014 MOZ_ASSERT(key->isKind(ParseNodeKind::NumberExpr) || 4015 key->isKind(ParseNodeKind::BigIntExpr) || 4016 key->isKind(ParseNodeKind::ComputedName)); 4017 return false; 4018 } 4019 4020 if (propCount > SharedPropMap::MaxPropsForNonDictionary) { 4021 // JSOp::NewObject cannot accept dictionary-mode objects. 4022 return false; 4023 } 4024 4025 return true; 4026 } 4027 4028 bool BytecodeEmitter::emitDestructuringObjRestExclusionSet( 4029 ListNode* pattern, uint8_t estimatedRestSize) { 4030 MOZ_ASSERT(pattern->isKind(ParseNodeKind::ObjectExpr)); 4031 MOZ_ASSERT(pattern->last()->isKind(ParseNodeKind::Spread)); 4032 4033 // See if we can use ObjLiteral to construct the exclusion set object. 4034 if (IsDestructuringRestExclusionSetObjLiteralCompatible(pattern)) { 4035 if (!emitDestructuringRestExclusionSetObjLiteral(pattern)) { 4036 // [stack] OBJ 4037 return false; 4038 } 4039 } else { 4040 // Take the slow but sure way and start off with a blank object. 4041 if (!emit2(JSOp::NewInit, estimatedRestSize)) { 4042 // [stack] OBJ 4043 return false; 4044 } 4045 } 4046 4047 for (ParseNode* member : pattern->contents()) { 4048 if (member->isKind(ParseNodeKind::Spread)) { 4049 MOZ_ASSERT(!member->pn_next, "unexpected trailing element after spread"); 4050 break; 4051 } 4052 4053 TaggedParserAtomIndex pnatom; 4054 if (member->isKind(ParseNodeKind::MutateProto)) { 4055 pnatom = TaggedParserAtomIndex::WellKnown::proto_(); 4056 } else { 4057 ParseNode* key = member->as<BinaryNode>().left(); 4058 if (key->isKind(ParseNodeKind::ObjectPropertyName) || 4059 key->isKind(ParseNodeKind::StringExpr)) { 4060 pnatom = key->as<NameNode>().atom(); 4061 } else if (key->isKind(ParseNodeKind::NumberExpr)) { 4062 if (!emitNumberOp(key->as<NumericLiteral>().value())) { 4063 return false; 4064 } 4065 } else { 4066 // Otherwise this is a computed property name which needs to be added 4067 // dynamically. BigInt keys are parsed as (synthetic) computed property 4068 // names, too. 4069 MOZ_ASSERT(key->isKind(ParseNodeKind::ComputedName)); 4070 continue; 4071 } 4072 } 4073 4074 // Initialize elements with |undefined|. 4075 if (!emit1(JSOp::Undefined)) { 4076 return false; 4077 } 4078 4079 if (!pnatom) { 4080 if (!emit1(JSOp::InitElem)) { 4081 return false; 4082 } 4083 } else { 4084 if (!emitAtomOp(JSOp::InitProp, pnatom)) { 4085 return false; 4086 } 4087 } 4088 } 4089 4090 return true; 4091 } 4092 4093 bool BytecodeEmitter::emitDestructuringOps(ListNode* pattern, 4094 DestructuringFlavor flav, 4095 SelfHostedIter selfHostedIter) { 4096 if (pattern->isKind(ParseNodeKind::ArrayExpr)) { 4097 return emitDestructuringOpsArray(pattern, flav, selfHostedIter); 4098 } 4099 return emitDestructuringOpsObject(pattern, flav); 4100 } 4101 4102 bool BytecodeEmitter::emitTemplateString(ListNode* templateString) { 4103 bool pushedString = false; 4104 4105 for (ParseNode* item : templateString->contents()) { 4106 bool isString = (item->getKind() == ParseNodeKind::StringExpr || 4107 item->getKind() == ParseNodeKind::TemplateStringExpr); 4108 4109 // Skip empty strings. These are very common: a template string like 4110 // `${a}${b}` has three empty strings and without this optimization 4111 // we'd emit four JSOp::Add operations instead of just one. 4112 if (isString && item->as<NameNode>().atom() == 4113 TaggedParserAtomIndex::WellKnown::empty()) { 4114 continue; 4115 } 4116 4117 if (!isString) { 4118 // We update source notes before emitting the expression 4119 if (!updateSourceCoordNotes(item->pn_pos.begin)) { 4120 return false; 4121 } 4122 } 4123 4124 if (!emitTree(item)) { 4125 return false; 4126 } 4127 4128 if (!isString) { 4129 // We need to convert the expression to a string 4130 if (!emit1(JSOp::ToString)) { 4131 return false; 4132 } 4133 } 4134 4135 if (pushedString) { 4136 // We've pushed two strings onto the stack. Add them together, leaving 4137 // just one. 4138 if (!emit1(JSOp::Add)) { 4139 return false; 4140 } 4141 } else { 4142 pushedString = true; 4143 } 4144 } 4145 4146 if (!pushedString) { 4147 // All strings were empty, this can happen for something like `${""}`. 4148 // Just push an empty string. 4149 if (!emitStringOp(JSOp::String, 4150 TaggedParserAtomIndex::WellKnown::empty())) { 4151 return false; 4152 } 4153 } 4154 4155 return true; 4156 } 4157 4158 bool BytecodeEmitter::emitDeclarationList(ListNode* declList) { 4159 for (ParseNode* decl : declList->contents()) { 4160 ParseNode* pattern; 4161 ParseNode* initializer; 4162 if (decl->isKind(ParseNodeKind::Name)) { 4163 pattern = decl; 4164 initializer = nullptr; 4165 } else { 4166 AssignmentNode* assignNode = &decl->as<AssignmentNode>(); 4167 pattern = assignNode->left(); 4168 initializer = assignNode->right(); 4169 } 4170 4171 if (pattern->isKind(ParseNodeKind::Name)) { 4172 // initializer can be null here. 4173 if (!emitSingleDeclaration(declList, &pattern->as<NameNode>(), 4174 initializer)) { 4175 return false; 4176 } 4177 } else { 4178 MOZ_ASSERT(pattern->isKind(ParseNodeKind::ArrayExpr) || 4179 pattern->isKind(ParseNodeKind::ObjectExpr)); 4180 MOZ_ASSERT(initializer != nullptr); 4181 4182 if (!updateSourceCoordNotes(initializer->pn_pos.begin)) { 4183 return false; 4184 } 4185 if (!markStepBreakpoint()) { 4186 return false; 4187 } 4188 if (!emitTree(initializer)) { 4189 return false; 4190 } 4191 4192 if (!emitDestructuringOps(&pattern->as<ListNode>(), 4193 DestructuringFlavor::Declaration, 4194 getSelfHostedIterFor(initializer))) { 4195 return false; 4196 } 4197 4198 if (!emit1(JSOp::Pop)) { 4199 return false; 4200 } 4201 } 4202 } 4203 return true; 4204 } 4205 4206 bool BytecodeEmitter::emitSingleDeclaration(ListNode* declList, NameNode* decl, 4207 ParseNode* initializer) { 4208 MOZ_ASSERT(decl->isKind(ParseNodeKind::Name)); 4209 4210 // Nothing to do for initializer-less 'var' declarations, as there's no TDZ. 4211 if (!initializer && declList->isKind(ParseNodeKind::VarStmt)) { 4212 return true; 4213 } 4214 4215 auto nameAtom = decl->name(); 4216 NameOpEmitter noe(this, nameAtom, NameOpEmitter::Kind::Initialize); 4217 if (!noe.prepareForRhs()) { 4218 // [stack] ENV? 4219 return false; 4220 } 4221 if (!initializer) { 4222 // Lexical declarations are initialized to undefined without an 4223 // initializer. 4224 MOZ_ASSERT(declList->isKind(ParseNodeKind::LetDecl), 4225 "var declarations without initializers handled above, " 4226 "and const declarations must have initializers"); 4227 if (!emit1(JSOp::Undefined)) { 4228 // [stack] ENV? UNDEF 4229 return false; 4230 } 4231 } else { 4232 MOZ_ASSERT(initializer); 4233 4234 if (!updateSourceCoordNotes(initializer->pn_pos.begin)) { 4235 return false; 4236 } 4237 if (!markStepBreakpoint()) { 4238 return false; 4239 } 4240 if (!emitInitializer(initializer, decl)) { 4241 // [stack] ENV? V 4242 return false; 4243 } 4244 } 4245 4246 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT 4247 if (declList->isKind(ParseNodeKind::UsingDecl)) { 4248 if (!innermostEmitterScope()->prepareForDisposableAssignment( 4249 UsingHint::Sync)) { 4250 // [stack] ENV? V 4251 return false; 4252 } 4253 } else if (declList->isKind(ParseNodeKind::AwaitUsingDecl)) { 4254 if (!innermostEmitterScope()->prepareForDisposableAssignment( 4255 UsingHint::Async)) { 4256 // [stack] ENV? V 4257 return false; 4258 } 4259 } 4260 #endif 4261 4262 if (!noe.emitAssignment()) { 4263 // [stack] V 4264 return false; 4265 } 4266 4267 if (!emit1(JSOp::Pop)) { 4268 // [stack] 4269 return false; 4270 } 4271 4272 return true; 4273 } 4274 4275 bool BytecodeEmitter::emitAssignmentRhs( 4276 ParseNode* rhs, TaggedParserAtomIndex anonFunctionName) { 4277 if (rhs->isDirectRHSAnonFunction()) { 4278 if (anonFunctionName) { 4279 return emitAnonymousFunctionWithName(rhs, anonFunctionName); 4280 } 4281 return emitAnonymousFunctionWithComputedName(rhs, FunctionPrefixKind::None); 4282 } 4283 return emitTree(rhs); 4284 } 4285 4286 // The RHS value to assign is already on the stack, i.e., the next enumeration 4287 // value in a for-in or for-of loop. Offset is the location in the stack of the 4288 // already-emitted rhs. If we emitted a JSOp::BindUnqualifiedName or 4289 // JSOp::BindUnqualifiedGName, then the scope is on the top of the stack and we 4290 // need to dig one deeper to get the right RHS value. 4291 bool BytecodeEmitter::emitAssignmentRhs(uint8_t offset) { 4292 if (offset != 1) { 4293 return emitPickN(offset - 1); 4294 } 4295 4296 return true; 4297 } 4298 4299 static inline JSOp CompoundAssignmentParseNodeKindToJSOp(ParseNodeKind pnk) { 4300 switch (pnk) { 4301 case ParseNodeKind::InitExpr: 4302 return JSOp::Nop; 4303 case ParseNodeKind::AssignExpr: 4304 return JSOp::Nop; 4305 case ParseNodeKind::AddAssignExpr: 4306 return JSOp::Add; 4307 case ParseNodeKind::SubAssignExpr: 4308 return JSOp::Sub; 4309 case ParseNodeKind::BitOrAssignExpr: 4310 return JSOp::BitOr; 4311 case ParseNodeKind::BitXorAssignExpr: 4312 return JSOp::BitXor; 4313 case ParseNodeKind::BitAndAssignExpr: 4314 return JSOp::BitAnd; 4315 case ParseNodeKind::LshAssignExpr: 4316 return JSOp::Lsh; 4317 case ParseNodeKind::RshAssignExpr: 4318 return JSOp::Rsh; 4319 case ParseNodeKind::UrshAssignExpr: 4320 return JSOp::Ursh; 4321 case ParseNodeKind::MulAssignExpr: 4322 return JSOp::Mul; 4323 case ParseNodeKind::DivAssignExpr: 4324 return JSOp::Div; 4325 case ParseNodeKind::ModAssignExpr: 4326 return JSOp::Mod; 4327 case ParseNodeKind::PowAssignExpr: 4328 return JSOp::Pow; 4329 case ParseNodeKind::CoalesceAssignExpr: 4330 case ParseNodeKind::OrAssignExpr: 4331 case ParseNodeKind::AndAssignExpr: 4332 // Short-circuit assignment operators are handled elsewhere. 4333 [[fallthrough]]; 4334 default: 4335 MOZ_CRASH("unexpected compound assignment op"); 4336 } 4337 } 4338 4339 bool BytecodeEmitter::emitAssignmentOrInit(ParseNodeKind kind, ParseNode* lhs, 4340 ParseNode* rhs) { 4341 JSOp compoundOp = CompoundAssignmentParseNodeKindToJSOp(kind); 4342 bool isCompound = compoundOp != JSOp::Nop; 4343 bool isInit = kind == ParseNodeKind::InitExpr; 4344 4345 // We estimate the number of properties this could create 4346 // if used as constructor merely by counting this.foo = assignment 4347 // or init expressions; 4348 // 4349 // This currently doesn't handle this[x] = foo; 4350 if (isInit || kind == ParseNodeKind::AssignExpr) { 4351 if (lhs->isKind(ParseNodeKind::DotExpr)) { 4352 if (lhs->as<PropertyAccess>().expression().isKind( 4353 ParseNodeKind::ThisExpr)) { 4354 propertyAdditionEstimate++; 4355 } 4356 } 4357 } 4358 4359 MOZ_ASSERT_IF(isInit, lhs->isKind(ParseNodeKind::DotExpr) || 4360 lhs->isKind(ParseNodeKind::ElemExpr) || 4361 lhs->isKind(ParseNodeKind::PrivateMemberExpr)); 4362 4363 // |name| is used within NameOpEmitter, so its lifetime must surpass |noe|. 4364 TaggedParserAtomIndex name; 4365 4366 Maybe<NameOpEmitter> noe; 4367 Maybe<PropOpEmitter> poe; 4368 Maybe<ElemOpEmitter> eoe; 4369 Maybe<PrivateOpEmitter> xoe; 4370 4371 // Deal with non-name assignments. 4372 uint8_t offset = 1; 4373 4374 // Purpose of anonFunctionName: 4375 // 4376 // In normal name assignments (`f = function(){}`), an anonymous function gets 4377 // an inferred name based on the left-hand side name node. 4378 // 4379 // In normal property assignments (`obj.x = function(){}`), the anonymous 4380 // function does not have a computed name, and rhs->isDirectRHSAnonFunction() 4381 // will be false (and anonFunctionName will not be used). However, in field 4382 // initializers (`class C { x = function(){} }`), field initialization is 4383 // implemented via a property or elem assignment (where we are now), and 4384 // rhs->isDirectRHSAnonFunction() is set - so we'll assign the name of the 4385 // function. 4386 TaggedParserAtomIndex anonFunctionName; 4387 4388 switch (lhs->getKind()) { 4389 case ParseNodeKind::Name: { 4390 name = lhs->as<NameNode>().name(); 4391 anonFunctionName = name; 4392 noe.emplace(this, name, 4393 isCompound ? NameOpEmitter::Kind::CompoundAssignment 4394 : NameOpEmitter::Kind::SimpleAssignment); 4395 break; 4396 } 4397 case ParseNodeKind::ArgumentsLength: 4398 case ParseNodeKind::DotExpr: { 4399 PropertyAccess* prop = &lhs->as<PropertyAccess>(); 4400 bool isSuper = prop->isSuper(); 4401 poe.emplace(this, 4402 isCompound ? PropOpEmitter::Kind::CompoundAssignment 4403 : isInit ? PropOpEmitter::Kind::PropInit 4404 : PropOpEmitter::Kind::SimpleAssignment, 4405 isSuper ? PropOpEmitter::ObjKind::Super 4406 : PropOpEmitter::ObjKind::Other); 4407 if (!poe->prepareForObj()) { 4408 return false; 4409 } 4410 anonFunctionName = prop->name(); 4411 if (isSuper) { 4412 UnaryNode* base = &prop->expression().as<UnaryNode>(); 4413 if (!emitGetThisForSuperBase(base)) { 4414 // [stack] THIS SUPERBASE 4415 return false; 4416 } 4417 // SUPERBASE is pushed onto THIS later in poe->emitGet below. 4418 offset += 2; 4419 } else { 4420 if (!emitTree(&prop->expression())) { 4421 // [stack] OBJ 4422 return false; 4423 } 4424 offset += 1; 4425 } 4426 break; 4427 } 4428 case ParseNodeKind::ElemExpr: { 4429 PropertyByValue* elem = &lhs->as<PropertyByValue>(); 4430 bool isSuper = elem->isSuper(); 4431 MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName)); 4432 eoe.emplace(this, 4433 isCompound ? ElemOpEmitter::Kind::CompoundAssignment 4434 : isInit ? ElemOpEmitter::Kind::PropInit 4435 : ElemOpEmitter::Kind::SimpleAssignment, 4436 isSuper ? ElemOpEmitter::ObjKind::Super 4437 : ElemOpEmitter::ObjKind::Other); 4438 if (!emitElemObjAndKey(elem, *eoe)) { 4439 // [stack] # if Super 4440 // [stack] THIS KEY 4441 // [stack] # otherwise 4442 // [stack] OBJ KEY 4443 return false; 4444 } 4445 if (isSuper) { 4446 // SUPERBASE is pushed onto KEY in eoe->emitGet below. 4447 offset += 3; 4448 } else { 4449 offset += 2; 4450 } 4451 break; 4452 } 4453 case ParseNodeKind::PrivateMemberExpr: { 4454 PrivateMemberAccess* privateExpr = &lhs->as<PrivateMemberAccess>(); 4455 xoe.emplace(this, 4456 isCompound ? PrivateOpEmitter::Kind::CompoundAssignment 4457 : isInit ? PrivateOpEmitter::Kind::PropInit 4458 : PrivateOpEmitter::Kind::SimpleAssignment, 4459 privateExpr->privateName().name()); 4460 if (!emitTree(&privateExpr->expression())) { 4461 // [stack] OBJ 4462 return false; 4463 } 4464 if (!xoe->emitReference()) { 4465 // [stack] OBJ KEY 4466 return false; 4467 } 4468 offset += xoe->numReferenceSlots(); 4469 break; 4470 } 4471 case ParseNodeKind::ArrayExpr: 4472 case ParseNodeKind::ObjectExpr: 4473 break; 4474 case ParseNodeKind::CallExpr: 4475 if (!emitTree(lhs)) { 4476 return false; 4477 } 4478 4479 // Assignment to function calls is forbidden, but we have to make the 4480 // call first. Now we can throw. 4481 if (!emit2(JSOp::ThrowMsg, uint8_t(ThrowMsgKind::AssignToCall))) { 4482 return false; 4483 } 4484 4485 // Rebalance the stack to placate stack-depth assertions. 4486 if (!emit1(JSOp::Pop)) { 4487 return false; 4488 } 4489 break; 4490 default: 4491 MOZ_ASSERT(0); 4492 } 4493 4494 if (isCompound) { 4495 MOZ_ASSERT(rhs); 4496 switch (lhs->getKind()) { 4497 case ParseNodeKind::ArgumentsLength: 4498 case ParseNodeKind::DotExpr: { 4499 PropertyAccess* prop = &lhs->as<PropertyAccess>(); 4500 if (!poe->emitGet(prop->key().atom())) { 4501 // [stack] # if Super 4502 // [stack] THIS SUPERBASE PROP 4503 // [stack] # otherwise 4504 // [stack] OBJ PROP 4505 return false; 4506 } 4507 break; 4508 } 4509 case ParseNodeKind::ElemExpr: { 4510 if (!eoe->emitGet()) { 4511 // [stack] KEY THIS OBJ ELEM 4512 return false; 4513 } 4514 break; 4515 } 4516 case ParseNodeKind::PrivateMemberExpr: { 4517 if (!xoe->emitGet()) { 4518 // [stack] OBJ KEY VALUE 4519 return false; 4520 } 4521 break; 4522 } 4523 case ParseNodeKind::CallExpr: 4524 // We just emitted a JSOp::ThrowMsg and popped the call's return 4525 // value. Push a random value to make sure the stack depth is 4526 // correct. 4527 if (!emit1(JSOp::Null)) { 4528 // [stack] NULL 4529 return false; 4530 } 4531 break; 4532 default:; 4533 } 4534 } 4535 4536 switch (lhs->getKind()) { 4537 case ParseNodeKind::Name: 4538 if (!noe->prepareForRhs()) { 4539 // [stack] ENV? VAL? 4540 return false; 4541 } 4542 offset += noe->emittedBindOp(); 4543 break; 4544 case ParseNodeKind::ArgumentsLength: 4545 case ParseNodeKind::DotExpr: 4546 if (!poe->prepareForRhs()) { 4547 // [stack] # if Simple Assignment with Super 4548 // [stack] THIS SUPERBASE 4549 // [stack] # if Simple Assignment with other 4550 // [stack] OBJ 4551 // [stack] # if Compound Assignment with Super 4552 // [stack] THIS SUPERBASE PROP 4553 // [stack] # if Compound Assignment with other 4554 // [stack] OBJ PROP 4555 return false; 4556 } 4557 break; 4558 case ParseNodeKind::ElemExpr: 4559 if (!eoe->prepareForRhs()) { 4560 // [stack] # if Simple Assignment with Super 4561 // [stack] THIS KEY SUPERBASE 4562 // [stack] # if Simple Assignment with other 4563 // [stack] OBJ KEY 4564 // [stack] # if Compound Assignment with Super 4565 // [stack] THIS KEY SUPERBASE ELEM 4566 // [stack] # if Compound Assignment with other 4567 // [stack] OBJ KEY ELEM 4568 return false; 4569 } 4570 break; 4571 case ParseNodeKind::PrivateMemberExpr: 4572 // no stack adjustment needed 4573 break; 4574 default: 4575 break; 4576 } 4577 4578 if (rhs) { 4579 if (!emitAssignmentRhs(rhs, anonFunctionName)) { 4580 // [stack] ... VAL? RHS 4581 return false; 4582 } 4583 } else { 4584 // Assumption: Things with pre-emitted RHS values never need to be named. 4585 if (!emitAssignmentRhs(offset)) { 4586 // [stack] ... VAL? RHS 4587 return false; 4588 } 4589 } 4590 4591 /* If += etc., emit the binary operator with a hint for the decompiler. */ 4592 if (isCompound) { 4593 if (!emit1(compoundOp)) { 4594 // [stack] ... VAL 4595 return false; 4596 } 4597 if (!emit1(JSOp::NopIsAssignOp)) { 4598 // [stack] ... VAL 4599 return false; 4600 } 4601 } 4602 4603 /* Finally, emit the specialized assignment bytecode. */ 4604 switch (lhs->getKind()) { 4605 case ParseNodeKind::Name: { 4606 if (!noe->emitAssignment()) { 4607 // [stack] VAL 4608 return false; 4609 } 4610 break; 4611 } 4612 case ParseNodeKind::ArgumentsLength: 4613 case ParseNodeKind::DotExpr: { 4614 PropertyAccess* prop = &lhs->as<PropertyAccess>(); 4615 if (!poe->emitAssignment(prop->key().atom())) { 4616 // [stack] VAL 4617 return false; 4618 } 4619 break; 4620 } 4621 case ParseNodeKind::CallExpr: 4622 // We threw above, so nothing to do here. 4623 break; 4624 case ParseNodeKind::ElemExpr: { 4625 if (!eoe->emitAssignment()) { 4626 // [stack] VAL 4627 return false; 4628 } 4629 break; 4630 } 4631 case ParseNodeKind::PrivateMemberExpr: 4632 if (!xoe->emitAssignment()) { 4633 // [stack] VAL 4634 return false; 4635 } 4636 break; 4637 case ParseNodeKind::ArrayExpr: 4638 case ParseNodeKind::ObjectExpr: { 4639 auto selfHostedIter = 4640 rhs ? getSelfHostedIterFor(rhs) : SelfHostedIter::Deny; 4641 if (!emitDestructuringOps(&lhs->as<ListNode>(), 4642 DestructuringFlavor::Assignment, 4643 selfHostedIter)) { 4644 return false; 4645 } 4646 break; 4647 } 4648 default: 4649 MOZ_ASSERT(0); 4650 } 4651 return true; 4652 } 4653 4654 bool BytecodeEmitter::emitShortCircuitAssignment(AssignmentNode* node) { 4655 TDZCheckCache tdzCache(this); 4656 4657 JSOp op; 4658 switch (node->getKind()) { 4659 case ParseNodeKind::CoalesceAssignExpr: 4660 op = JSOp::Coalesce; 4661 break; 4662 case ParseNodeKind::OrAssignExpr: 4663 op = JSOp::Or; 4664 break; 4665 case ParseNodeKind::AndAssignExpr: 4666 op = JSOp::And; 4667 break; 4668 default: 4669 MOZ_CRASH("Unexpected ParseNodeKind"); 4670 } 4671 4672 ParseNode* lhs = node->left(); 4673 ParseNode* rhs = node->right(); 4674 4675 // |name| is used within NameOpEmitter, so its lifetime must surpass |noe|. 4676 TaggedParserAtomIndex name; 4677 4678 // Select the appropriate emitter based on the left-hand side. 4679 Maybe<NameOpEmitter> noe; 4680 Maybe<PropOpEmitter> poe; 4681 Maybe<ElemOpEmitter> eoe; 4682 Maybe<PrivateOpEmitter> xoe; 4683 4684 int32_t depth = bytecodeSection().stackDepth(); 4685 4686 // Number of values pushed onto the stack in addition to the lhs value. 4687 int32_t numPushed; 4688 4689 // Evaluate the left-hand side expression and compute any stack values needed 4690 // for the assignment. 4691 switch (lhs->getKind()) { 4692 case ParseNodeKind::Name: { 4693 name = lhs->as<NameNode>().name(); 4694 noe.emplace(this, name, NameOpEmitter::Kind::CompoundAssignment); 4695 4696 if (!noe->prepareForRhs()) { 4697 // [stack] ENV? LHS 4698 return false; 4699 } 4700 4701 numPushed = noe->emittedBindOp(); 4702 break; 4703 } 4704 case ParseNodeKind::ArgumentsLength: 4705 case ParseNodeKind::DotExpr: { 4706 PropertyAccess* prop = &lhs->as<PropertyAccess>(); 4707 bool isSuper = prop->isSuper(); 4708 4709 poe.emplace(this, PropOpEmitter::Kind::CompoundAssignment, 4710 isSuper ? PropOpEmitter::ObjKind::Super 4711 : PropOpEmitter::ObjKind::Other); 4712 4713 if (!poe->prepareForObj()) { 4714 return false; 4715 } 4716 4717 if (isSuper) { 4718 UnaryNode* base = &prop->expression().as<UnaryNode>(); 4719 if (!emitGetThisForSuperBase(base)) { 4720 // [stack] THIS SUPERBASE 4721 return false; 4722 } 4723 } else { 4724 if (!emitTree(&prop->expression())) { 4725 // [stack] OBJ 4726 return false; 4727 } 4728 } 4729 4730 if (!poe->emitGet(prop->key().atom())) { 4731 // [stack] # if Super 4732 // [stack] THIS SUPERBASE LHS 4733 // [stack] # otherwise 4734 // [stack] OBJ LHS 4735 return false; 4736 } 4737 4738 if (!poe->prepareForRhs()) { 4739 // [stack] # if Super 4740 // [stack] THIS SUPERBASE LHS 4741 // [stack] # otherwise 4742 // [stack] OBJ LHS 4743 return false; 4744 } 4745 4746 numPushed = 1 + isSuper; 4747 break; 4748 } 4749 4750 case ParseNodeKind::ElemExpr: { 4751 PropertyByValue* elem = &lhs->as<PropertyByValue>(); 4752 bool isSuper = elem->isSuper(); 4753 MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName)); 4754 eoe.emplace(this, ElemOpEmitter::Kind::CompoundAssignment, 4755 isSuper ? ElemOpEmitter::ObjKind::Super 4756 : ElemOpEmitter::ObjKind::Other); 4757 4758 if (!emitElemObjAndKey(elem, *eoe)) { 4759 // [stack] # if Super 4760 // [stack] THIS KEY 4761 // [stack] # otherwise 4762 // [stack] OBJ KEY 4763 return false; 4764 } 4765 4766 if (!eoe->emitGet()) { 4767 // [stack] # if Super 4768 // [stack] THIS KEY SUPERBASE LHS 4769 // [stack] # otherwise 4770 // [stack] OBJ KEY LHS 4771 return false; 4772 } 4773 4774 if (!eoe->prepareForRhs()) { 4775 // [stack] # if Super 4776 // [stack] THIS KEY SUPERBASE LHS 4777 // [stack] # otherwise 4778 // [stack] OBJ KEY LHS 4779 return false; 4780 } 4781 4782 numPushed = 2 + isSuper; 4783 break; 4784 } 4785 4786 case ParseNodeKind::PrivateMemberExpr: { 4787 PrivateMemberAccess* privateExpr = &lhs->as<PrivateMemberAccess>(); 4788 xoe.emplace(this, PrivateOpEmitter::Kind::CompoundAssignment, 4789 privateExpr->privateName().name()); 4790 if (!emitTree(&privateExpr->expression())) { 4791 // [stack] OBJ 4792 return false; 4793 } 4794 if (!xoe->emitReference()) { 4795 // [stack] OBJ NAME 4796 return false; 4797 } 4798 if (!xoe->emitGet()) { 4799 // [stack] OBJ NAME LHS 4800 return false; 4801 } 4802 numPushed = xoe->numReferenceSlots(); 4803 break; 4804 } 4805 4806 default: 4807 MOZ_CRASH(); 4808 } 4809 4810 MOZ_ASSERT(bytecodeSection().stackDepth() == depth + numPushed + 1); 4811 4812 // Test for the short-circuit condition. 4813 JumpList jump; 4814 if (!emitJump(op, &jump)) { 4815 // [stack] ... LHS 4816 return false; 4817 } 4818 4819 // The short-circuit condition wasn't fulfilled, pop the left-hand side value 4820 // which was kept on the stack. 4821 if (!emit1(JSOp::Pop)) { 4822 // [stack] ... 4823 return false; 4824 } 4825 4826 if (!emitAssignmentRhs(rhs, name)) { 4827 // [stack] ... RHS 4828 return false; 4829 } 4830 4831 // Perform the actual assignment. 4832 switch (lhs->getKind()) { 4833 case ParseNodeKind::Name: { 4834 if (!noe->emitAssignment()) { 4835 // [stack] RHS 4836 return false; 4837 } 4838 break; 4839 } 4840 case ParseNodeKind::ArgumentsLength: 4841 case ParseNodeKind::DotExpr: { 4842 PropertyAccess* prop = &lhs->as<PropertyAccess>(); 4843 4844 if (!poe->emitAssignment(prop->key().atom())) { 4845 // [stack] RHS 4846 return false; 4847 } 4848 break; 4849 } 4850 4851 case ParseNodeKind::ElemExpr: { 4852 if (!eoe->emitAssignment()) { 4853 // [stack] RHS 4854 return false; 4855 } 4856 break; 4857 } 4858 4859 case ParseNodeKind::PrivateMemberExpr: 4860 if (!xoe->emitAssignment()) { 4861 // [stack] RHS 4862 return false; 4863 } 4864 break; 4865 4866 default: 4867 MOZ_CRASH(); 4868 } 4869 4870 MOZ_ASSERT(bytecodeSection().stackDepth() == depth + 1); 4871 4872 // Join with the short-circuit jump and pop anything left on the stack. 4873 if (numPushed > 0) { 4874 JumpList jumpAroundPop; 4875 if (!emitJump(JSOp::Goto, &jumpAroundPop)) { 4876 // [stack] RHS 4877 return false; 4878 } 4879 4880 if (!emitJumpTargetAndPatch(jump)) { 4881 // [stack] ... LHS 4882 return false; 4883 } 4884 4885 // Reconstruct the stack depth after the jump. 4886 bytecodeSection().setStackDepth(depth + 1 + numPushed); 4887 4888 // Move the left-hand side value to the bottom and pop the rest. 4889 if (!emitUnpickN(numPushed)) { 4890 // [stack] LHS ... 4891 return false; 4892 } 4893 if (!emitPopN(numPushed)) { 4894 // [stack] LHS 4895 return false; 4896 } 4897 4898 if (!emitJumpTargetAndPatch(jumpAroundPop)) { 4899 // [stack] LHS | RHS 4900 return false; 4901 } 4902 } else { 4903 if (!emitJumpTargetAndPatch(jump)) { 4904 // [stack] LHS | RHS 4905 return false; 4906 } 4907 } 4908 4909 MOZ_ASSERT(bytecodeSection().stackDepth() == depth + 1); 4910 4911 return true; 4912 } 4913 4914 bool BytecodeEmitter::emitCallSiteObjectArray(ObjLiteralWriter& writer, 4915 ListNode* cookedOrRaw, 4916 ParseNode* head, uint32_t count) { 4917 DebugOnly<size_t> idx = 0; 4918 for (ParseNode* pn : cookedOrRaw->contentsFrom(head)) { 4919 MOZ_ASSERT(pn->isKind(ParseNodeKind::TemplateStringExpr) || 4920 pn->isKind(ParseNodeKind::RawUndefinedExpr)); 4921 4922 if (!emitObjLiteralValue(writer, pn)) { 4923 return false; 4924 } 4925 idx++; 4926 } 4927 MOZ_ASSERT(idx == count); 4928 4929 return true; 4930 } 4931 4932 bool BytecodeEmitter::emitCallSiteObject(CallSiteNode* callSiteObj) { 4933 constexpr JSOp op = JSOp::CallSiteObj; 4934 4935 // The first element of a call-site node is the raw-values list. Skip over it. 4936 ListNode* raw = callSiteObj->rawNodes(); 4937 MOZ_ASSERT(raw->isKind(ParseNodeKind::ArrayExpr)); 4938 ParseNode* head = callSiteObj->head()->pn_next; 4939 4940 uint32_t count = callSiteObj->count() - 1; 4941 MOZ_ASSERT(count == raw->count()); 4942 4943 ObjLiteralWriter writer; 4944 writer.beginCallSiteObj(op); 4945 writer.beginDenseArrayElements(); 4946 4947 // Write elements of the two arrays: the 'cooked' values followed by the 4948 // 'raw' values. 4949 MOZ_RELEASE_ASSERT(count < UINT32_MAX / 2, 4950 "Number of elements for both arrays must fit in uint32_t"); 4951 if (!emitCallSiteObjectArray(writer, callSiteObj, head, count)) { 4952 return false; 4953 } 4954 if (!emitCallSiteObjectArray(writer, raw, raw->head(), count)) { 4955 return false; 4956 } 4957 4958 GCThingIndex cookedIndex; 4959 if (!addObjLiteralData(writer, &cookedIndex)) { 4960 return false; 4961 } 4962 4963 MOZ_ASSERT(sc->hasCallSiteObj()); 4964 4965 return emitInternedObjectOp(cookedIndex, op); 4966 } 4967 4968 bool BytecodeEmitter::emitCatch(BinaryNode* catchClause) { 4969 // We must be nested under a try-finally statement. 4970 MOZ_ASSERT(innermostNestableControl->is<TryFinallyControl>()); 4971 4972 ParseNode* param = catchClause->left(); 4973 if (!param) { 4974 // Catch parameter was omitted; just discard the exception. 4975 if (!emit1(JSOp::Pop)) { 4976 return false; 4977 } 4978 } else { 4979 switch (param->getKind()) { 4980 case ParseNodeKind::ArrayExpr: 4981 case ParseNodeKind::ObjectExpr: 4982 if (!emitDestructuringOps(¶m->as<ListNode>(), 4983 DestructuringFlavor::Declaration, 4984 SelfHostedIter::Deny)) { 4985 return false; 4986 } 4987 if (!emit1(JSOp::Pop)) { 4988 return false; 4989 } 4990 break; 4991 4992 case ParseNodeKind::Name: 4993 if (!emitLexicalInitialization(¶m->as<NameNode>())) { 4994 return false; 4995 } 4996 if (!emit1(JSOp::Pop)) { 4997 return false; 4998 } 4999 break; 5000 5001 default: 5002 MOZ_ASSERT(0); 5003 } 5004 } 5005 5006 /* Emit the catch body. */ 5007 return emitTree(catchClause->right()); 5008 } 5009 5010 // Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See the 5011 // comment on EmitSwitch. 5012 MOZ_NEVER_INLINE bool BytecodeEmitter::emitTry(TryNode* tryNode) { 5013 LexicalScopeNode* catchScope = tryNode->catchScope(); 5014 ParseNode* finallyNode = tryNode->finallyBlock(); 5015 5016 TryEmitter::Kind kind; 5017 if (catchScope) { 5018 if (finallyNode) { 5019 kind = TryEmitter::Kind::TryCatchFinally; 5020 } else { 5021 kind = TryEmitter::Kind::TryCatch; 5022 } 5023 } else { 5024 MOZ_ASSERT(finallyNode); 5025 kind = TryEmitter::Kind::TryFinally; 5026 } 5027 TryEmitter tryCatch(this, kind, TryEmitter::ControlKind::Syntactic); 5028 5029 if (!tryCatch.emitTry()) { 5030 return false; 5031 } 5032 5033 if (!emitTree(tryNode->body())) { 5034 return false; 5035 } 5036 5037 // If this try has a catch block, emit it. 5038 if (catchScope) { 5039 // The emitted code for a catch block looks like: 5040 // 5041 // [pushlexicalenv] only if any local aliased 5042 // exception 5043 // setlocal 0; pop assign or possibly destructure exception 5044 // < catch block contents > 5045 // debugleaveblock 5046 // [poplexicalenv] only if any local aliased 5047 // if there is a finally block: 5048 // goto <finally> 5049 // [jump target for returning from finally] 5050 // goto <after finally> 5051 if (!tryCatch.emitCatch()) { 5052 return false; 5053 } 5054 5055 // Emit the lexical scope and catch body. 5056 if (!emitTree(catchScope)) { 5057 return false; 5058 } 5059 } 5060 5061 // Emit the finally handler, if there is one. 5062 if (finallyNode) { 5063 if (!tryCatch.emitFinally(Some(finallyNode->pn_pos.begin))) { 5064 return false; 5065 } 5066 5067 if (!emitTree(finallyNode)) { 5068 return false; 5069 } 5070 } 5071 5072 if (!tryCatch.emitEnd()) { 5073 return false; 5074 } 5075 5076 return true; 5077 } 5078 5079 [[nodiscard]] bool BytecodeEmitter::emitJumpToFinally(JumpList* jump, 5080 uint32_t idx) { 5081 // Push the continuation index. 5082 if (!emitNumberOp(idx)) { 5083 return false; 5084 } 5085 5086 // Push |exception_stack|. 5087 if (!emit1(JSOp::Null)) { 5088 return false; 5089 } 5090 5091 // Push |throwing|. 5092 if (!emit1(JSOp::False)) { 5093 return false; 5094 } 5095 5096 // Jump to the finally block. 5097 if (!emitJumpNoFallthrough(JSOp::Goto, jump)) { 5098 return false; 5099 } 5100 5101 return true; 5102 } 5103 5104 bool BytecodeEmitter::emitIf(TernaryNode* ifNode) { 5105 IfEmitter ifThenElse(this); 5106 5107 if (!ifThenElse.emitIf(Some(ifNode->kid1()->pn_pos.begin))) { 5108 return false; 5109 } 5110 5111 if_again: 5112 ParseNode* testNode = ifNode->kid1(); 5113 auto conditionKind = IfEmitter::ConditionKind::Positive; 5114 if (testNode->isKind(ParseNodeKind::NotExpr)) { 5115 testNode = testNode->as<UnaryNode>().kid(); 5116 conditionKind = IfEmitter::ConditionKind::Negative; 5117 } 5118 5119 if (!markStepBreakpoint()) { 5120 return false; 5121 } 5122 5123 // Emit code for the condition before pushing stmtInfo. 5124 // NOTE: NotExpr of testNode may be unwrapped, and in that case the negation 5125 // is handled by conditionKind. 5126 if (!emitTree(testNode)) { 5127 return false; 5128 } 5129 5130 ParseNode* elseNode = ifNode->kid3(); 5131 if (elseNode) { 5132 if (!ifThenElse.emitThenElse(conditionKind)) { 5133 return false; 5134 } 5135 } else { 5136 if (!ifThenElse.emitThen(conditionKind)) { 5137 return false; 5138 } 5139 } 5140 5141 /* Emit code for the then part. */ 5142 if (!emitTree(ifNode->kid2())) { 5143 return false; 5144 } 5145 5146 if (elseNode) { 5147 if (elseNode->isKind(ParseNodeKind::IfStmt)) { 5148 ifNode = &elseNode->as<TernaryNode>(); 5149 5150 if (!ifThenElse.emitElseIf(Some(ifNode->kid1()->pn_pos.begin))) { 5151 return false; 5152 } 5153 5154 goto if_again; 5155 } 5156 5157 if (!ifThenElse.emitElse()) { 5158 return false; 5159 } 5160 5161 /* Emit code for the else part. */ 5162 if (!emitTree(elseNode)) { 5163 return false; 5164 } 5165 } 5166 5167 if (!ifThenElse.emitEnd()) { 5168 return false; 5169 } 5170 5171 return true; 5172 } 5173 5174 bool BytecodeEmitter::emitHoistedFunctionsInList(ListNode* stmtList) { 5175 MOZ_ASSERT(stmtList->hasTopLevelFunctionDeclarations()); 5176 5177 // We can call this multiple times for sloppy eval scopes. 5178 if (stmtList->emittedTopLevelFunctionDeclarations()) { 5179 return true; 5180 } 5181 5182 stmtList->setEmittedTopLevelFunctionDeclarations(); 5183 5184 for (ParseNode* stmt : stmtList->contents()) { 5185 ParseNode* maybeFun = stmt; 5186 5187 if (!sc->strict()) { 5188 while (maybeFun->isKind(ParseNodeKind::LabelStmt)) { 5189 maybeFun = maybeFun->as<LabeledStatement>().statement(); 5190 } 5191 } 5192 5193 if (maybeFun->is<FunctionNode>() && 5194 maybeFun->as<FunctionNode>().functionIsHoisted()) { 5195 if (!emitTree(maybeFun)) { 5196 return false; 5197 } 5198 } 5199 } 5200 5201 return true; 5202 } 5203 5204 bool BytecodeEmitter::emitLexicalScopeBody( 5205 ParseNode* body, EmitLineNumberNote emitLineNote /* = EMIT_LINENOTE */) { 5206 if (body->isKind(ParseNodeKind::StatementList) && 5207 body->as<ListNode>().hasTopLevelFunctionDeclarations()) { 5208 // This block contains function statements whose definitions are 5209 // hoisted to the top of the block. Emit these as a separate pass 5210 // before the rest of the block. 5211 if (!emitHoistedFunctionsInList(&body->as<ListNode>())) { 5212 return false; 5213 } 5214 } 5215 5216 // Line notes were updated by emitLexicalScope or emitScript. 5217 return emitTree(body, ValueUsage::WantValue, emitLineNote); 5218 } 5219 5220 // Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See 5221 // the comment on emitSwitch. 5222 MOZ_NEVER_INLINE bool BytecodeEmitter::emitLexicalScope( 5223 LexicalScopeNode* lexicalScope) { 5224 LexicalScopeEmitter lse(this); 5225 5226 ParseNode* body = lexicalScope->scopeBody(); 5227 if (lexicalScope->isEmptyScope()) { 5228 if (!lse.emitEmptyScope()) { 5229 return false; 5230 } 5231 5232 if (!emitLexicalScopeBody(body)) { 5233 return false; 5234 } 5235 5236 if (!lse.emitEnd()) { 5237 return false; 5238 } 5239 5240 return true; 5241 } 5242 5243 // We are about to emit some bytecode for what the spec calls "declaration 5244 // instantiation". Assign these instructions to the opening `{` of the 5245 // block. (Using the location of each declaration we're instantiating is 5246 // too weird when stepping in the debugger.) 5247 if (!ParseNodeRequiresSpecialLineNumberNotes(body)) { 5248 if (!updateSourceCoordNotes(lexicalScope->pn_pos.begin)) { 5249 return false; 5250 } 5251 } 5252 5253 ScopeKind kind; 5254 if (body->isKind(ParseNodeKind::Catch)) { 5255 BinaryNode* catchNode = &body->as<BinaryNode>(); 5256 kind = 5257 (!catchNode->left() || catchNode->left()->isKind(ParseNodeKind::Name)) 5258 ? ScopeKind::SimpleCatch 5259 : ScopeKind::Catch; 5260 } else { 5261 kind = lexicalScope->kind(); 5262 } 5263 5264 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT 5265 BlockKind blockKind = BlockKind::Other; 5266 if (body->isKind(ParseNodeKind::ForStmt) && 5267 body->as<ForNode>().head()->isKind(ParseNodeKind::ForOf)) { 5268 MOZ_ASSERT(kind == ScopeKind::Lexical); 5269 blockKind = BlockKind::ForOf; 5270 } 5271 #endif 5272 5273 if (!lse.emitScope(kind, lexicalScope->scopeBindings() 5274 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT 5275 , 5276 blockKind 5277 #endif 5278 )) { 5279 return false; 5280 } 5281 5282 if (body->isKind(ParseNodeKind::ForStmt)) { 5283 // for loops need to emit JSOp::FreshenLexicalEnv/JSOp::RecreateLexicalEnv 5284 // if there are lexical declarations in the head. Signal this by passing a 5285 // non-nullptr lexical scope. 5286 if (!emitFor(&body->as<ForNode>(), &lse.emitterScope())) { 5287 return false; 5288 } 5289 } else { 5290 if (!emitLexicalScopeBody(body, SUPPRESS_LINENOTE)) { 5291 return false; 5292 } 5293 } 5294 5295 if (!lse.emitEnd()) { 5296 return false; 5297 } 5298 return true; 5299 } 5300 5301 bool BytecodeEmitter::emitWith(BinaryNode* withNode) { 5302 // Ensure that the column of the 'with' is set properly. 5303 if (!updateSourceCoordNotes(withNode->left()->pn_pos.begin)) { 5304 return false; 5305 } 5306 5307 if (!markStepBreakpoint()) { 5308 return false; 5309 } 5310 5311 if (!emitTree(withNode->left())) { 5312 return false; 5313 } 5314 5315 EmitterScope emitterScope(this); 5316 if (!emitterScope.enterWith(this)) { 5317 return false; 5318 } 5319 5320 if (!emitTree(withNode->right())) { 5321 return false; 5322 } 5323 5324 return emitterScope.leave(this); 5325 } 5326 5327 bool BytecodeEmitter::emitCopyDataProperties(CopyOption option) { 5328 DebugOnly<int32_t> depth = bytecodeSection().stackDepth(); 5329 5330 uint32_t argc; 5331 if (option == CopyOption::Filtered) { 5332 MOZ_ASSERT(depth > 2); 5333 // [stack] TARGET SOURCE SET 5334 argc = 3; 5335 5336 if (!emitAtomOp(JSOp::GetIntrinsic, 5337 TaggedParserAtomIndex::WellKnown::CopyDataProperties())) { 5338 // [stack] TARGET SOURCE SET COPYDATAPROPERTIES 5339 return false; 5340 } 5341 } else { 5342 MOZ_ASSERT(depth > 1); 5343 // [stack] TARGET SOURCE 5344 argc = 2; 5345 5346 if (!emitAtomOp( 5347 JSOp::GetIntrinsic, 5348 TaggedParserAtomIndex::WellKnown::CopyDataPropertiesUnfiltered())) { 5349 // [stack] TARGET SOURCE COPYDATAPROPERTIES 5350 return false; 5351 } 5352 } 5353 5354 if (!emit1(JSOp::Undefined)) { 5355 // [stack] TARGET SOURCE SET? COPYDATAPROPERTIES 5356 // UNDEFINED 5357 return false; 5358 } 5359 if (!emit2(JSOp::Pick, argc + 1)) { 5360 // [stack] SOURCE SET? COPYDATAPROPERTIES UNDEFINED 5361 // TARGET 5362 return false; 5363 } 5364 if (!emit2(JSOp::Pick, argc + 1)) { 5365 // [stack] SET? COPYDATAPROPERTIES UNDEFINED TARGET 5366 // SOURCE 5367 return false; 5368 } 5369 if (option == CopyOption::Filtered) { 5370 if (!emit2(JSOp::Pick, argc + 1)) { 5371 // [stack] COPYDATAPROPERTIES UNDEFINED TARGET SOURCE SET 5372 return false; 5373 } 5374 } 5375 // Callee is always self-hosted instrinsic, and cannot be content function. 5376 if (!emitCall(JSOp::CallIgnoresRv, argc)) { 5377 // [stack] IGNORED 5378 return false; 5379 } 5380 5381 if (!emit1(JSOp::Pop)) { 5382 // [stack] 5383 return false; 5384 } 5385 5386 MOZ_ASSERT(depth - int(argc) == bytecodeSection().stackDepth()); 5387 return true; 5388 } 5389 5390 bool BytecodeEmitter::emitBigIntOp(BigIntLiteral* bigint) { 5391 GCThingIndex index; 5392 if (!perScriptData().gcThingList().append(bigint, &index)) { 5393 return false; 5394 } 5395 return emitGCIndexOp(JSOp::BigInt, index); 5396 } 5397 5398 bool BytecodeEmitter::emitIterable(ParseNode* value, 5399 SelfHostedIter selfHostedIter, 5400 IteratorKind iterKind) { 5401 MOZ_ASSERT(getSelfHostedIterFor(value) == selfHostedIter); 5402 5403 if (!emitTree(value)) { 5404 // [stack] ITERABLE 5405 return false; 5406 } 5407 5408 switch (selfHostedIter) { 5409 case SelfHostedIter::Deny: 5410 case SelfHostedIter::AllowContent: 5411 // [stack] ITERABLE 5412 return true; 5413 5414 case SelfHostedIter::AllowContentWith: { 5415 // This is the following case: 5416 // 5417 // for (const nextValue of allowContentIterWith(items, usingIterator)) { 5418 // 5419 // `items` is emitted by `emitTree(value)` above, and the result is on the 5420 // stack as ITERABLE. 5421 // `usingIterator` is the value of `items[Symbol.iterator]`, that's 5422 // already retrieved. 5423 ListNode* argsList = value->as<CallNode>().args(); 5424 MOZ_ASSERT_IF(iterKind == IteratorKind::Sync, argsList->count() == 2); 5425 MOZ_ASSERT_IF(iterKind == IteratorKind::Async, argsList->count() == 3); 5426 5427 if (!emitTree(argsList->head()->pn_next)) { 5428 // [stack] ITERABLE ITERFN 5429 return false; 5430 } 5431 5432 // Async iterator has two possible iterators: An async iterator and a sync 5433 // iterator. 5434 if (iterKind == IteratorKind::Async) { 5435 if (!emitTree(argsList->head()->pn_next->pn_next)) { 5436 // [stack] ITERABLE ASYNC_ITERFN SYNC_ITERFN 5437 return false; 5438 } 5439 } 5440 5441 // [stack] ITERABLE ASYNC_ITERFN? SYNC_ITERFN 5442 return true; 5443 } 5444 5445 case SelfHostedIter::AllowContentWithNext: { 5446 // This is the following case: 5447 // 5448 // for (const nextValue of allowContentIterWithNext(iterator, next)) { 5449 // 5450 // `iterator` is emitted by `emitTree(value)` above, and the result is on 5451 // the stack as ITER. 5452 // `next` is the value of `iterator.next`, that's already retrieved. 5453 ListNode* argsList = value->as<CallNode>().args(); 5454 MOZ_ASSERT(argsList->count() == 2); 5455 5456 if (!emitTree(argsList->head()->pn_next)) { 5457 // [stack] ITER NEXT 5458 return false; 5459 } 5460 5461 if (!emit1(JSOp::Swap)) { 5462 // [stack] NEXT ITER 5463 return false; 5464 } 5465 5466 // [stack] NEXT ITER 5467 return true; 5468 } 5469 } 5470 5471 MOZ_CRASH("invalid self-hosted iteration kind"); 5472 } 5473 5474 bool BytecodeEmitter::emitIterator(SelfHostedIter selfHostedIter) { 5475 MOZ_ASSERT(selfHostedIter != SelfHostedIter::Deny || 5476 emitterMode != BytecodeEmitter::SelfHosting, 5477 "[Symbol.iterator]() call is prohibited in self-hosted code " 5478 "because it can run user-modifiable iteration code"); 5479 5480 if (selfHostedIter == SelfHostedIter::AllowContentWithNext) { 5481 // [stack] NEXT ITER 5482 5483 // Nothing to do, stack already contains the iterator and its `next` method. 5484 return true; 5485 } 5486 5487 if (selfHostedIter != SelfHostedIter::AllowContentWith) { 5488 // [stack] OBJ 5489 5490 // Convert iterable to iterator. 5491 if (!emit1(JSOp::Dup)) { 5492 // [stack] OBJ OBJ 5493 return false; 5494 } 5495 if (!emit2(JSOp::Symbol, uint8_t(JS::SymbolCode::iterator))) { 5496 // [stack] OBJ OBJ @@ITERATOR 5497 return false; 5498 } 5499 if (!emitElemOpBase(JSOp::GetElem)) { 5500 // [stack] OBJ ITERFN 5501 return false; 5502 } 5503 } 5504 5505 if (!emit1(JSOp::Swap)) { 5506 // [stack] ITERFN OBJ 5507 return false; 5508 } 5509 if (!emitCall(getIterCallOp(JSOp::CallIter, selfHostedIter), 0)) { 5510 // [stack] ITER 5511 return false; 5512 } 5513 if (!emitCheckIsObj(CheckIsObjectKind::GetIterator)) { 5514 // [stack] ITER 5515 return false; 5516 } 5517 if (!emit1(JSOp::Dup)) { 5518 // [stack] ITER ITER 5519 return false; 5520 } 5521 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::next())) { 5522 // [stack] ITER NEXT 5523 return false; 5524 } 5525 if (!emit1(JSOp::Swap)) { 5526 // [stack] NEXT ITER 5527 return false; 5528 } 5529 return true; 5530 } 5531 5532 bool BytecodeEmitter::emitAsyncIterator(SelfHostedIter selfHostedIter) { 5533 MOZ_ASSERT(selfHostedIter != SelfHostedIter::AllowContentWithNext); 5534 MOZ_ASSERT(selfHostedIter != SelfHostedIter::Deny || 5535 emitterMode != BytecodeEmitter::SelfHosting, 5536 "[Symbol.asyncIterator]() call is prohibited in self-hosted code " 5537 "because it can run user-modifiable iteration code"); 5538 5539 if (selfHostedIter != SelfHostedIter::AllowContentWith) { 5540 // [stack] OBJ 5541 5542 // Convert iterable to iterator. 5543 if (!emit1(JSOp::Dup)) { 5544 // [stack] OBJ OBJ 5545 return false; 5546 } 5547 if (!emit2(JSOp::Symbol, uint8_t(JS::SymbolCode::asyncIterator))) { 5548 // [stack] OBJ OBJ @@ASYNCITERATOR 5549 return false; 5550 } 5551 if (!emitElemOpBase(JSOp::GetElem)) { 5552 // [stack] OBJ ASYNC_ITERFN 5553 return false; 5554 } 5555 } else { 5556 // [stack] OBJ ASYNC_ITERFN SYNC_ITERFN 5557 5558 if (!emitElemOpBase(JSOp::Swap)) { 5559 // [stack] OBJ SYNC_ITERFN ASYNC_ITERFN 5560 return false; 5561 } 5562 } 5563 5564 InternalIfEmitter ifAsyncIterIsUndefined(this); 5565 if (!emit1(JSOp::IsNullOrUndefined)) { 5566 // [stack] OBJ SYNC_ITERFN? ASYNC_ITERFN NULL-OR-UNDEF 5567 return false; 5568 } 5569 if (!ifAsyncIterIsUndefined.emitThenElse()) { 5570 // [stack] OBJ SYNC_ITERFN? ASYNC_ITERFN 5571 return false; 5572 } 5573 5574 if (!emit1(JSOp::Pop)) { 5575 // [stack] OBJ SYNC_ITERFN? 5576 return false; 5577 } 5578 5579 if (selfHostedIter != SelfHostedIter::AllowContentWith) { 5580 if (!emit1(JSOp::Dup)) { 5581 // [stack] OBJ OBJ 5582 return false; 5583 } 5584 if (!emit2(JSOp::Symbol, uint8_t(JS::SymbolCode::iterator))) { 5585 // [stack] OBJ OBJ @@ITERATOR 5586 return false; 5587 } 5588 if (!emitElemOpBase(JSOp::GetElem)) { 5589 // [stack] OBJ SYNC_ITERFN 5590 return false; 5591 } 5592 } else { 5593 // [stack] OBJ SYNC_ITERFN 5594 } 5595 5596 if (!emit1(JSOp::Swap)) { 5597 // [stack] SYNC_ITERFN OBJ 5598 return false; 5599 } 5600 if (!emitCall(getIterCallOp(JSOp::CallIter, selfHostedIter), 0)) { 5601 // [stack] ITER 5602 return false; 5603 } 5604 if (!emitCheckIsObj(CheckIsObjectKind::GetIterator)) { 5605 // [stack] ITER 5606 return false; 5607 } 5608 5609 if (!emit1(JSOp::Dup)) { 5610 // [stack] ITER ITER 5611 return false; 5612 } 5613 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::next())) { 5614 // [stack] ITER SYNCNEXT 5615 return false; 5616 } 5617 5618 if (!emit1(JSOp::ToAsyncIter)) { 5619 // [stack] ITER 5620 return false; 5621 } 5622 5623 if (!ifAsyncIterIsUndefined.emitElse()) { 5624 // [stack] OBJ SYNC_ITERFN? ASYNC_ITERFN 5625 return false; 5626 } 5627 5628 if (selfHostedIter == SelfHostedIter::AllowContentWith) { 5629 if (!emit1(JSOp::Swap)) { 5630 // [stack] OBJ ASYNC_ITERFN SYNC_ITERFN 5631 return false; 5632 } 5633 if (!emit1(JSOp::Pop)) { 5634 // [stack] OBJ ASYNC_ITERFN 5635 return false; 5636 } 5637 } 5638 5639 if (!emit1(JSOp::Swap)) { 5640 // [stack] ASYNC_ITERFN OBJ 5641 return false; 5642 } 5643 if (!emitCall(getIterCallOp(JSOp::CallIter, selfHostedIter), 0)) { 5644 // [stack] ITER 5645 return false; 5646 } 5647 if (!emitCheckIsObj(CheckIsObjectKind::GetAsyncIterator)) { 5648 // [stack] ITER 5649 return false; 5650 } 5651 5652 if (!ifAsyncIterIsUndefined.emitEnd()) { 5653 // [stack] ITER 5654 return false; 5655 } 5656 5657 if (!emit1(JSOp::Dup)) { 5658 // [stack] ITER ITER 5659 return false; 5660 } 5661 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::next())) { 5662 // [stack] ITER NEXT 5663 return false; 5664 } 5665 if (!emit1(JSOp::Swap)) { 5666 // [stack] NEXT ITER 5667 return false; 5668 } 5669 5670 return true; 5671 } 5672 5673 bool BytecodeEmitter::emitSpread(SelfHostedIter selfHostedIter) { 5674 LoopControl loopInfo(this, StatementKind::Spread); 5675 5676 if (!loopInfo.emitLoopHead(this, Nothing())) { 5677 // [stack] NEXT ITER ARR I 5678 return false; 5679 } 5680 5681 { 5682 #ifdef DEBUG 5683 auto loopDepth = bytecodeSection().stackDepth(); 5684 #endif 5685 5686 // Spread operations can't contain |continue|, so don't bother setting loop 5687 // and enclosing "update" offsets, as we do with for-loops. 5688 5689 if (!emitDupAt(3, 2)) { 5690 // [stack] NEXT ITER ARR I NEXT ITER 5691 return false; 5692 } 5693 if (!emitIteratorNext(Nothing(), IteratorKind::Sync, selfHostedIter)) { 5694 // [stack] NEXT ITER ARR I RESULT 5695 return false; 5696 } 5697 if (!emit1(JSOp::Dup)) { 5698 // [stack] NEXT ITER ARR I RESULT RESULT 5699 return false; 5700 } 5701 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::done())) { 5702 // [stack] NEXT ITER ARR I RESULT DONE 5703 return false; 5704 } 5705 if (!emitJump(JSOp::JumpIfTrue, &loopInfo.breaks)) { 5706 // [stack] NEXT ITER ARR I RESULT 5707 return false; 5708 } 5709 5710 // Emit code to assign result.value to the iteration variable. 5711 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::value())) { 5712 // [stack] NEXT ITER ARR I VALUE 5713 return false; 5714 } 5715 if (!emit1(JSOp::InitElemInc)) { 5716 // [stack] NEXT ITER ARR I 5717 return false; 5718 } 5719 5720 if (!loopInfo.emitLoopEnd(this, JSOp::Goto, TryNoteKind::ForOf)) { 5721 // [stack] NEXT ITER ARR I 5722 return false; 5723 } 5724 5725 MOZ_ASSERT(bytecodeSection().stackDepth() == loopDepth); 5726 } 5727 5728 // When we leave the loop body and jump to this point, the result value is 5729 // still on the stack. Account for that by updating the stack depth 5730 // manually. 5731 bytecodeSection().setStackDepth(bytecodeSection().stackDepth() + 1); 5732 5733 // No continues should occur in spreads. 5734 MOZ_ASSERT(!loopInfo.continues.offset.valid()); 5735 5736 if (!emit2(JSOp::Pick, 4)) { 5737 // [stack] ITER ARR I RESULT NEXT 5738 return false; 5739 } 5740 if (!emit2(JSOp::Pick, 4)) { 5741 // [stack] ARR I RESULT NEXT ITER 5742 return false; 5743 } 5744 5745 return emitPopN(3); 5746 // [stack] ARR I 5747 } 5748 5749 bool BytecodeEmitter::emitInitializeForInOrOfTarget(TernaryNode* forHead) { 5750 MOZ_ASSERT(forHead->isKind(ParseNodeKind::ForIn) || 5751 forHead->isKind(ParseNodeKind::ForOf)); 5752 5753 MOZ_ASSERT(bytecodeSection().stackDepth() >= 1, 5754 "must have a per-iteration value for initializing"); 5755 5756 ParseNode* target = forHead->kid1(); 5757 MOZ_ASSERT(!forHead->kid2()); 5758 5759 // If the for-in/of loop didn't have a variable declaration, per-loop 5760 // initialization is just assigning the iteration value to a target 5761 // expression. 5762 if (!target->is<DeclarationListNode>()) { 5763 return emitAssignmentOrInit(ParseNodeKind::AssignExpr, target, nullptr); 5764 // [stack] ... ITERVAL 5765 } 5766 5767 // Otherwise, per-loop initialization is (possibly) declaration 5768 // initialization. If the declaration is a lexical declaration, it must be 5769 // initialized. If the declaration is a variable declaration, an 5770 // assignment to that name (which does *not* necessarily assign to the 5771 // variable!) must be generated. 5772 5773 auto* declarationList = &target->as<DeclarationListNode>(); 5774 if (!updateSourceCoordNotes(declarationList->pn_pos.begin)) { 5775 return false; 5776 } 5777 5778 target = declarationList->singleBinding(); 5779 5780 NameNode* nameNode = nullptr; 5781 if (target->isKind(ParseNodeKind::Name)) { 5782 nameNode = &target->as<NameNode>(); 5783 } else if (target->isKind(ParseNodeKind::AssignExpr)) { 5784 BinaryNode* assignNode = &target->as<BinaryNode>(); 5785 if (assignNode->left()->is<NameNode>()) { 5786 nameNode = &assignNode->left()->as<NameNode>(); 5787 } 5788 } 5789 5790 if (nameNode) { 5791 auto nameAtom = nameNode->name(); 5792 NameOpEmitter noe(this, nameAtom, NameOpEmitter::Kind::Initialize); 5793 if (!noe.prepareForRhs()) { 5794 return false; 5795 } 5796 if (noe.emittedBindOp()) { 5797 // Per-iteration initialization in for-in/of loops computes the 5798 // iteration value *before* initializing. Thus the initializing 5799 // value may be buried under a bind-specific value on the stack. 5800 // Swap it to the top of the stack. 5801 MOZ_ASSERT(bytecodeSection().stackDepth() >= 2); 5802 if (!emit1(JSOp::Swap)) { 5803 return false; 5804 } 5805 } else { 5806 // In cases of emitting a frame slot or environment slot, 5807 // nothing needs be done. 5808 MOZ_ASSERT(bytecodeSection().stackDepth() >= 1); 5809 } 5810 5811 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT 5812 if (declarationList->isKind(ParseNodeKind::UsingDecl)) { 5813 if (!innermostEmitterScope()->prepareForDisposableAssignment( 5814 UsingHint::Sync)) { 5815 // [stack] ENV? V 5816 return false; 5817 } 5818 } else if (declarationList->isKind(ParseNodeKind::AwaitUsingDecl)) { 5819 if (!innermostEmitterScope()->prepareForDisposableAssignment( 5820 UsingHint::Async)) { 5821 // [stack] ENV? V 5822 return false; 5823 } 5824 } 5825 #endif 5826 5827 if (!noe.emitAssignment()) { 5828 return false; 5829 } 5830 5831 // The caller handles removing the iteration value from the stack. 5832 return true; 5833 } 5834 5835 MOZ_ASSERT( 5836 !target->isKind(ParseNodeKind::AssignExpr), 5837 "for-in/of loop destructuring declarations can't have initializers"); 5838 5839 MOZ_ASSERT(target->isKind(ParseNodeKind::ArrayExpr) || 5840 target->isKind(ParseNodeKind::ObjectExpr)); 5841 return emitDestructuringOps(&target->as<ListNode>(), 5842 DestructuringFlavor::Declaration, 5843 SelfHostedIter::Deny); 5844 } 5845 5846 bool BytecodeEmitter::emitForOf(ForNode* forOfLoop, 5847 const EmitterScope* headLexicalEmitterScope) { 5848 MOZ_ASSERT(forOfLoop->isKind(ParseNodeKind::ForStmt)); 5849 5850 TernaryNode* forOfHead = forOfLoop->head(); 5851 MOZ_ASSERT(forOfHead->isKind(ParseNodeKind::ForOf)); 5852 5853 unsigned iflags = forOfLoop->iflags(); 5854 IteratorKind iterKind = 5855 (iflags & JSITER_FORAWAITOF) ? IteratorKind::Async : IteratorKind::Sync; 5856 MOZ_ASSERT_IF(iterKind == IteratorKind::Async, sc->isSuspendableContext()); 5857 MOZ_ASSERT_IF(iterKind == IteratorKind::Async, 5858 sc->asSuspendableContext()->isAsync()); 5859 5860 ParseNode* forHeadExpr = forOfHead->kid3(); 5861 5862 // Certain builtins (e.g. Array.from) are implemented in self-hosting 5863 // as for-of loops. 5864 auto selfHostedIter = getSelfHostedIterFor(forHeadExpr); 5865 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT 5866 ForOfEmitter::HeadUsingDeclarationKind headUsingDeclKind = 5867 ForOfEmitter::HeadUsingDeclarationKind::None; 5868 if (forOfHead->kid1()->isKind(ParseNodeKind::UsingDecl)) { 5869 headUsingDeclKind = ForOfEmitter::HeadUsingDeclarationKind::Sync; 5870 } else if (forOfHead->kid1()->isKind(ParseNodeKind::AwaitUsingDecl)) { 5871 headUsingDeclKind = ForOfEmitter::HeadUsingDeclarationKind::Async; 5872 } 5873 #endif 5874 5875 ForOfEmitter forOf(this, headLexicalEmitterScope, selfHostedIter, iterKind 5876 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT 5877 , 5878 headUsingDeclKind 5879 #endif 5880 ); 5881 5882 if (!forOf.emitIterated()) { 5883 // [stack] 5884 return false; 5885 } 5886 5887 if (!updateSourceCoordNotes(forHeadExpr->pn_pos.begin)) { 5888 return false; 5889 } 5890 if (!markStepBreakpoint()) { 5891 return false; 5892 } 5893 if (!emitIterable(forHeadExpr, selfHostedIter, iterKind)) { 5894 // [stack] ITERABLE 5895 return false; 5896 } 5897 5898 if (headLexicalEmitterScope) { 5899 DebugOnly<ParseNode*> forOfTarget = forOfHead->kid1(); 5900 MOZ_ASSERT(forOfTarget->isKind(ParseNodeKind::LetDecl) || 5901 forOfTarget->isKind(ParseNodeKind::ConstDecl) 5902 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT 5903 || forOfTarget->isKind(ParseNodeKind::UsingDecl) || 5904 forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl) 5905 #endif 5906 ); 5907 } 5908 5909 if (!forOf.emitInitialize(forOfHead->pn_pos.begin)) { 5910 // [stack] NEXT ITER VALUE 5911 return false; 5912 } 5913 5914 if (!emitInitializeForInOrOfTarget(forOfHead)) { 5915 // [stack] NEXT ITER VALUE 5916 return false; 5917 } 5918 5919 if (!forOf.emitBody()) { 5920 // [stack] NEXT ITER UNDEF 5921 return false; 5922 } 5923 5924 // Perform the loop body. 5925 ParseNode* forBody = forOfLoop->body(); 5926 if (!emitTree(forBody)) { 5927 // [stack] NEXT ITER UNDEF 5928 return false; 5929 } 5930 5931 if (!forOf.emitEnd(forHeadExpr->pn_pos.begin)) { 5932 // [stack] 5933 return false; 5934 } 5935 5936 return true; 5937 } 5938 5939 bool BytecodeEmitter::emitForIn(ForNode* forInLoop, 5940 const EmitterScope* headLexicalEmitterScope) { 5941 TernaryNode* forInHead = forInLoop->head(); 5942 MOZ_ASSERT(forInHead->isKind(ParseNodeKind::ForIn)); 5943 5944 ForInEmitter forIn(this, headLexicalEmitterScope); 5945 5946 // Annex B: Evaluate the var-initializer expression if present. 5947 // |for (var i = initializer in expr) { ... }| 5948 ParseNode* forInTarget = forInHead->kid1(); 5949 if (forInTarget->is<DeclarationListNode>()) { 5950 auto* declarationList = &forInTarget->as<DeclarationListNode>(); 5951 5952 ParseNode* decl = declarationList->singleBinding(); 5953 if (decl->isKind(ParseNodeKind::AssignExpr)) { 5954 BinaryNode* assignNode = &decl->as<BinaryNode>(); 5955 if (assignNode->left()->is<NameNode>()) { 5956 NameNode* nameNode = &assignNode->left()->as<NameNode>(); 5957 ParseNode* initializer = assignNode->right(); 5958 MOZ_ASSERT( 5959 forInTarget->isKind(ParseNodeKind::VarStmt), 5960 "for-in initializers are only permitted for |var| declarations"); 5961 5962 if (!updateSourceCoordNotes(decl->pn_pos.begin)) { 5963 return false; 5964 } 5965 5966 auto nameAtom = nameNode->name(); 5967 NameOpEmitter noe(this, nameAtom, NameOpEmitter::Kind::Initialize); 5968 if (!noe.prepareForRhs()) { 5969 return false; 5970 } 5971 if (!emitInitializer(initializer, nameNode)) { 5972 return false; 5973 } 5974 if (!noe.emitAssignment()) { 5975 return false; 5976 } 5977 5978 // Pop the initializer. 5979 if (!emit1(JSOp::Pop)) { 5980 return false; 5981 } 5982 } 5983 } 5984 } 5985 5986 if (!forIn.emitIterated()) { 5987 // [stack] 5988 return false; 5989 } 5990 5991 // Evaluate the expression being iterated. 5992 ParseNode* expr = forInHead->kid3(); 5993 5994 if (!updateSourceCoordNotes(expr->pn_pos.begin)) { 5995 return false; 5996 } 5997 if (!markStepBreakpoint()) { 5998 return false; 5999 } 6000 if (!emitTree(expr)) { 6001 // [stack] EXPR 6002 return false; 6003 } 6004 6005 MOZ_ASSERT(forInLoop->iflags() == 0); 6006 6007 MOZ_ASSERT_IF(headLexicalEmitterScope, 6008 forInTarget->isKind(ParseNodeKind::LetDecl) || 6009 forInTarget->isKind(ParseNodeKind::ConstDecl)); 6010 6011 if (!forIn.emitInitialize()) { 6012 // [stack] ITER ITERVAL 6013 return false; 6014 } 6015 6016 if (!emitInitializeForInOrOfTarget(forInHead)) { 6017 // [stack] ITER ITERVAL 6018 return false; 6019 } 6020 6021 if (!forIn.emitBody()) { 6022 // [stack] ITER ITERVAL 6023 return false; 6024 } 6025 6026 // Perform the loop body. 6027 ParseNode* forBody = forInLoop->body(); 6028 if (!emitTree(forBody)) { 6029 // [stack] ITER ITERVAL 6030 return false; 6031 } 6032 6033 if (!forIn.emitEnd(forInHead->pn_pos.begin)) { 6034 // [stack] 6035 return false; 6036 } 6037 6038 return true; 6039 } 6040 6041 /* C-style `for (init; cond; update) ...` loop. */ 6042 bool BytecodeEmitter::emitCStyleFor( 6043 ForNode* forNode, const EmitterScope* headLexicalEmitterScope) { 6044 TernaryNode* forHead = forNode->head(); 6045 ParseNode* forBody = forNode->body(); 6046 ParseNode* init = forHead->kid1(); 6047 ParseNode* cond = forHead->kid2(); 6048 ParseNode* update = forHead->kid3(); 6049 bool isLet = init && init->isKind(ParseNodeKind::LetDecl); 6050 6051 CForEmitter cfor(this, isLet ? headLexicalEmitterScope : nullptr); 6052 6053 if (!cfor.emitInit(init ? Some(init->pn_pos.begin) : Nothing())) { 6054 // [stack] 6055 return false; 6056 } 6057 6058 // If the head of this for-loop declared any lexical variables, the parser 6059 // wrapped this ParseNodeKind::For node in a ParseNodeKind::LexicalScope 6060 // representing the implicit scope of those variables. By the time we get 6061 // here, we have already entered that scope. So far, so good. 6062 if (init) { 6063 // Emit the `init` clause, whether it's an expression or a variable 6064 // declaration. (The loop variables were hoisted into an enclosing 6065 // scope, but we still need to emit code for the initializers.) 6066 if (init->is<DeclarationListNode>()) { 6067 MOZ_ASSERT(!init->as<DeclarationListNode>().empty()); 6068 6069 if (!emitTree(init)) { 6070 // [stack] 6071 return false; 6072 } 6073 } else { 6074 if (!updateSourceCoordNotes(init->pn_pos.begin)) { 6075 return false; 6076 } 6077 if (!markStepBreakpoint()) { 6078 return false; 6079 } 6080 6081 // 'init' is an expression, not a declaration. emitTree left its 6082 // value on the stack. 6083 if (!emitTree(init, ValueUsage::IgnoreValue)) { 6084 // [stack] VAL 6085 return false; 6086 } 6087 if (!emit1(JSOp::Pop)) { 6088 // [stack] 6089 return false; 6090 } 6091 } 6092 } 6093 6094 if (!cfor.emitCond(cond ? Some(cond->pn_pos.begin) : Nothing())) { 6095 // [stack] 6096 return false; 6097 } 6098 6099 if (cond) { 6100 if (!updateSourceCoordNotes(cond->pn_pos.begin)) { 6101 return false; 6102 } 6103 if (!markStepBreakpoint()) { 6104 return false; 6105 } 6106 if (!emitTree(cond)) { 6107 // [stack] VAL 6108 return false; 6109 } 6110 } 6111 6112 if (!cfor.emitBody(cond ? CForEmitter::Cond::Present 6113 : CForEmitter::Cond::Missing)) { 6114 // [stack] 6115 return false; 6116 } 6117 6118 if (!emitTree(forBody)) { 6119 // [stack] 6120 return false; 6121 } 6122 6123 if (!cfor.emitUpdate( 6124 update ? CForEmitter::Update::Present : CForEmitter::Update::Missing, 6125 update ? Some(update->pn_pos.begin) : Nothing())) { 6126 // [stack] 6127 return false; 6128 } 6129 6130 // Check for update code to do before the condition (if any). 6131 if (update) { 6132 if (!updateSourceCoordNotes(update->pn_pos.begin)) { 6133 return false; 6134 } 6135 if (!markStepBreakpoint()) { 6136 return false; 6137 } 6138 if (!emitTree(update, ValueUsage::IgnoreValue)) { 6139 // [stack] VAL 6140 return false; 6141 } 6142 } 6143 6144 if (!cfor.emitEnd(forNode->pn_pos.begin)) { 6145 // [stack] 6146 return false; 6147 } 6148 6149 return true; 6150 } 6151 6152 bool BytecodeEmitter::emitFor(ForNode* forNode, 6153 const EmitterScope* headLexicalEmitterScope) { 6154 if (forNode->head()->isKind(ParseNodeKind::ForHead)) { 6155 return emitCStyleFor(forNode, headLexicalEmitterScope); 6156 } 6157 6158 if (!updateLineNumberNotes(forNode->pn_pos.begin)) { 6159 return false; 6160 } 6161 6162 if (forNode->head()->isKind(ParseNodeKind::ForIn)) { 6163 return emitForIn(forNode, headLexicalEmitterScope); 6164 } 6165 6166 MOZ_ASSERT(forNode->head()->isKind(ParseNodeKind::ForOf)); 6167 return emitForOf(forNode, headLexicalEmitterScope); 6168 } 6169 6170 MOZ_NEVER_INLINE bool BytecodeEmitter::emitFunction( 6171 FunctionNode* funNode, bool needsProto /* = false */) { 6172 FunctionBox* funbox = funNode->funbox(); 6173 6174 // [stack] 6175 6176 FunctionEmitter fe(this, funbox, funNode->syntaxKind(), 6177 funNode->functionIsHoisted() 6178 ? FunctionEmitter::IsHoisted::Yes 6179 : FunctionEmitter::IsHoisted::No); 6180 6181 // |wasEmittedByEnclosingScript| flag is set to true once the function has 6182 // been emitted. Function definitions that need hoisting to the top of the 6183 // function will be seen by emitFunction in two places. 6184 if (funbox->wasEmittedByEnclosingScript()) { 6185 if (!fe.emitAgain()) { 6186 // [stack] 6187 return false; 6188 } 6189 MOZ_ASSERT(funNode->functionIsHoisted()); 6190 } else if (funbox->isInterpreted()) { 6191 if (!funbox->emitBytecode) { 6192 return fe.emitLazy(); 6193 // [stack] FUN? 6194 } 6195 6196 if (!fe.prepareForNonLazy()) { 6197 // [stack] 6198 return false; 6199 } 6200 6201 BytecodeEmitter bce2(this, funbox); 6202 if (!bce2.init(funNode->pn_pos)) { 6203 return false; 6204 } 6205 6206 /* We measured the max scope depth when we parsed the function. */ 6207 if (!bce2.emitFunctionScript(funNode)) { 6208 return false; 6209 } 6210 6211 if (!fe.emitNonLazyEnd()) { 6212 // [stack] FUN? 6213 return false; 6214 } 6215 } else { 6216 if (!fe.emitAsmJSModule()) { 6217 // [stack] 6218 return false; 6219 } 6220 } 6221 6222 // Track the last emitted top-level self-hosted function, so that intrinsics 6223 // can adjust attributes at parse time. 6224 // 6225 // NOTE: We also disallow lambda functions in the top-level body. This is done 6226 // to simplify handling of the self-hosted stencil. Within normal function 6227 // declarations there are no such restrictions. 6228 if (emitterMode == EmitterMode::SelfHosting) { 6229 if (sc->isTopLevelContext()) { 6230 MOZ_ASSERT(!funbox->isLambda()); 6231 MOZ_ASSERT(funbox->explicitName()); 6232 prevSelfHostedTopLevelFunction = funbox; 6233 } 6234 } 6235 6236 return true; 6237 } 6238 6239 bool BytecodeEmitter::emitDo(BinaryNode* doNode) { 6240 ParseNode* bodyNode = doNode->left(); 6241 6242 DoWhileEmitter doWhile(this); 6243 if (!doWhile.emitBody(doNode->pn_pos.begin, getOffsetForLoop(bodyNode))) { 6244 return false; 6245 } 6246 6247 if (!emitTree(bodyNode)) { 6248 return false; 6249 } 6250 6251 if (!doWhile.emitCond()) { 6252 return false; 6253 } 6254 6255 ParseNode* condNode = doNode->right(); 6256 if (!updateSourceCoordNotes(condNode->pn_pos.begin)) { 6257 return false; 6258 } 6259 if (!markStepBreakpoint()) { 6260 return false; 6261 } 6262 if (!emitTree(condNode)) { 6263 return false; 6264 } 6265 6266 if (!doWhile.emitEnd()) { 6267 return false; 6268 } 6269 6270 return true; 6271 } 6272 6273 bool BytecodeEmitter::emitWhile(BinaryNode* whileNode) { 6274 ParseNode* bodyNode = whileNode->right(); 6275 6276 WhileEmitter wh(this); 6277 6278 ParseNode* condNode = whileNode->left(); 6279 if (!wh.emitCond(whileNode->pn_pos.begin, getOffsetForLoop(condNode), 6280 whileNode->pn_pos.end)) { 6281 return false; 6282 } 6283 6284 if (!updateSourceCoordNotes(condNode->pn_pos.begin)) { 6285 return false; 6286 } 6287 if (!markStepBreakpoint()) { 6288 return false; 6289 } 6290 if (!emitTree(condNode)) { 6291 return false; 6292 } 6293 6294 if (!wh.emitBody()) { 6295 return false; 6296 } 6297 if (!emitTree(bodyNode)) { 6298 return false; 6299 } 6300 6301 if (!wh.emitEnd()) { 6302 return false; 6303 } 6304 6305 return true; 6306 } 6307 6308 bool BytecodeEmitter::emitBreak(TaggedParserAtomIndex label) { 6309 BreakableControl* target; 6310 if (label) { 6311 // Any statement with the matching label may be the break target. 6312 auto hasSameLabel = [label](LabelControl* labelControl) { 6313 return labelControl->label() == label; 6314 }; 6315 target = findInnermostNestableControl<LabelControl>(hasSameLabel); 6316 } else { 6317 auto isNotLabel = [](BreakableControl* control) { 6318 return !control->is<LabelControl>(); 6319 }; 6320 target = findInnermostNestableControl<BreakableControl>(isNotLabel); 6321 } 6322 6323 return emitGoto(target, GotoKind::Break); 6324 } 6325 6326 bool BytecodeEmitter::emitContinue(TaggedParserAtomIndex label) { 6327 LoopControl* target = nullptr; 6328 if (label) { 6329 // Find the loop statement enclosed by the matching label. 6330 NestableControl* control = innermostNestableControl; 6331 while (!control->is<LabelControl>() || 6332 control->as<LabelControl>().label() != label) { 6333 if (control->is<LoopControl>()) { 6334 target = &control->as<LoopControl>(); 6335 } 6336 control = control->enclosing(); 6337 } 6338 } else { 6339 target = findInnermostNestableControl<LoopControl>(); 6340 } 6341 return emitGoto(target, GotoKind::Continue); 6342 } 6343 6344 bool BytecodeEmitter::emitGetFunctionThis(NameNode* thisName) { 6345 MOZ_ASSERT(sc->hasFunctionThisBinding()); 6346 MOZ_ASSERT(thisName->isName(TaggedParserAtomIndex::WellKnown::dot_this_())); 6347 6348 if (!updateLineNumberNotes(thisName->pn_pos.begin)) { 6349 return false; 6350 } 6351 6352 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_this_())) { 6353 // [stack] THIS 6354 return false; 6355 } 6356 if (sc->needsThisTDZChecks()) { 6357 if (!emit1(JSOp::CheckThis)) { 6358 // [stack] THIS 6359 return false; 6360 } 6361 } 6362 6363 return true; 6364 } 6365 6366 bool BytecodeEmitter::emitGetThisForSuperBase(UnaryNode* superBase) { 6367 MOZ_ASSERT(superBase->isKind(ParseNodeKind::SuperBase)); 6368 NameNode* nameNode = &superBase->kid()->as<NameNode>(); 6369 return emitGetFunctionThis(nameNode); 6370 // [stack] THIS 6371 } 6372 6373 bool BytecodeEmitter::emitThisLiteral(ThisLiteral* pn) { 6374 if (ParseNode* kid = pn->kid()) { 6375 NameNode* thisName = &kid->as<NameNode>(); 6376 return emitGetFunctionThis(thisName); 6377 // [stack] THIS 6378 } 6379 6380 if (sc->thisBinding() == ThisBinding::Module) { 6381 return emit1(JSOp::Undefined); 6382 // [stack] UNDEF 6383 } 6384 6385 MOZ_ASSERT(sc->thisBinding() == ThisBinding::Global); 6386 6387 MOZ_ASSERT(outermostScope().hasNonSyntacticScopeOnChain() == 6388 sc->hasNonSyntacticScope()); 6389 if (sc->hasNonSyntacticScope()) { 6390 return emit1(JSOp::NonSyntacticGlobalThis); 6391 // [stack] THIS 6392 } 6393 6394 return emit1(JSOp::GlobalThis); 6395 // [stack] THIS 6396 } 6397 6398 bool BytecodeEmitter::emitCheckDerivedClassConstructorReturn() { 6399 MOZ_ASSERT( 6400 lookupName(TaggedParserAtomIndex::WellKnown::dot_this_()).hasKnownSlot()); 6401 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_this_())) { 6402 return false; 6403 } 6404 if (!emit1(JSOp::CheckReturn)) { 6405 return false; 6406 } 6407 if (!emit1(JSOp::SetRval)) { 6408 return false; 6409 } 6410 return true; 6411 } 6412 6413 bool BytecodeEmitter::emitNewTarget() { 6414 MOZ_ASSERT(sc->allowNewTarget()); 6415 6416 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_newTarget_())) { 6417 // [stack] NEW.TARGET 6418 return false; 6419 } 6420 return true; 6421 } 6422 6423 bool BytecodeEmitter::emitNewTarget(NewTargetNode* pn) { 6424 MOZ_ASSERT(pn->newTargetName()->isName( 6425 TaggedParserAtomIndex::WellKnown::dot_newTarget_())); 6426 6427 return emitNewTarget(); 6428 } 6429 6430 bool BytecodeEmitter::emitNewTarget(CallNode* pn) { 6431 MOZ_ASSERT(pn->callOp() == JSOp::SuperCall || 6432 pn->callOp() == JSOp::SpreadSuperCall); 6433 6434 // The parser is responsible for marking the "new.target" binding as being 6435 // implicitly used in super() calls. 6436 return emitNewTarget(); 6437 } 6438 6439 bool BytecodeEmitter::emitReturn(UnaryNode* returnNode) { 6440 if (!updateSourceCoordNotes(returnNode->pn_pos.begin)) { 6441 return false; 6442 } 6443 6444 if (!markStepBreakpoint()) { 6445 return false; 6446 } 6447 6448 /* Push a return value */ 6449 if (ParseNode* expr = returnNode->kid()) { 6450 if (!emitTree(expr)) { 6451 return false; 6452 } 6453 6454 if (sc->asSuspendableContext()->isAsync() && 6455 sc->asSuspendableContext()->isGenerator()) { 6456 if (!emitAwaitInInnermostScope()) { 6457 return false; 6458 } 6459 } 6460 } else { 6461 /* No explicit return value provided */ 6462 if (!emit1(JSOp::Undefined)) { 6463 return false; 6464 } 6465 } 6466 6467 // We know functionBodyEndPos is set because "return" is only 6468 // valid in a function, and so we've passed through 6469 // emitFunctionScript. 6470 if (!updateSourceCoordNotes(*functionBodyEndPos)) { 6471 return false; 6472 } 6473 6474 /* 6475 * The return value is currently on the stack. We would like to 6476 * generate JSOp::Return, but if we have work to do before returning, 6477 * we will instead generate JSOp::SetRval / JSOp::RetRval. 6478 * 6479 * We don't know whether we will need fixup code until after calling 6480 * prepareForNonLocalJumpToOutermost, so we start by generating 6481 * JSOp::SetRval, then mutate it to JSOp::Return in finishReturn if it 6482 * wasn't needed. 6483 */ 6484 BytecodeOffset setRvalOffset = bytecodeSection().offset(); 6485 if (!emit1(JSOp::SetRval)) { 6486 return false; 6487 } 6488 6489 NonLocalExitControl nle(this, NonLocalExitKind::Return); 6490 return nle.emitReturn(setRvalOffset); 6491 } 6492 6493 bool BytecodeEmitter::finishReturn(BytecodeOffset setRvalOffset) { 6494 // The return value is currently in rval. Depending on the current function, 6495 // we may have to do additional work before returning: 6496 // - Derived class constructors must check if the return value is an object. 6497 // - Generators and async functions must do a final yield. 6498 // - Non-async generators must return the value as an iterator result: 6499 // { value: <rval>, done: true } 6500 // - Non-generator async functions must resolve the function's result promise 6501 // with the value. 6502 // 6503 // If we have not generated any code since the SetRval that stored the return 6504 // value, we can also optimize the bytecode by rewriting that SetRval as a 6505 // JSOp::Return. See |emitReturn| above. 6506 6507 bool isDerivedClassConstructor = 6508 sc->isFunctionBox() && sc->asFunctionBox()->isDerivedClassConstructor(); 6509 bool needsFinalYield = 6510 sc->isFunctionBox() && sc->asFunctionBox()->needsFinalYield(); 6511 bool isSimpleReturn = 6512 setRvalOffset.valid() && 6513 setRvalOffset + BytecodeOffsetDiff(JSOpLength_SetRval) == 6514 bytecodeSection().offset(); 6515 6516 if (isDerivedClassConstructor) { 6517 MOZ_ASSERT(!needsFinalYield); 6518 if (!emitJump(JSOp::Goto, &endOfDerivedClassConstructorBody)) { 6519 return false; 6520 } 6521 return true; 6522 } 6523 6524 if (needsFinalYield) { 6525 if (!emitJump(JSOp::Goto, &finalYields)) { 6526 return false; 6527 } 6528 return true; 6529 } 6530 6531 if (isSimpleReturn) { 6532 MOZ_ASSERT(JSOp(bytecodeSection().code()[setRvalOffset.value()]) == 6533 JSOp::SetRval); 6534 bytecodeSection().code()[setRvalOffset.value()] = jsbytecode(JSOp::Return); 6535 return true; 6536 } 6537 6538 // Nothing special needs to be done. 6539 return emitReturnRval(); 6540 } 6541 6542 bool BytecodeEmitter::emitGetDotGeneratorInScope(EmitterScope& currentScope) { 6543 if (!sc->isFunction() && sc->isModuleContext() && 6544 sc->asModuleContext()->isAsync()) { 6545 NameLocation loc = *locationOfNameBoundInScopeType<ModuleScope>( 6546 TaggedParserAtomIndex::WellKnown::dot_generator_(), ¤tScope); 6547 return emitGetNameAtLocation( 6548 TaggedParserAtomIndex::WellKnown::dot_generator_(), loc); 6549 } 6550 NameLocation loc = *locationOfNameBoundInScopeType<FunctionScope>( 6551 TaggedParserAtomIndex::WellKnown::dot_generator_(), ¤tScope); 6552 return emitGetNameAtLocation( 6553 TaggedParserAtomIndex::WellKnown::dot_generator_(), loc); 6554 } 6555 6556 bool BytecodeEmitter::emitInitialYield(UnaryNode* yieldNode) { 6557 if (!emitTree(yieldNode->kid())) { 6558 return false; 6559 } 6560 6561 if (!emitYieldOp(JSOp::InitialYield)) { 6562 // [stack] RVAL GENERATOR RESUMEKIND 6563 return false; 6564 } 6565 if (!emit1(JSOp::CheckResumeKind)) { 6566 // [stack] RVAL 6567 return false; 6568 } 6569 if (!emit1(JSOp::Pop)) { 6570 // [stack] 6571 return false; 6572 } 6573 6574 return true; 6575 } 6576 6577 bool BytecodeEmitter::emitYield(UnaryNode* yieldNode) { 6578 MOZ_ASSERT(sc->isFunctionBox()); 6579 MOZ_ASSERT(sc->asFunctionBox()->isGenerator()); 6580 MOZ_ASSERT(yieldNode->isKind(ParseNodeKind::YieldExpr)); 6581 6582 bool needsIteratorResult = sc->asFunctionBox()->needsIteratorResult(); 6583 if (needsIteratorResult) { 6584 if (!emitPrepareIteratorResult()) { 6585 // [stack] ITEROBJ 6586 return false; 6587 } 6588 } 6589 if (ParseNode* expr = yieldNode->kid()) { 6590 if (!emitTree(expr)) { 6591 // [stack] ITEROBJ? VAL 6592 return false; 6593 } 6594 } else { 6595 if (!emit1(JSOp::Undefined)) { 6596 // [stack] ITEROBJ? UNDEFINED 6597 return false; 6598 } 6599 } 6600 6601 if (sc->asSuspendableContext()->isAsync()) { 6602 MOZ_ASSERT(!needsIteratorResult); 6603 if (!emitAwaitInInnermostScope()) { 6604 // [stack] RESULT 6605 return false; 6606 } 6607 } 6608 6609 if (needsIteratorResult) { 6610 if (!emitFinishIteratorResult(false)) { 6611 // [stack] ITEROBJ 6612 return false; 6613 } 6614 } 6615 6616 if (!emitGetDotGeneratorInInnermostScope()) { 6617 // [stack] # if needsIteratorResult 6618 // [stack] ITEROBJ .GENERATOR 6619 // [stack] # else 6620 // [stack] RESULT .GENERATOR 6621 return false; 6622 } 6623 6624 if (!emitYieldOp(JSOp::Yield)) { 6625 // [stack] YIELDRESULT GENERATOR RESUMEKIND 6626 return false; 6627 } 6628 6629 if (!emit1(JSOp::CheckResumeKind)) { 6630 // [stack] YIELDRESULT 6631 return false; 6632 } 6633 6634 return true; 6635 } 6636 6637 bool BytecodeEmitter::emitAwaitInInnermostScope(UnaryNode* awaitNode) { 6638 MOZ_ASSERT(sc->isSuspendableContext()); 6639 MOZ_ASSERT(awaitNode->isKind(ParseNodeKind::AwaitExpr)); 6640 6641 if (!emitTree(awaitNode->kid())) { 6642 return false; 6643 } 6644 return emitAwaitInInnermostScope(); 6645 } 6646 6647 bool BytecodeEmitter::emitAwaitInScope(EmitterScope& currentScope) { 6648 if (!emit1(JSOp::CanSkipAwait)) { 6649 // [stack] VALUE CANSKIP 6650 return false; 6651 } 6652 6653 if (!emit1(JSOp::MaybeExtractAwaitValue)) { 6654 // [stack] VALUE_OR_RESOLVED CANSKIP 6655 return false; 6656 } 6657 6658 InternalIfEmitter ifCanSkip(this); 6659 if (!ifCanSkip.emitThen(IfEmitter::ConditionKind::Negative)) { 6660 // [stack] VALUE_OR_RESOLVED 6661 return false; 6662 } 6663 6664 if (sc->asSuspendableContext()->needsPromiseResult()) { 6665 if (!emitGetDotGeneratorInScope(currentScope)) { 6666 // [stack] VALUE GENERATOR 6667 return false; 6668 } 6669 if (!emit1(JSOp::AsyncAwait)) { 6670 // [stack] PROMISE 6671 return false; 6672 } 6673 } 6674 6675 if (!emitGetDotGeneratorInScope(currentScope)) { 6676 // [stack] VALUE|PROMISE GENERATOR 6677 return false; 6678 } 6679 if (!emitYieldOp(JSOp::Await)) { 6680 // [stack] RESOLVED GENERATOR RESUMEKIND 6681 return false; 6682 } 6683 if (!emit1(JSOp::CheckResumeKind)) { 6684 // [stack] RESOLVED 6685 return false; 6686 } 6687 6688 if (!ifCanSkip.emitEnd()) { 6689 return false; 6690 } 6691 6692 MOZ_ASSERT(ifCanSkip.popped() == 0); 6693 6694 return true; 6695 } 6696 6697 // ES2019 draft rev 49b781ec80117b60f73327ef3054703a3111e40c 6698 // 14.4.14 Runtime Semantics: Evaluation 6699 // YieldExpression : yield* AssignmentExpression 6700 bool BytecodeEmitter::emitYieldStar(ParseNode* iter) { 6701 MOZ_ASSERT(getSelfHostedIterFor(iter) == SelfHostedIter::Deny, 6702 "yield* is prohibited in self-hosted code because it can run " 6703 "user-modifiable iteration code"); 6704 6705 MOZ_ASSERT(sc->isSuspendableContext()); 6706 MOZ_ASSERT(sc->asSuspendableContext()->isGenerator()); 6707 6708 // Step 1. 6709 IteratorKind iterKind = sc->asSuspendableContext()->isAsync() 6710 ? IteratorKind::Async 6711 : IteratorKind::Sync; 6712 bool needsIteratorResult = sc->asSuspendableContext()->needsIteratorResult(); 6713 6714 // Steps 2-5. 6715 if (!emitTree(iter)) { 6716 // [stack] ITERABLE 6717 return false; 6718 } 6719 if (iterKind == IteratorKind::Async) { 6720 if (!emitAsyncIterator(SelfHostedIter::Deny)) { 6721 // [stack] NEXT ITER 6722 return false; 6723 } 6724 } else { 6725 if (!emitIterator(SelfHostedIter::Deny)) { 6726 // [stack] NEXT ITER 6727 return false; 6728 } 6729 } 6730 6731 // Step 6. 6732 // Start with NormalCompletion(undefined). 6733 if (!emit1(JSOp::Undefined)) { 6734 // [stack] NEXT ITER RECEIVED 6735 return false; 6736 } 6737 if (!emitPushResumeKind(GeneratorResumeKind::Next)) { 6738 // [stack] NEXT ITER RECEIVED RESUMEKIND 6739 return false; 6740 } 6741 6742 const int32_t startDepth = bytecodeSection().stackDepth(); 6743 MOZ_ASSERT(startDepth >= 4); 6744 6745 // Step 7 is a loop. 6746 LoopControl loopInfo(this, StatementKind::YieldStar); 6747 if (!loopInfo.emitLoopHead(this, Nothing())) { 6748 // [stack] NEXT ITER RECEIVED RESUMEKIND 6749 return false; 6750 } 6751 6752 // Step 7.a. Check for Normal completion. 6753 if (!emit1(JSOp::Dup)) { 6754 // [stack] NEXT ITER RECEIVED RESUMEKIND RESUMEKIND 6755 return false; 6756 } 6757 if (!emitPushResumeKind(GeneratorResumeKind::Next)) { 6758 // [stack] NEXT ITER RECEIVED RESUMEKIND RESUMEKIND NORMAL 6759 return false; 6760 } 6761 if (!emit1(JSOp::StrictEq)) { 6762 // [stack] NEXT ITER RECEIVED RESUMEKIND IS_NORMAL 6763 return false; 6764 } 6765 6766 InternalIfEmitter ifKind(this); 6767 if (!ifKind.emitThenElse()) { 6768 // [stack] NEXT ITER RECEIVED RESUMEKIND 6769 return false; 6770 } 6771 { 6772 if (!emit1(JSOp::Pop)) { 6773 // [stack] NEXT ITER RECEIVED 6774 return false; 6775 } 6776 6777 // Step 7.a.i. 6778 // result = iter.next(received) 6779 if (!emit2(JSOp::Unpick, 2)) { 6780 // [stack] RECEIVED NEXT ITER 6781 return false; 6782 } 6783 if (!emit1(JSOp::Dup2)) { 6784 // [stack] RECEIVED NEXT ITER NEXT ITER 6785 return false; 6786 } 6787 if (!emit2(JSOp::Pick, 4)) { 6788 // [stack] NEXT ITER NEXT ITER RECEIVED 6789 return false; 6790 } 6791 if (!emitCall(JSOp::Call, 1, iter)) { 6792 // [stack] NEXT ITER RESULT 6793 return false; 6794 } 6795 6796 // Step 7.a.ii. 6797 if (iterKind == IteratorKind::Async) { 6798 if (!emitAwaitInInnermostScope()) { 6799 // [stack] NEXT ITER RESULT 6800 return false; 6801 } 6802 } 6803 6804 // Step 7.a.iii. 6805 if (!emitCheckIsObj(CheckIsObjectKind::IteratorNext)) { 6806 // [stack] NEXT ITER RESULT 6807 return false; 6808 } 6809 6810 // Bytecode for steps 7.a.iv-vii is emitted after the ifKind if-else because 6811 // it's shared with other branches. 6812 } 6813 6814 // Step 7.b. Check for Throw completion. 6815 if (!ifKind.emitElseIf(Nothing())) { 6816 // [stack] NEXT ITER RECEIVED RESUMEKIND 6817 return false; 6818 } 6819 if (!emit1(JSOp::Dup)) { 6820 // [stack] NEXT ITER RECEIVED RESUMEKIND RESUMEKIND 6821 return false; 6822 } 6823 if (!emitPushResumeKind(GeneratorResumeKind::Throw)) { 6824 // [stack] NEXT ITER RECEIVED RESUMEKIND RESUMEKIND THROW 6825 return false; 6826 } 6827 if (!emit1(JSOp::StrictEq)) { 6828 // [stack] NEXT ITER RECEIVED RESUMEKIND IS_THROW 6829 return false; 6830 } 6831 if (!ifKind.emitThenElse()) { 6832 // [stack] NEXT ITER RECEIVED RESUMEKIND 6833 return false; 6834 } 6835 { 6836 if (!emit1(JSOp::Pop)) { 6837 // [stack] NEXT ITER RECEIVED 6838 return false; 6839 } 6840 // Step 7.b.i. 6841 if (!emitDupAt(1)) { 6842 // [stack] NEXT ITER RECEIVED ITER 6843 return false; 6844 } 6845 if (!emit1(JSOp::Dup)) { 6846 // [stack] NEXT ITER RECEIVED ITER ITER 6847 return false; 6848 } 6849 if (!emitAtomOp(JSOp::GetProp, 6850 TaggedParserAtomIndex::WellKnown::throw_())) { 6851 // [stack] NEXT ITER RECEIVED ITER THROW 6852 return false; 6853 } 6854 6855 // Step 7.b.ii. 6856 InternalIfEmitter ifThrowMethodIsNotDefined(this); 6857 if (!emit1(JSOp::IsNullOrUndefined)) { 6858 // [stack] NEXT ITER RECEIVED ITER THROW NULL-OR-UNDEF 6859 return false; 6860 } 6861 6862 if (!ifThrowMethodIsNotDefined.emitThenElse( 6863 IfEmitter::ConditionKind::Negative)) { 6864 // [stack] NEXT ITER RECEIVED ITER THROW 6865 return false; 6866 } 6867 6868 // Step 7.b.ii.1. 6869 // RESULT = ITER.throw(EXCEPTION) 6870 if (!emit1(JSOp::Swap)) { 6871 // [stack] NEXT ITER RECEIVED THROW ITER 6872 return false; 6873 } 6874 if (!emit2(JSOp::Pick, 2)) { 6875 // [stack] NEXT ITER THROW ITER RECEIVED 6876 return false; 6877 } 6878 if (!emitCall(JSOp::Call, 1, iter)) { 6879 // [stack] NEXT ITER RESULT 6880 return false; 6881 } 6882 6883 // Step 7.b.ii.2. 6884 if (iterKind == IteratorKind::Async) { 6885 if (!emitAwaitInInnermostScope()) { 6886 // [stack] NEXT ITER RESULT 6887 return false; 6888 } 6889 } 6890 6891 // Step 7.b.ii.4. 6892 if (!emitCheckIsObj(CheckIsObjectKind::IteratorThrow)) { 6893 // [stack] NEXT ITER RESULT 6894 return false; 6895 } 6896 6897 // Bytecode for steps 7.b.ii.5-8 is emitted after the ifKind if-else because 6898 // it's shared with other branches. 6899 6900 // Step 7.b.iii. 6901 if (!ifThrowMethodIsNotDefined.emitElse()) { 6902 // [stack] NEXT ITER RECEIVED ITER THROW 6903 return false; 6904 } 6905 if (!emit1(JSOp::Pop)) { 6906 // [stack] NEXT ITER RECEIVED ITER 6907 return false; 6908 } 6909 6910 // Steps 7.b.iii.1-4. 6911 // 6912 // If the iterator does not have a "throw" method, it calls IteratorClose 6913 // and then throws a TypeError. 6914 if (!emitIteratorCloseInInnermostScope(iterKind, CompletionKind::Normal, 6915 SelfHostedIter::Deny)) { 6916 // [stack] NEXT ITER RECEIVED ITER 6917 return false; 6918 } 6919 // Steps 7.b.iii.5-6. 6920 if (!emit2(JSOp::ThrowMsg, uint8_t(ThrowMsgKind::IteratorNoThrow))) { 6921 // [stack] NEXT ITER RECEIVED ITER 6922 // [stack] # throw 6923 return false; 6924 } 6925 6926 if (!ifThrowMethodIsNotDefined.emitEnd()) { 6927 return false; 6928 } 6929 } 6930 6931 // Step 7.c. It must be a Return completion. 6932 if (!ifKind.emitElse()) { 6933 // [stack] NEXT ITER RECEIVED RESUMEKIND 6934 return false; 6935 } 6936 { 6937 if (!emit1(JSOp::Pop)) { 6938 // [stack] NEXT ITER RECEIVED 6939 return false; 6940 } 6941 6942 // Step 7.c.i. 6943 // 6944 // Call iterator.return() for receiving a "forced return" completion from 6945 // the generator. 6946 6947 // Step 7.c.ii. 6948 // 6949 // Get the "return" method. 6950 if (!emitDupAt(1)) { 6951 // [stack] NEXT ITER RECEIVED ITER 6952 return false; 6953 } 6954 if (!emit1(JSOp::Dup)) { 6955 // [stack] NEXT ITER RECEIVED ITER ITER 6956 return false; 6957 } 6958 if (!emitAtomOp(JSOp::GetProp, 6959 TaggedParserAtomIndex::WellKnown::return_())) { 6960 // [stack] NEXT ITER RECEIVED ITER RET 6961 return false; 6962 } 6963 6964 // Step 7.c.iii. 6965 // 6966 // Do nothing if "return" is undefined or null. 6967 InternalIfEmitter ifReturnMethodIsDefined(this); 6968 if (!emit1(JSOp::IsNullOrUndefined)) { 6969 // [stack] NEXT ITER RECEIVED ITER RET NULL-OR-UNDEF 6970 return false; 6971 } 6972 6973 // Step 7.c.iv. 6974 // 6975 // Call "return" with the argument passed to Generator.prototype.return. 6976 if (!ifReturnMethodIsDefined.emitThenElse( 6977 IfEmitter::ConditionKind::Negative)) { 6978 // [stack] NEXT ITER RECEIVED ITER RET 6979 return false; 6980 } 6981 if (!emit1(JSOp::Swap)) { 6982 // [stack] NEXT ITER RECEIVED RET ITER 6983 return false; 6984 } 6985 if (!emit2(JSOp::Pick, 2)) { 6986 // [stack] NEXT ITER RET ITER RECEIVED 6987 return false; 6988 } 6989 if (needsIteratorResult) { 6990 if (!emitAtomOp(JSOp::GetProp, 6991 TaggedParserAtomIndex::WellKnown::value())) { 6992 // [stack] NEXT ITER RET ITER VAL 6993 return false; 6994 } 6995 } 6996 if (!emitCall(JSOp::Call, 1)) { 6997 // [stack] NEXT ITER RESULT 6998 return false; 6999 } 7000 7001 // Step 7.c.v. 7002 if (iterKind == IteratorKind::Async) { 7003 if (!emitAwaitInInnermostScope()) { 7004 // [stack] NEXT ITER RESULT 7005 return false; 7006 } 7007 } 7008 7009 // Step 7.c.vi. 7010 if (!emitCheckIsObj(CheckIsObjectKind::IteratorReturn)) { 7011 // [stack] NEXT ITER RESULT 7012 return false; 7013 } 7014 7015 // Check if the returned object from iterator.return() is done. If not, 7016 // continue yielding. 7017 7018 // Steps 7.c.vii-viii. 7019 InternalIfEmitter ifReturnDone(this); 7020 if (!emit1(JSOp::Dup)) { 7021 // [stack] NEXT ITER RESULT RESULT 7022 return false; 7023 } 7024 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::done())) { 7025 // [stack] NEXT ITER RESULT DONE 7026 return false; 7027 } 7028 if (!ifReturnDone.emitThenElse()) { 7029 // [stack] NEXT ITER RESULT 7030 return false; 7031 } 7032 7033 // Step 7.c.viii.1. 7034 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::value())) { 7035 // [stack] NEXT ITER VALUE 7036 return false; 7037 } 7038 if (needsIteratorResult) { 7039 if (!emitPrepareIteratorResult()) { 7040 // [stack] NEXT ITER VALUE RESULT 7041 return false; 7042 } 7043 if (!emit1(JSOp::Swap)) { 7044 // [stack] NEXT ITER RESULT VALUE 7045 return false; 7046 } 7047 if (!emitFinishIteratorResult(true)) { 7048 // [stack] NEXT ITER RESULT 7049 return false; 7050 } 7051 } 7052 7053 if (!ifReturnDone.emitElse()) { 7054 // [stack] NEXT ITER RESULT 7055 return false; 7056 } 7057 7058 // Jump to continue label for steps 7.c.ix-x. 7059 if (!emitJump(JSOp::Goto, &loopInfo.continues)) { 7060 // [stack] NEXT ITER RESULT 7061 return false; 7062 } 7063 7064 if (!ifReturnDone.emitEnd()) { 7065 // [stack] NEXT ITER RESULT 7066 return false; 7067 } 7068 7069 // Step 7.c.iii. 7070 if (!ifReturnMethodIsDefined.emitElse()) { 7071 // [stack] NEXT ITER RECEIVED ITER RET 7072 return false; 7073 } 7074 if (!emitPopN(2)) { 7075 // [stack] NEXT ITER RECEIVED 7076 return false; 7077 } 7078 if (iterKind == IteratorKind::Async) { 7079 // Step 7.c.iii.1. 7080 if (!emitAwaitInInnermostScope()) { 7081 // [stack] NEXT ITER RECEIVED 7082 return false; 7083 } 7084 } 7085 if (!ifReturnMethodIsDefined.emitEnd()) { 7086 // [stack] NEXT ITER RECEIVED 7087 return false; 7088 } 7089 7090 // Perform a "forced generator return". 7091 // 7092 // Step 7.c.iii.2. 7093 // Step 7.c.viii.2. 7094 if (!emitGetDotGeneratorInInnermostScope()) { 7095 // [stack] NEXT ITER RESULT GENOBJ 7096 return false; 7097 } 7098 if (!emitPushResumeKind(GeneratorResumeKind::Return)) { 7099 // [stack] NEXT ITER RESULT GENOBJ RESUMEKIND 7100 return false; 7101 } 7102 if (!emit1(JSOp::CheckResumeKind)) { 7103 // [stack] NEXT ITER RESULT GENOBJ RESUMEKIND 7104 return false; 7105 } 7106 } 7107 7108 if (!ifKind.emitEnd()) { 7109 // [stack] NEXT ITER RESULT 7110 return false; 7111 } 7112 7113 // Shared tail for Normal/Throw completions. 7114 // 7115 // Steps 7.a.iv-v. 7116 // Steps 7.b.ii.5-6. 7117 // 7118 // [stack] NEXT ITER RESULT 7119 7120 // if (result.done) break; 7121 if (!emit1(JSOp::Dup)) { 7122 // [stack] NEXT ITER RESULT RESULT 7123 return false; 7124 } 7125 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::done())) { 7126 // [stack] NEXT ITER RESULT DONE 7127 return false; 7128 } 7129 if (!emitJump(JSOp::JumpIfTrue, &loopInfo.breaks)) { 7130 // [stack] NEXT ITER RESULT 7131 return false; 7132 } 7133 7134 // Steps 7.a.vi-vii. 7135 // Steps 7.b.ii.7-8. 7136 // Steps 7.c.ix-x. 7137 if (!loopInfo.emitContinueTarget(this)) { 7138 // [stack] NEXT ITER RESULT 7139 return false; 7140 } 7141 if (iterKind == IteratorKind::Async) { 7142 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::value())) { 7143 // [stack] NEXT ITER RESULT 7144 return false; 7145 } 7146 } 7147 if (!emitGetDotGeneratorInInnermostScope()) { 7148 // [stack] NEXT ITER RESULT GENOBJ 7149 return false; 7150 } 7151 if (!emitYieldOp(JSOp::Yield)) { 7152 // [stack] NEXT ITER RVAL GENOBJ RESUMEKIND 7153 return false; 7154 } 7155 if (!emit1(JSOp::Swap)) { 7156 // [stack] NEXT ITER RVAL RESUMEKIND GENOBJ 7157 return false; 7158 } 7159 if (!emit1(JSOp::Pop)) { 7160 // [stack] NEXT ITER RVAL RESUMEKIND 7161 return false; 7162 } 7163 if (!loopInfo.emitLoopEnd(this, JSOp::Goto, TryNoteKind::Loop)) { 7164 // [stack] NEXT ITER RVAL RESUMEKIND 7165 return false; 7166 } 7167 7168 // Jumps to this point have 3 (instead of 4) values on the stack. 7169 MOZ_ASSERT(bytecodeSection().stackDepth() == startDepth); 7170 bytecodeSection().setStackDepth(startDepth - 1); 7171 7172 // [stack] NEXT ITER RESULT 7173 7174 // Step 7.a.v.1. 7175 // Step 7.b.ii.6.a. 7176 // 7177 // result.value 7178 if (!emit2(JSOp::Unpick, 2)) { 7179 // [stack] RESULT NEXT ITER 7180 return false; 7181 } 7182 if (!emitPopN(2)) { 7183 // [stack] RESULT 7184 return false; 7185 } 7186 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::value())) { 7187 // [stack] VALUE 7188 return false; 7189 } 7190 7191 MOZ_ASSERT(bytecodeSection().stackDepth() == startDepth - 3); 7192 7193 return true; 7194 } 7195 7196 bool BytecodeEmitter::emitStatementList(ListNode* stmtList) { 7197 for (ParseNode* stmt : stmtList->contents()) { 7198 if (!emitTree(stmt)) { 7199 return false; 7200 } 7201 } 7202 return true; 7203 } 7204 7205 bool BytecodeEmitter::emitExpressionStatement(UnaryNode* exprStmt) { 7206 MOZ_ASSERT(exprStmt->isKind(ParseNodeKind::ExpressionStmt)); 7207 7208 /* 7209 * Top-level or called-from-a-native JS_Execute/EvaluateScript, 7210 * debugger, and eval frames may need the value of the ultimate 7211 * expression statement as the script's result, despite the fact 7212 * that it appears useless to the compiler. 7213 * 7214 * API users may also set the ReadOnlyCompileOptions::noScriptRval option when 7215 * calling JS_Compile* to suppress JSOp::SetRval. 7216 */ 7217 bool wantval = false; 7218 bool useful = false; 7219 if (sc->isTopLevelContext()) { 7220 useful = wantval = !sc->noScriptRval(); 7221 } 7222 7223 /* Don't eliminate expressions with side effects. */ 7224 ParseNode* expr = exprStmt->kid(); 7225 if (!useful) { 7226 if (!checkSideEffects(expr, &useful)) { 7227 return false; 7228 } 7229 7230 /* 7231 * Don't eliminate apparently useless expressions if they are labeled 7232 * expression statements. The startOffset() test catches the case 7233 * where we are nesting in emitTree for a labeled compound statement. 7234 */ 7235 if (innermostNestableControl && 7236 innermostNestableControl->is<LabelControl>() && 7237 innermostNestableControl->as<LabelControl>().startOffset() >= 7238 bytecodeSection().offset()) { 7239 useful = true; 7240 } 7241 } 7242 7243 if (useful) { 7244 ValueUsage valueUsage = 7245 wantval ? ValueUsage::WantValue : ValueUsage::IgnoreValue; 7246 ExpressionStatementEmitter ese(this, valueUsage); 7247 if (!ese.prepareForExpr(exprStmt->pn_pos.begin)) { 7248 return false; 7249 } 7250 if (!markStepBreakpoint()) { 7251 return false; 7252 } 7253 if (!emitTree(expr, valueUsage)) { 7254 return false; 7255 } 7256 if (!ese.emitEnd()) { 7257 return false; 7258 } 7259 } 7260 7261 return true; 7262 } 7263 7264 bool BytecodeEmitter::emitDeleteName(UnaryNode* deleteNode) { 7265 MOZ_ASSERT(deleteNode->isKind(ParseNodeKind::DeleteNameExpr)); 7266 7267 NameNode* nameExpr = &deleteNode->kid()->as<NameNode>(); 7268 MOZ_ASSERT(nameExpr->isKind(ParseNodeKind::Name)); 7269 7270 return emitAtomOp(JSOp::DelName, nameExpr->atom()); 7271 } 7272 7273 bool BytecodeEmitter::emitDeleteProperty(UnaryNode* deleteNode) { 7274 MOZ_ASSERT(deleteNode->isKind(ParseNodeKind::DeletePropExpr)); 7275 7276 PropertyAccess* propExpr = &deleteNode->kid()->as<PropertyAccess>(); 7277 PropOpEmitter poe(this, PropOpEmitter::Kind::Delete, 7278 propExpr->as<PropertyAccess>().isSuper() 7279 ? PropOpEmitter::ObjKind::Super 7280 : PropOpEmitter::ObjKind::Other); 7281 7282 if (!poe.prepareForObj()) { 7283 return false; 7284 } 7285 7286 if (propExpr->isSuper()) { 7287 // The expression |delete super.foo;| has to evaluate |super.foo|, which 7288 // could throw if |this| hasn't yet been set by a |super(...)| call. 7289 auto* base = &propExpr->expression().as<UnaryNode>(); 7290 if (!emitGetThisForSuperBase(base)) { 7291 // [stack] THIS 7292 return false; 7293 } 7294 } else { 7295 if (!emitPropLHS(propExpr)) { 7296 // [stack] OBJ 7297 return false; 7298 } 7299 } 7300 7301 if (!poe.emitDelete(propExpr->key().atom())) { 7302 // [stack] # if Super 7303 // [stack] THIS 7304 // [stack] # otherwise 7305 // [stack] SUCCEEDED 7306 return false; 7307 } 7308 7309 return true; 7310 } 7311 7312 bool BytecodeEmitter::emitDeleteElement(UnaryNode* deleteNode) { 7313 MOZ_ASSERT(deleteNode->isKind(ParseNodeKind::DeleteElemExpr)); 7314 7315 auto* elemExpr = &deleteNode->kid()->as<PropertyByValue>(); 7316 bool isSuper = elemExpr->isSuper(); 7317 MOZ_ASSERT(!elemExpr->key().isKind(ParseNodeKind::PrivateName)); 7318 ElemOpEmitter eoe( 7319 this, ElemOpEmitter::Kind::Delete, 7320 isSuper ? ElemOpEmitter::ObjKind::Super : ElemOpEmitter::ObjKind::Other); 7321 7322 if (!emitElemObjAndKey(elemExpr, eoe)) { 7323 // [stack] # if Super 7324 // [stack] THIS KEY 7325 // [stack] # otherwise 7326 // [stack] OBJ KEY 7327 return false; 7328 } 7329 7330 if (!eoe.emitDelete()) { 7331 // [stack] # if Super 7332 // [stack] THIS 7333 // [stack] # otherwise 7334 // [stack] SUCCEEDED 7335 return false; 7336 } 7337 7338 return true; 7339 } 7340 7341 bool BytecodeEmitter::emitDeleteExpression(UnaryNode* deleteNode) { 7342 MOZ_ASSERT(deleteNode->isKind(ParseNodeKind::DeleteExpr)); 7343 7344 ParseNode* expression = deleteNode->kid(); 7345 7346 // If useless, just emit JSOp::True; otherwise convert |delete <expr>| to 7347 // effectively |<expr>, true|. 7348 bool useful = false; 7349 if (!checkSideEffects(expression, &useful)) { 7350 return false; 7351 } 7352 7353 if (useful) { 7354 if (!emitTree(expression)) { 7355 return false; 7356 } 7357 if (!emit1(JSOp::Pop)) { 7358 return false; 7359 } 7360 } 7361 7362 return emit1(JSOp::True); 7363 } 7364 7365 bool BytecodeEmitter::emitDeleteOptionalChain(UnaryNode* deleteNode) { 7366 MOZ_ASSERT(deleteNode->isKind(ParseNodeKind::DeleteOptionalChainExpr)); 7367 7368 OptionalEmitter oe(this, bytecodeSection().stackDepth()); 7369 7370 ParseNode* kid = deleteNode->kid(); 7371 switch (kid->getKind()) { 7372 case ParseNodeKind::ElemExpr: 7373 case ParseNodeKind::OptionalElemExpr: { 7374 auto* elemExpr = &kid->as<PropertyByValueBase>(); 7375 if (!emitDeleteElementInOptChain(elemExpr, oe)) { 7376 // [stack] # If shortcircuit 7377 // [stack] UNDEFINED-OR-NULL 7378 // [stack] # otherwise 7379 // [stack] SUCCEEDED 7380 return false; 7381 } 7382 7383 break; 7384 } 7385 case ParseNodeKind::ArgumentsLength: 7386 case ParseNodeKind::DotExpr: 7387 case ParseNodeKind::OptionalDotExpr: { 7388 auto* propExpr = &kid->as<PropertyAccessBase>(); 7389 if (!emitDeletePropertyInOptChain(propExpr, oe)) { 7390 // [stack] # If shortcircuit 7391 // [stack] UNDEFINED-OR-NULL 7392 // [stack] # otherwise 7393 // [stack] SUCCEEDED 7394 return false; 7395 } 7396 break; 7397 } 7398 default: 7399 MOZ_ASSERT_UNREACHABLE("Unrecognized optional delete ParseNodeKind"); 7400 } 7401 7402 if (!oe.emitOptionalJumpTarget(JSOp::True)) { 7403 // [stack] # If shortcircuit 7404 // [stack] TRUE 7405 // [stack] # otherwise 7406 // [stack] SUCCEEDED 7407 return false; 7408 } 7409 7410 return true; 7411 } 7412 7413 bool BytecodeEmitter::emitDeletePropertyInOptChain(PropertyAccessBase* propExpr, 7414 OptionalEmitter& oe) { 7415 MOZ_ASSERT_IF(propExpr->is<PropertyAccess>(), 7416 !propExpr->as<PropertyAccess>().isSuper()); 7417 PropOpEmitter poe(this, PropOpEmitter::Kind::Delete, 7418 PropOpEmitter::ObjKind::Other); 7419 7420 if (!poe.prepareForObj()) { 7421 // [stack] 7422 return false; 7423 } 7424 if (!emitOptionalTree(&propExpr->expression(), oe)) { 7425 // [stack] OBJ 7426 return false; 7427 } 7428 if (propExpr->isKind(ParseNodeKind::OptionalDotExpr)) { 7429 if (!oe.emitJumpShortCircuit()) { 7430 // [stack] # if Jump 7431 // [stack] UNDEFINED-OR-NULL 7432 // [stack] # otherwise 7433 // [stack] OBJ 7434 return false; 7435 } 7436 } 7437 7438 if (!poe.emitDelete(propExpr->key().atom())) { 7439 // [stack] SUCCEEDED 7440 return false; 7441 } 7442 7443 return true; 7444 } 7445 7446 bool BytecodeEmitter::emitDeleteElementInOptChain(PropertyByValueBase* elemExpr, 7447 OptionalEmitter& oe) { 7448 MOZ_ASSERT_IF(elemExpr->is<PropertyByValue>(), 7449 !elemExpr->as<PropertyByValue>().isSuper()); 7450 ElemOpEmitter eoe(this, ElemOpEmitter::Kind::Delete, 7451 ElemOpEmitter::ObjKind::Other); 7452 7453 if (!eoe.prepareForObj()) { 7454 // [stack] 7455 return false; 7456 } 7457 7458 if (!emitOptionalTree(&elemExpr->expression(), oe)) { 7459 // [stack] OBJ 7460 return false; 7461 } 7462 7463 if (elemExpr->isKind(ParseNodeKind::OptionalElemExpr)) { 7464 if (!oe.emitJumpShortCircuit()) { 7465 // [stack] # if Jump 7466 // [stack] UNDEFINED-OR-NULL 7467 // [stack] # otherwise 7468 // [stack] OBJ 7469 return false; 7470 } 7471 } 7472 7473 if (!eoe.prepareForKey()) { 7474 // [stack] OBJ 7475 return false; 7476 } 7477 7478 if (!emitTree(&elemExpr->key())) { 7479 // [stack] OBJ KEY 7480 return false; 7481 } 7482 7483 if (!eoe.emitDelete()) { 7484 // [stack] SUCCEEDED 7485 return false; 7486 } 7487 7488 return true; 7489 } 7490 7491 bool BytecodeEmitter::emitDebugCheckSelfHosted() { 7492 // [stack] CALLEE 7493 7494 #ifdef DEBUG 7495 if (!emit1(JSOp::DebugCheckSelfHosted)) { 7496 // [stack] CALLEE 7497 return false; 7498 } 7499 #endif 7500 7501 return true; 7502 } 7503 7504 bool BytecodeEmitter::emitSelfHostedCallFunction(CallNode* callNode, JSOp op) { 7505 // Special-casing of callFunction to emit bytecode that directly 7506 // invokes the callee with the correct |this| object and arguments. 7507 // callFunction(fun, thisArg, arg0, arg1) thus becomes: 7508 // - emit lookup for fun 7509 // - emit lookup for thisArg 7510 // - emit lookups for arg0, arg1 7511 // 7512 // argc is set to the amount of actually emitted args and the 7513 // emitting of args below is disabled by setting emitArgs to false. 7514 NameNode* calleeNode = &callNode->callee()->as<NameNode>(); 7515 ListNode* argsList = callNode->args(); 7516 7517 MOZ_ASSERT(argsList->count() >= 2); 7518 7519 MOZ_ASSERT(callNode->callOp() == JSOp::Call); 7520 7521 bool constructing = 7522 calleeNode->name() == 7523 TaggedParserAtomIndex::WellKnown::constructContentFunction(); 7524 ParseNode* funNode = argsList->head(); 7525 7526 if (!emitTree(funNode)) { 7527 // [stack] CALLEE 7528 return false; 7529 } 7530 7531 #ifdef DEBUG 7532 MOZ_ASSERT(op == JSOp::Call || op == JSOp::CallContent || 7533 op == JSOp::NewContent); 7534 if (op == JSOp::Call) { 7535 if (!emitDebugCheckSelfHosted()) { 7536 // [stack] CALLEE 7537 return false; 7538 } 7539 } 7540 #endif 7541 7542 ParseNode* thisOrNewTarget = funNode->pn_next; 7543 if (constructing) { 7544 // Save off the new.target value, but here emit a proper |this| for a 7545 // constructing call. 7546 if (!emit1(JSOp::IsConstructing)) { 7547 // [stack] CALLEE IS_CONSTRUCTING 7548 return false; 7549 } 7550 } else { 7551 // It's |this|, emit it. 7552 if (!emitTree(thisOrNewTarget)) { 7553 // [stack] CALLEE THIS 7554 return false; 7555 } 7556 } 7557 7558 for (ParseNode* argpn : argsList->contentsFrom(thisOrNewTarget->pn_next)) { 7559 if (!emitTree(argpn)) { 7560 // [stack] CALLEE ... ARGS... 7561 return false; 7562 } 7563 } 7564 7565 if (constructing) { 7566 if (!emitTree(thisOrNewTarget)) { 7567 // [stack] CALLEE IS_CONSTRUCTING ARGS... NEW.TARGET 7568 return false; 7569 } 7570 } 7571 7572 uint32_t argc = argsList->count() - 2; 7573 if (!emitCall(op, argc)) { 7574 // [stack] RVAL 7575 return false; 7576 } 7577 7578 return true; 7579 } 7580 7581 bool BytecodeEmitter::emitSelfHostedResumeGenerator(CallNode* callNode) { 7582 ListNode* argsList = callNode->args(); 7583 7584 // Syntax: resumeGenerator(gen, value, 'next'|'throw'|'return') 7585 MOZ_ASSERT(argsList->count() == 3); 7586 7587 ParseNode* genNode = argsList->head(); 7588 if (!emitTree(genNode)) { 7589 // [stack] GENERATOR 7590 return false; 7591 } 7592 7593 ParseNode* valNode = genNode->pn_next; 7594 if (!emitTree(valNode)) { 7595 // [stack] GENERATOR VALUE 7596 return false; 7597 } 7598 7599 ParseNode* kindNode = valNode->pn_next; 7600 MOZ_ASSERT(kindNode->isKind(ParseNodeKind::StringExpr)); 7601 GeneratorResumeKind kind = 7602 ParserAtomToResumeKind(kindNode->as<NameNode>().atom()); 7603 MOZ_ASSERT(!kindNode->pn_next); 7604 7605 if (!emitPushResumeKind(kind)) { 7606 // [stack] GENERATOR VALUE RESUMEKIND 7607 return false; 7608 } 7609 7610 if (!emit1(JSOp::Resume)) { 7611 // [stack] RVAL 7612 return false; 7613 } 7614 7615 return true; 7616 } 7617 7618 bool BytecodeEmitter::emitSelfHostedForceInterpreter() { 7619 // JSScript::hasForceInterpreterOp() relies on JSOp::ForceInterpreter being 7620 // the first bytecode op in the script. 7621 MOZ_ASSERT(bytecodeSection().code().empty()); 7622 7623 if (!emit1(JSOp::ForceInterpreter)) { 7624 return false; 7625 } 7626 if (!emit1(JSOp::Undefined)) { 7627 return false; 7628 } 7629 7630 return true; 7631 } 7632 7633 bool BytecodeEmitter::emitSelfHostedAllowContentIter(CallNode* callNode) { 7634 ListNode* argsList = callNode->args(); 7635 7636 MOZ_ASSERT(argsList->count() == 1); 7637 7638 // We're just here as a sentinel. Pass the value through directly. 7639 return emitTree(argsList->head()); 7640 } 7641 7642 bool BytecodeEmitter::emitSelfHostedAllowContentIterWith(CallNode* callNode) { 7643 ListNode* argsList = callNode->args(); 7644 7645 MOZ_ASSERT(argsList->count() == 2 || argsList->count() == 3); 7646 7647 // We're just here as a sentinel. Pass the value through directly. 7648 return emitTree(argsList->head()); 7649 } 7650 7651 bool BytecodeEmitter::emitSelfHostedAllowContentIterWithNext( 7652 CallNode* callNode) { 7653 ListNode* argsList = callNode->args(); 7654 7655 MOZ_ASSERT(argsList->count() == 2); 7656 7657 // We're just here as a sentinel. Pass the value through directly. 7658 return emitTree(argsList->head()); 7659 } 7660 7661 bool BytecodeEmitter::emitSelfHostedDefineDataProperty(CallNode* callNode) { 7662 ListNode* argsList = callNode->args(); 7663 7664 // Only optimize when 3 arguments are passed. 7665 MOZ_ASSERT(argsList->count() == 3); 7666 7667 ParseNode* objNode = argsList->head(); 7668 if (!emitTree(objNode)) { 7669 return false; 7670 } 7671 7672 ParseNode* idNode = objNode->pn_next; 7673 if (!emitTree(idNode)) { 7674 return false; 7675 } 7676 7677 ParseNode* valNode = idNode->pn_next; 7678 if (!emitTree(valNode)) { 7679 return false; 7680 } 7681 7682 // This will leave the object on the stack instead of pushing |undefined|, 7683 // but that's fine because the self-hosted code doesn't use the return 7684 // value. 7685 return emit1(JSOp::InitElem); 7686 } 7687 7688 bool BytecodeEmitter::emitSelfHostedHasOwn(CallNode* callNode) { 7689 ListNode* argsList = callNode->args(); 7690 7691 MOZ_ASSERT(argsList->count() == 2); 7692 7693 ParseNode* idNode = argsList->head(); 7694 if (!emitTree(idNode)) { 7695 return false; 7696 } 7697 7698 ParseNode* objNode = idNode->pn_next; 7699 if (!emitTree(objNode)) { 7700 return false; 7701 } 7702 7703 return emit1(JSOp::HasOwn); 7704 } 7705 7706 bool BytecodeEmitter::emitSelfHostedGetPropertySuper(CallNode* callNode) { 7707 ListNode* argsList = callNode->args(); 7708 7709 MOZ_ASSERT(argsList->count() == 3); 7710 7711 ParseNode* objNode = argsList->head(); 7712 ParseNode* idNode = objNode->pn_next; 7713 ParseNode* receiverNode = idNode->pn_next; 7714 7715 if (!emitTree(receiverNode)) { 7716 return false; 7717 } 7718 7719 if (!emitTree(idNode)) { 7720 return false; 7721 } 7722 7723 if (!emitTree(objNode)) { 7724 return false; 7725 } 7726 7727 return emitElemOpBase(JSOp::GetElemSuper); 7728 } 7729 7730 bool BytecodeEmitter::emitSelfHostedToNumeric(CallNode* callNode) { 7731 ListNode* argsList = callNode->args(); 7732 7733 MOZ_ASSERT(argsList->count() == 1); 7734 7735 ParseNode* argNode = argsList->head(); 7736 7737 if (!emitTree(argNode)) { 7738 return false; 7739 } 7740 7741 return emit1(JSOp::ToNumeric); 7742 } 7743 7744 bool BytecodeEmitter::emitSelfHostedToString(CallNode* callNode) { 7745 ListNode* argsList = callNode->args(); 7746 7747 MOZ_ASSERT(argsList->count() == 1); 7748 7749 ParseNode* argNode = argsList->head(); 7750 7751 if (!emitTree(argNode)) { 7752 return false; 7753 } 7754 7755 return emit1(JSOp::ToString); 7756 } 7757 7758 bool BytecodeEmitter::emitSelfHostedIsNullOrUndefined(CallNode* callNode) { 7759 ListNode* argsList = callNode->args(); 7760 7761 MOZ_ASSERT(argsList->count() == 1); 7762 7763 ParseNode* argNode = argsList->head(); 7764 7765 if (!emitTree(argNode)) { 7766 // [stack] ARG 7767 return false; 7768 } 7769 if (!emit1(JSOp::IsNullOrUndefined)) { 7770 // [stack] ARG IS_NULL_OR_UNDEF 7771 return false; 7772 } 7773 if (!emit1(JSOp::Swap)) { 7774 // [stack] IS_NULL_OR_UNDEF ARG 7775 return false; 7776 } 7777 if (!emit1(JSOp::Pop)) { 7778 // [stack] IS_NULL_OR_UNDEF 7779 return false; 7780 } 7781 return true; 7782 } 7783 7784 bool BytecodeEmitter::emitSelfHostedIteratorClose(CallNode* callNode) { 7785 ListNode* argsList = callNode->args(); 7786 MOZ_ASSERT(argsList->count() == 1); 7787 7788 ParseNode* argNode = argsList->head(); 7789 if (!emitTree(argNode)) { 7790 // [stack] ARG 7791 return false; 7792 } 7793 7794 if (!emit2(JSOp::CloseIter, uint8_t(CompletionKind::Normal))) { 7795 // [stack] 7796 return false; 7797 } 7798 7799 // This is still a call node, so we must generate a stack value. 7800 if (!emit1(JSOp::Undefined)) { 7801 // [stack] RVAL 7802 return false; 7803 } 7804 7805 return true; 7806 } 7807 7808 bool BytecodeEmitter::emitSelfHostedGetBuiltinConstructorOrPrototype( 7809 CallNode* callNode, bool isConstructor) { 7810 ListNode* argsList = callNode->args(); 7811 7812 MOZ_ASSERT(argsList->count() == 1); 7813 7814 ParseNode* argNode = argsList->head(); 7815 7816 if (!argNode->isKind(ParseNodeKind::StringExpr)) { 7817 reportError(callNode, JSMSG_UNEXPECTED_TYPE, "built-in name", 7818 "not a string constant"); 7819 return false; 7820 } 7821 7822 auto name = argNode->as<NameNode>().atom(); 7823 7824 BuiltinObjectKind kind; 7825 if (isConstructor) { 7826 kind = BuiltinConstructorForName(name); 7827 } else { 7828 kind = BuiltinPrototypeForName(name); 7829 } 7830 7831 if (kind == BuiltinObjectKind::None) { 7832 reportError(callNode, JSMSG_UNEXPECTED_TYPE, "built-in name", 7833 "not a valid built-in"); 7834 return false; 7835 } 7836 7837 return emitBuiltinObject(kind); 7838 } 7839 7840 bool BytecodeEmitter::emitSelfHostedGetBuiltinConstructor(CallNode* callNode) { 7841 return emitSelfHostedGetBuiltinConstructorOrPrototype( 7842 callNode, /* isConstructor = */ true); 7843 } 7844 7845 bool BytecodeEmitter::emitSelfHostedGetBuiltinPrototype(CallNode* callNode) { 7846 return emitSelfHostedGetBuiltinConstructorOrPrototype( 7847 callNode, /* isConstructor = */ false); 7848 } 7849 7850 JS::SymbolCode ParserAtomToSymbolCode(TaggedParserAtomIndex atom) { 7851 // NOTE: This is a linear search, but the set of entries is quite small and 7852 // this is only used for initial self-hosted parse. 7853 #define MATCH_WELL_KNOWN_SYMBOL(NAME) \ 7854 if (atom == TaggedParserAtomIndex::WellKnown::NAME()) { \ 7855 return JS::SymbolCode::NAME; \ 7856 } 7857 JS_FOR_EACH_WELL_KNOWN_SYMBOL(MATCH_WELL_KNOWN_SYMBOL) 7858 #undef MATCH_WELL_KNOWN_SYMBOL 7859 7860 return JS::SymbolCode::Limit; 7861 } 7862 7863 bool BytecodeEmitter::emitSelfHostedGetBuiltinSymbol(CallNode* callNode) { 7864 ListNode* argsList = callNode->args(); 7865 7866 MOZ_ASSERT(argsList->count() == 1); 7867 7868 ParseNode* argNode = argsList->head(); 7869 7870 if (!argNode->isKind(ParseNodeKind::StringExpr)) { 7871 reportError(callNode, JSMSG_UNEXPECTED_TYPE, "built-in name", 7872 "not a string constant"); 7873 return false; 7874 } 7875 7876 auto name = argNode->as<NameNode>().atom(); 7877 7878 JS::SymbolCode code = ParserAtomToSymbolCode(name); 7879 if (code == JS::SymbolCode::Limit) { 7880 reportError(callNode, JSMSG_UNEXPECTED_TYPE, "built-in name", 7881 "not a valid built-in"); 7882 return false; 7883 } 7884 7885 return emit2(JSOp::Symbol, uint8_t(code)); 7886 } 7887 7888 bool BytecodeEmitter::emitSelfHostedArgumentsLength(CallNode* callNode) { 7889 MOZ_ASSERT(!sc->asFunctionBox()->needsArgsObj()); 7890 sc->asFunctionBox()->setUsesArgumentsIntrinsics(); 7891 7892 MOZ_ASSERT(callNode->args()->count() == 0); 7893 7894 return emit1(JSOp::ArgumentsLength); 7895 } 7896 7897 bool BytecodeEmitter::emitSelfHostedGetArgument(CallNode* callNode) { 7898 MOZ_ASSERT(!sc->asFunctionBox()->needsArgsObj()); 7899 sc->asFunctionBox()->setUsesArgumentsIntrinsics(); 7900 7901 ListNode* argsList = callNode->args(); 7902 MOZ_ASSERT(argsList->count() == 1); 7903 7904 ParseNode* argNode = argsList->head(); 7905 if (!emitTree(argNode)) { 7906 return false; 7907 } 7908 7909 return emit1(JSOp::GetActualArg); 7910 } 7911 7912 #ifdef DEBUG 7913 void BytecodeEmitter::assertSelfHostedExpectedTopLevel(ParseNode* node) { 7914 // The function argument is expected to be a simple binding/function name. 7915 // Eg. `function foo() { }; SpecialIntrinsic(foo)` 7916 MOZ_ASSERT(node->isKind(ParseNodeKind::Name), 7917 "argument must be a function name"); 7918 TaggedParserAtomIndex targetName = node->as<NameNode>().name(); 7919 7920 // The special intrinsics must follow the target functions definition. A 7921 // simple assert is fine here since any hoisted function will cause a non-null 7922 // value to be set here. 7923 MOZ_ASSERT(prevSelfHostedTopLevelFunction); 7924 7925 // The target function must match the most recently defined top-level 7926 // self-hosted function. 7927 MOZ_ASSERT(prevSelfHostedTopLevelFunction->explicitName() == targetName, 7928 "selfhost decorator must immediately follow target function"); 7929 } 7930 #endif 7931 7932 bool BytecodeEmitter::emitSelfHostedSetIsInlinableLargeFunction( 7933 CallNode* callNode) { 7934 #ifdef DEBUG 7935 ListNode* argsList = callNode->args(); 7936 7937 MOZ_ASSERT(argsList->count() == 1); 7938 7939 assertSelfHostedExpectedTopLevel(argsList->head()); 7940 #endif 7941 7942 MOZ_ASSERT(prevSelfHostedTopLevelFunction->isInitialCompilation); 7943 prevSelfHostedTopLevelFunction->setIsInlinableLargeFunction(); 7944 7945 // This is still a call node, so we must generate a stack value. 7946 return emit1(JSOp::Undefined); 7947 } 7948 7949 bool BytecodeEmitter::emitSelfHostedSetCanonicalName(CallNode* callNode) { 7950 ListNode* argsList = callNode->args(); 7951 7952 MOZ_ASSERT(argsList->count() == 2); 7953 7954 #ifdef DEBUG 7955 assertSelfHostedExpectedTopLevel(argsList->head()); 7956 #endif 7957 7958 ParseNode* nameNode = argsList->last(); 7959 MOZ_ASSERT(nameNode->isKind(ParseNodeKind::StringExpr)); 7960 TaggedParserAtomIndex specName = nameNode->as<NameNode>().atom(); 7961 // Canonical name must be atomized. 7962 compilationState.parserAtoms.markUsedByStencil(specName, 7963 ParserAtom::Atomize::Yes); 7964 7965 // Store the canonical name for instantiation. 7966 prevSelfHostedTopLevelFunction->functionStencil().setSelfHostedCanonicalName( 7967 specName); 7968 7969 return emit1(JSOp::Undefined); 7970 } 7971 7972 #ifdef DEBUG 7973 void BytecodeEmitter::assertSelfHostedUnsafeGetReservedSlot( 7974 ListNode* argsList) { 7975 MOZ_ASSERT(argsList->count() == 2); 7976 7977 ParseNode* objNode = argsList->head(); 7978 ParseNode* slotNode = objNode->pn_next; 7979 7980 // Ensure that the slot argument is fixed, this is required by the JITs. 7981 MOZ_ASSERT(slotNode->isKind(ParseNodeKind::NumberExpr), 7982 "slot argument must be a constant"); 7983 } 7984 7985 void BytecodeEmitter::assertSelfHostedUnsafeSetReservedSlot( 7986 ListNode* argsList) { 7987 MOZ_ASSERT(argsList->count() == 3); 7988 7989 ParseNode* objNode = argsList->head(); 7990 ParseNode* slotNode = objNode->pn_next; 7991 7992 // Ensure that the slot argument is fixed, this is required by the JITs. 7993 MOZ_ASSERT(slotNode->isKind(ParseNodeKind::NumberExpr), 7994 "slot argument must be a constant"); 7995 } 7996 #endif 7997 7998 /* A version of emitCalleeAndThis for the optional cases: 7999 * * a?.() 8000 * * a?.b() 8001 * * a?.["b"]() 8002 * * (a?.b)() 8003 * * a?.#b() 8004 * 8005 * See emitCallOrNew and emitOptionalCall for more context. 8006 */ 8007 bool BytecodeEmitter::emitOptionalCalleeAndThis(ParseNode* callee, 8008 CallNode* call, 8009 CallOrNewEmitter& cone, 8010 OptionalEmitter& oe) { 8011 AutoCheckRecursionLimit recursion(fc); 8012 if (!recursion.check(fc)) { 8013 return false; 8014 } 8015 8016 switch (ParseNodeKind kind = callee->getKind()) { 8017 case ParseNodeKind::Name: { 8018 auto name = callee->as<NameNode>().name(); 8019 if (!cone.emitNameCallee(name)) { 8020 // [stack] CALLEE THIS 8021 return false; 8022 } 8023 break; 8024 } 8025 8026 case ParseNodeKind::OptionalDotExpr: { 8027 MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting); 8028 OptionalPropertyAccess* prop = &callee->as<OptionalPropertyAccess>(); 8029 bool isSuper = false; 8030 8031 PropOpEmitter& poe = cone.prepareForPropCallee(isSuper); 8032 if (!emitOptionalDotExpression(prop, poe, isSuper, oe)) { 8033 // [stack] CALLEE THIS 8034 return false; 8035 } 8036 break; 8037 } 8038 case ParseNodeKind::ArgumentsLength: 8039 case ParseNodeKind::DotExpr: { 8040 MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting); 8041 PropertyAccess* prop = &callee->as<PropertyAccess>(); 8042 bool isSuper = prop->isSuper(); 8043 8044 PropOpEmitter& poe = cone.prepareForPropCallee(isSuper); 8045 if (!emitOptionalDotExpression(prop, poe, isSuper, oe)) { 8046 // [stack] CALLEE THIS 8047 return false; 8048 } 8049 break; 8050 } 8051 8052 case ParseNodeKind::OptionalElemExpr: { 8053 OptionalPropertyByValue* elem = &callee->as<OptionalPropertyByValue>(); 8054 bool isSuper = false; 8055 MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName)); 8056 ElemOpEmitter& eoe = cone.prepareForElemCallee(isSuper); 8057 if (!emitOptionalElemExpression(elem, eoe, isSuper, oe)) { 8058 // [stack] CALLEE THIS 8059 return false; 8060 } 8061 break; 8062 } 8063 case ParseNodeKind::ElemExpr: { 8064 PropertyByValue* elem = &callee->as<PropertyByValue>(); 8065 bool isSuper = elem->isSuper(); 8066 MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName)); 8067 ElemOpEmitter& eoe = cone.prepareForElemCallee(isSuper); 8068 if (!emitOptionalElemExpression(elem, eoe, isSuper, oe)) { 8069 // [stack] CALLEE THIS 8070 return false; 8071 } 8072 break; 8073 } 8074 8075 case ParseNodeKind::PrivateMemberExpr: 8076 case ParseNodeKind::OptionalPrivateMemberExpr: { 8077 PrivateMemberAccessBase* privateExpr = 8078 &callee->as<PrivateMemberAccessBase>(); 8079 PrivateOpEmitter& xoe = 8080 cone.prepareForPrivateCallee(privateExpr->privateName().name()); 8081 if (!emitOptionalPrivateExpression(privateExpr, xoe, oe)) { 8082 // [stack] CALLEE THIS 8083 return false; 8084 } 8085 break; 8086 } 8087 8088 case ParseNodeKind::Function: 8089 if (!cone.prepareForFunctionCallee()) { 8090 return false; 8091 } 8092 if (!emitOptionalTree(callee, oe)) { 8093 // [stack] CALLEE 8094 return false; 8095 } 8096 break; 8097 8098 case ParseNodeKind::OptionalChain: { 8099 return emitCalleeAndThisForOptionalChain(&callee->as<UnaryNode>(), call, 8100 cone); 8101 } 8102 8103 default: 8104 MOZ_RELEASE_ASSERT(kind != ParseNodeKind::SuperBase); 8105 8106 if (!cone.prepareForOtherCallee()) { 8107 return false; 8108 } 8109 if (!emitOptionalTree(callee, oe)) { 8110 // [stack] CALLEE 8111 return false; 8112 } 8113 break; 8114 } 8115 8116 if (!cone.emitThis()) { 8117 // [stack] CALLEE THIS 8118 return false; 8119 } 8120 8121 return true; 8122 } 8123 8124 bool BytecodeEmitter::emitCalleeAndThis(ParseNode* callee, CallNode* maybeCall, 8125 CallOrNewEmitter& cone) { 8126 MOZ_ASSERT_IF(maybeCall, maybeCall->callee() == callee); 8127 8128 switch (callee->getKind()) { 8129 case ParseNodeKind::Name: { 8130 auto name = callee->as<NameNode>().name(); 8131 if (!cone.emitNameCallee(name)) { 8132 // [stack] CALLEE THIS? 8133 return false; 8134 } 8135 break; 8136 } 8137 case ParseNodeKind::ArgumentsLength: 8138 case ParseNodeKind::DotExpr: { 8139 MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting); 8140 PropertyAccess* prop = &callee->as<PropertyAccess>(); 8141 bool isSuper = prop->isSuper(); 8142 8143 PropOpEmitter& poe = cone.prepareForPropCallee(isSuper); 8144 if (!poe.prepareForObj()) { 8145 return false; 8146 } 8147 if (isSuper) { 8148 UnaryNode* base = &prop->expression().as<UnaryNode>(); 8149 if (!emitGetThisForSuperBase(base)) { 8150 // [stack] THIS 8151 return false; 8152 } 8153 } else { 8154 if (!emitPropLHS(prop)) { 8155 // [stack] OBJ 8156 return false; 8157 } 8158 } 8159 if (!poe.emitGet(prop->key().atom())) { 8160 // [stack] CALLEE THIS? 8161 return false; 8162 } 8163 8164 break; 8165 } 8166 case ParseNodeKind::ElemExpr: { 8167 MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting); 8168 PropertyByValue* elem = &callee->as<PropertyByValue>(); 8169 bool isSuper = elem->isSuper(); 8170 MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName)); 8171 ElemOpEmitter& eoe = cone.prepareForElemCallee(isSuper); 8172 if (!emitElemObjAndKey(elem, eoe)) { 8173 // [stack] # if Super 8174 // [stack] THIS? THIS KEY 8175 // [stack] # otherwise 8176 // [stack] OBJ? OBJ KEY 8177 return false; 8178 } 8179 if (!eoe.emitGet()) { 8180 // [stack] CALLEE THIS? 8181 return false; 8182 } 8183 8184 break; 8185 } 8186 case ParseNodeKind::PrivateMemberExpr: { 8187 MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting); 8188 PrivateMemberAccessBase* privateExpr = 8189 &callee->as<PrivateMemberAccessBase>(); 8190 PrivateOpEmitter& xoe = 8191 cone.prepareForPrivateCallee(privateExpr->privateName().name()); 8192 if (!emitTree(&privateExpr->expression())) { 8193 // [stack] OBJ 8194 return false; 8195 } 8196 if (!xoe.emitReference()) { 8197 // [stack] OBJ NAME 8198 return false; 8199 } 8200 if (!xoe.emitGetForCallOrNew()) { 8201 // [stack] CALLEE THIS 8202 return false; 8203 } 8204 8205 break; 8206 } 8207 case ParseNodeKind::Function: 8208 if (!cone.prepareForFunctionCallee()) { 8209 return false; 8210 } 8211 if (!emitTree(callee)) { 8212 // [stack] CALLEE 8213 return false; 8214 } 8215 break; 8216 case ParseNodeKind::SuperBase: 8217 MOZ_ASSERT(maybeCall); 8218 MOZ_ASSERT(maybeCall->isKind(ParseNodeKind::SuperCallExpr)); 8219 MOZ_ASSERT(callee->isKind(ParseNodeKind::SuperBase)); 8220 if (!cone.emitSuperCallee()) { 8221 // [stack] CALLEE IsConstructing 8222 return false; 8223 } 8224 break; 8225 case ParseNodeKind::OptionalChain: { 8226 MOZ_ASSERT(maybeCall); 8227 return emitCalleeAndThisForOptionalChain(&callee->as<UnaryNode>(), 8228 maybeCall, cone); 8229 } 8230 default: 8231 if (!cone.prepareForOtherCallee()) { 8232 return false; 8233 } 8234 if (!emitTree(callee)) { 8235 return false; 8236 } 8237 break; 8238 } 8239 8240 if (!cone.emitThis()) { 8241 // [stack] CALLEE THIS 8242 return false; 8243 } 8244 8245 return true; 8246 } 8247 8248 ParseNode* BytecodeEmitter::getCoordNode(ParseNode* callNode, 8249 ParseNode* calleeNode, JSOp op, 8250 ListNode* argsList) const { 8251 ParseNode* coordNode = callNode; 8252 if (op == JSOp::Call || op == JSOp::SpreadCall) { 8253 // Default to using the location of the `(` itself. 8254 // obj[expr]() // expression 8255 // ^ // column coord 8256 coordNode = argsList; 8257 8258 switch (calleeNode->getKind()) { 8259 case ParseNodeKind::ArgumentsLength: 8260 case ParseNodeKind::DotExpr: 8261 // Use the position of a property access identifier. 8262 // 8263 // obj().aprop() // expression 8264 // ^ // column coord 8265 // 8266 // Note: Because of the constant folding logic in FoldElement, 8267 // this case also applies for constant string properties. 8268 // 8269 // obj()['aprop']() // expression 8270 // ^ // column coord 8271 coordNode = &calleeNode->as<PropertyAccess>().key(); 8272 break; 8273 case ParseNodeKind::Name: { 8274 // Use the start of callee name unless it is at a separator 8275 // or has no args. 8276 // 8277 // 2 + obj() // expression 8278 // ^ // column coord 8279 // 8280 if (argsList->empty() || 8281 !bytecodeSection().atSeparator(calleeNode->pn_pos.begin)) { 8282 // Use the start of callee names. 8283 coordNode = calleeNode; 8284 } 8285 break; 8286 } 8287 8288 default: 8289 break; 8290 } 8291 } 8292 return coordNode; 8293 } 8294 8295 bool BytecodeEmitter::emitArguments(ListNode* argsList, bool isCall, 8296 bool isSpread, CallOrNewEmitter& cone) { 8297 uint32_t argc = argsList->count(); 8298 if (argc >= ARGC_LIMIT) { 8299 reportError(argsList, 8300 isCall ? JSMSG_TOO_MANY_FUN_ARGS : JSMSG_TOO_MANY_CON_ARGS); 8301 return false; 8302 } 8303 if (!isSpread) { 8304 if (!cone.prepareForNonSpreadArguments()) { 8305 // [stack] CALLEE THIS 8306 return false; 8307 } 8308 for (ParseNode* arg : argsList->contents()) { 8309 if (!updateSourceCoordNotesIfNonLiteral(arg)) { 8310 return false; 8311 } 8312 if (!emitTree(arg)) { 8313 // [stack] CALLEE THIS ARG* 8314 return false; 8315 } 8316 } 8317 } else if (cone.wantSpreadOperand()) { 8318 auto* spreadNode = &argsList->head()->as<UnaryNode>(); 8319 if (!updateSourceCoordNotesIfNonLiteral(spreadNode->kid())) { 8320 return false; 8321 } 8322 if (!emitTree(spreadNode->kid())) { 8323 // [stack] CALLEE THIS ARG0 8324 return false; 8325 } 8326 8327 if (!cone.emitSpreadArgumentsTest()) { 8328 // [stack] CALLEE THIS ARG0 8329 return false; 8330 } 8331 8332 if (cone.wantSpreadIteration()) { 8333 if (!emitSpreadIntoArray(spreadNode)) { 8334 // [stack] CALLEE THIS ARR 8335 return false; 8336 } 8337 } 8338 8339 if (!cone.emitSpreadArgumentsTestEnd()) { 8340 // [stack] CALLEE THIS ARR 8341 return false; 8342 } 8343 } else { 8344 if (!cone.prepareForSpreadArguments()) { 8345 // [stack] CALLEE THIS 8346 return false; 8347 } 8348 if (!emitArray(argsList)) { 8349 // [stack] CALLEE THIS ARR 8350 return false; 8351 } 8352 } 8353 8354 return true; 8355 } 8356 8357 bool BytecodeEmitter::emitOptionalCall(CallNode* callNode, OptionalEmitter& oe, 8358 ValueUsage valueUsage) { 8359 /* 8360 * A modified version of emitCallOrNew that handles optional calls. 8361 * 8362 * These include the following: 8363 * a?.() 8364 * a.b?.() 8365 * a.["b"]?.() 8366 * (a?.b)?.() 8367 * 8368 * See CallOrNewEmitter for more context. 8369 */ 8370 ParseNode* calleeNode = callNode->callee(); 8371 ListNode* argsList = callNode->args(); 8372 bool isSpread = IsSpreadOp(callNode->callOp()); 8373 JSOp op = callNode->callOp(); 8374 uint32_t argc = argsList->count(); 8375 bool isOptimizableSpread = isSpread && argc == 1; 8376 8377 CallOrNewEmitter cone(this, op, 8378 isOptimizableSpread 8379 ? CallOrNewEmitter::ArgumentsKind::SingleSpread 8380 : CallOrNewEmitter::ArgumentsKind::Other, 8381 valueUsage); 8382 8383 ParseNode* coordNode = getCoordNode(callNode, calleeNode, op, argsList); 8384 8385 if (!emitOptionalCalleeAndThis(calleeNode, callNode, cone, oe)) { 8386 // [stack] CALLEE THIS 8387 return false; 8388 } 8389 8390 if (callNode->isKind(ParseNodeKind::OptionalCallExpr)) { 8391 if (!oe.emitJumpShortCircuitForCall()) { 8392 // [stack] CALLEE THIS 8393 return false; 8394 } 8395 } 8396 8397 if (!emitArguments(argsList, /* isCall = */ true, isSpread, cone)) { 8398 // [stack] CALLEE THIS ARGS... 8399 return false; 8400 } 8401 8402 if (!cone.emitEnd(argc, coordNode->pn_pos.begin)) { 8403 // [stack] RVAL 8404 return false; 8405 } 8406 8407 return true; 8408 } 8409 8410 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT 8411 bool BytecodeEmitter::emitSelfHostedDisposeResources(CallNode* callNode, 8412 DisposalKind kind) { 8413 ListNode* argsList = callNode->args(); 8414 MOZ_ASSERT(argsList->count() == 2); 8415 8416 ParseNode* resourcesNode = argsList->head(); 8417 ParseNode* countNode = resourcesNode->pn_next; 8418 8419 DisposalEmitter de(this, bool(kind)); 8420 8421 if (!emit1(JSOp::False)) { 8422 // [stack] THROWING 8423 return false; 8424 } 8425 8426 if (!emit1(JSOp::Undefined)) { 8427 // [stack] THROWING UNDEF 8428 return false; 8429 } 8430 8431 if (!de.prepareForDisposeCapability()) { 8432 // [stack] RVAL? NEEDS-AWAIT? HAS-AWAITED? THROWING UNDEF 8433 return false; 8434 } 8435 8436 if (!emitTree(resourcesNode)) { 8437 // [stack] RVAL? NEEDS-AWAIT? HAS-AWAITED? THROWING UNDEF RESOURCES 8438 return false; 8439 } 8440 8441 if (!emitTree(countNode)) { 8442 // [stack] RVAL? NEEDS-AWAIT? HAS-AWAITED? THROWING UNDEF RESOURCES COUNT 8443 return false; 8444 } 8445 8446 if (!de.emitEnd(*innermostEmitterScope())) { 8447 // [stack] EXC THROWING 8448 return false; 8449 } 8450 8451 // [stack] EXC THROWING 8452 8453 InternalIfEmitter ifThrow(this); 8454 8455 if (!ifThrow.emitThenElse()) { 8456 // [stack] EXC 8457 return false; 8458 } 8459 8460 if (!emit1(JSOp::Throw)) { 8461 // [stack] 8462 return false; 8463 } 8464 8465 if (!ifThrow.emitElse()) { 8466 // [stack] EXC 8467 return false; 8468 } 8469 8470 if (!emit1(JSOp::Pop)) { 8471 // [stack] 8472 return false; 8473 } 8474 8475 if (!ifThrow.emitEnd()) { 8476 // [stack] 8477 return false; 8478 } 8479 8480 if (!emit1(JSOp::Undefined)) { 8481 // [stack] RVAL 8482 return false; 8483 } 8484 8485 return true; 8486 } 8487 #endif 8488 8489 bool BytecodeEmitter::emitCallOrNew(CallNode* callNode, ValueUsage valueUsage) { 8490 /* 8491 * Emit callable invocation or operator new (constructor call) code. 8492 * First, emit code for the left operand to evaluate the callable or 8493 * constructable object expression. 8494 * 8495 * Then (or in a call case that has no explicit reference-base 8496 * object) we emit JSOp::Undefined to produce the undefined |this| 8497 * value required for calls (which non-strict mode functions 8498 * will box into the global object). 8499 */ 8500 bool isCall = callNode->isKind(ParseNodeKind::CallExpr) || 8501 callNode->isKind(ParseNodeKind::TaggedTemplateExpr); 8502 ParseNode* calleeNode = callNode->callee(); 8503 ListNode* argsList = callNode->args(); 8504 JSOp op = callNode->callOp(); 8505 8506 if (calleeNode->isKind(ParseNodeKind::Name) && 8507 emitterMode == BytecodeEmitter::SelfHosting && op == JSOp::Call) { 8508 // Calls to "forceInterpreter", "callFunction", 8509 // "callContentFunction", or "resumeGenerator" in self-hosted 8510 // code generate inline bytecode. 8511 // 8512 // NOTE: The list of special instruction names has to be kept in sync with 8513 // "js/src/builtin/.eslintrc.js". 8514 auto calleeName = calleeNode->as<NameNode>().name(); 8515 if (calleeName == TaggedParserAtomIndex::WellKnown::callFunction()) { 8516 return emitSelfHostedCallFunction(callNode, JSOp::Call); 8517 } 8518 if (calleeName == TaggedParserAtomIndex::WellKnown::callContentFunction()) { 8519 return emitSelfHostedCallFunction(callNode, JSOp::CallContent); 8520 } 8521 if (calleeName == 8522 TaggedParserAtomIndex::WellKnown::constructContentFunction()) { 8523 return emitSelfHostedCallFunction(callNode, JSOp::NewContent); 8524 } 8525 if (calleeName == TaggedParserAtomIndex::WellKnown::resumeGenerator()) { 8526 return emitSelfHostedResumeGenerator(callNode); 8527 } 8528 if (calleeName == TaggedParserAtomIndex::WellKnown::forceInterpreter()) { 8529 return emitSelfHostedForceInterpreter(); 8530 } 8531 if (calleeName == TaggedParserAtomIndex::WellKnown::allowContentIter()) { 8532 return emitSelfHostedAllowContentIter(callNode); 8533 } 8534 if (calleeName == 8535 TaggedParserAtomIndex::WellKnown::allowContentIterWith()) { 8536 return emitSelfHostedAllowContentIterWith(callNode); 8537 } 8538 if (calleeName == 8539 TaggedParserAtomIndex::WellKnown::allowContentIterWithNext()) { 8540 return emitSelfHostedAllowContentIterWithNext(callNode); 8541 } 8542 if (calleeName == TaggedParserAtomIndex::WellKnown::DefineDataProperty() && 8543 argsList->count() == 3) { 8544 return emitSelfHostedDefineDataProperty(callNode); 8545 } 8546 if (calleeName == TaggedParserAtomIndex::WellKnown::hasOwn()) { 8547 return emitSelfHostedHasOwn(callNode); 8548 } 8549 if (calleeName == TaggedParserAtomIndex::WellKnown::getPropertySuper()) { 8550 return emitSelfHostedGetPropertySuper(callNode); 8551 } 8552 if (calleeName == TaggedParserAtomIndex::WellKnown::ToNumeric()) { 8553 return emitSelfHostedToNumeric(callNode); 8554 } 8555 if (calleeName == TaggedParserAtomIndex::WellKnown::ToString()) { 8556 return emitSelfHostedToString(callNode); 8557 } 8558 if (calleeName == 8559 TaggedParserAtomIndex::WellKnown::GetBuiltinConstructor()) { 8560 return emitSelfHostedGetBuiltinConstructor(callNode); 8561 } 8562 if (calleeName == TaggedParserAtomIndex::WellKnown::GetBuiltinPrototype()) { 8563 return emitSelfHostedGetBuiltinPrototype(callNode); 8564 } 8565 if (calleeName == TaggedParserAtomIndex::WellKnown::GetBuiltinSymbol()) { 8566 return emitSelfHostedGetBuiltinSymbol(callNode); 8567 } 8568 if (calleeName == TaggedParserAtomIndex::WellKnown::ArgumentsLength()) { 8569 return emitSelfHostedArgumentsLength(callNode); 8570 } 8571 if (calleeName == TaggedParserAtomIndex::WellKnown::GetArgument()) { 8572 return emitSelfHostedGetArgument(callNode); 8573 } 8574 if (calleeName == 8575 TaggedParserAtomIndex::WellKnown::SetIsInlinableLargeFunction()) { 8576 return emitSelfHostedSetIsInlinableLargeFunction(callNode); 8577 } 8578 if (calleeName == TaggedParserAtomIndex::WellKnown::SetCanonicalName()) { 8579 return emitSelfHostedSetCanonicalName(callNode); 8580 } 8581 if (calleeName == TaggedParserAtomIndex::WellKnown::IsNullOrUndefined()) { 8582 return emitSelfHostedIsNullOrUndefined(callNode); 8583 } 8584 if (calleeName == TaggedParserAtomIndex::WellKnown::IteratorClose()) { 8585 return emitSelfHostedIteratorClose(callNode); 8586 } 8587 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT 8588 if (calleeName == 8589 TaggedParserAtomIndex::WellKnown::DisposeResourcesAsync()) { 8590 return emitSelfHostedDisposeResources(callNode, DisposalKind::Async); 8591 } 8592 if (calleeName == 8593 TaggedParserAtomIndex::WellKnown::DisposeResourcesSync()) { 8594 return emitSelfHostedDisposeResources(callNode, DisposalKind::Sync); 8595 } 8596 #endif 8597 #ifdef DEBUG 8598 if (calleeName == 8599 TaggedParserAtomIndex::WellKnown::UnsafeGetReservedSlot() || 8600 calleeName == TaggedParserAtomIndex::WellKnown:: 8601 UnsafeGetObjectFromReservedSlot() || 8602 calleeName == TaggedParserAtomIndex::WellKnown:: 8603 UnsafeGetInt32FromReservedSlot() || 8604 calleeName == TaggedParserAtomIndex::WellKnown:: 8605 UnsafeGetStringFromReservedSlot()) { 8606 // Make sure that this call is correct, but don't emit any special code. 8607 assertSelfHostedUnsafeGetReservedSlot(argsList); 8608 } 8609 if (calleeName == 8610 TaggedParserAtomIndex::WellKnown::UnsafeSetReservedSlot()) { 8611 // Make sure that this call is correct, but don't emit any special code. 8612 assertSelfHostedUnsafeSetReservedSlot(argsList); 8613 } 8614 #endif 8615 // Fall through 8616 } 8617 8618 uint32_t argc = argsList->count(); 8619 bool isSpread = IsSpreadOp(op); 8620 bool isOptimizableSpread = isSpread && argc == 1; 8621 bool isDefaultDerivedClassConstructor = 8622 sc->isFunctionBox() && sc->asFunctionBox()->isDerivedClassConstructor() && 8623 sc->asFunctionBox()->isSyntheticFunction(); 8624 MOZ_ASSERT_IF(isDefaultDerivedClassConstructor, isOptimizableSpread); 8625 CallOrNewEmitter cone( 8626 this, op, 8627 isOptimizableSpread 8628 ? isDefaultDerivedClassConstructor 8629 ? CallOrNewEmitter::ArgumentsKind::PassthroughRest 8630 : CallOrNewEmitter::ArgumentsKind::SingleSpread 8631 : CallOrNewEmitter::ArgumentsKind::Other, 8632 valueUsage); 8633 8634 if (!emitCalleeAndThis(calleeNode, callNode, cone)) { 8635 // [stack] CALLEE THIS 8636 return false; 8637 } 8638 if (!emitArguments(argsList, isCall, isSpread, cone)) { 8639 // [stack] CALLEE THIS ARGS... 8640 return false; 8641 } 8642 8643 // Push new.target for construct calls. 8644 if (IsConstructOp(op)) { 8645 if (op == JSOp::SuperCall || op == JSOp::SpreadSuperCall) { 8646 if (!emitNewTarget(callNode)) { 8647 // [stack] CALLEE THIS ARGS.. NEW.TARGET 8648 return false; 8649 } 8650 } else { 8651 // Repush the callee as new.target 8652 uint32_t effectiveArgc = isSpread ? 1 : argc; 8653 if (!emitDupAt(effectiveArgc + 1)) { 8654 // [stack] CALLEE THIS ARGS.. CALLEE 8655 return false; 8656 } 8657 } 8658 } 8659 8660 ParseNode* coordNode = getCoordNode(callNode, calleeNode, op, argsList); 8661 8662 if (!cone.emitEnd(argc, coordNode->pn_pos.begin)) { 8663 // [stack] RVAL 8664 return false; 8665 } 8666 8667 return true; 8668 } 8669 8670 // This list must be kept in the same order in several places: 8671 // - The binary operators in ParseNode.h , 8672 // - the binary operators in TokenKind.h 8673 // - the precedence list in Parser.cpp 8674 static const JSOp ParseNodeKindToJSOp[] = { 8675 // Some binary ops require special code generation (PrivateIn); 8676 // these should not use BinaryOpParseNodeKindToJSOp. This table fills those 8677 // slots with Nops to make the rest of the table lookup work. 8678 JSOp::Coalesce, JSOp::Or, JSOp::And, JSOp::BitOr, JSOp::BitXor, 8679 JSOp::BitAnd, JSOp::StrictEq, JSOp::Eq, JSOp::StrictNe, JSOp::Ne, 8680 JSOp::Lt, JSOp::Le, JSOp::Gt, JSOp::Ge, JSOp::Instanceof, 8681 JSOp::In, JSOp::Nop, JSOp::Lsh, JSOp::Rsh, JSOp::Ursh, 8682 JSOp::Add, JSOp::Sub, JSOp::Mul, JSOp::Div, JSOp::Mod, 8683 JSOp::Pow}; 8684 8685 static inline JSOp BinaryOpParseNodeKindToJSOp(ParseNodeKind pnk) { 8686 MOZ_ASSERT(pnk >= ParseNodeKind::BinOpFirst); 8687 MOZ_ASSERT(pnk <= ParseNodeKind::BinOpLast); 8688 int parseNodeFirst = size_t(ParseNodeKind::BinOpFirst); 8689 #ifdef DEBUG 8690 int jsopArraySize = std::size(ParseNodeKindToJSOp); 8691 int parseNodeKindListSize = 8692 size_t(ParseNodeKind::BinOpLast) - parseNodeFirst + 1; 8693 MOZ_ASSERT(jsopArraySize == parseNodeKindListSize); 8694 // Ensure we don't use this to find an op for a parse node 8695 // requiring special emission rules. 8696 MOZ_ASSERT(ParseNodeKindToJSOp[size_t(pnk) - parseNodeFirst] != JSOp::Nop); 8697 #endif 8698 return ParseNodeKindToJSOp[size_t(pnk) - parseNodeFirst]; 8699 } 8700 8701 bool BytecodeEmitter::emitRightAssociative(ListNode* node) { 8702 // ** is the only right-associative operator. 8703 MOZ_ASSERT(node->isKind(ParseNodeKind::PowExpr)); 8704 8705 // Right-associative operator chain. 8706 for (ParseNode* subexpr : node->contents()) { 8707 if (!updateSourceCoordNotesIfNonLiteral(subexpr)) { 8708 return false; 8709 } 8710 if (!emitTree(subexpr)) { 8711 return false; 8712 } 8713 } 8714 for (uint32_t i = 0; i < node->count() - 1; i++) { 8715 if (!emit1(JSOp::Pow)) { 8716 return false; 8717 } 8718 } 8719 return true; 8720 } 8721 8722 Maybe<ConstantCompareOperand> 8723 BytecodeEmitter::parseNodeToConstantCompareOperand(ParseNode* constant) { 8724 switch (constant->getKind()) { 8725 case ParseNodeKind::NumberExpr: { 8726 double d = constant->as<NumericLiteral>().value(); 8727 int32_t ival; 8728 if (NumberEqualsInt32(d, &ival)) { 8729 if (ConstantCompareOperand::CanEncodeInt32ValueAsOperand(ival)) { 8730 return Some(ConstantCompareOperand(int8_t(ival))); 8731 } 8732 } 8733 return Nothing(); 8734 } 8735 case ParseNodeKind::TrueExpr: 8736 case ParseNodeKind::FalseExpr: 8737 return Some( 8738 ConstantCompareOperand(constant->isKind(ParseNodeKind::TrueExpr))); 8739 case ParseNodeKind::NullExpr: 8740 return Some( 8741 ConstantCompareOperand(ConstantCompareOperand::EncodedType::Null)); 8742 case ParseNodeKind::RawUndefinedExpr: 8743 return Some(ConstantCompareOperand( 8744 ConstantCompareOperand::EncodedType::Undefined)); 8745 case ParseNodeKind::Name: { 8746 MOZ_ASSERT(constant->as<NameNode>().name() == 8747 TaggedParserAtomIndex::WellKnown::undefined()); 8748 NameLocation loc = lookupName(constant->as<NameNode>().name()); 8749 switch (loc.kind()) { 8750 case NameLocation::Kind::Global: 8751 if (!sc->hasNonSyntacticScope()) { 8752 return Some(ConstantCompareOperand( 8753 ConstantCompareOperand::EncodedType::Undefined)); 8754 } 8755 return Nothing(); 8756 case NameLocation::Kind::Intrinsic: 8757 return Some(ConstantCompareOperand( 8758 ConstantCompareOperand::EncodedType::Undefined)); 8759 default: 8760 return Nothing(); 8761 } 8762 } 8763 default: 8764 return Nothing(); 8765 } 8766 } 8767 8768 bool BytecodeEmitter::tryEmitConstantEq(ListNode* node, JSOp op, 8769 bool* emitted) { 8770 // We ignore long chains of === or !==, we 8771 // only optimise cases a === b or a !== b 8772 if (node->count() != 2) { 8773 *emitted = false; 8774 return true; 8775 } 8776 8777 JSOp constantOp; 8778 switch (op) { 8779 case JSOp::StrictEq: 8780 constantOp = JSOp::StrictConstantEq; 8781 break; 8782 case JSOp::StrictNe: 8783 constantOp = JSOp::StrictConstantNe; 8784 break; 8785 default: 8786 *emitted = false; 8787 return true; 8788 } 8789 8790 ParseNode* left = node->head(); 8791 ParseNode* right = node->head()->pn_next; 8792 8793 ParseNode* expressionNode; 8794 ParseNode* constantNode; 8795 if (left->isConstant() || left->isUndefinedLiteral()) { 8796 expressionNode = right; 8797 constantNode = left; 8798 } else if (right->isConstant() || right->isUndefinedLiteral()) { 8799 expressionNode = left; 8800 constantNode = right; 8801 } else { 8802 *emitted = false; 8803 return true; 8804 } 8805 8806 Maybe<ConstantCompareOperand> operand = 8807 parseNodeToConstantCompareOperand(constantNode); 8808 if (operand.isNothing()) { 8809 *emitted = false; 8810 return true; 8811 } 8812 8813 if (!emitTree(expressionNode)) { 8814 return false; 8815 } 8816 8817 if (!emitUint16Operand(constantOp, operand->rawValue())) { 8818 return false; 8819 } 8820 8821 *emitted = true; 8822 return true; 8823 } 8824 8825 bool BytecodeEmitter::emitLeftAssociative(ListNode* node) { 8826 JSOp op = BinaryOpParseNodeKindToJSOp(node->getKind()); 8827 bool constantEqEmitted = false; 8828 if (!tryEmitConstantEq(node, op, &constantEqEmitted)) { 8829 return false; 8830 } 8831 if (constantEqEmitted) { 8832 return true; 8833 } 8834 // Left-associative operator chain. 8835 if (!emitTree(node->head())) { 8836 return false; 8837 } 8838 ParseNode* nextExpr = node->head()->pn_next; 8839 do { 8840 if (!updateSourceCoordNotesIfNonLiteral(nextExpr)) { 8841 return false; 8842 } 8843 if (!emitTree(nextExpr)) { 8844 return false; 8845 } 8846 if (!emit1(op)) { 8847 return false; 8848 } 8849 } while ((nextExpr = nextExpr->pn_next)); 8850 return true; 8851 } 8852 8853 bool BytecodeEmitter::emitPrivateInExpr(ListNode* node) { 8854 MOZ_ASSERT(node->head()->isKind(ParseNodeKind::PrivateName)); 8855 8856 NameNode& privateNameNode = node->head()->as<NameNode>(); 8857 TaggedParserAtomIndex privateName = privateNameNode.name(); 8858 8859 PrivateOpEmitter xoe(this, PrivateOpEmitter::Kind::ErgonomicBrandCheck, 8860 privateName); 8861 8862 ParseNode* valueNode = node->head()->pn_next; 8863 MOZ_ASSERT(valueNode->pn_next == nullptr); 8864 8865 if (!emitTree(valueNode)) { 8866 // [stack] OBJ 8867 return false; 8868 } 8869 8870 if (!xoe.emitReference()) { 8871 // [stack] OBJ BRAND if private method 8872 // [stack] OBJ NAME if private field or accessor. 8873 return false; 8874 } 8875 8876 if (!xoe.emitBrandCheck()) { 8877 // [stack] OBJ BRAND BOOL if private method 8878 // [stack] OBJ NAME BOOL if private field or accessor. 8879 return false; 8880 } 8881 8882 if (!emitUnpickN(2)) { 8883 // [stack] BOOL OBJ BRAND if private method 8884 // [stack] BOOL OBJ NAME if private field or accessor. 8885 return false; 8886 } 8887 8888 if (!emitPopN(2)) { 8889 // [stack] BOOL 8890 return false; 8891 } 8892 8893 return true; 8894 } 8895 8896 /* 8897 * Special `emitTree` for Optional Chaining case. 8898 * Examples of this are `emitOptionalChain`, `emitDeleteOptionalChain` and 8899 * `emitCalleeAndThisForOptionalChain`. 8900 */ 8901 bool BytecodeEmitter::emitOptionalTree( 8902 ParseNode* pn, OptionalEmitter& oe, 8903 ValueUsage valueUsage /* = ValueUsage::WantValue */) { 8904 AutoCheckRecursionLimit recursion(fc); 8905 if (!recursion.check(fc)) { 8906 return false; 8907 } 8908 ParseNodeKind kind = pn->getKind(); 8909 switch (kind) { 8910 case ParseNodeKind::OptionalDotExpr: { 8911 OptionalPropertyAccess* prop = &pn->as<OptionalPropertyAccess>(); 8912 bool isSuper = false; 8913 PropOpEmitter poe(this, PropOpEmitter::Kind::Get, 8914 PropOpEmitter::ObjKind::Other); 8915 if (!emitOptionalDotExpression(prop, poe, isSuper, oe)) { 8916 return false; 8917 } 8918 break; 8919 } 8920 case ParseNodeKind::ArgumentsLength: 8921 case ParseNodeKind::DotExpr: { 8922 PropertyAccess* prop = &pn->as<PropertyAccess>(); 8923 bool isSuper = prop->isSuper(); 8924 PropOpEmitter poe(this, PropOpEmitter::Kind::Get, 8925 isSuper ? PropOpEmitter::ObjKind::Super 8926 : PropOpEmitter::ObjKind::Other); 8927 if (!emitOptionalDotExpression(prop, poe, isSuper, oe)) { 8928 return false; 8929 } 8930 break; 8931 } 8932 8933 case ParseNodeKind::OptionalElemExpr: { 8934 OptionalPropertyByValue* elem = &pn->as<OptionalPropertyByValue>(); 8935 bool isSuper = false; 8936 MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName)); 8937 ElemOpEmitter eoe(this, ElemOpEmitter::Kind::Get, 8938 ElemOpEmitter::ObjKind::Other); 8939 8940 if (!emitOptionalElemExpression(elem, eoe, isSuper, oe)) { 8941 return false; 8942 } 8943 break; 8944 } 8945 case ParseNodeKind::ElemExpr: { 8946 PropertyByValue* elem = &pn->as<PropertyByValue>(); 8947 bool isSuper = elem->isSuper(); 8948 MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName)); 8949 ElemOpEmitter eoe(this, ElemOpEmitter::Kind::Get, 8950 isSuper ? ElemOpEmitter::ObjKind::Super 8951 : ElemOpEmitter::ObjKind::Other); 8952 8953 if (!emitOptionalElemExpression(elem, eoe, isSuper, oe)) { 8954 return false; 8955 } 8956 break; 8957 } 8958 case ParseNodeKind::PrivateMemberExpr: 8959 case ParseNodeKind::OptionalPrivateMemberExpr: { 8960 PrivateMemberAccessBase* privateExpr = &pn->as<PrivateMemberAccessBase>(); 8961 PrivateOpEmitter xoe(this, PrivateOpEmitter::Kind::Get, 8962 privateExpr->privateName().name()); 8963 if (!emitOptionalPrivateExpression(privateExpr, xoe, oe)) { 8964 return false; 8965 } 8966 break; 8967 } 8968 case ParseNodeKind::CallExpr: 8969 case ParseNodeKind::OptionalCallExpr: 8970 if (!emitOptionalCall(&pn->as<CallNode>(), oe, valueUsage)) { 8971 return false; 8972 } 8973 break; 8974 // List of accepted ParseNodeKinds that might appear only at the beginning 8975 // of an Optional Chain. 8976 // For example, a taggedTemplateExpr node might occur if we have 8977 // `test`?.b, with `test` as the taggedTemplateExpr ParseNode. 8978 default: 8979 #ifdef DEBUG 8980 // https://tc39.es/ecma262/#sec-primary-expression 8981 bool isPrimaryExpression = 8982 kind == ParseNodeKind::ThisExpr || kind == ParseNodeKind::Name || 8983 kind == ParseNodeKind::PrivateName || 8984 kind == ParseNodeKind::NullExpr || kind == ParseNodeKind::TrueExpr || 8985 kind == ParseNodeKind::FalseExpr || 8986 kind == ParseNodeKind::NumberExpr || 8987 kind == ParseNodeKind::BigIntExpr || 8988 kind == ParseNodeKind::StringExpr || 8989 kind == ParseNodeKind::ArrayExpr || 8990 kind == ParseNodeKind::ObjectExpr || 8991 kind == ParseNodeKind::Function || kind == ParseNodeKind::ClassDecl || 8992 kind == ParseNodeKind::RegExpExpr || 8993 kind == ParseNodeKind::TemplateStringExpr || 8994 kind == ParseNodeKind::TemplateStringListExpr || 8995 kind == ParseNodeKind::RawUndefinedExpr || pn->isInParens(); 8996 8997 // https://tc39.es/ecma262/#sec-left-hand-side-expressions 8998 bool isMemberExpression = isPrimaryExpression || 8999 kind == ParseNodeKind::TaggedTemplateExpr || 9000 kind == ParseNodeKind::NewExpr || 9001 kind == ParseNodeKind::NewTargetExpr || 9002 kind == ParseNodeKind::ImportMetaExpr; 9003 9004 bool isCallExpression = kind == ParseNodeKind::SetThis || 9005 kind == ParseNodeKind::CallImportExpr; 9006 9007 MOZ_ASSERT(isMemberExpression || isCallExpression, 9008 "Unknown ParseNodeKind for OptionalChain"); 9009 #endif 9010 return emitTree(pn); 9011 } 9012 return true; 9013 } 9014 9015 // Handle the case of a call made on a OptionalChainParseNode. 9016 // For example `(a?.b)()` and `(a?.b)?.()`. 9017 bool BytecodeEmitter::emitCalleeAndThisForOptionalChain( 9018 UnaryNode* optionalChain, CallNode* callNode, CallOrNewEmitter& cone) { 9019 ParseNode* calleeNode = optionalChain->kid(); 9020 9021 // Create a new OptionalEmitter, in order to emit the right bytecode 9022 // in isolation. 9023 OptionalEmitter oe(this, bytecodeSection().stackDepth()); 9024 9025 if (!emitOptionalCalleeAndThis(calleeNode, callNode, cone, oe)) { 9026 // [stack] CALLEE THIS 9027 return false; 9028 } 9029 9030 // complete the jump if necessary. This will set both the "this" value 9031 // and the "callee" value to undefined, if the callee is undefined. It 9032 // does not matter much what the this value is, the function call will 9033 // fail if it is not optional, and be set to undefined otherwise. 9034 if (!oe.emitOptionalJumpTarget(JSOp::Undefined, 9035 OptionalEmitter::Kind::Reference)) { 9036 // [stack] # If shortcircuit 9037 // [stack] UNDEFINED UNDEFINED 9038 // [stack] # otherwise 9039 // [stack] CALLEE THIS 9040 return false; 9041 } 9042 return true; 9043 } 9044 9045 bool BytecodeEmitter::emitOptionalChain(UnaryNode* optionalChain, 9046 ValueUsage valueUsage) { 9047 ParseNode* expr = optionalChain->kid(); 9048 9049 OptionalEmitter oe(this, bytecodeSection().stackDepth()); 9050 9051 if (!emitOptionalTree(expr, oe, valueUsage)) { 9052 // [stack] VAL 9053 return false; 9054 } 9055 9056 if (!oe.emitOptionalJumpTarget(JSOp::Undefined)) { 9057 // [stack] # If shortcircuit 9058 // [stack] UNDEFINED 9059 // [stack] # otherwise 9060 // [stack] VAL 9061 return false; 9062 } 9063 9064 return true; 9065 } 9066 9067 bool BytecodeEmitter::emitOptionalDotExpression(PropertyAccessBase* prop, 9068 PropOpEmitter& poe, 9069 bool isSuper, 9070 OptionalEmitter& oe) { 9071 if (!poe.prepareForObj()) { 9072 // [stack] 9073 return false; 9074 } 9075 9076 if (isSuper) { 9077 UnaryNode* base = &prop->expression().as<UnaryNode>(); 9078 if (!emitGetThisForSuperBase(base)) { 9079 // [stack] OBJ 9080 return false; 9081 } 9082 } else { 9083 if (!emitOptionalTree(&prop->expression(), oe)) { 9084 // [stack] OBJ 9085 return false; 9086 } 9087 } 9088 9089 if (prop->isKind(ParseNodeKind::OptionalDotExpr)) { 9090 MOZ_ASSERT(!isSuper); 9091 if (!oe.emitJumpShortCircuit()) { 9092 // [stack] # if Jump 9093 // [stack] UNDEFINED-OR-NULL 9094 // [stack] # otherwise 9095 // [stack] OBJ 9096 return false; 9097 } 9098 } 9099 9100 if (!poe.emitGet(prop->key().atom())) { 9101 // [stack] PROP 9102 return false; 9103 } 9104 9105 return true; 9106 } 9107 9108 bool BytecodeEmitter::emitOptionalElemExpression(PropertyByValueBase* elem, 9109 ElemOpEmitter& eoe, 9110 bool isSuper, 9111 OptionalEmitter& oe) { 9112 if (!eoe.prepareForObj()) { 9113 // [stack] 9114 return false; 9115 } 9116 9117 if (isSuper) { 9118 UnaryNode* base = &elem->expression().as<UnaryNode>(); 9119 if (!emitGetThisForSuperBase(base)) { 9120 // [stack] OBJ 9121 return false; 9122 } 9123 } else { 9124 if (!emitOptionalTree(&elem->expression(), oe)) { 9125 // [stack] OBJ 9126 return false; 9127 } 9128 } 9129 9130 if (elem->isKind(ParseNodeKind::OptionalElemExpr)) { 9131 MOZ_ASSERT(!isSuper); 9132 if (!oe.emitJumpShortCircuit()) { 9133 // [stack] # if Jump 9134 // [stack] UNDEFINED-OR-NULL 9135 // [stack] # otherwise 9136 // [stack] OBJ 9137 return false; 9138 } 9139 } 9140 9141 if (!eoe.prepareForKey()) { 9142 // [stack] OBJ? OBJ 9143 return false; 9144 } 9145 9146 if (!emitTree(&elem->key())) { 9147 // [stack] OBJ? OBJ KEY 9148 return false; 9149 } 9150 9151 if (!eoe.emitGet()) { 9152 // [stack] ELEM 9153 return false; 9154 } 9155 9156 return true; 9157 } 9158 9159 bool BytecodeEmitter::emitOptionalPrivateExpression( 9160 PrivateMemberAccessBase* privateExpr, PrivateOpEmitter& xoe, 9161 OptionalEmitter& oe) { 9162 if (!emitOptionalTree(&privateExpr->expression(), oe)) { 9163 // [stack] OBJ 9164 return false; 9165 } 9166 9167 if (privateExpr->isKind(ParseNodeKind::OptionalPrivateMemberExpr)) { 9168 if (!oe.emitJumpShortCircuit()) { 9169 // [stack] # if Jump 9170 // [stack] UNDEFINED-OR-NULL 9171 // [stack] # otherwise 9172 // [stack] OBJ 9173 return false; 9174 } 9175 } 9176 9177 if (!xoe.emitReference()) { 9178 // [stack] OBJ NAME 9179 return false; 9180 } 9181 if (!xoe.emitGet()) { 9182 // [stack] CALLEE THIS # if call 9183 // [stack] VALUE # otherwise 9184 return false; 9185 } 9186 9187 return true; 9188 } 9189 9190 bool BytecodeEmitter::emitShortCircuit(ListNode* node, ValueUsage valueUsage) { 9191 MOZ_ASSERT(node->isKind(ParseNodeKind::OrExpr) || 9192 node->isKind(ParseNodeKind::CoalesceExpr) || 9193 node->isKind(ParseNodeKind::AndExpr)); 9194 9195 /* 9196 * JSOp::Or converts the operand on the stack to boolean, leaves the original 9197 * value on the stack and jumps if true; otherwise it falls into the next 9198 * bytecode, which pops the left operand and then evaluates the right operand. 9199 * The jump goes around the right operand evaluation. 9200 * 9201 * JSOp::And converts the operand on the stack to boolean and jumps if false; 9202 * otherwise it falls into the right operand's bytecode. 9203 */ 9204 9205 TDZCheckCache tdzCache(this); 9206 9207 JSOp op; 9208 switch (node->getKind()) { 9209 case ParseNodeKind::OrExpr: 9210 op = JSOp::Or; 9211 break; 9212 case ParseNodeKind::CoalesceExpr: 9213 op = JSOp::Coalesce; 9214 break; 9215 case ParseNodeKind::AndExpr: 9216 op = JSOp::And; 9217 break; 9218 default: 9219 MOZ_CRASH("Unexpected ParseNodeKind"); 9220 } 9221 9222 JumpList jump; 9223 9224 // Left-associative operator chain: avoid too much recursion. 9225 // 9226 // Emit all nodes but the last. 9227 for (ParseNode* expr : node->contentsTo(node->last())) { 9228 if (!emitTree(expr)) { 9229 return false; 9230 } 9231 if (!emitJump(op, &jump)) { 9232 return false; 9233 } 9234 if (!emit1(JSOp::Pop)) { 9235 return false; 9236 } 9237 } 9238 9239 // Emit the last node 9240 if (!emitTree(node->last(), valueUsage)) { 9241 return false; 9242 } 9243 9244 if (!emitJumpTargetAndPatch(jump)) { 9245 return false; 9246 } 9247 return true; 9248 } 9249 9250 bool BytecodeEmitter::emitSequenceExpr(ListNode* node, ValueUsage valueUsage) { 9251 for (ParseNode* child : node->contentsTo(node->last())) { 9252 if (!updateSourceCoordNotes(child->pn_pos.begin)) { 9253 return false; 9254 } 9255 if (!emitTree(child, ValueUsage::IgnoreValue)) { 9256 return false; 9257 } 9258 if (!emit1(JSOp::Pop)) { 9259 return false; 9260 } 9261 } 9262 9263 ParseNode* child = node->last(); 9264 if (!updateSourceCoordNotes(child->pn_pos.begin)) { 9265 return false; 9266 } 9267 if (!emitTree(child, valueUsage)) { 9268 return false; 9269 } 9270 return true; 9271 } 9272 9273 // Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See 9274 // the comment on emitSwitch. 9275 MOZ_NEVER_INLINE bool BytecodeEmitter::emitIncOrDec(UnaryNode* incDec, 9276 ValueUsage valueUsage) { 9277 switch (incDec->kid()->getKind()) { 9278 case ParseNodeKind::ArgumentsLength: 9279 case ParseNodeKind::DotExpr: 9280 return emitPropIncDec(incDec, valueUsage); 9281 case ParseNodeKind::ElemExpr: 9282 return emitElemIncDec(incDec, valueUsage); 9283 case ParseNodeKind::PrivateMemberExpr: 9284 return emitPrivateIncDec(incDec, valueUsage); 9285 case ParseNodeKind::CallExpr: 9286 return emitCallIncDec(incDec); 9287 default: 9288 return emitNameIncDec(incDec, valueUsage); 9289 } 9290 } 9291 9292 // Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See 9293 // the comment on emitSwitch. 9294 MOZ_NEVER_INLINE bool BytecodeEmitter::emitLabeledStatement( 9295 const LabeledStatement* labeledStmt) { 9296 auto name = labeledStmt->label(); 9297 LabelEmitter label(this); 9298 9299 label.emitLabel(name); 9300 9301 if (!emitTree(labeledStmt->statement())) { 9302 return false; 9303 } 9304 if (!label.emitEnd()) { 9305 return false; 9306 } 9307 9308 return true; 9309 } 9310 9311 bool BytecodeEmitter::emitConditionalExpression( 9312 ConditionalExpression& conditional, ValueUsage valueUsage) { 9313 CondEmitter cond(this); 9314 if (!cond.emitCond()) { 9315 return false; 9316 } 9317 9318 ParseNode* conditionNode = &conditional.condition(); 9319 auto conditionKind = IfEmitter::ConditionKind::Positive; 9320 if (conditionNode->isKind(ParseNodeKind::NotExpr)) { 9321 conditionNode = conditionNode->as<UnaryNode>().kid(); 9322 conditionKind = IfEmitter::ConditionKind::Negative; 9323 } 9324 9325 // NOTE: NotExpr of conditionNode may be unwrapped, and in that case the 9326 // negation is handled by conditionKind. 9327 if (!emitTree(conditionNode)) { 9328 return false; 9329 } 9330 9331 if (!cond.emitThenElse(conditionKind)) { 9332 return false; 9333 } 9334 9335 if (!emitTree(&conditional.thenExpression(), valueUsage)) { 9336 return false; 9337 } 9338 9339 if (!cond.emitElse()) { 9340 return false; 9341 } 9342 9343 if (!emitTree(&conditional.elseExpression(), valueUsage)) { 9344 return false; 9345 } 9346 9347 if (!cond.emitEnd()) { 9348 return false; 9349 } 9350 MOZ_ASSERT(cond.pushed() == 1); 9351 9352 return true; 9353 } 9354 9355 // Check for an object-literal property list that can be handled by the 9356 // ObjLiteral writer. We ensure that for each `prop: value` pair, the key is a 9357 // constant name or numeric index, there is no accessor specified, and the value 9358 // can be encoded by an ObjLiteral instruction (constant number, string, 9359 // boolean, null/undefined). 9360 void BytecodeEmitter::isPropertyListObjLiteralCompatible( 9361 ListNode* obj, bool* withValues, bool* withoutValues) const { 9362 bool keysOK = true; 9363 bool valuesOK = true; 9364 uint32_t propCount = 0; 9365 9366 for (ParseNode* propdef : obj->contents()) { 9367 if (!propdef->is<BinaryNode>()) { 9368 keysOK = false; 9369 break; 9370 } 9371 propCount++; 9372 9373 BinaryNode* prop = &propdef->as<BinaryNode>(); 9374 ParseNode* key = prop->left(); 9375 ParseNode* value = prop->right(); 9376 9377 // Computed keys not OK (ObjLiteral data stores constant keys). 9378 if (key->isKind(ParseNodeKind::ComputedName)) { 9379 keysOK = false; 9380 break; 9381 } 9382 9383 // BigIntExprs should have been lowered to computed names at parse 9384 // time, and so should be excluded above. 9385 MOZ_ASSERT(!key->isKind(ParseNodeKind::BigIntExpr)); 9386 9387 // Numeric keys OK as long as they are integers and in range. 9388 if (key->isKind(ParseNodeKind::NumberExpr)) { 9389 double numValue = key->as<NumericLiteral>().value(); 9390 int32_t i = 0; 9391 if (!NumberIsInt32(numValue, &i)) { 9392 keysOK = false; 9393 break; 9394 } 9395 if (!ObjLiteralWriter::arrayIndexInRange(i)) { 9396 keysOK = false; 9397 break; 9398 } 9399 } 9400 9401 MOZ_ASSERT(key->isKind(ParseNodeKind::ObjectPropertyName) || 9402 key->isKind(ParseNodeKind::StringExpr) || 9403 key->isKind(ParseNodeKind::NumberExpr)); 9404 9405 AccessorType accessorType = 9406 prop->is<PropertyDefinition>() 9407 ? prop->as<PropertyDefinition>().accessorType() 9408 : AccessorType::None; 9409 if (accessorType != AccessorType::None) { 9410 keysOK = false; 9411 break; 9412 } 9413 9414 if (!isRHSObjLiteralCompatible(value)) { 9415 valuesOK = false; 9416 } 9417 } 9418 9419 if (propCount > SharedPropMap::MaxPropsForNonDictionary) { 9420 // JSOp::NewObject cannot accept dictionary-mode objects. 9421 keysOK = false; 9422 } 9423 9424 *withValues = keysOK && valuesOK; 9425 *withoutValues = keysOK; 9426 } 9427 9428 bool BytecodeEmitter::isArrayObjLiteralCompatible(ListNode* array) const { 9429 for (ParseNode* elem : array->contents()) { 9430 if (elem->isKind(ParseNodeKind::Spread)) { 9431 return false; 9432 } 9433 if (!isRHSObjLiteralCompatible(elem)) { 9434 return false; 9435 } 9436 } 9437 return true; 9438 } 9439 9440 bool BytecodeEmitter::emitPropertyList(ListNode* obj, PropertyEmitter& pe, 9441 PropListType type) { 9442 // [stack] CTOR? OBJ 9443 9444 size_t curFieldKeyIndex = 0; 9445 size_t curStaticFieldKeyIndex = 0; 9446 for (ParseNode* propdef : obj->contents()) { 9447 if (propdef->is<ClassField>()) { 9448 MOZ_ASSERT(type == ClassBody); 9449 // Only handle computing field keys here: the .initializers lambda array 9450 // is created elsewhere. 9451 ClassField* field = &propdef->as<ClassField>(); 9452 if (field->name().getKind() == ParseNodeKind::ComputedName) { 9453 auto fieldKeys = 9454 field->isStatic() 9455 ? TaggedParserAtomIndex::WellKnown::dot_staticFieldKeys_() 9456 : TaggedParserAtomIndex::WellKnown::dot_fieldKeys_(); 9457 if (!emitGetName(fieldKeys)) { 9458 // [stack] CTOR OBJ ARRAY 9459 return false; 9460 } 9461 9462 ParseNode* nameExpr = field->name().as<UnaryNode>().kid(); 9463 9464 if (!emitTree(nameExpr, ValueUsage::WantValue)) { 9465 // [stack] CTOR OBJ ARRAY KEY 9466 return false; 9467 } 9468 9469 if (!emit1(JSOp::ToPropertyKey)) { 9470 // [stack] CTOR OBJ ARRAY KEY 9471 return false; 9472 } 9473 9474 size_t fieldKeysIndex; 9475 if (field->isStatic()) { 9476 fieldKeysIndex = curStaticFieldKeyIndex++; 9477 } else { 9478 fieldKeysIndex = curFieldKeyIndex++; 9479 } 9480 9481 if (!emitUint32Operand(JSOp::InitElemArray, fieldKeysIndex)) { 9482 // [stack] CTOR OBJ ARRAY 9483 return false; 9484 } 9485 9486 if (!emit1(JSOp::Pop)) { 9487 // [stack] CTOR OBJ 9488 return false; 9489 } 9490 } 9491 continue; 9492 } 9493 9494 if (propdef->isKind(ParseNodeKind::StaticClassBlock)) { 9495 // Static class blocks are emitted as part of 9496 // emitCreateMemberInitializers. 9497 continue; 9498 } 9499 9500 if (propdef->is<LexicalScopeNode>()) { 9501 // Constructors are sometimes wrapped in LexicalScopeNodes. As we 9502 // already handled emitting the constructor, skip it. 9503 MOZ_ASSERT( 9504 propdef->as<LexicalScopeNode>().scopeBody()->is<ClassMethod>()); 9505 continue; 9506 } 9507 9508 // Handle __proto__: v specially because *only* this form, and no other 9509 // involving "__proto__", performs [[Prototype]] mutation. 9510 if (propdef->isKind(ParseNodeKind::MutateProto)) { 9511 // [stack] OBJ 9512 MOZ_ASSERT(type == ObjectLiteral); 9513 if (!pe.prepareForProtoValue(propdef->pn_pos.begin)) { 9514 // [stack] OBJ 9515 return false; 9516 } 9517 if (!emitTree(propdef->as<UnaryNode>().kid())) { 9518 // [stack] OBJ PROTO 9519 return false; 9520 } 9521 if (!pe.emitMutateProto()) { 9522 // [stack] OBJ 9523 return false; 9524 } 9525 continue; 9526 } 9527 9528 if (propdef->isKind(ParseNodeKind::Spread)) { 9529 MOZ_ASSERT(type == ObjectLiteral); 9530 // [stack] OBJ 9531 if (!pe.prepareForSpreadOperand(propdef->pn_pos.begin)) { 9532 // [stack] OBJ OBJ 9533 return false; 9534 } 9535 if (!emitTree(propdef->as<UnaryNode>().kid())) { 9536 // [stack] OBJ OBJ VAL 9537 return false; 9538 } 9539 if (!pe.emitSpread()) { 9540 // [stack] OBJ 9541 return false; 9542 } 9543 continue; 9544 } 9545 9546 BinaryNode* prop = &propdef->as<BinaryNode>(); 9547 9548 ParseNode* key = prop->left(); 9549 AccessorType accessorType; 9550 if (prop->is<ClassMethod>()) { 9551 ClassMethod& method = prop->as<ClassMethod>(); 9552 accessorType = method.accessorType(); 9553 9554 if (!method.isStatic() && key->isKind(ParseNodeKind::PrivateName) && 9555 accessorType != AccessorType::None) { 9556 // Private non-static accessors are stamped onto instances from 9557 // initializers; see emitCreateMemberInitializers. 9558 continue; 9559 } 9560 } else if (prop->is<PropertyDefinition>()) { 9561 accessorType = prop->as<PropertyDefinition>().accessorType(); 9562 } else { 9563 accessorType = AccessorType::None; 9564 } 9565 9566 auto emitValue = [this, &key, &prop, accessorType, &pe]() { 9567 // [stack] CTOR? OBJ CTOR? KEY? 9568 9569 ParseNode* propVal = prop->right(); 9570 if (propVal->isDirectRHSAnonFunction()) { 9571 // The following branches except for the last `else` clause emit the 9572 // cases handled in NameResolver::resolveFun (see NameFunctions.cpp) 9573 if (key->isKind(ParseNodeKind::ObjectPropertyName) || 9574 key->isKind(ParseNodeKind::PrivateName) || 9575 key->isKind(ParseNodeKind::StringExpr)) { 9576 auto keyAtom = key->as<NameNode>().atom(); 9577 if (!emitAnonymousFunctionWithName(propVal, keyAtom)) { 9578 // [stack] CTOR? OBJ CTOR? VAL 9579 return false; 9580 } 9581 } else if (key->isKind(ParseNodeKind::NumberExpr)) { 9582 MOZ_ASSERT(accessorType == AccessorType::None); 9583 9584 auto keyAtom = key->as<NumericLiteral>().toAtom(fc, parserAtoms()); 9585 if (!keyAtom) { 9586 return false; 9587 } 9588 if (!emitAnonymousFunctionWithName(propVal, keyAtom)) { 9589 // [stack] CTOR? OBJ CTOR? KEY VAL 9590 return false; 9591 } 9592 } else if (key->isKind(ParseNodeKind::ComputedName) && 9593 (key->as<UnaryNode>().kid()->isKind( 9594 ParseNodeKind::NumberExpr) || 9595 key->as<UnaryNode>().kid()->isKind( 9596 ParseNodeKind::StringExpr)) && 9597 accessorType == AccessorType::None) { 9598 ParseNode* keyKid = key->as<UnaryNode>().kid(); 9599 if (keyKid->isKind(ParseNodeKind::NumberExpr)) { 9600 auto keyAtom = 9601 keyKid->as<NumericLiteral>().toAtom(fc, parserAtoms()); 9602 if (!keyAtom) { 9603 return false; 9604 } 9605 if (!emitAnonymousFunctionWithName(propVal, keyAtom)) { 9606 // [stack] CTOR? OBJ CTOR? KEY VAL 9607 return false; 9608 } 9609 } else { 9610 MOZ_ASSERT(keyKid->isKind(ParseNodeKind::StringExpr)); 9611 auto keyAtom = keyKid->as<NameNode>().atom(); 9612 if (!emitAnonymousFunctionWithName(propVal, keyAtom)) { 9613 // [stack] CTOR? OBJ CTOR? KEY VAL 9614 return false; 9615 } 9616 } 9617 } else { 9618 // Either a proper computed property name or a synthetic computed 9619 // property name for BigInt keys. 9620 MOZ_ASSERT(key->isKind(ParseNodeKind::ComputedName)); 9621 9622 FunctionPrefixKind prefix = 9623 accessorType == AccessorType::None ? FunctionPrefixKind::None 9624 : accessorType == AccessorType::Getter ? FunctionPrefixKind::Get 9625 : FunctionPrefixKind::Set; 9626 9627 if (!emitAnonymousFunctionWithComputedName(propVal, prefix)) { 9628 // [stack] CTOR? OBJ CTOR? KEY VAL 9629 return false; 9630 } 9631 } 9632 } else { 9633 if (!emitTree(propVal)) { 9634 // [stack] CTOR? OBJ CTOR? KEY? VAL 9635 return false; 9636 } 9637 } 9638 9639 if (propVal->is<FunctionNode>() && 9640 propVal->as<FunctionNode>().funbox()->needsHomeObject()) { 9641 if (!pe.emitInitHomeObject()) { 9642 // [stack] CTOR? OBJ CTOR? KEY? FUN 9643 return false; 9644 } 9645 } 9646 9647 #ifdef ENABLE_DECORATORS 9648 if (prop->is<ClassMethod>()) { 9649 ClassMethod& method = prop->as<ClassMethod>(); 9650 if (method.decorators() && !method.decorators()->empty()) { 9651 DecoratorEmitter::Kind kind; 9652 switch (method.accessorType()) { 9653 case AccessorType::Getter: 9654 kind = DecoratorEmitter::Getter; 9655 break; 9656 case AccessorType::Setter: 9657 kind = DecoratorEmitter::Setter; 9658 break; 9659 case AccessorType::None: 9660 kind = DecoratorEmitter::Method; 9661 break; 9662 } 9663 9664 if (!method.isStatic()) { 9665 bool hasKeyOnStack = key->isKind(ParseNodeKind::NumberExpr) || 9666 key->isKind(ParseNodeKind::ComputedName); 9667 if (!emitDupAt(hasKeyOnStack ? 4 : 3)) { 9668 // [stack] ADDINIT OBJ KEY? VAL ADDINIT 9669 return false; 9670 } 9671 } else { 9672 // TODO: See bug 1868220 for support for static methods. 9673 // Note: Key will be present if this has a private name. 9674 if (!emit1(JSOp::Undefined)) { 9675 // [stack] CTOR OBJ CTOR KEY? VAL ADDINIT 9676 return false; 9677 } 9678 } 9679 9680 if (!emit1(JSOp::Swap)) { 9681 // [stack] ADDINIT CTOR? OBJ CTOR? KEY? ADDINIT VAL 9682 return false; 9683 } 9684 9685 // The decorators are applied to the current value on the stack, 9686 // possibly replacing it. 9687 DecoratorEmitter de(this); 9688 if (!de.emitApplyDecoratorsToElementDefinition( 9689 kind, key, method.decorators(), method.isStatic())) { 9690 // [stack] ADDINIT CTOR? OBJ CTOR? KEY? ADDINIT VAL 9691 return false; 9692 } 9693 9694 if (!emit1(JSOp::Swap)) { 9695 // [stack] ADDINIT CTOR? OBJ CTOR? KEY? VAL ADDINIT 9696 return false; 9697 } 9698 9699 if (!emitPopN(1)) { 9700 // [stack] ADDINIT CTOR? OBJ CTOR? KEY? VAL 9701 return false; 9702 } 9703 } 9704 } 9705 #endif 9706 9707 return true; 9708 }; 9709 9710 PropertyEmitter::Kind kind = 9711 (type == ClassBody && propdef->as<ClassMethod>().isStatic()) 9712 ? PropertyEmitter::Kind::Static 9713 : PropertyEmitter::Kind::Prototype; 9714 if (key->isKind(ParseNodeKind::ObjectPropertyName) || 9715 key->isKind(ParseNodeKind::StringExpr)) { 9716 // [stack] CTOR? OBJ 9717 9718 auto keyAtom = key->as<NameNode>().atom(); 9719 9720 // emitClass took care of constructor already. 9721 if (type == ClassBody && 9722 keyAtom == TaggedParserAtomIndex::WellKnown::constructor() && 9723 !propdef->as<ClassMethod>().isStatic()) { 9724 continue; 9725 } 9726 9727 if (!pe.prepareForPropValue(propdef->pn_pos.begin, kind)) { 9728 // [stack] CTOR? OBJ CTOR? 9729 return false; 9730 } 9731 9732 if (!emitValue()) { 9733 // [stack] CTOR? OBJ CTOR? VAL 9734 return false; 9735 } 9736 9737 if (!pe.emitInit(accessorType, keyAtom)) { 9738 // [stack] CTOR? OBJ 9739 return false; 9740 } 9741 9742 continue; 9743 } 9744 9745 if (key->isKind(ParseNodeKind::NumberExpr)) { 9746 // [stack] CTOR? OBJ 9747 if (!pe.prepareForIndexPropKey(propdef->pn_pos.begin, kind)) { 9748 // [stack] CTOR? OBJ CTOR? 9749 return false; 9750 } 9751 if (!emitNumberOp(key->as<NumericLiteral>().value())) { 9752 // [stack] CTOR? OBJ CTOR? KEY 9753 return false; 9754 } 9755 if (!pe.prepareForIndexPropValue()) { 9756 // [stack] CTOR? OBJ CTOR? KEY 9757 return false; 9758 } 9759 if (!emitValue()) { 9760 // [stack] CTOR? OBJ CTOR? KEY VAL 9761 return false; 9762 } 9763 9764 if (!pe.emitInitIndexOrComputed(accessorType)) { 9765 // [stack] CTOR? OBJ 9766 return false; 9767 } 9768 9769 continue; 9770 } 9771 9772 if (key->isKind(ParseNodeKind::ComputedName)) { 9773 // Either a proper computed property name or a synthetic computed property 9774 // name for BigInt keys. 9775 9776 // [stack] CTOR? OBJ 9777 9778 if (!pe.prepareForComputedPropKey(propdef->pn_pos.begin, kind)) { 9779 // [stack] CTOR? OBJ CTOR? 9780 return false; 9781 } 9782 if (!emitTree(key->as<UnaryNode>().kid())) { 9783 // [stack] CTOR? OBJ CTOR? KEY 9784 return false; 9785 } 9786 if (!pe.prepareForComputedPropValue()) { 9787 // [stack] CTOR? OBJ CTOR? KEY 9788 return false; 9789 } 9790 if (!emitValue()) { 9791 // [stack] CTOR? OBJ CTOR? KEY VAL 9792 return false; 9793 } 9794 9795 if (!pe.emitInitIndexOrComputed(accessorType)) { 9796 // [stack] CTOR? OBJ 9797 return false; 9798 } 9799 9800 continue; 9801 } 9802 9803 MOZ_ASSERT(key->isKind(ParseNodeKind::PrivateName)); 9804 MOZ_ASSERT(type == ClassBody); 9805 9806 auto* privateName = &key->as<NameNode>(); 9807 9808 if (kind == PropertyEmitter::Kind::Prototype) { 9809 MOZ_ASSERT(accessorType == AccessorType::None); 9810 if (!pe.prepareForPrivateMethod()) { 9811 // [stack] CTOR OBJ 9812 return false; 9813 } 9814 NameOpEmitter noe(this, privateName->atom(), 9815 NameOpEmitter::Kind::SimpleAssignment); 9816 9817 // Ensure the NameOp emitter doesn't push an environment onto the stack, 9818 // because that would change the stack location of the home object. 9819 MOZ_ASSERT(noe.loc().kind() == NameLocation::Kind::FrameSlot || 9820 noe.loc().kind() == NameLocation::Kind::EnvironmentCoordinate); 9821 9822 if (!noe.prepareForRhs()) { 9823 // [stack] CTOR OBJ 9824 return false; 9825 } 9826 if (!emitValue()) { 9827 // [stack] CTOR OBJ METHOD 9828 return false; 9829 } 9830 if (!noe.emitAssignment()) { 9831 // [stack] CTOR OBJ METHOD 9832 return false; 9833 } 9834 if (!emit1(JSOp::Pop)) { 9835 // [stack] CTOR OBJ 9836 return false; 9837 } 9838 if (!pe.skipInit()) { 9839 // [stack] CTOR OBJ 9840 return false; 9841 } 9842 continue; 9843 } 9844 9845 MOZ_ASSERT(kind == PropertyEmitter::Kind::Static); 9846 9847 // [stack] CTOR OBJ 9848 9849 if (!pe.prepareForPrivateStaticMethod(propdef->pn_pos.begin)) { 9850 // [stack] CTOR OBJ CTOR 9851 return false; 9852 } 9853 if (!emitGetPrivateName(privateName)) { 9854 // [stack] CTOR OBJ CTOR KEY 9855 return false; 9856 } 9857 if (!emitValue()) { 9858 // [stack] CTOR OBJ CTOR KEY VAL 9859 return false; 9860 } 9861 9862 if (!pe.emitPrivateStaticMethod(accessorType)) { 9863 // [stack] CTOR OBJ 9864 return false; 9865 } 9866 9867 if (privateName->privateNameKind() == PrivateNameKind::Setter) { 9868 if (!emitDupAt(1)) { 9869 // [stack] CTOR OBJ CTOR 9870 return false; 9871 } 9872 if (!emitGetPrivateName(privateName)) { 9873 // [stack] CTOR OBJ CTOR NAME 9874 return false; 9875 } 9876 if (!emitAtomOp(JSOp::GetIntrinsic, 9877 TaggedParserAtomIndex::WellKnown::NoPrivateGetter())) { 9878 // [stack] CTOR OBJ CTOR NAME FUN 9879 return false; 9880 } 9881 if (!emit1(JSOp::InitHiddenElemGetter)) { 9882 // [stack] CTOR OBJ CTOR 9883 return false; 9884 } 9885 if (!emit1(JSOp::Pop)) { 9886 // [stack] CTOR OBJ 9887 return false; 9888 } 9889 } 9890 } 9891 9892 return true; 9893 } 9894 9895 bool BytecodeEmitter::emitPropertyListObjLiteral(ListNode* obj, JSOp op, 9896 bool useObjLiteralValues) { 9897 ObjLiteralWriter writer; 9898 9899 #ifdef DEBUG 9900 // In self-hosted JS, we check duplication only on debug build. 9901 mozilla::Maybe<mozilla::HashSet<frontend::TaggedParserAtomIndex, 9902 frontend::TaggedParserAtomIndexHasher>> 9903 selfHostedPropNames; 9904 if (emitterMode == BytecodeEmitter::SelfHosting) { 9905 selfHostedPropNames.emplace(); 9906 } 9907 #endif 9908 9909 if (op == JSOp::Object) { 9910 writer.beginObject(op); 9911 } else { 9912 MOZ_ASSERT(op == JSOp::NewObject); 9913 writer.beginShape(op); 9914 } 9915 9916 for (ParseNode* propdef : obj->contents()) { 9917 BinaryNode* prop = &propdef->as<BinaryNode>(); 9918 ParseNode* key = prop->left(); 9919 9920 if (key->is<NameNode>()) { 9921 if (emitterMode == BytecodeEmitter::SelfHosting) { 9922 auto propName = key->as<NameNode>().atom(); 9923 #ifdef DEBUG 9924 // Self-hosted JS shouldn't contain duplicate properties. 9925 auto p = selfHostedPropNames->lookupForAdd(propName); 9926 MOZ_ASSERT(!p); 9927 if (!selfHostedPropNames->add(p, propName)) { 9928 js::ReportOutOfMemory(fc); 9929 return false; 9930 } 9931 #endif 9932 writer.setPropNameNoDuplicateCheck(parserAtoms(), propName); 9933 } else { 9934 if (!writer.setPropName(parserAtoms(), key->as<NameNode>().atom())) { 9935 return false; 9936 } 9937 } 9938 } else { 9939 double numValue = key->as<NumericLiteral>().value(); 9940 int32_t i = 0; 9941 DebugOnly<bool> numIsInt = 9942 NumberIsInt32(numValue, &i); // checked previously. 9943 MOZ_ASSERT(numIsInt); 9944 MOZ_ASSERT( 9945 ObjLiteralWriter::arrayIndexInRange(i)); // checked previously. 9946 9947 // Ignore indexed properties if we're not storing property values, and 9948 // rely on InitElem ops to define those. These properties will be either 9949 // dense elements (not possible to represent in the literal's shape) or 9950 // sparse elements (enumerated separately, so this doesn't affect property 9951 // iteration order). 9952 if (!useObjLiteralValues) { 9953 continue; 9954 } 9955 9956 writer.setPropIndex(i); 9957 } 9958 9959 if (useObjLiteralValues) { 9960 MOZ_ASSERT(op == JSOp::Object); 9961 ParseNode* value = prop->right(); 9962 if (!emitObjLiteralValue(writer, value)) { 9963 return false; 9964 } 9965 } else { 9966 if (!writer.propWithUndefinedValue(fc)) { 9967 return false; 9968 } 9969 } 9970 } 9971 9972 GCThingIndex index; 9973 if (!addObjLiteralData(writer, &index)) { 9974 return false; 9975 } 9976 9977 // JSOp::Object may only be used by (top-level) run-once scripts. 9978 MOZ_ASSERT_IF(op == JSOp::Object, 9979 sc->isTopLevelContext() && sc->treatAsRunOnce()); 9980 9981 if (!emitGCIndexOp(op, index)) { 9982 // [stack] OBJ 9983 return false; 9984 } 9985 9986 return true; 9987 } 9988 9989 bool BytecodeEmitter::emitDestructuringRestExclusionSetObjLiteral( 9990 ListNode* pattern) { 9991 // Note: if we want to squeeze out a little more performance, we could switch 9992 // to the `JSOp::Object` opcode, because the exclusion set object is never 9993 // exposed to the user, so it's safe to bake the object into the bytecode. 9994 constexpr JSOp op = JSOp::NewObject; 9995 9996 ObjLiteralWriter writer; 9997 writer.beginShape(op); 9998 9999 for (ParseNode* member : pattern->contents()) { 10000 if (member->isKind(ParseNodeKind::Spread)) { 10001 MOZ_ASSERT(!member->pn_next, "unexpected trailing element after spread"); 10002 break; 10003 } 10004 10005 TaggedParserAtomIndex atom; 10006 if (member->isKind(ParseNodeKind::MutateProto)) { 10007 atom = TaggedParserAtomIndex::WellKnown::proto_(); 10008 } else { 10009 ParseNode* key = member->as<BinaryNode>().left(); 10010 atom = key->as<NameNode>().atom(); 10011 } 10012 10013 if (!writer.setPropName(parserAtoms(), atom)) { 10014 return false; 10015 } 10016 10017 if (!writer.propWithUndefinedValue(fc)) { 10018 return false; 10019 } 10020 } 10021 10022 GCThingIndex index; 10023 if (!addObjLiteralData(writer, &index)) { 10024 return false; 10025 } 10026 10027 if (!emitGCIndexOp(op, index)) { 10028 // [stack] OBJ 10029 return false; 10030 } 10031 10032 return true; 10033 } 10034 10035 bool BytecodeEmitter::emitObjLiteralArray(ListNode* array) { 10036 MOZ_ASSERT(checkSingletonContext()); 10037 10038 constexpr JSOp op = JSOp::Object; 10039 10040 ObjLiteralWriter writer; 10041 writer.beginArray(op); 10042 10043 writer.beginDenseArrayElements(); 10044 for (ParseNode* elem : array->contents()) { 10045 if (!emitObjLiteralValue(writer, elem)) { 10046 return false; 10047 } 10048 } 10049 10050 GCThingIndex index; 10051 if (!addObjLiteralData(writer, &index)) { 10052 return false; 10053 } 10054 10055 if (!emitGCIndexOp(op, index)) { 10056 // [stack] OBJ 10057 return false; 10058 } 10059 10060 return true; 10061 } 10062 10063 bool BytecodeEmitter::isRHSObjLiteralCompatible(ParseNode* value) const { 10064 return value->isKind(ParseNodeKind::NumberExpr) || 10065 value->isKind(ParseNodeKind::TrueExpr) || 10066 value->isKind(ParseNodeKind::FalseExpr) || 10067 value->isKind(ParseNodeKind::NullExpr) || 10068 value->isKind(ParseNodeKind::RawUndefinedExpr) || 10069 value->isKind(ParseNodeKind::StringExpr) || 10070 value->isKind(ParseNodeKind::TemplateStringExpr); 10071 } 10072 10073 bool BytecodeEmitter::emitObjLiteralValue(ObjLiteralWriter& writer, 10074 ParseNode* value) { 10075 MOZ_ASSERT(isRHSObjLiteralCompatible(value)); 10076 if (value->isKind(ParseNodeKind::NumberExpr)) { 10077 double numValue = value->as<NumericLiteral>().value(); 10078 int32_t i = 0; 10079 js::Value v; 10080 if (NumberIsInt32(numValue, &i)) { 10081 v.setInt32(i); 10082 } else { 10083 v.setDouble(numValue); 10084 } 10085 if (!writer.propWithConstNumericValue(fc, v)) { 10086 return false; 10087 } 10088 } else if (value->isKind(ParseNodeKind::TrueExpr)) { 10089 if (!writer.propWithTrueValue(fc)) { 10090 return false; 10091 } 10092 } else if (value->isKind(ParseNodeKind::FalseExpr)) { 10093 if (!writer.propWithFalseValue(fc)) { 10094 return false; 10095 } 10096 } else if (value->isKind(ParseNodeKind::NullExpr)) { 10097 if (!writer.propWithNullValue(fc)) { 10098 return false; 10099 } 10100 } else if (value->isKind(ParseNodeKind::RawUndefinedExpr)) { 10101 if (!writer.propWithUndefinedValue(fc)) { 10102 return false; 10103 } 10104 } else if (value->isKind(ParseNodeKind::StringExpr) || 10105 value->isKind(ParseNodeKind::TemplateStringExpr)) { 10106 if (!writer.propWithAtomValue(fc, parserAtoms(), 10107 value->as<NameNode>().atom())) { 10108 return false; 10109 } 10110 } else { 10111 MOZ_CRASH("Unexpected parse node"); 10112 } 10113 return true; 10114 } 10115 10116 static bool NeedsPrivateBrand(ParseNode* member) { 10117 return member->is<ClassMethod>() && 10118 member->as<ClassMethod>().name().isKind(ParseNodeKind::PrivateName) && 10119 !member->as<ClassMethod>().isStatic(); 10120 } 10121 10122 #ifdef ENABLE_DECORATORS 10123 static bool HasDecorators(ParseNode* member) { 10124 return member->is<ClassMethod>() && member->as<ClassMethod>().decorators(); 10125 } 10126 #endif 10127 10128 mozilla::Maybe<MemberInitializers> BytecodeEmitter::setupMemberInitializers( 10129 ListNode* classMembers, FieldPlacement placement) const { 10130 bool isStatic = placement == FieldPlacement::Static; 10131 10132 size_t numFields = 0; 10133 size_t numPrivateInitializers = 0; 10134 bool hasPrivateBrand = false; 10135 #ifdef ENABLE_DECORATORS 10136 bool hasDecorators = false; 10137 #endif 10138 for (ParseNode* member : classMembers->contents()) { 10139 if (NeedsFieldInitializer(member, isStatic)) { 10140 numFields++; 10141 } else if (NeedsAccessorInitializer(member, isStatic)) { 10142 numPrivateInitializers++; 10143 hasPrivateBrand = true; 10144 } else if (NeedsPrivateBrand(member)) { 10145 hasPrivateBrand = true; 10146 } 10147 #ifdef ENABLE_DECORATORS 10148 if (!hasDecorators && HasDecorators(member)) { 10149 hasDecorators = true; 10150 } 10151 #endif 10152 } 10153 10154 // If there are more initializers than can be represented, return invalid. 10155 if (numFields + numPrivateInitializers > 10156 MemberInitializers::MaxInitializers) { 10157 return Nothing(); 10158 } 10159 return Some(MemberInitializers(hasPrivateBrand, 10160 #ifdef ENABLE_DECORATORS 10161 hasDecorators, 10162 #endif 10163 numFields + numPrivateInitializers)); 10164 } 10165 10166 // Purpose of .fieldKeys: 10167 // Computed field names (`["x"] = 2;`) must be ran at class-evaluation time, 10168 // not object construction time. The transformation to do so is roughly as 10169 // follows: 10170 // 10171 // class C { 10172 // [keyExpr] = valueExpr; 10173 // } 10174 // --> 10175 // let .fieldKeys = [keyExpr]; 10176 // let .initializers = [ 10177 // () => { 10178 // this[.fieldKeys[0]] = valueExpr; 10179 // } 10180 // ]; 10181 // class C { 10182 // constructor() { 10183 // .initializers[0](); 10184 // } 10185 // } 10186 // 10187 // BytecodeEmitter::emitCreateFieldKeys does `let .fieldKeys = [...];` 10188 // BytecodeEmitter::emitPropertyList fills in the elements of the array. 10189 // See GeneralParser::fieldInitializer for the `this[.fieldKeys[0]]` part. 10190 bool BytecodeEmitter::emitCreateFieldKeys(ListNode* obj, 10191 FieldPlacement placement) { 10192 bool isStatic = placement == FieldPlacement::Static; 10193 auto isFieldWithComputedName = [isStatic](ParseNode* propdef) { 10194 return propdef->is<ClassField>() && 10195 propdef->as<ClassField>().isStatic() == isStatic && 10196 propdef->as<ClassField>().name().getKind() == 10197 ParseNodeKind::ComputedName; 10198 }; 10199 10200 size_t numFieldKeys = std::count_if( 10201 obj->contents().begin(), obj->contents().end(), isFieldWithComputedName); 10202 if (numFieldKeys == 0) { 10203 return true; 10204 } 10205 10206 auto fieldKeys = 10207 isStatic ? TaggedParserAtomIndex::WellKnown::dot_staticFieldKeys_() 10208 : TaggedParserAtomIndex::WellKnown::dot_fieldKeys_(); 10209 NameOpEmitter noe(this, fieldKeys, NameOpEmitter::Kind::Initialize); 10210 if (!noe.prepareForRhs()) { 10211 return false; 10212 } 10213 10214 if (!emitUint32Operand(JSOp::NewArray, numFieldKeys)) { 10215 // [stack] ARRAY 10216 return false; 10217 } 10218 10219 if (!noe.emitAssignment()) { 10220 // [stack] ARRAY 10221 return false; 10222 } 10223 10224 if (!emit1(JSOp::Pop)) { 10225 // [stack] 10226 return false; 10227 } 10228 10229 return true; 10230 } 10231 10232 static bool HasInitializer(ParseNode* node, bool isStaticContext) { 10233 return (node->is<ClassField>() && 10234 node->as<ClassField>().isStatic() == isStaticContext) || 10235 (isStaticContext && node->is<StaticClassBlock>()); 10236 } 10237 10238 static FunctionNode* GetInitializer(ParseNode* node, bool isStaticContext) { 10239 MOZ_ASSERT(HasInitializer(node, isStaticContext)); 10240 MOZ_ASSERT_IF(!node->is<ClassField>(), isStaticContext); 10241 return node->is<ClassField>() ? node->as<ClassField>().initializer() 10242 : node->as<StaticClassBlock>().function(); 10243 } 10244 10245 static bool IsPrivateInstanceAccessor(const ClassMethod* classMethod) { 10246 return !classMethod->isStatic() && 10247 classMethod->name().isKind(ParseNodeKind::PrivateName) && 10248 classMethod->accessorType() != AccessorType::None; 10249 } 10250 10251 bool BytecodeEmitter::emitCreateMemberInitializers(ClassEmitter& ce, 10252 ListNode* obj, 10253 FieldPlacement placement 10254 #ifdef ENABLE_DECORATORS 10255 , 10256 bool hasHeritage 10257 #endif 10258 ) { 10259 // FieldPlacement::Instance, hasHeritage == false 10260 // [stack] HOME 10261 // 10262 // FieldPlacement::Instance, hasHeritage == true 10263 // [stack] HOME HERIT 10264 // 10265 // FieldPlacement::Static 10266 // [stack] CTOR HOME 10267 #ifdef ENABLE_DECORATORS 10268 MOZ_ASSERT_IF(placement == FieldPlacement::Static, !hasHeritage); 10269 #endif 10270 mozilla::Maybe<MemberInitializers> memberInitializers = 10271 setupMemberInitializers(obj, placement); 10272 if (!memberInitializers) { 10273 ReportAllocationOverflow(fc); 10274 return false; 10275 } 10276 10277 size_t numInitializers = memberInitializers->numMemberInitializers; 10278 if (numInitializers == 0) { 10279 return true; 10280 } 10281 10282 bool isStatic = placement == FieldPlacement::Static; 10283 if (!ce.prepareForMemberInitializers(numInitializers, isStatic)) { 10284 // [stack] HOME HERIT? ARR 10285 // or: 10286 // [stack] CTOR HOME ARR 10287 return false; 10288 } 10289 10290 // Private accessors could be used in the field initializers, so make sure 10291 // accessor initializers appear earlier in the .initializers array so they 10292 // run first. Static private methods are not initialized using initializers 10293 // (emitPropertyList emits bytecode to stamp them onto the constructor), so 10294 // skip this step if isStatic. 10295 if (!isStatic) { 10296 if (!emitPrivateMethodInitializers(ce, obj)) { 10297 return false; 10298 } 10299 } 10300 10301 for (ParseNode* propdef : obj->contents()) { 10302 if (!HasInitializer(propdef, isStatic)) { 10303 continue; 10304 } 10305 10306 FunctionNode* initializer = GetInitializer(propdef, isStatic); 10307 10308 if (!ce.prepareForMemberInitializer()) { 10309 return false; 10310 } 10311 if (!emitTree(initializer)) { 10312 // [stack] HOME HERIT? ARR LAMBDA 10313 // or: 10314 // [stack] CTOR HOME ARR LAMBDA 10315 return false; 10316 } 10317 if (initializer->funbox()->needsHomeObject()) { 10318 MOZ_ASSERT(initializer->funbox()->allowSuperProperty()); 10319 if (!ce.emitMemberInitializerHomeObject(isStatic)) { 10320 // [stack] HOME HERIT? ARR LAMBDA 10321 // or: 10322 // [stack] CTOR HOME ARR LAMBDA 10323 return false; 10324 } 10325 } 10326 if (!ce.emitStoreMemberInitializer()) { 10327 // [stack] HOME HERIT? ARR 10328 // or: 10329 // [stack] CTOR HOME ARR 10330 return false; 10331 } 10332 } 10333 10334 #ifdef ENABLE_DECORATORS 10335 // Index to use to append new initializers returned by decorators to the array 10336 if (!emitNumberOp(numInitializers)) { 10337 // [stack] HOME HERIT? ARR I 10338 // or: 10339 // [stack] CTOR HOME ARR I 10340 return false; 10341 } 10342 10343 for (ParseNode* propdef : obj->contents()) { 10344 if (!propdef->is<ClassField>()) { 10345 continue; 10346 } 10347 ClassField* field = &propdef->as<ClassField>(); 10348 if (field->isStatic() != isStatic) { 10349 continue; 10350 } 10351 if (field->decorators() && !field->decorators()->empty()) { 10352 DecoratorEmitter de(this); 10353 if (!field->hasAccessor()) { 10354 if (!emitDupAt((hasHeritage || isStatic) ? 4 : 3)) { 10355 // [stack] ADDINIT HOME HERIT? ARR I ADDINIT 10356 // or: 10357 // [stack] ADDINIT CTOR HOME ARR I ADDINIT 10358 return false; 10359 } 10360 if (!de.emitApplyDecoratorsToFieldDefinition( 10361 &field->name(), field->decorators(), field->isStatic())) { 10362 // [stack] HOME HERIT? ARR I ADDINIT INITS 10363 // or: 10364 // [stack] CTOR HOME ARR I ADDINIT INITS 10365 return false; 10366 } 10367 if (!emit1(JSOp::Swap)) { 10368 // [stack] HOME HERIT? ARR I INITS ADDINIT 10369 // or: 10370 // [stack] CTOR HOME ARR I INITS ADDINIT 10371 return false; 10372 } 10373 if (!emitPopN(1)) { 10374 // [stack] ADDINIT HOME HERIT? ARR I INITS 10375 // or: 10376 // [stack] ADDINIT CTOR HOME ARR I INITS 10377 return false; 10378 } 10379 } else { 10380 ClassMethod* accessorGetterNode = field->accessorGetterNode(); 10381 auto accessorGetterKeyAtom = 10382 accessorGetterNode->left()->as<NameNode>().atom(); 10383 ClassMethod* accessorSetterNode = field->accessorSetterNode(); 10384 auto accessorSetterKeyAtom = 10385 accessorSetterNode->left()->as<NameNode>().atom(); 10386 if (!IsPrivateInstanceAccessor(accessorGetterNode)) { 10387 if (!emitTree(&accessorGetterNode->method())) { 10388 // [stack] ADDINIT HOME HERIT? ARR I GET 10389 // or: 10390 // [stack] ADDINIT CTOR HOME ARR I GET 10391 return false; 10392 } 10393 if (!emitTree(&accessorSetterNode->method())) { 10394 // [stack] ADDINIT HOME HERIT? ARR I GET 10395 // SET 10396 // or: 10397 // [stack] ADDINIT CTOR HOME ARR I GET SET 10398 return false; 10399 } 10400 } else { 10401 MOZ_ASSERT(IsPrivateInstanceAccessor(accessorSetterNode)); 10402 auto getAccessor = [this]( 10403 ClassMethod* classMethod, 10404 TaggedParserAtomIndex& updatedAtom) -> bool { 10405 // [stack] 10406 10407 // Synthesize a name for the lexical variable that will store the 10408 // private method body. 10409 TaggedParserAtomIndex name = 10410 classMethod->name().as<NameNode>().atom(); 10411 AccessorType accessorType = classMethod->accessorType(); 10412 StringBuilder storedMethodName(fc); 10413 if (!storedMethodName.append(parserAtoms(), name)) { 10414 return false; 10415 } 10416 if (!storedMethodName.append(accessorType == AccessorType::Getter 10417 ? ".getter" 10418 : ".setter")) { 10419 return false; 10420 } 10421 updatedAtom = storedMethodName.finishParserAtom(parserAtoms(), fc); 10422 if (!updatedAtom) { 10423 return false; 10424 } 10425 10426 return emitGetName(updatedAtom); 10427 // [stack] ACCESSOR 10428 }; 10429 10430 if (!getAccessor(accessorGetterNode, accessorGetterKeyAtom)) { 10431 // [stack] ADDINIT HOME HERIT? ARR I GET 10432 // or: 10433 // [stack] ADDINIT CTOR HOME ARR I GET 10434 return false; 10435 }; 10436 10437 if (!getAccessor(accessorSetterNode, accessorSetterKeyAtom)) { 10438 // [stack] ADDINIT HOME HERIT? ARR I GET SET 10439 // or: 10440 // [stack] ADDINIT CTOR HOME ARR I GET SET 10441 return false; 10442 }; 10443 } 10444 10445 if (!emitDupAt((hasHeritage || isStatic) ? 6 : 5)) { 10446 // [stack] ADDINIT HOME HERIT? ARR I GET SET ADDINIT 10447 // or: 10448 // [stack] ADDINIT CTOR HOME ARR I GET SET ADDINIT 10449 return false; 10450 } 10451 10452 if (!emitUnpickN(2)) { 10453 // [stack] ADDINIT HOME HERIT? ARR I ADDINIT GET SET 10454 // or: 10455 // [stack] ADDINIT CTOR HOME ARR I ADDINIT GET SET 10456 return false; 10457 } 10458 10459 if (!de.emitApplyDecoratorsToAccessorDefinition( 10460 &field->name(), field->decorators(), field->isStatic())) { 10461 // [stack] ADDINIT HOME HERIT? ARR I ADDINIT GET SET INITS 10462 // or: 10463 // [stack] ADDINIT CTOR HOME ARR I ADDINIT GET SET INITS 10464 return false; 10465 } 10466 10467 if (!emitPickN(3)) { 10468 // [stack] HOME HERIT? ARR I GET SET INITS ADDINIT 10469 // or: 10470 // [stack] CTOR HOME ARR I GET SET INITS ADDINIT 10471 return false; 10472 } 10473 10474 if (!emitPopN(1)) { 10475 // [stack] ADDINIT HOME HERIT? ARR I GET SET INITS 10476 // or: 10477 // [stack] ADDINIT CTOR HOME ARR I GET SET INITS 10478 return false; 10479 } 10480 10481 if (!emitUnpickN(2)) { 10482 // [stack] ADDINIT HOME HERIT? ARR I INITS GET SET 10483 // or: 10484 // [stack] ADDINIT CTOR HOME ARR I INITS GET SET 10485 return false; 10486 } 10487 10488 if (!IsPrivateInstanceAccessor(accessorGetterNode)) { 10489 if (!isStatic) { 10490 if (!emitDupAt(hasHeritage ? 6 : 5)) { 10491 // [stack] ADDINIT HOME HERIT? ARR I INITS GET SET HOME 10492 return false; 10493 } 10494 } else { 10495 if (!emitDupAt(6)) { 10496 // [stack] ADDINIT CTOR HOME ARR I INITS GET SET CTOR 10497 return false; 10498 } 10499 if (!emitDupAt(6)) { 10500 // [stack] ADDINIT CTOR HOME ARR I INITS GET SET CTOR HOME 10501 return false; 10502 } 10503 } 10504 10505 PropertyEmitter::Kind kind = field->isStatic() 10506 ? PropertyEmitter::Kind::Static 10507 : PropertyEmitter::Kind::Prototype; 10508 if (!accessorGetterNode->name().isKind(ParseNodeKind::PrivateName)) { 10509 MOZ_ASSERT( 10510 !accessorSetterNode->name().isKind(ParseNodeKind::PrivateName)); 10511 10512 if (!ce.prepareForPropValue(propdef->pn_pos.begin, kind)) { 10513 // [stack] ADDINIT HOME HERIT? ARR I INITS GET SET HOME 10514 // or: 10515 // [stack] ADDINIT CTOR HOME ARR I INITS GET SET CTOR HOME CTOR 10516 return false; 10517 } 10518 if (!emitPickN(isStatic ? 3 : 1)) { 10519 // [stack] ADDINIT HOME HERIT? ARR I INITS GET HOME SET 10520 // or: 10521 // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME CTOR SET 10522 return false; 10523 } 10524 if (!ce.emitInit(AccessorType::Setter, accessorSetterKeyAtom)) { 10525 // [stack] ADDINIT HOME HERIT? ARR I INITS GET HOME 10526 // or: 10527 // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME 10528 return false; 10529 } 10530 10531 if (!ce.prepareForPropValue(propdef->pn_pos.begin, kind)) { 10532 // [stack] ADDINIT HOME HERIT? ARR I INITS GET HOME 10533 // or: 10534 // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME CTOR 10535 return false; 10536 } 10537 if (!emitPickN(isStatic ? 3 : 1)) { 10538 // [stack] ADDINIT HOME HERIT? ARR I INITS HOME GET 10539 // or: 10540 // [stack] ADDINIT CTOR HOME ARR I INITS CTOR HOME CTOR GET 10541 return false; 10542 } 10543 if (!ce.emitInit(AccessorType::Getter, accessorGetterKeyAtom)) { 10544 // [stack] ADDINIT HOME HERIT? ARR I INITS HOME 10545 // or: 10546 // [stack] ADDINIT CTOR HOME ARR I INITS CTOR HOME 10547 return false; 10548 } 10549 } else { 10550 MOZ_ASSERT(isStatic); 10551 // The getter and setter share the same name. 10552 if (!emitNewPrivateName(accessorSetterKeyAtom, 10553 accessorSetterKeyAtom)) { 10554 return false; 10555 } 10556 if (!ce.prepareForPrivateStaticMethod(propdef->pn_pos.begin)) { 10557 // [stack] ADDINIT CTOR HOME ARR I INITS GET SET CTOR HOME CTOR 10558 return false; 10559 } 10560 if (!emitGetPrivateName( 10561 &accessorSetterNode->name().as<NameNode>())) { 10562 // [stack] ADDINIT CTOR HOME ARR I INITS GET SET CTOR HOME CTOR 10563 // KEY 10564 return false; 10565 } 10566 if (!emitPickN(4)) { 10567 // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME CTOR KEY 10568 // SET 10569 return false; 10570 } 10571 if (!ce.emitPrivateStaticMethod(AccessorType::Setter)) { 10572 // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME 10573 return false; 10574 } 10575 10576 if (!ce.prepareForPrivateStaticMethod(propdef->pn_pos.begin)) { 10577 // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME CTOR 10578 return false; 10579 } 10580 if (!emitGetPrivateName( 10581 &accessorGetterNode->name().as<NameNode>())) { 10582 // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME CTOR KEY 10583 return false; 10584 } 10585 if (!emitPickN(4)) { 10586 // [stack] ADDINIT CTOR HOME ARR I INITS CTOR HOME CTOR KEY GET 10587 return false; 10588 } 10589 if (!ce.emitPrivateStaticMethod(AccessorType::Getter)) { 10590 // [stack] ADDINIT CTOR HOME ARR I INITS CTOR HOME 10591 return false; 10592 } 10593 } 10594 10595 if (!isStatic) { 10596 if (!emitPopN(1)) { 10597 // [stack] ADDINIT HOME HERIT? ARR I INITS 10598 return false; 10599 } 10600 } else { 10601 if (!emitPopN(2)) { 10602 // [stack] ADDINIT CTOR HOME ARR I INITS 10603 return false; 10604 } 10605 } 10606 } else { 10607 MOZ_ASSERT(IsPrivateInstanceAccessor(accessorSetterNode)); 10608 10609 if (!emitLexicalInitialization(accessorSetterKeyAtom)) { 10610 // [stack] ADDINIT HOME HERIT? ARR I INITS GET SET 10611 // or: 10612 // [stack] ADDINIT CTOR HOME ARR I INITS GET SET 10613 return false; 10614 } 10615 10616 if (!emitPopN(1)) { 10617 // [stack] ADDINIT HOME HERIT? ARR I INITS GET 10618 // or: 10619 // [stack] ADDINIT CTOR HOME ARR I INITS GET 10620 return false; 10621 } 10622 10623 if (!emitLexicalInitialization(accessorGetterKeyAtom)) { 10624 // [stack] ADDINIT HOME HERIT? ARR I INITS GET 10625 // or: 10626 // [stack] ADDINIT CTOR HOME ARR I INITS GET 10627 return false; 10628 } 10629 10630 if (!emitPopN(1)) { 10631 // [stack] ADDINIT HOME HERIT? ARR I INITS 10632 // or: 10633 // [stack] ADDINIT CTOR HOME ARR I INITS 10634 return false; 10635 } 10636 } 10637 } 10638 if (!emit1(JSOp::InitElemInc)) { 10639 // [stack] ADDINIT HOME HERIT? ARR I 10640 // or: 10641 // [stack] ADDINIT CTOR HOME ARR I 10642 return false; 10643 } 10644 } 10645 } 10646 10647 // Pop I 10648 if (!emitPopN(1)) { 10649 // [stack] ADDINIT HOME HERIT? ARR 10650 // or: 10651 // [stack] ADDINIT CTOR HOME ARR 10652 return false; 10653 } 10654 #endif 10655 10656 if (!ce.emitMemberInitializersEnd()) { 10657 // [stack] ADDINIT HOME HERIT? 10658 // or: 10659 // [stack] ADDINIT CTOR HOME 10660 return false; 10661 } 10662 10663 return true; 10664 } 10665 10666 bool BytecodeEmitter::emitPrivateMethodInitializers(ClassEmitter& ce, 10667 ListNode* obj) { 10668 for (ParseNode* propdef : obj->contents()) { 10669 if (!propdef->is<ClassMethod>()) { 10670 continue; 10671 } 10672 auto* classMethod = &propdef->as<ClassMethod>(); 10673 10674 // Skip over anything which isn't a private instance accessor. 10675 if (!IsPrivateInstanceAccessor(classMethod)) { 10676 continue; 10677 } 10678 10679 if (!ce.prepareForMemberInitializer()) { 10680 // [stack] HOMEOBJ HERITAGE? ARRAY 10681 // or: 10682 // [stack] CTOR HOMEOBJ ARRAY 10683 return false; 10684 } 10685 10686 // Synthesize a name for the lexical variable that will store the 10687 // private method body. 10688 TaggedParserAtomIndex name = classMethod->name().as<NameNode>().atom(); 10689 AccessorType accessorType = classMethod->accessorType(); 10690 StringBuilder storedMethodName(fc); 10691 if (!storedMethodName.append(parserAtoms(), name)) { 10692 return false; 10693 } 10694 if (!storedMethodName.append( 10695 accessorType == AccessorType::Getter ? ".getter" : ".setter")) { 10696 return false; 10697 } 10698 auto storedMethodAtom = 10699 storedMethodName.finishParserAtom(parserAtoms(), fc); 10700 10701 // Emit the private method body and store it as a lexical var. 10702 if (!emitFunction(&classMethod->method())) { 10703 // [stack] HOMEOBJ HERITAGE? ARRAY METHOD 10704 // or: 10705 // [stack] CTOR HOMEOBJ ARRAY METHOD 10706 return false; 10707 } 10708 // The private method body needs to access the home object, 10709 // and the CE knows where that is on the stack. 10710 if (classMethod->method().funbox()->needsHomeObject()) { 10711 if (!ce.emitMemberInitializerHomeObject(false)) { 10712 // [stack] HOMEOBJ HERITAGE? ARRAY METHOD 10713 // or: 10714 // [stack] CTOR HOMEOBJ ARRAY METHOD 10715 return false; 10716 } 10717 } 10718 if (!emitLexicalInitialization(storedMethodAtom)) { 10719 // [stack] HOMEOBJ HERITAGE? ARRAY METHOD 10720 // or: 10721 // [stack] CTOR HOMEOBJ ARRAY METHOD 10722 return false; 10723 } 10724 if (!emit1(JSOp::Pop)) { 10725 // [stack] HOMEOBJ HERITAGE? ARRAY 10726 // or: 10727 // [stack] CTOR HOMEOBJ ARRAY 10728 return false; 10729 } 10730 10731 if (!emitPrivateMethodInitializer(classMethod, storedMethodAtom)) { 10732 // [stack] HOMEOBJ HERITAGE? ARRAY 10733 // or: 10734 // [stack] CTOR HOMEOBJ ARRAY 10735 return false; 10736 } 10737 10738 // Store the emitted initializer function into the .initializers array. 10739 if (!ce.emitStoreMemberInitializer()) { 10740 // [stack] HOMEOBJ HERITAGE? ARRAY 10741 // or: 10742 // [stack] CTOR HOMEOBJ ARRAY 10743 return false; 10744 } 10745 } 10746 10747 return true; 10748 } 10749 10750 bool BytecodeEmitter::emitPrivateMethodInitializer( 10751 ClassMethod* classMethod, TaggedParserAtomIndex storedMethodAtom) { 10752 MOZ_ASSERT(IsPrivateInstanceAccessor(classMethod)); 10753 10754 auto* name = &classMethod->name().as<NameNode>(); 10755 10756 // Emit the synthesized initializer function. 10757 FunctionNode* funNode = classMethod->initializerIfPrivate(); 10758 MOZ_ASSERT(funNode); 10759 FunctionBox* funbox = funNode->funbox(); 10760 FunctionEmitter fe(this, funbox, funNode->syntaxKind(), 10761 FunctionEmitter::IsHoisted::No); 10762 if (!fe.prepareForNonLazy()) { 10763 // [stack] 10764 return false; 10765 } 10766 10767 BytecodeEmitter bce2(this, funbox); 10768 if (!bce2.init(funNode->pn_pos)) { 10769 return false; 10770 } 10771 ParamsBodyNode* paramsBody = funNode->body(); 10772 FunctionScriptEmitter fse(&bce2, funbox, Nothing(), Nothing()); 10773 if (!fse.prepareForParameters()) { 10774 // [stack] 10775 return false; 10776 } 10777 if (!bce2.emitFunctionFormalParameters(paramsBody)) { 10778 // [stack] 10779 return false; 10780 } 10781 if (!fse.prepareForBody()) { 10782 // [stack] 10783 return false; 10784 } 10785 10786 if (!bce2.emit1(JSOp::FunctionThis)) { 10787 // [stack] THIS 10788 return false; 10789 } 10790 if (!bce2.emitGetPrivateName(name)) { 10791 // [stack] THIS NAME 10792 return false; 10793 } 10794 if (!bce2.emitGetName(storedMethodAtom)) { 10795 // [stack] THIS NAME METHOD 10796 return false; 10797 } 10798 10799 switch (name->privateNameKind()) { 10800 case PrivateNameKind::Setter: 10801 if (!bce2.emit1(JSOp::InitHiddenElemSetter)) { 10802 // [stack] THIS 10803 return false; 10804 } 10805 if (!bce2.emitGetPrivateName(name)) { 10806 // [stack] THIS NAME 10807 return false; 10808 } 10809 if (!bce2.emitAtomOp( 10810 JSOp::GetIntrinsic, 10811 TaggedParserAtomIndex::WellKnown::NoPrivateGetter())) { 10812 // [stack] THIS NAME FUN 10813 return false; 10814 } 10815 if (!bce2.emit1(JSOp::InitHiddenElemGetter)) { 10816 // [stack] THIS 10817 return false; 10818 } 10819 break; 10820 case PrivateNameKind::Getter: 10821 case PrivateNameKind::GetterSetter: 10822 if (classMethod->accessorType() == AccessorType::Getter) { 10823 if (!bce2.emit1(JSOp::InitHiddenElemGetter)) { 10824 // [stack] THIS 10825 return false; 10826 } 10827 } else { 10828 if (!bce2.emit1(JSOp::InitHiddenElemSetter)) { 10829 // [stack] THIS 10830 return false; 10831 } 10832 } 10833 break; 10834 default: 10835 MOZ_CRASH("Invalid op"); 10836 } 10837 10838 // Pop remaining THIS. 10839 if (!bce2.emit1(JSOp::Pop)) { 10840 // [stack] 10841 return false; 10842 } 10843 10844 if (!fse.emitEndBody()) { 10845 // [stack] 10846 return false; 10847 } 10848 if (!fse.intoStencil()) { 10849 return false; 10850 } 10851 10852 if (!fe.emitNonLazyEnd()) { 10853 // [stack] HOMEOBJ HERITAGE? ARRAY FUN 10854 // or: 10855 // [stack] CTOR HOMEOBJ ARRAY FUN 10856 return false; 10857 } 10858 10859 return true; 10860 } 10861 10862 const MemberInitializers& BytecodeEmitter::findMemberInitializersForCall() 10863 const { 10864 for (const auto* current = this; current; current = current->parent) { 10865 if (current->sc->isFunctionBox()) { 10866 FunctionBox* funbox = current->sc->asFunctionBox(); 10867 10868 if (funbox->isArrow()) { 10869 continue; 10870 } 10871 10872 // If we found a non-arrow / non-constructor we were never allowed to 10873 // expect fields in the first place. 10874 MOZ_RELEASE_ASSERT(funbox->isClassConstructor()); 10875 10876 return funbox->useMemberInitializers() ? funbox->memberInitializers() 10877 : MemberInitializers::Empty(); 10878 } 10879 } 10880 10881 MOZ_RELEASE_ASSERT(compilationState.scopeContext.memberInitializers); 10882 return *compilationState.scopeContext.memberInitializers; 10883 } 10884 10885 bool BytecodeEmitter::emitInitializeInstanceMembers( 10886 bool isDerivedClassConstructor) { 10887 const MemberInitializers& memberInitializers = 10888 findMemberInitializersForCall(); 10889 MOZ_ASSERT(memberInitializers.valid); 10890 10891 if (memberInitializers.hasPrivateBrand) { 10892 // This is guaranteed to run after super(), so we don't need TDZ checks. 10893 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_this_())) { 10894 // [stack] THIS 10895 return false; 10896 } 10897 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_privateBrand_())) { 10898 // [stack] THIS BRAND 10899 return false; 10900 } 10901 if (isDerivedClassConstructor) { 10902 if (!emitCheckPrivateField(ThrowCondition::ThrowHas, 10903 ThrowMsgKind::PrivateBrandDoubleInit)) { 10904 // [stack] THIS BRAND BOOL 10905 return false; 10906 } 10907 if (!emit1(JSOp::Pop)) { 10908 // [stack] THIS BRAND 10909 return false; 10910 } 10911 } 10912 if (!emit1(JSOp::Null)) { 10913 // [stack] THIS BRAND NULL 10914 return false; 10915 } 10916 if (!emit1(JSOp::InitHiddenElem)) { 10917 // [stack] THIS 10918 return false; 10919 } 10920 if (!emit1(JSOp::Pop)) { 10921 // [stack] 10922 return false; 10923 } 10924 } 10925 10926 size_t numInitializers = memberInitializers.numMemberInitializers; 10927 if (numInitializers > 0) { 10928 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_initializers_())) { 10929 // [stack] ARRAY 10930 return false; 10931 } 10932 10933 for (size_t index = 0; index < numInitializers; index++) { 10934 if (index < numInitializers - 1) { 10935 // We Dup to keep the array around (it is consumed in the bytecode 10936 // below) for next iterations of this loop, except for the last 10937 // iteration, which avoids an extra Pop at the end of the loop. 10938 if (!emit1(JSOp::Dup)) { 10939 // [stack] ARRAY ARRAY 10940 return false; 10941 } 10942 } 10943 10944 if (!emitNumberOp(index)) { 10945 // [stack] ARRAY? ARRAY INDEX 10946 return false; 10947 } 10948 10949 if (!emit1(JSOp::GetElem)) { 10950 // [stack] ARRAY? FUNC 10951 return false; 10952 } 10953 10954 // This is guaranteed to run after super(), so we don't need TDZ checks. 10955 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_this_())) { 10956 // [stack] ARRAY? FUNC THIS 10957 return false; 10958 } 10959 10960 // Callee is always internal function. 10961 if (!emitCall(JSOp::CallIgnoresRv, 0)) { 10962 // [stack] ARRAY? RVAL 10963 return false; 10964 } 10965 10966 if (!emit1(JSOp::Pop)) { 10967 // [stack] ARRAY? 10968 return false; 10969 } 10970 } 10971 #ifdef ENABLE_DECORATORS 10972 if (memberInitializers.hasDecorators) { 10973 // Decorators Proposal 10974 // https://arai-a.github.io/ecma262-compare/?pr=2417&id=sec-initializeinstanceelements 10975 // 4. For each element e of elements, do 10976 // 4.a. If elementRecord.[[Kind]] is field or accessor, then 10977 // 4.a.i. Perform ? InitializeFieldOrAccessor(O, elementRecord). 10978 // 10979 10980 // TODO: (See Bug 1817993) At the moment, we're applying the 10981 // initialization logic in two steps. The pre-decorator initialization 10982 // code runs, stores the initial value, and then we retrieve it here and 10983 // apply the initializers added by decorators. We should unify these two 10984 // steps. 10985 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_initializers_())) { 10986 // [stack] ARRAY 10987 return false; 10988 } 10989 10990 if (!emit1(JSOp::Dup)) { 10991 // [stack] ARRAY ARRAY 10992 return false; 10993 } 10994 10995 if (!emitAtomOp(JSOp::GetProp, 10996 TaggedParserAtomIndex::WellKnown::length())) { 10997 // [stack] ARRAY LENGTH 10998 return false; 10999 } 11000 11001 if (!emitNumberOp(static_cast<double>(numInitializers))) { 11002 // [stack] ARRAY LENGTH INDEX 11003 return false; 11004 } 11005 11006 InternalWhileEmitter wh(this); 11007 // At this point, we have no context to determine offsets in the 11008 // code for this while statement. Ideally, it would correspond to 11009 // the field we're initializing. 11010 if (!wh.emitCond()) { 11011 // [stack] ARRAY LENGTH INDEX 11012 return false; 11013 } 11014 11015 if (!emit1(JSOp::Dup)) { 11016 // [stack] ARRAY LENGTH INDEX INDEX 11017 return false; 11018 } 11019 11020 if (!emitDupAt(2)) { 11021 // [stack] ARRAY LENGTH INDEX INDEX LENGTH 11022 return false; 11023 } 11024 11025 if (!emit1(JSOp::Lt)) { 11026 // [stack] ARRAY LENGTH INDEX BOOL 11027 return false; 11028 } 11029 11030 if (!wh.emitBody()) { 11031 // [stack] ARRAY LENGTH INDEX 11032 return false; 11033 } 11034 11035 if (!emitDupAt(2)) { 11036 // [stack] ARRAY LENGTH INDEX ARRAY 11037 return false; 11038 } 11039 11040 if (!emitDupAt(1)) { 11041 // [stack] ARRAY LENGTH INDEX ARRAY INDEX 11042 return false; 11043 } 11044 11045 // Retrieve initializers for this field 11046 if (!emit1(JSOp::GetElem)) { 11047 // [stack] ARRAY LENGTH INDEX INITIALIZERS 11048 return false; 11049 } 11050 11051 // This is guaranteed to run after super(), so we don't need TDZ checks. 11052 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_this_())) { 11053 // [stack] ARRAY LENGTH INDEX INITIALIZERS THIS 11054 return false; 11055 } 11056 11057 if (!emit1(JSOp::Swap)) { 11058 // [stack] ARRAY LENGTH INDEX THIS INITIALIZERS 11059 return false; 11060 } 11061 11062 DecoratorEmitter de(this); 11063 if (!de.emitInitializeFieldOrAccessor()) { 11064 // [stack] ARRAY LENGTH INDEX 11065 return false; 11066 } 11067 11068 if (!emit1(JSOp::Inc)) { 11069 // [stack] ARRAY LENGTH INDEX 11070 return false; 11071 } 11072 11073 if (!wh.emitEnd()) { 11074 // [stack] ARRAY LENGTH INDEX 11075 return false; 11076 } 11077 11078 if (!emitPopN(3)) { 11079 // [stack] 11080 return false; 11081 } 11082 // 5. Return unused. 11083 11084 if (!de.emitCallExtraInitializers(TaggedParserAtomIndex::WellKnown:: 11085 dot_instanceExtraInitializers_())) { 11086 return false; 11087 } 11088 } 11089 #endif 11090 } 11091 return true; 11092 } 11093 11094 bool BytecodeEmitter::emitInitializeStaticFields(ListNode* classMembers) { 11095 auto isStaticField = [](ParseNode* propdef) { 11096 return HasInitializer(propdef, true); 11097 }; 11098 size_t numFields = 11099 std::count_if(classMembers->contents().begin(), 11100 classMembers->contents().end(), isStaticField); 11101 11102 if (numFields == 0) { 11103 return true; 11104 } 11105 11106 if (!emitGetName( 11107 TaggedParserAtomIndex::WellKnown::dot_staticInitializers_())) { 11108 // [stack] CTOR ARRAY 11109 return false; 11110 } 11111 11112 for (size_t fieldIndex = 0; fieldIndex < numFields; fieldIndex++) { 11113 bool hasNext = fieldIndex < numFields - 1; 11114 if (hasNext) { 11115 // We Dup to keep the array around (it is consumed in the bytecode below) 11116 // for next iterations of this loop, except for the last iteration, which 11117 // avoids an extra Pop at the end of the loop. 11118 if (!emit1(JSOp::Dup)) { 11119 // [stack] CTOR ARRAY ARRAY 11120 return false; 11121 } 11122 } 11123 11124 if (!emitNumberOp(fieldIndex)) { 11125 // [stack] CTOR ARRAY? ARRAY INDEX 11126 return false; 11127 } 11128 11129 if (!emit1(JSOp::GetElem)) { 11130 // [stack] CTOR ARRAY? FUNC 11131 return false; 11132 } 11133 11134 if (!emitDupAt(1 + hasNext)) { 11135 // [stack] CTOR ARRAY? FUNC CTOR 11136 return false; 11137 } 11138 11139 // Callee is always internal function. 11140 if (!emitCall(JSOp::CallIgnoresRv, 0)) { 11141 // [stack] CTOR ARRAY? RVAL 11142 return false; 11143 } 11144 11145 if (!emit1(JSOp::Pop)) { 11146 // [stack] CTOR ARRAY? 11147 return false; 11148 } 11149 } 11150 11151 #ifdef ENABLE_DECORATORS 11152 // Decorators Proposal 11153 // https://arai-a.github.io/ecma262-compare/?pr=2417&id=sec-initializeinstanceelements 11154 // 4. For each element e of elements, do 11155 // 4.a. If elementRecord.[[Kind]] is field or accessor, then 11156 // 4.a.i. Perform ? InitializeFieldOrAccessor(O, elementRecord). 11157 // 11158 11159 // TODO: (See Bug 1817993) At the moment, we're applying the initialization 11160 // logic in two steps. The pre-decorator initialization code runs, stores 11161 // the initial value, and then we retrieve it here and apply the 11162 // initializers added by decorators. We should unify these two steps. 11163 if (!emitGetName( 11164 TaggedParserAtomIndex::WellKnown::dot_staticInitializers_())) { 11165 // [stack] CTOR ARRAY 11166 return false; 11167 } 11168 11169 if (!emit1(JSOp::Dup)) { 11170 // [stack] CTOR ARRAY ARRAY 11171 return false; 11172 } 11173 11174 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::length())) { 11175 // [stack] CTOR ARRAY LENGTH 11176 return false; 11177 } 11178 11179 if (!emitNumberOp(static_cast<double>(numFields))) { 11180 // [stack] CTOR ARRAY LENGTH INDEX 11181 return false; 11182 } 11183 11184 InternalWhileEmitter wh(this); 11185 // At this point, we have no context to determine offsets in the 11186 // code for this while statement. Ideally, it would correspond to 11187 // the field we're initializing. 11188 if (!wh.emitCond()) { 11189 // [stack] CTOR ARRAY LENGTH INDEX 11190 return false; 11191 } 11192 11193 if (!emit1(JSOp::Dup)) { 11194 // [stack] CTOR ARRAY LENGTH INDEX INDEX 11195 return false; 11196 } 11197 11198 if (!emitDupAt(2)) { 11199 // [stack] CTOR ARRAY LENGTH INDEX INDEX LENGTH 11200 return false; 11201 } 11202 11203 if (!emit1(JSOp::Lt)) { 11204 // [stack] CTOR ARRAY LENGTH INDEX BOOL 11205 return false; 11206 } 11207 11208 if (!wh.emitBody()) { 11209 // [stack] CTOR ARRAY LENGTH INDEX 11210 return false; 11211 } 11212 11213 if (!emitDupAt(2)) { 11214 // [stack] CTOR ARRAY LENGTH INDEX ARRAY 11215 return false; 11216 } 11217 11218 if (!emitDupAt(1)) { 11219 // [stack] CTOR ARRAY LENGTH INDEX ARRAY INDEX 11220 return false; 11221 } 11222 11223 // Retrieve initializers for this field 11224 if (!emit1(JSOp::GetElem)) { 11225 // [stack] CTOR ARRAY LENGTH INDEX INITIALIZERS 11226 return false; 11227 } 11228 11229 if (!emitDupAt(4)) { 11230 // [stack] CTOR ARRAY LENGTH INDEX INITIALIZERS CTOR 11231 return false; 11232 } 11233 11234 if (!emit1(JSOp::Swap)) { 11235 // [stack] CTOR ARRAY LENGTH INDEX CTOR INITIALIZERS 11236 return false; 11237 } 11238 11239 DecoratorEmitter de(this); 11240 if (!de.emitInitializeFieldOrAccessor()) { 11241 // [stack] CTOR ARRAY LENGTH INDEX 11242 return false; 11243 } 11244 11245 if (!emit1(JSOp::Inc)) { 11246 // [stack] CTOR ARRAY LENGTH INDEX 11247 return false; 11248 } 11249 11250 if (!wh.emitEnd()) { 11251 // [stack] CTOR ARRAY LENGTH INDEX 11252 return false; 11253 } 11254 11255 if (!emitPopN(3)) { 11256 // [stack] CTOR 11257 return false; 11258 } 11259 // 5. Return unused. 11260 #endif 11261 11262 // Overwrite |.staticInitializers| and |.staticFieldKeys| with undefined to 11263 // avoid keeping the arrays alive indefinitely. 11264 auto clearStaticFieldSlot = [&](TaggedParserAtomIndex name) { 11265 NameOpEmitter noe(this, name, NameOpEmitter::Kind::SimpleAssignment); 11266 if (!noe.prepareForRhs()) { 11267 // [stack] ENV? VAL? 11268 return false; 11269 } 11270 11271 if (!emit1(JSOp::Undefined)) { 11272 // [stack] ENV? VAL? UNDEFINED 11273 return false; 11274 } 11275 11276 if (!noe.emitAssignment()) { 11277 // [stack] VAL 11278 return false; 11279 } 11280 11281 if (!emit1(JSOp::Pop)) { 11282 // [stack] 11283 return false; 11284 } 11285 11286 return true; 11287 }; 11288 11289 if (!clearStaticFieldSlot( 11290 TaggedParserAtomIndex::WellKnown::dot_staticInitializers_())) { 11291 return false; 11292 } 11293 11294 auto isStaticFieldWithComputedName = [](ParseNode* propdef) { 11295 return propdef->is<ClassField>() && propdef->as<ClassField>().isStatic() && 11296 propdef->as<ClassField>().name().getKind() == 11297 ParseNodeKind::ComputedName; 11298 }; 11299 11300 if (std::any_of(classMembers->contents().begin(), 11301 classMembers->contents().end(), 11302 isStaticFieldWithComputedName)) { 11303 if (!clearStaticFieldSlot( 11304 TaggedParserAtomIndex::WellKnown::dot_staticFieldKeys_())) { 11305 return false; 11306 } 11307 } 11308 11309 return true; 11310 } 11311 11312 // Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See 11313 // the comment on emitSwitch. 11314 MOZ_NEVER_INLINE bool BytecodeEmitter::emitObject(ListNode* objNode) { 11315 // Note: this method uses the ObjLiteralWriter and emits ObjLiteralStencil 11316 // objects into the GCThingList, which will evaluate them into real GC objects 11317 // or shapes during JSScript::fullyInitFromEmitter. Eventually we want 11318 // JSOp::Object to be a real opcode, but for now, performance constraints 11319 // limit us to evaluating object literals at the end of parse, when we're 11320 // allowed to allocate GC things. 11321 // 11322 // There are four cases here, in descending order of preference: 11323 // 11324 // 1. The list of property names is "normal" and constant (no computed 11325 // values, no integer indices), the values are all simple constants 11326 // (numbers, booleans, strings), *and* this occurs in a run-once 11327 // (singleton) context. In this case, we can emit ObjLiteral 11328 // instructions to build an object with values, and the object will be 11329 // attached to a JSOp::Object opcode, whose semantics are for the backend 11330 // to simply steal the object from the script. 11331 // 11332 // 2. The list of property names is "normal" and constant as above, *and* this 11333 // occurs in a run-once (singleton) context, but some values are complex 11334 // (computed expressions, sub-objects, functions, etc.). In this case, we 11335 // can still use JSOp::Object (because singleton context), but the object 11336 // has |undefined| property values and InitProp ops are emitted to set the 11337 // values. 11338 // 11339 // 3. The list of property names is "normal" and constant as above, but this 11340 // occurs in a non-run-once (non-singleton) context. In this case, we can 11341 // use the ObjLiteral functionality to describe an *empty* object (all 11342 // values left undefined) with the right fields, which will become a 11343 // JSOp::NewObject opcode using the object's shape to speed up the creation 11344 // of the object each time it executes. The emitted bytecode still needs 11345 // InitProp ops to set the values in this case. 11346 // 11347 // 4. Any other case. As a fallback, we use NewInit to create a new, empty 11348 // object (i.e., `{}`) and then emit bytecode to initialize its properties 11349 // one-by-one. 11350 11351 bool useObjLiteral = false; 11352 bool useObjLiteralValues = false; 11353 isPropertyListObjLiteralCompatible(objNode, &useObjLiteralValues, 11354 &useObjLiteral); 11355 11356 // [stack] 11357 // 11358 ObjectEmitter oe(this); 11359 if (useObjLiteral) { 11360 bool singleton = checkSingletonContext() && 11361 !objNode->hasNonConstInitializer() && objNode->head(); 11362 JSOp op; 11363 if (singleton) { 11364 // Case 1 or 2. 11365 op = JSOp::Object; 11366 } else { 11367 // Case 3. 11368 useObjLiteralValues = false; 11369 op = JSOp::NewObject; 11370 } 11371 11372 // Use an ObjLiteral op. This will record ObjLiteral insns in the 11373 // objLiteralWriter's buffer and add a fixup to the list of ObjLiteral 11374 // fixups so that at GC-publish time at the end of parse, the full object 11375 // (case 1 or 2) or shape (case 3) can be allocated and the bytecode can be 11376 // patched to refer to it. 11377 if (!emitPropertyListObjLiteral(objNode, op, useObjLiteralValues)) { 11378 // [stack] OBJ 11379 return false; 11380 } 11381 // Put the ObjectEmitter in the right state. This tells it that there will 11382 // already be an object on the stack as a result of the (eventual) 11383 // NewObject or Object op, and prepares it to emit values if needed. 11384 if (!oe.emitObjectWithTemplateOnStack()) { 11385 // [stack] OBJ 11386 return false; 11387 } 11388 if (!useObjLiteralValues) { 11389 // Case 2 or 3 above: we still need to emit bytecode to fill in the 11390 // object's property values. 11391 if (!emitPropertyList(objNode, oe, ObjectLiteral)) { 11392 // [stack] OBJ 11393 return false; 11394 } 11395 } 11396 } else { 11397 // Case 4 above: no ObjLiteral use, just bytecode to build the object from 11398 // scratch. 11399 if (!oe.emitObject(objNode->count())) { 11400 // [stack] OBJ 11401 return false; 11402 } 11403 if (!emitPropertyList(objNode, oe, ObjectLiteral)) { 11404 // [stack] OBJ 11405 return false; 11406 } 11407 } 11408 11409 if (!oe.emitEnd()) { 11410 // [stack] OBJ 11411 return false; 11412 } 11413 11414 return true; 11415 } 11416 11417 bool BytecodeEmitter::emitArrayLiteral(ListNode* array) { 11418 // Emit JSOp::Object if the array consists entirely of primitive values and we 11419 // are in a singleton context. 11420 if (checkSingletonContext() && !array->hasNonConstInitializer() && 11421 !array->empty() && isArrayObjLiteralCompatible(array)) { 11422 return emitObjLiteralArray(array); 11423 } 11424 11425 return emitArray(array); 11426 } 11427 11428 bool BytecodeEmitter::emitArray(ListNode* array) { 11429 /* 11430 * Emit code for [a, b, c] that is equivalent to constructing a new 11431 * array and in source order evaluating each element value and adding 11432 * it to the array, without invoking latent setters. We use the 11433 * JSOp::NewInit and JSOp::InitElemArray bytecodes to ignore setters and 11434 * to avoid dup'ing and popping the array as each element is added, as 11435 * JSOp::SetElem/JSOp::SetProp would do. 11436 */ 11437 11438 uint32_t nspread = 0; 11439 for (ParseNode* elem : array->contents()) { 11440 if (elem->isKind(ParseNodeKind::Spread)) { 11441 nspread++; 11442 } 11443 } 11444 11445 // Array literal's length is limited to NELEMENTS_LIMIT in parser. 11446 static_assert(NativeObject::MAX_DENSE_ELEMENTS_COUNT <= INT32_MAX, 11447 "array literals' maximum length must not exceed limits " 11448 "required by BaselineCompiler::emit_NewArray, " 11449 "BaselineCompiler::emit_InitElemArray, " 11450 "and DoSetElemFallback's handling of JSOp::InitElemArray"); 11451 11452 uint32_t count = array->count(); 11453 MOZ_ASSERT(count >= nspread); 11454 MOZ_ASSERT(count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT, 11455 "the parser must throw an error if the array exceeds maximum " 11456 "length"); 11457 11458 // For arrays with spread, this is a very pessimistic allocation, the 11459 // minimum possible final size. 11460 if (!emitUint32Operand(JSOp::NewArray, count - nspread)) { 11461 // [stack] ARRAY 11462 return false; 11463 } 11464 11465 uint32_t index = 0; 11466 bool afterSpread = false; 11467 for (ParseNode* elem : array->contents()) { 11468 if (elem->isKind(ParseNodeKind::Spread)) { 11469 if (!afterSpread) { 11470 afterSpread = true; 11471 if (!emitNumberOp(index)) { 11472 // [stack] ARRAY INDEX 11473 return false; 11474 } 11475 } 11476 11477 ParseNode* expr = elem->as<UnaryNode>().kid(); 11478 SelfHostedIter selfHostedIter = getSelfHostedIterFor(expr); 11479 11480 if (!updateSourceCoordNotes(elem->pn_pos.begin)) { 11481 return false; 11482 } 11483 if (!emitIterable(expr, selfHostedIter)) { 11484 // [stack] ARRAY INDEX ITERABLE 11485 return false; 11486 } 11487 if (!emitIterator(selfHostedIter)) { 11488 // [stack] ARRAY INDEX NEXT ITER 11489 return false; 11490 } 11491 if (!emit2(JSOp::Pick, 3)) { 11492 // [stack] INDEX NEXT ITER ARRAY 11493 return false; 11494 } 11495 if (!emit2(JSOp::Pick, 3)) { 11496 // [stack] NEXT ITER ARRAY INDEX 11497 return false; 11498 } 11499 if (!emitSpread(selfHostedIter)) { 11500 // [stack] ARRAY INDEX 11501 return false; 11502 } 11503 } else { 11504 if (!updateSourceCoordNotesIfNonLiteral(elem)) { 11505 return false; 11506 } 11507 if (elem->isKind(ParseNodeKind::Elision)) { 11508 if (!emit1(JSOp::Hole)) { 11509 return false; 11510 } 11511 } else { 11512 if (!emitTree(elem, ValueUsage::WantValue)) { 11513 // [stack] ARRAY INDEX? VALUE 11514 return false; 11515 } 11516 } 11517 11518 if (afterSpread) { 11519 if (!emit1(JSOp::InitElemInc)) { 11520 // [stack] ARRAY (INDEX+1) 11521 return false; 11522 } 11523 } else { 11524 if (!emitUint32Operand(JSOp::InitElemArray, index)) { 11525 // [stack] ARRAY 11526 return false; 11527 } 11528 } 11529 } 11530 11531 index++; 11532 } 11533 MOZ_ASSERT(index == count); 11534 if (afterSpread) { 11535 if (!emit1(JSOp::Pop)) { 11536 // [stack] ARRAY 11537 return false; 11538 } 11539 } 11540 return true; 11541 } 11542 11543 bool BytecodeEmitter::emitSpreadIntoArray(UnaryNode* elem) { 11544 MOZ_ASSERT(elem->isKind(ParseNodeKind::Spread)); 11545 11546 if (!updateSourceCoordNotes(elem->pn_pos.begin)) { 11547 // [stack] VALUE 11548 return false; 11549 } 11550 11551 SelfHostedIter selfHostedIter = getSelfHostedIterFor(elem->kid()); 11552 MOZ_ASSERT(selfHostedIter == SelfHostedIter::Deny || 11553 selfHostedIter == SelfHostedIter::AllowContent); 11554 11555 if (!emitIterator(selfHostedIter)) { 11556 // [stack] NEXT ITER 11557 return false; 11558 } 11559 11560 if (!emitUint32Operand(JSOp::NewArray, 0)) { 11561 // [stack] NEXT ITER ARRAY 11562 return false; 11563 } 11564 11565 if (!emitNumberOp(0)) { 11566 // [stack] NEXT ITER ARRAY INDEX 11567 return false; 11568 } 11569 11570 if (!emitSpread(selfHostedIter)) { 11571 // [stack] ARRAY INDEX 11572 return false; 11573 } 11574 11575 if (!emit1(JSOp::Pop)) { 11576 // [stack] ARRAY 11577 return false; 11578 } 11579 return true; 11580 } 11581 11582 static inline JSOp UnaryOpParseNodeKindToJSOp(ParseNodeKind pnk) { 11583 switch (pnk) { 11584 case ParseNodeKind::ThrowStmt: 11585 return JSOp::Throw; 11586 case ParseNodeKind::VoidExpr: 11587 return JSOp::Void; 11588 case ParseNodeKind::NotExpr: 11589 return JSOp::Not; 11590 case ParseNodeKind::BitNotExpr: 11591 return JSOp::BitNot; 11592 case ParseNodeKind::PosExpr: 11593 return JSOp::Pos; 11594 case ParseNodeKind::NegExpr: 11595 return JSOp::Neg; 11596 default: 11597 MOZ_CRASH("unexpected unary op"); 11598 } 11599 } 11600 11601 bool BytecodeEmitter::emitUnary(UnaryNode* unaryNode) { 11602 if (!updateSourceCoordNotes(unaryNode->pn_pos.begin)) { 11603 return false; 11604 } 11605 11606 JSOp op = UnaryOpParseNodeKindToJSOp(unaryNode->getKind()); 11607 ValueUsage valueUsage = 11608 op == JSOp::Void ? ValueUsage::IgnoreValue : ValueUsage::WantValue; 11609 if (!emitTree(unaryNode->kid(), valueUsage)) { 11610 return false; 11611 } 11612 return emit1(op); 11613 } 11614 11615 bool BytecodeEmitter::emitTypeof(UnaryNode* typeofNode, JSOp op) { 11616 MOZ_ASSERT(op == JSOp::Typeof || op == JSOp::TypeofExpr); 11617 11618 if (!updateSourceCoordNotes(typeofNode->pn_pos.begin)) { 11619 return false; 11620 } 11621 11622 if (!emitTree(typeofNode->kid())) { 11623 return false; 11624 } 11625 11626 return emit1(op); 11627 } 11628 11629 bool BytecodeEmitter::tryEmitTypeofEq(ListNode* node, bool* emitted) { 11630 // Emit specialized opcode for the following if possible: 11631 // * typeof val == "type" 11632 // * typeof val != "type" 11633 // * typeof val > "u" # minified `typeof val === "undefined"` 11634 // * typeof val < "u" # minified `typeof val !== "undefined"` 11635 // 11636 // NOTE: Given the comparison is done for string, `==` and `===` have 11637 // no difference. Same for `!=` and `!==`. 11638 MOZ_ASSERT(node->isKind(ParseNodeKind::StrictEqExpr) || 11639 node->isKind(ParseNodeKind::EqExpr) || 11640 node->isKind(ParseNodeKind::StrictNeExpr) || 11641 node->isKind(ParseNodeKind::NeExpr) || 11642 node->isKind(ParseNodeKind::LtExpr) || 11643 node->isKind(ParseNodeKind::GtExpr)); 11644 11645 if (node->count() != 2) { 11646 *emitted = false; 11647 return true; 11648 } 11649 11650 ParseNode* left = node->head(); 11651 ParseNode* right = left->pn_next; 11652 MOZ_ASSERT(right); 11653 11654 UnaryNode* typeofNode; 11655 NameNode* typenameNode; 11656 JSOp op; 11657 JSType type; 11658 11659 if (node->isKind(ParseNodeKind::LtExpr) || 11660 node->isKind(ParseNodeKind::GtExpr)) { 11661 if (left->isKind(ParseNodeKind::TypeOfNameExpr) && 11662 right->isKind(ParseNodeKind::StringExpr)) { 11663 typeofNode = &left->as<UnaryNode>(); 11664 typenameNode = &right->as<NameNode>(); 11665 11666 if (node->isKind(ParseNodeKind::LtExpr)) { 11667 op = JSOp::Ne; 11668 } else { 11669 op = JSOp::Eq; 11670 } 11671 } else if (left->isKind(ParseNodeKind::TypeOfNameExpr) && 11672 right->isKind(ParseNodeKind::StringExpr)) { 11673 typeofNode = &left->as<UnaryNode>(); 11674 typenameNode = &right->as<NameNode>(); 11675 11676 if (node->isKind(ParseNodeKind::LtExpr)) { 11677 op = JSOp::Eq; 11678 } else { 11679 op = JSOp::Ne; 11680 } 11681 } else { 11682 *emitted = false; 11683 return true; 11684 } 11685 11686 TaggedParserAtomIndex typeName = typenameNode->atom(); 11687 if (typeName.isLength1StaticParserString() && 11688 typeName.toLength1StaticParserString() == 11689 Length1StaticParserString('u')) { 11690 type = JSTYPE_UNDEFINED; 11691 } else { 11692 *emitted = false; 11693 return true; 11694 } 11695 } else { 11696 if (node->isKind(ParseNodeKind::StrictEqExpr) || 11697 node->isKind(ParseNodeKind::EqExpr)) { 11698 op = JSOp::Eq; 11699 } else { 11700 op = JSOp::Ne; 11701 } 11702 11703 // NOTE: ParseNodeKind::TypeOfExpr cannot use JSOp::TypeofEq. 11704 // See JSOp::GetName document. 11705 if (left->isKind(ParseNodeKind::TypeOfNameExpr) && 11706 right->isKind(ParseNodeKind::StringExpr)) { 11707 typeofNode = &left->as<UnaryNode>(); 11708 typenameNode = &right->as<NameNode>(); 11709 } else if (right->isKind(ParseNodeKind::TypeOfNameExpr) && 11710 left->isKind(ParseNodeKind::StringExpr)) { 11711 typeofNode = &right->as<UnaryNode>(); 11712 typenameNode = &left->as<NameNode>(); 11713 } else { 11714 *emitted = false; 11715 return true; 11716 } 11717 11718 TaggedParserAtomIndex typeName = typenameNode->atom(); 11719 if (typeName == TaggedParserAtomIndex::WellKnown::undefined()) { 11720 type = JSTYPE_UNDEFINED; 11721 } else if (typeName == TaggedParserAtomIndex::WellKnown::object()) { 11722 type = JSTYPE_OBJECT; 11723 } else if (typeName == TaggedParserAtomIndex::WellKnown::function()) { 11724 type = JSTYPE_FUNCTION; 11725 } else if (typeName == TaggedParserAtomIndex::WellKnown::string()) { 11726 type = JSTYPE_STRING; 11727 } else if (typeName == TaggedParserAtomIndex::WellKnown::number()) { 11728 type = JSTYPE_NUMBER; 11729 } else if (typeName == TaggedParserAtomIndex::WellKnown::boolean()) { 11730 type = JSTYPE_BOOLEAN; 11731 } else if (typeName == TaggedParserAtomIndex::WellKnown::symbol()) { 11732 type = JSTYPE_SYMBOL; 11733 } else if (typeName == TaggedParserAtomIndex::WellKnown::bigint()) { 11734 type = JSTYPE_BIGINT; 11735 } else { 11736 *emitted = false; 11737 return true; 11738 } 11739 } 11740 11741 if (!updateSourceCoordNotes(typeofNode->pn_pos.begin)) { 11742 return false; 11743 } 11744 11745 if (!emitTree(typeofNode->kid())) { 11746 // [stack] VAL 11747 return false; 11748 } 11749 11750 if (!emit2(JSOp::TypeofEq, TypeofEqOperand(type, op).rawValue())) { 11751 // [stack] CMP 11752 return false; 11753 } 11754 11755 *emitted = true; 11756 return true; 11757 } 11758 11759 bool BytecodeEmitter::emitFunctionFormalParameters(ParamsBodyNode* paramsBody) { 11760 FunctionBox* funbox = sc->asFunctionBox(); 11761 11762 bool hasRest = funbox->hasRest(); 11763 11764 FunctionParamsEmitter fpe(this, funbox); 11765 for (ParseNode* arg : paramsBody->parameters()) { 11766 ParseNode* bindingElement = arg; 11767 ParseNode* initializer = nullptr; 11768 if (arg->isKind(ParseNodeKind::AssignExpr)) { 11769 bindingElement = arg->as<BinaryNode>().left(); 11770 initializer = arg->as<BinaryNode>().right(); 11771 } 11772 bool hasInitializer = !!initializer; 11773 bool isRest = 11774 hasRest && arg->pn_next == *std::end(paramsBody->parameters()); 11775 bool isDestructuring = !bindingElement->isKind(ParseNodeKind::Name); 11776 11777 // Left-hand sides are either simple names or destructuring patterns. 11778 MOZ_ASSERT(bindingElement->isKind(ParseNodeKind::Name) || 11779 bindingElement->isKind(ParseNodeKind::ArrayExpr) || 11780 bindingElement->isKind(ParseNodeKind::ObjectExpr)); 11781 11782 auto emitDefaultInitializer = [this, &initializer, &bindingElement]() { 11783 // [stack] 11784 11785 if (!this->emitInitializer(initializer, bindingElement)) { 11786 // [stack] DEFAULT 11787 return false; 11788 } 11789 return true; 11790 }; 11791 11792 auto emitDestructuring = [this, &bindingElement]() { 11793 // [stack] ARG 11794 11795 if (!this->emitDestructuringOps(&bindingElement->as<ListNode>(), 11796 DestructuringFlavor::Declaration, 11797 SelfHostedIter::Deny)) { 11798 // [stack] ARG 11799 return false; 11800 } 11801 11802 return true; 11803 }; 11804 11805 if (isRest) { 11806 if (isDestructuring) { 11807 if (!fpe.prepareForDestructuringRest()) { 11808 // [stack] 11809 return false; 11810 } 11811 if (!emitDestructuring()) { 11812 // [stack] 11813 return false; 11814 } 11815 if (!fpe.emitDestructuringRestEnd()) { 11816 // [stack] 11817 return false; 11818 } 11819 } else { 11820 auto paramName = bindingElement->as<NameNode>().name(); 11821 if (!fpe.emitRest(paramName)) { 11822 // [stack] 11823 return false; 11824 } 11825 } 11826 11827 continue; 11828 } 11829 11830 if (isDestructuring) { 11831 if (hasInitializer) { 11832 if (!fpe.prepareForDestructuringDefaultInitializer()) { 11833 // [stack] 11834 return false; 11835 } 11836 if (!emitDefaultInitializer()) { 11837 // [stack] 11838 return false; 11839 } 11840 if (!fpe.prepareForDestructuringDefault()) { 11841 // [stack] 11842 return false; 11843 } 11844 if (!emitDestructuring()) { 11845 // [stack] 11846 return false; 11847 } 11848 if (!fpe.emitDestructuringDefaultEnd()) { 11849 // [stack] 11850 return false; 11851 } 11852 } else { 11853 if (!fpe.prepareForDestructuring()) { 11854 // [stack] 11855 return false; 11856 } 11857 if (!emitDestructuring()) { 11858 // [stack] 11859 return false; 11860 } 11861 if (!fpe.emitDestructuringEnd()) { 11862 // [stack] 11863 return false; 11864 } 11865 } 11866 11867 continue; 11868 } 11869 11870 if (hasInitializer) { 11871 if (!fpe.prepareForDefault()) { 11872 // [stack] 11873 return false; 11874 } 11875 if (!emitDefaultInitializer()) { 11876 // [stack] 11877 return false; 11878 } 11879 auto paramName = bindingElement->as<NameNode>().name(); 11880 if (!fpe.emitDefaultEnd(paramName)) { 11881 // [stack] 11882 return false; 11883 } 11884 11885 continue; 11886 } 11887 11888 auto paramName = bindingElement->as<NameNode>().name(); 11889 if (!fpe.emitSimple(paramName)) { 11890 // [stack] 11891 return false; 11892 } 11893 } 11894 11895 return true; 11896 } 11897 11898 bool BytecodeEmitter::emitInitializeFunctionSpecialNames() { 11899 FunctionBox* funbox = sc->asFunctionBox(); 11900 11901 // [stack] 11902 11903 auto emitInitializeFunctionSpecialName = 11904 [](BytecodeEmitter* bce, TaggedParserAtomIndex name, JSOp op) { 11905 // A special name must be slotful, either on the frame or on the 11906 // call environment. 11907 MOZ_ASSERT(bce->lookupName(name).hasKnownSlot()); 11908 11909 NameOpEmitter noe(bce, name, NameOpEmitter::Kind::Initialize); 11910 if (!noe.prepareForRhs()) { 11911 // [stack] 11912 return false; 11913 } 11914 if (!bce->emit1(op)) { 11915 // [stack] THIS/ARGUMENTS/NEW.TARGET 11916 return false; 11917 } 11918 if (!noe.emitAssignment()) { 11919 // [stack] THIS/ARGUMENTS/NEW.TARGET 11920 return false; 11921 } 11922 if (!bce->emit1(JSOp::Pop)) { 11923 // [stack] 11924 return false; 11925 } 11926 11927 return true; 11928 }; 11929 11930 // Do nothing if the function doesn't have an arguments binding. 11931 if (funbox->needsArgsObj()) { 11932 // Self-hosted code should use the more efficient ArgumentsLength and 11933 // GetArgument intrinsics instead of `arguments`. 11934 MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting); 11935 if (!emitInitializeFunctionSpecialName( 11936 this, TaggedParserAtomIndex::WellKnown::arguments(), 11937 JSOp::Arguments)) { 11938 // [stack] 11939 return false; 11940 } 11941 } 11942 11943 // Do nothing if the function doesn't have a this-binding (this 11944 // happens for instance if it doesn't use this/eval or if it's an 11945 // arrow function). 11946 if (funbox->functionHasThisBinding()) { 11947 if (!emitInitializeFunctionSpecialName( 11948 this, TaggedParserAtomIndex::WellKnown::dot_this_(), 11949 JSOp::FunctionThis)) { 11950 return false; 11951 } 11952 } 11953 11954 // Do nothing if the function doesn't have a new.target-binding (this happens 11955 // for instance if it doesn't use new.target/eval or if it's an arrow 11956 // function). 11957 if (funbox->functionHasNewTargetBinding()) { 11958 if (!emitInitializeFunctionSpecialName( 11959 this, TaggedParserAtomIndex::WellKnown::dot_newTarget_(), 11960 JSOp::NewTarget)) { 11961 return false; 11962 } 11963 } 11964 11965 // Do nothing if the function doesn't implicitly return a promise result. 11966 if (funbox->needsPromiseResult()) { 11967 if (!emitInitializeFunctionSpecialName( 11968 this, TaggedParserAtomIndex::WellKnown::dot_generator_(), 11969 JSOp::Generator)) { 11970 // [stack] 11971 return false; 11972 } 11973 } 11974 return true; 11975 } 11976 11977 bool BytecodeEmitter::emitLexicalInitialization(NameNode* name) { 11978 return emitLexicalInitialization(name->name()); 11979 } 11980 11981 bool BytecodeEmitter::emitLexicalInitialization(TaggedParserAtomIndex name) { 11982 NameOpEmitter noe(this, name, NameOpEmitter::Kind::Initialize); 11983 if (!noe.prepareForRhs()) { 11984 return false; 11985 } 11986 11987 // The caller has pushed the RHS to the top of the stack. Assert that the 11988 // binding can be initialized without a binding object on the stack, and that 11989 // no JSOp::BindUnqualifiedName or JSOp::BindUnqualifiedGName ops were 11990 // emitted. 11991 MOZ_ASSERT(noe.loc().isLexical() || noe.loc().isSynthetic() || 11992 noe.loc().isPrivateMethod()); 11993 MOZ_ASSERT(!noe.emittedBindOp()); 11994 11995 if (!noe.emitAssignment()) { 11996 return false; 11997 } 11998 11999 return true; 12000 } 12001 12002 static MOZ_ALWAYS_INLINE ParseNode* FindConstructor(ListNode* classMethods) { 12003 for (ParseNode* classElement : classMethods->contents()) { 12004 ParseNode* unwrappedElement = classElement; 12005 if (unwrappedElement->is<LexicalScopeNode>()) { 12006 unwrappedElement = unwrappedElement->as<LexicalScopeNode>().scopeBody(); 12007 } 12008 if (unwrappedElement->is<ClassMethod>()) { 12009 ClassMethod& method = unwrappedElement->as<ClassMethod>(); 12010 ParseNode& methodName = method.name(); 12011 if (!method.isStatic() && 12012 (methodName.isKind(ParseNodeKind::ObjectPropertyName) || 12013 methodName.isKind(ParseNodeKind::StringExpr)) && 12014 methodName.as<NameNode>().atom() == 12015 TaggedParserAtomIndex::WellKnown::constructor()) { 12016 return classElement; 12017 } 12018 } 12019 } 12020 return nullptr; 12021 } 12022 12023 bool BytecodeEmitter::emitNewPrivateName(TaggedParserAtomIndex bindingName, 12024 TaggedParserAtomIndex symbolName) { 12025 if (!emitAtomOp(JSOp::NewPrivateName, symbolName)) { 12026 // [stack] HERITAGE PRIVATENAME 12027 return false; 12028 } 12029 12030 // Add a binding for #name => privatename 12031 if (!emitLexicalInitialization(bindingName)) { 12032 // [stack] HERITAGE PRIVATENAME 12033 return false; 12034 } 12035 12036 // Pop Private name off the stack. 12037 if (!emit1(JSOp::Pop)) { 12038 // [stack] HERITAGE 12039 return false; 12040 } 12041 12042 return true; 12043 } 12044 12045 bool BytecodeEmitter::emitNewPrivateNames( 12046 TaggedParserAtomIndex privateBrandName, ListNode* classMembers) { 12047 bool hasPrivateBrand = false; 12048 12049 for (ParseNode* classElement : classMembers->contents()) { 12050 ParseNode* elementName; 12051 if (classElement->is<ClassMethod>()) { 12052 elementName = &classElement->as<ClassMethod>().name(); 12053 } else if (classElement->is<ClassField>()) { 12054 elementName = &classElement->as<ClassField>().name(); 12055 } else { 12056 continue; 12057 } 12058 12059 if (!elementName->isKind(ParseNodeKind::PrivateName)) { 12060 continue; 12061 } 12062 12063 // Non-static private methods' private names are optimized away. 12064 bool isOptimized = false; 12065 if (classElement->is<ClassMethod>() && 12066 !classElement->as<ClassMethod>().isStatic()) { 12067 hasPrivateBrand = true; 12068 if (classElement->as<ClassMethod>().accessorType() == 12069 AccessorType::None) { 12070 isOptimized = true; 12071 } 12072 } 12073 12074 if (!isOptimized) { 12075 auto privateName = elementName->as<NameNode>().name(); 12076 if (!emitNewPrivateName(privateName, privateName)) { 12077 return false; 12078 } 12079 } 12080 } 12081 12082 if (hasPrivateBrand) { 12083 // We don't make a private name for every optimized method, but we need one 12084 // private name per class, the `.privateBrand`. 12085 if (!emitNewPrivateName( 12086 TaggedParserAtomIndex::WellKnown::dot_privateBrand_(), 12087 privateBrandName)) { 12088 return false; 12089 } 12090 } 12091 return true; 12092 } 12093 12094 // This follows ES6 14.5.14 (ClassDefinitionEvaluation) and ES6 14.5.15 12095 // (BindingClassDeclarationEvaluation). 12096 bool BytecodeEmitter::emitClass( 12097 ClassNode* classNode, 12098 ClassNameKind nameKind /* = ClassNameKind::BindingName */, 12099 TaggedParserAtomIndex 12100 nameForAnonymousClass /* = TaggedParserAtomIndex::null() */) { 12101 MOZ_ASSERT((nameKind == ClassNameKind::InferredName) == 12102 bool(nameForAnonymousClass)); 12103 12104 ParseNode* heritageExpression = classNode->heritage(); 12105 ListNode* classMembers = classNode->memberList(); 12106 ParseNode* constructor = FindConstructor(classMembers); 12107 12108 // If |nameKind != ClassNameKind::ComputedName| 12109 // [stack] 12110 // Else 12111 // [stack] NAME 12112 12113 ClassEmitter ce(this); 12114 TaggedParserAtomIndex innerName; 12115 ClassEmitter::Kind kind = ClassEmitter::Kind::Expression; 12116 if (ClassNames* names = classNode->names()) { 12117 MOZ_ASSERT(nameKind == ClassNameKind::BindingName); 12118 innerName = names->innerBinding()->name(); 12119 MOZ_ASSERT(innerName); 12120 12121 if (names->outerBinding()) { 12122 MOZ_ASSERT(names->outerBinding()->name()); 12123 MOZ_ASSERT(names->outerBinding()->name() == innerName); 12124 kind = ClassEmitter::Kind::Declaration; 12125 } 12126 } 12127 12128 if (LexicalScopeNode* scopeBindings = classNode->scopeBindings()) { 12129 if (!ce.emitScope(scopeBindings->scopeBindings())) { 12130 // [stack] 12131 return false; 12132 } 12133 } 12134 12135 bool isDerived = !!heritageExpression; 12136 if (isDerived) { 12137 if (!updateSourceCoordNotes(classNode->pn_pos.begin)) { 12138 return false; 12139 } 12140 if (!markStepBreakpoint()) { 12141 return false; 12142 } 12143 if (!emitTree(heritageExpression)) { 12144 // [stack] HERITAGE 12145 return false; 12146 } 12147 } 12148 12149 // The class body scope holds any private names. Those mustn't be visible in 12150 // the heritage expression and hence the scope must be emitted after the 12151 // heritage expression. 12152 if (ClassBodyScopeNode* bodyScopeBindings = classNode->bodyScopeBindings()) { 12153 if (!ce.emitBodyScope(bodyScopeBindings->scopeBindings())) { 12154 // [stack] HERITAGE 12155 return false; 12156 } 12157 12158 // The spec does not say anything about private brands being symbols. It's 12159 // an implementation detail. So we can give the special private brand 12160 // symbol any description we want and users won't normally see it. For 12161 // debugging, use the class name. 12162 auto privateBrandName = innerName; 12163 if (!innerName) { 12164 privateBrandName = nameForAnonymousClass 12165 ? nameForAnonymousClass 12166 : TaggedParserAtomIndex::WellKnown::anonymous(); 12167 } 12168 if (!emitNewPrivateNames(privateBrandName, classMembers)) { 12169 return false; 12170 } 12171 } 12172 12173 bool hasNameOnStack = nameKind == ClassNameKind::ComputedName; 12174 if (isDerived) { 12175 if (!ce.emitDerivedClass(innerName, nameForAnonymousClass, 12176 hasNameOnStack)) { 12177 // [stack] HOMEOBJ HERITAGE 12178 return false; 12179 } 12180 } else { 12181 int membersCount = 0; 12182 for (ParseNode* node : classMembers->contents()) { 12183 if (node->getKind() == ParseNodeKind::ClassField) { 12184 membersCount++; 12185 } 12186 } 12187 membersCount = (membersCount > 255) ? 255 : membersCount; 12188 if (!ce.emitClass(innerName, nameForAnonymousClass, hasNameOnStack, 12189 uint8_t(membersCount))) { 12190 // [stack] HOMEOBJ 12191 return false; 12192 } 12193 } 12194 12195 // Stack currently has HOMEOBJ followed by optional HERITAGE. When HERITAGE 12196 // is not used, an implicit value of %FunctionPrototype% is implied. 12197 12198 // See |Parser::classMember(...)| for the reason why |.initializers| is 12199 // created within its own scope. 12200 Maybe<LexicalScopeEmitter> lse; 12201 FunctionNode* ctor; 12202 #ifdef ENABLE_DECORATORS 12203 bool extraInitializersPresent = false; 12204 #endif 12205 if (constructor->is<LexicalScopeNode>()) { 12206 LexicalScopeNode* constructorScope = &constructor->as<LexicalScopeNode>(); 12207 12208 MOZ_ASSERT(!constructorScope->isEmptyScope()); 12209 #ifdef ENABLE_DECORATORS 12210 // With decorators enabled we expect to see |.initializers|, 12211 // and |.instanceExtraInitializers| in this scope. 12212 MOZ_ASSERT(constructorScope->scopeBindings()->length == 2); 12213 MOZ_ASSERT(GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] 12214 .name() == 12215 TaggedParserAtomIndex::WellKnown::dot_initializers_()); 12216 MOZ_ASSERT( 12217 GetScopeDataTrailingNames(constructorScope->scopeBindings())[1] 12218 .name() == 12219 TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_()); 12220 12221 // We should only call this code if we know decorators are present, see bug 12222 // 1871147. 12223 lse.emplace(this); 12224 if (!lse->emitScope(ScopeKind::Lexical, 12225 constructorScope->scopeBindings())) { 12226 return false; 12227 } 12228 12229 // TODO: See bug 1868220 for support for static extra initializers. 12230 if (!ce.prepareForExtraInitializers(TaggedParserAtomIndex::WellKnown:: 12231 dot_instanceExtraInitializers_())) { 12232 return false; 12233 } 12234 12235 if (classNode->addInitializerFunction()) { 12236 DecoratorEmitter de(this); 12237 if (!de.emitCreateAddInitializerFunction( 12238 classNode->addInitializerFunction(), 12239 TaggedParserAtomIndex::WellKnown:: 12240 dot_instanceExtraInitializers_())) { 12241 // [stack] HOMEOBJ HERITAGE? ADDINIT 12242 return false; 12243 } 12244 12245 if (!emitUnpickN(isDerived ? 2 : 1)) { 12246 // [stack] ADDINIT HOMEOBJ HERITAGE? 12247 return false; 12248 } 12249 12250 extraInitializersPresent = true; 12251 } 12252 #else 12253 // The constructor scope should only contain the |.initializers| binding. 12254 MOZ_ASSERT(constructorScope->scopeBindings()->length == 1); 12255 MOZ_ASSERT(GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] 12256 .name() == 12257 TaggedParserAtomIndex::WellKnown::dot_initializers_()); 12258 #endif 12259 12260 auto needsInitializer = [](ParseNode* propdef) { 12261 return NeedsFieldInitializer(propdef, false) || 12262 NeedsAccessorInitializer(propdef, false); 12263 }; 12264 12265 // As an optimization omit the |.initializers| binding when no instance 12266 // fields or private methods are present. 12267 bool needsInitializers = 12268 std::any_of(classMembers->contents().begin(), 12269 classMembers->contents().end(), needsInitializer); 12270 if (needsInitializers) { 12271 #ifndef ENABLE_DECORATORS 12272 lse.emplace(this); 12273 if (!lse->emitScope(ScopeKind::Lexical, 12274 constructorScope->scopeBindings())) { 12275 return false; 12276 } 12277 #endif 12278 // Any class with field initializers will have a constructor 12279 if (!emitCreateMemberInitializers(ce, classMembers, 12280 FieldPlacement::Instance 12281 #ifdef ENABLE_DECORATORS 12282 , 12283 isDerived 12284 #endif 12285 )) { 12286 return false; 12287 } 12288 } 12289 12290 ctor = &constructorScope->scopeBody()->as<ClassMethod>().method(); 12291 } else { 12292 // The |.initializers| binding is never emitted when in self-hosting mode. 12293 MOZ_ASSERT(emitterMode == BytecodeEmitter::SelfHosting); 12294 ctor = &constructor->as<ClassMethod>().method(); 12295 } 12296 12297 bool needsHomeObject = ctor->funbox()->needsHomeObject(); 12298 // HERITAGE is consumed inside emitFunction. 12299 if (nameKind == ClassNameKind::InferredName) { 12300 setFunName(ctor->funbox(), nameForAnonymousClass); 12301 } 12302 if (!emitFunction(ctor, isDerived)) { 12303 // [stack] HOMEOBJ CTOR 12304 return false; 12305 } 12306 if (lse.isSome()) { 12307 if (!lse->emitEnd()) { 12308 return false; 12309 } 12310 lse.reset(); 12311 } 12312 if (!ce.emitInitConstructor(needsHomeObject)) { 12313 // [stack] CTOR HOMEOBJ 12314 return false; 12315 } 12316 12317 if (!emitCreateFieldKeys(classMembers, FieldPlacement::Instance)) { 12318 return false; 12319 } 12320 12321 #ifdef ENABLE_DECORATORS 12322 // TODO: See Bug 1868220 for support for static extra initializers. 12323 if (!emit1(JSOp::Undefined)) { 12324 // [stack] ADDINIT? CTOR HOMEOBJ UNDEFINED 12325 return false; 12326 } 12327 if (!emitUnpickN(2)) { 12328 // [stack] ADDINIT? UNDEFINED CTOR HOMEOBJ 12329 return false; 12330 } 12331 #endif 12332 12333 if (!emitCreateMemberInitializers(ce, classMembers, FieldPlacement::Static 12334 #ifdef ENABLE_DECORATORS 12335 , 12336 false 12337 #endif 12338 )) { 12339 return false; 12340 } 12341 12342 #ifdef ENABLE_DECORATORS 12343 if (!emitPickN(2)) { 12344 // [stack] ADDINIT? CTOR HOMEOBJ UNDEFINED 12345 return false; 12346 } 12347 if (!emitPopN(1)) { 12348 // [stack] ADDINIT? CTOR HOMEOBJ 12349 return false; 12350 } 12351 #endif 12352 12353 if (!emitCreateFieldKeys(classMembers, FieldPlacement::Static)) { 12354 return false; 12355 } 12356 12357 if (!emitPropertyList(classMembers, ce, ClassBody)) { 12358 // [stack] CTOR HOMEOBJ 12359 return false; 12360 } 12361 12362 #ifdef ENABLE_DECORATORS 12363 if (extraInitializersPresent) { 12364 if (!emitPickN(2)) { 12365 // [stack] CTOR HOMEOBJ ADDINIT 12366 return false; 12367 } 12368 if (!emitPopN(1)) { 12369 // [stack] CTOR HOMEOBJ 12370 return false; 12371 } 12372 } 12373 #endif 12374 12375 if (!ce.emitBinding()) { 12376 // [stack] CTOR 12377 return false; 12378 } 12379 12380 if (!emitInitializeStaticFields(classMembers)) { 12381 // [stack] CTOR 12382 return false; 12383 } 12384 12385 #if ENABLE_DECORATORS 12386 if (!ce.prepareForDecorators()) { 12387 // [stack] CTOR 12388 return false; 12389 } 12390 if (classNode->decorators() != nullptr) { 12391 DecoratorEmitter de(this); 12392 NameNode* className = 12393 classNode->names() ? classNode->names()->innerBinding() : nullptr; 12394 if (!de.emitApplyDecoratorsToClassDefinition(className, 12395 classNode->decorators())) { 12396 // [stack] CTOR 12397 return false; 12398 } 12399 } 12400 #endif 12401 12402 if (!ce.emitEnd(kind)) { 12403 // [stack] # class declaration 12404 // [stack] 12405 // [stack] # class expression 12406 // [stack] CTOR 12407 return false; 12408 } 12409 12410 return true; 12411 } 12412 12413 bool BytecodeEmitter::emitExportDefault(BinaryNode* exportNode) { 12414 MOZ_ASSERT(exportNode->isKind(ParseNodeKind::ExportDefaultStmt)); 12415 12416 ParseNode* valueNode = exportNode->left(); 12417 if (valueNode->isDirectRHSAnonFunction()) { 12418 MOZ_ASSERT(exportNode->right()); 12419 12420 if (!emitAnonymousFunctionWithName( 12421 valueNode, TaggedParserAtomIndex::WellKnown::default_())) { 12422 return false; 12423 } 12424 } else { 12425 if (!emitTree(valueNode)) { 12426 return false; 12427 } 12428 } 12429 12430 if (ParseNode* binding = exportNode->right()) { 12431 if (!emitLexicalInitialization(&binding->as<NameNode>())) { 12432 return false; 12433 } 12434 12435 if (!emit1(JSOp::Pop)) { 12436 return false; 12437 } 12438 } 12439 12440 return true; 12441 } 12442 12443 bool BytecodeEmitter::emitTree( 12444 ParseNode* pn, ValueUsage valueUsage /* = ValueUsage::WantValue */, 12445 EmitLineNumberNote emitLineNote /* = EMIT_LINENOTE */) { 12446 AutoCheckRecursionLimit recursion(fc); 12447 if (!recursion.check(fc)) { 12448 return false; 12449 } 12450 12451 /* Emit notes to tell the current bytecode's source line number. 12452 However, a couple trees require special treatment; see the 12453 relevant emitter functions for details. */ 12454 if (emitLineNote == EMIT_LINENOTE && 12455 !ParseNodeRequiresSpecialLineNumberNotes(pn)) { 12456 if (!updateLineNumberNotes(pn->pn_pos.begin)) { 12457 return false; 12458 } 12459 } 12460 12461 switch (pn->getKind()) { 12462 case ParseNodeKind::Function: 12463 if (!emitFunction(&pn->as<FunctionNode>())) { 12464 return false; 12465 } 12466 break; 12467 12468 case ParseNodeKind::ParamsBody: 12469 MOZ_ASSERT_UNREACHABLE( 12470 "ParamsBody should be handled in emitFunctionScript."); 12471 break; 12472 12473 case ParseNodeKind::IfStmt: 12474 if (!emitIf(&pn->as<TernaryNode>())) { 12475 return false; 12476 } 12477 break; 12478 12479 case ParseNodeKind::SwitchStmt: 12480 if (!emitSwitch(&pn->as<SwitchStatement>())) { 12481 return false; 12482 } 12483 break; 12484 12485 case ParseNodeKind::WhileStmt: 12486 if (!emitWhile(&pn->as<BinaryNode>())) { 12487 return false; 12488 } 12489 break; 12490 12491 case ParseNodeKind::DoWhileStmt: 12492 if (!emitDo(&pn->as<BinaryNode>())) { 12493 return false; 12494 } 12495 break; 12496 12497 case ParseNodeKind::ForStmt: 12498 if (!emitFor(&pn->as<ForNode>())) { 12499 return false; 12500 } 12501 break; 12502 12503 case ParseNodeKind::BreakStmt: 12504 // Ensure that the column of the 'break' is set properly. 12505 if (!updateSourceCoordNotes(pn->pn_pos.begin)) { 12506 return false; 12507 } 12508 if (!markStepBreakpoint()) { 12509 return false; 12510 } 12511 12512 if (!emitBreak(pn->as<BreakStatement>().label())) { 12513 return false; 12514 } 12515 break; 12516 12517 case ParseNodeKind::ContinueStmt: 12518 // Ensure that the column of the 'continue' is set properly. 12519 if (!updateSourceCoordNotes(pn->pn_pos.begin)) { 12520 return false; 12521 } 12522 if (!markStepBreakpoint()) { 12523 return false; 12524 } 12525 12526 if (!emitContinue(pn->as<ContinueStatement>().label())) { 12527 return false; 12528 } 12529 break; 12530 12531 case ParseNodeKind::WithStmt: 12532 if (!emitWith(&pn->as<BinaryNode>())) { 12533 return false; 12534 } 12535 break; 12536 12537 case ParseNodeKind::TryStmt: 12538 if (!emitTry(&pn->as<TryNode>())) { 12539 return false; 12540 } 12541 break; 12542 12543 case ParseNodeKind::Catch: 12544 if (!emitCatch(&pn->as<BinaryNode>())) { 12545 return false; 12546 } 12547 break; 12548 12549 case ParseNodeKind::VarStmt: 12550 if (!emitDeclarationList(&pn->as<ListNode>())) { 12551 return false; 12552 } 12553 break; 12554 12555 case ParseNodeKind::ReturnStmt: 12556 if (!emitReturn(&pn->as<UnaryNode>())) { 12557 return false; 12558 } 12559 break; 12560 12561 case ParseNodeKind::YieldStarExpr: 12562 if (!emitYieldStar(pn->as<UnaryNode>().kid())) { 12563 return false; 12564 } 12565 break; 12566 12567 case ParseNodeKind::Generator: 12568 if (!emit1(JSOp::Generator)) { 12569 return false; 12570 } 12571 break; 12572 12573 case ParseNodeKind::InitialYield: 12574 if (!emitInitialYield(&pn->as<UnaryNode>())) { 12575 return false; 12576 } 12577 break; 12578 12579 case ParseNodeKind::YieldExpr: 12580 if (!emitYield(&pn->as<UnaryNode>())) { 12581 return false; 12582 } 12583 break; 12584 12585 case ParseNodeKind::AwaitExpr: 12586 if (!emitAwaitInInnermostScope(&pn->as<UnaryNode>())) { 12587 return false; 12588 } 12589 break; 12590 12591 case ParseNodeKind::StatementList: 12592 if (!emitStatementList(&pn->as<ListNode>())) { 12593 return false; 12594 } 12595 break; 12596 12597 case ParseNodeKind::EmptyStmt: 12598 break; 12599 12600 case ParseNodeKind::ExpressionStmt: 12601 if (!emitExpressionStatement(&pn->as<UnaryNode>())) { 12602 return false; 12603 } 12604 break; 12605 12606 case ParseNodeKind::LabelStmt: 12607 if (!emitLabeledStatement(&pn->as<LabeledStatement>())) { 12608 return false; 12609 } 12610 break; 12611 12612 case ParseNodeKind::CommaExpr: 12613 if (!emitSequenceExpr(&pn->as<ListNode>(), valueUsage)) { 12614 return false; 12615 } 12616 break; 12617 12618 case ParseNodeKind::InitExpr: 12619 case ParseNodeKind::AssignExpr: 12620 case ParseNodeKind::AddAssignExpr: 12621 case ParseNodeKind::SubAssignExpr: 12622 case ParseNodeKind::BitOrAssignExpr: 12623 case ParseNodeKind::BitXorAssignExpr: 12624 case ParseNodeKind::BitAndAssignExpr: 12625 case ParseNodeKind::LshAssignExpr: 12626 case ParseNodeKind::RshAssignExpr: 12627 case ParseNodeKind::UrshAssignExpr: 12628 case ParseNodeKind::MulAssignExpr: 12629 case ParseNodeKind::DivAssignExpr: 12630 case ParseNodeKind::ModAssignExpr: 12631 case ParseNodeKind::PowAssignExpr: { 12632 BinaryNode* assignNode = &pn->as<BinaryNode>(); 12633 if (!emitAssignmentOrInit(assignNode->getKind(), assignNode->left(), 12634 assignNode->right())) { 12635 return false; 12636 } 12637 break; 12638 } 12639 12640 case ParseNodeKind::CoalesceAssignExpr: 12641 case ParseNodeKind::OrAssignExpr: 12642 case ParseNodeKind::AndAssignExpr: 12643 if (!emitShortCircuitAssignment(&pn->as<AssignmentNode>())) { 12644 return false; 12645 } 12646 break; 12647 12648 case ParseNodeKind::ConditionalExpr: 12649 if (!emitConditionalExpression(pn->as<ConditionalExpression>(), 12650 valueUsage)) { 12651 return false; 12652 } 12653 break; 12654 12655 case ParseNodeKind::OrExpr: 12656 case ParseNodeKind::CoalesceExpr: 12657 case ParseNodeKind::AndExpr: 12658 if (!emitShortCircuit(&pn->as<ListNode>(), valueUsage)) { 12659 return false; 12660 } 12661 break; 12662 12663 case ParseNodeKind::StrictEqExpr: 12664 case ParseNodeKind::EqExpr: 12665 case ParseNodeKind::StrictNeExpr: 12666 case ParseNodeKind::NeExpr: 12667 case ParseNodeKind::LtExpr: 12668 case ParseNodeKind::GtExpr: { 12669 bool emitted; 12670 if (!tryEmitTypeofEq(&pn->as<ListNode>(), &emitted)) { 12671 return false; 12672 } 12673 if (emitted) { 12674 return true; 12675 } 12676 } 12677 [[fallthrough]]; 12678 12679 case ParseNodeKind::AddExpr: 12680 case ParseNodeKind::SubExpr: 12681 case ParseNodeKind::BitOrExpr: 12682 case ParseNodeKind::BitXorExpr: 12683 case ParseNodeKind::BitAndExpr: 12684 case ParseNodeKind::LeExpr: 12685 case ParseNodeKind::GeExpr: 12686 case ParseNodeKind::InExpr: 12687 case ParseNodeKind::InstanceOfExpr: 12688 case ParseNodeKind::LshExpr: 12689 case ParseNodeKind::RshExpr: 12690 case ParseNodeKind::UrshExpr: 12691 case ParseNodeKind::MulExpr: 12692 case ParseNodeKind::DivExpr: 12693 case ParseNodeKind::ModExpr: 12694 if (!emitLeftAssociative(&pn->as<ListNode>())) { 12695 return false; 12696 } 12697 break; 12698 12699 case ParseNodeKind::PrivateInExpr: 12700 if (!emitPrivateInExpr(&pn->as<ListNode>())) { 12701 return false; 12702 } 12703 break; 12704 12705 case ParseNodeKind::PowExpr: 12706 if (!emitRightAssociative(&pn->as<ListNode>())) { 12707 return false; 12708 } 12709 break; 12710 12711 case ParseNodeKind::TypeOfNameExpr: 12712 if (!emitTypeof(&pn->as<UnaryNode>(), JSOp::Typeof)) { 12713 return false; 12714 } 12715 break; 12716 12717 case ParseNodeKind::TypeOfExpr: 12718 if (!emitTypeof(&pn->as<UnaryNode>(), JSOp::TypeofExpr)) { 12719 return false; 12720 } 12721 break; 12722 12723 case ParseNodeKind::ThrowStmt: 12724 if (!updateSourceCoordNotes(pn->pn_pos.begin)) { 12725 return false; 12726 } 12727 if (!markStepBreakpoint()) { 12728 return false; 12729 } 12730 [[fallthrough]]; 12731 case ParseNodeKind::VoidExpr: 12732 case ParseNodeKind::NotExpr: 12733 case ParseNodeKind::BitNotExpr: 12734 case ParseNodeKind::PosExpr: 12735 case ParseNodeKind::NegExpr: 12736 if (!emitUnary(&pn->as<UnaryNode>())) { 12737 return false; 12738 } 12739 break; 12740 12741 case ParseNodeKind::PreIncrementExpr: 12742 case ParseNodeKind::PreDecrementExpr: 12743 case ParseNodeKind::PostIncrementExpr: 12744 case ParseNodeKind::PostDecrementExpr: 12745 if (!emitIncOrDec(&pn->as<UnaryNode>(), valueUsage)) { 12746 return false; 12747 } 12748 break; 12749 12750 case ParseNodeKind::DeleteNameExpr: 12751 if (!emitDeleteName(&pn->as<UnaryNode>())) { 12752 return false; 12753 } 12754 break; 12755 12756 case ParseNodeKind::DeletePropExpr: 12757 if (!emitDeleteProperty(&pn->as<UnaryNode>())) { 12758 return false; 12759 } 12760 break; 12761 12762 case ParseNodeKind::DeleteElemExpr: 12763 if (!emitDeleteElement(&pn->as<UnaryNode>())) { 12764 return false; 12765 } 12766 break; 12767 12768 case ParseNodeKind::DeleteExpr: 12769 if (!emitDeleteExpression(&pn->as<UnaryNode>())) { 12770 return false; 12771 } 12772 break; 12773 12774 case ParseNodeKind::DeleteOptionalChainExpr: 12775 if (!emitDeleteOptionalChain(&pn->as<UnaryNode>())) { 12776 return false; 12777 } 12778 break; 12779 12780 case ParseNodeKind::OptionalChain: 12781 if (!emitOptionalChain(&pn->as<UnaryNode>(), valueUsage)) { 12782 return false; 12783 } 12784 break; 12785 12786 case ParseNodeKind::DotExpr: { 12787 PropertyAccess* prop = &pn->as<PropertyAccess>(); 12788 bool isSuper = prop->isSuper(); 12789 PropOpEmitter poe(this, PropOpEmitter::Kind::Get, 12790 isSuper ? PropOpEmitter::ObjKind::Super 12791 : PropOpEmitter::ObjKind::Other); 12792 if (!poe.prepareForObj()) { 12793 return false; 12794 } 12795 if (isSuper) { 12796 UnaryNode* base = &prop->expression().as<UnaryNode>(); 12797 if (!emitGetThisForSuperBase(base)) { 12798 // [stack] THIS 12799 return false; 12800 } 12801 } else { 12802 if (!emitPropLHS(prop)) { 12803 // [stack] OBJ 12804 return false; 12805 } 12806 } 12807 if (!poe.emitGet(prop->key().atom())) { 12808 // [stack] PROP 12809 return false; 12810 } 12811 break; 12812 } 12813 12814 case ParseNodeKind::ArgumentsLength: { 12815 if (sc->isFunctionBox() && 12816 sc->asFunctionBox()->isEligibleForArgumentsLength() && 12817 !sc->asFunctionBox()->needsArgsObj()) { 12818 if (!emit1(JSOp::ArgumentsLength)) { 12819 return false; 12820 } 12821 } else { 12822 PropOpEmitter poe(this, PropOpEmitter::Kind::Get, 12823 PropOpEmitter::ObjKind::Other); 12824 if (!poe.prepareForObj()) { 12825 return false; 12826 } 12827 12828 NameOpEmitter noe(this, TaggedParserAtomIndex::WellKnown::arguments(), 12829 NameOpEmitter::Kind::Get); 12830 if (!noe.emitGet()) { 12831 return false; 12832 } 12833 if (!poe.emitGet(TaggedParserAtomIndex::WellKnown::length())) { 12834 return false; 12835 } 12836 } 12837 break; 12838 } 12839 12840 case ParseNodeKind::ElemExpr: { 12841 PropertyByValue* elem = &pn->as<PropertyByValue>(); 12842 bool isSuper = elem->isSuper(); 12843 MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName)); 12844 ElemOpEmitter eoe(this, ElemOpEmitter::Kind::Get, 12845 isSuper ? ElemOpEmitter::ObjKind::Super 12846 : ElemOpEmitter::ObjKind::Other); 12847 if (!emitElemObjAndKey(elem, eoe)) { 12848 // [stack] # if Super 12849 // [stack] THIS KEY 12850 // [stack] # otherwise 12851 // [stack] OBJ KEY 12852 return false; 12853 } 12854 if (!eoe.emitGet()) { 12855 // [stack] ELEM 12856 return false; 12857 } 12858 12859 break; 12860 } 12861 12862 case ParseNodeKind::PrivateMemberExpr: { 12863 PrivateMemberAccess* privateExpr = &pn->as<PrivateMemberAccess>(); 12864 PrivateOpEmitter xoe(this, PrivateOpEmitter::Kind::Get, 12865 privateExpr->privateName().name()); 12866 if (!emitTree(&privateExpr->expression())) { 12867 // [stack] OBJ 12868 return false; 12869 } 12870 if (!xoe.emitReference()) { 12871 // [stack] OBJ NAME 12872 return false; 12873 } 12874 if (!xoe.emitGet()) { 12875 // [stack] VALUE 12876 return false; 12877 } 12878 12879 break; 12880 } 12881 12882 case ParseNodeKind::NewExpr: 12883 case ParseNodeKind::TaggedTemplateExpr: 12884 case ParseNodeKind::CallExpr: 12885 case ParseNodeKind::SuperCallExpr: 12886 if (!emitCallOrNew(&pn->as<CallNode>(), valueUsage)) { 12887 return false; 12888 } 12889 break; 12890 12891 case ParseNodeKind::LexicalScope: 12892 if (!emitLexicalScope(&pn->as<LexicalScopeNode>())) { 12893 return false; 12894 } 12895 break; 12896 12897 case ParseNodeKind::ConstDecl: 12898 case ParseNodeKind::LetDecl: 12899 if (!emitDeclarationList(&pn->as<ListNode>())) { 12900 return false; 12901 } 12902 break; 12903 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT 12904 case ParseNodeKind::AwaitUsingDecl: 12905 case ParseNodeKind::UsingDecl: 12906 if (!emitDeclarationList(&pn->as<ListNode>())) { 12907 return false; 12908 } 12909 break; 12910 #endif 12911 12912 case ParseNodeKind::ImportDecl: 12913 MOZ_ASSERT(sc->isModuleContext()); 12914 break; 12915 12916 case ParseNodeKind::ExportStmt: { 12917 MOZ_ASSERT(sc->isModuleContext()); 12918 UnaryNode* node = &pn->as<UnaryNode>(); 12919 ParseNode* decl = node->kid(); 12920 if (decl->getKind() != ParseNodeKind::ExportSpecList) { 12921 if (!emitTree(decl)) { 12922 return false; 12923 } 12924 } 12925 break; 12926 } 12927 12928 case ParseNodeKind::ExportDefaultStmt: 12929 MOZ_ASSERT(sc->isModuleContext()); 12930 if (!emitExportDefault(&pn->as<BinaryNode>())) { 12931 return false; 12932 } 12933 break; 12934 12935 case ParseNodeKind::ExportFromStmt: 12936 MOZ_ASSERT(sc->isModuleContext()); 12937 break; 12938 12939 case ParseNodeKind::CallSiteObj: 12940 if (!emitCallSiteObject(&pn->as<CallSiteNode>())) { 12941 return false; 12942 } 12943 break; 12944 12945 case ParseNodeKind::ArrayExpr: 12946 if (!emitArrayLiteral(&pn->as<ListNode>())) { 12947 return false; 12948 } 12949 break; 12950 12951 case ParseNodeKind::ObjectExpr: 12952 if (!emitObject(&pn->as<ListNode>())) { 12953 return false; 12954 } 12955 break; 12956 12957 case ParseNodeKind::Name: 12958 if (!emitGetName(&pn->as<NameNode>())) { 12959 return false; 12960 } 12961 break; 12962 12963 case ParseNodeKind::PrivateName: 12964 if (!emitGetPrivateName(&pn->as<NameNode>())) { 12965 return false; 12966 } 12967 break; 12968 12969 case ParseNodeKind::TemplateStringListExpr: 12970 if (!emitTemplateString(&pn->as<ListNode>())) { 12971 return false; 12972 } 12973 break; 12974 12975 case ParseNodeKind::TemplateStringExpr: 12976 case ParseNodeKind::StringExpr: 12977 if (!emitStringOp(JSOp::String, pn->as<NameNode>().atom())) { 12978 return false; 12979 } 12980 break; 12981 12982 case ParseNodeKind::NumberExpr: 12983 if (!emitNumberOp(pn->as<NumericLiteral>().value())) { 12984 return false; 12985 } 12986 break; 12987 12988 case ParseNodeKind::BigIntExpr: 12989 if (!emitBigIntOp(&pn->as<BigIntLiteral>())) { 12990 return false; 12991 } 12992 break; 12993 12994 case ParseNodeKind::RegExpExpr: { 12995 GCThingIndex index; 12996 if (!perScriptData().gcThingList().append(&pn->as<RegExpLiteral>(), 12997 &index)) { 12998 return false; 12999 } 13000 if (!emitRegExp(index)) { 13001 return false; 13002 } 13003 break; 13004 } 13005 13006 case ParseNodeKind::TrueExpr: 13007 if (!emit1(JSOp::True)) { 13008 return false; 13009 } 13010 break; 13011 case ParseNodeKind::FalseExpr: 13012 if (!emit1(JSOp::False)) { 13013 return false; 13014 } 13015 break; 13016 case ParseNodeKind::NullExpr: 13017 if (!emit1(JSOp::Null)) { 13018 return false; 13019 } 13020 break; 13021 case ParseNodeKind::RawUndefinedExpr: 13022 if (!emit1(JSOp::Undefined)) { 13023 return false; 13024 } 13025 break; 13026 13027 case ParseNodeKind::ThisExpr: 13028 if (!emitThisLiteral(&pn->as<ThisLiteral>())) { 13029 return false; 13030 } 13031 break; 13032 13033 case ParseNodeKind::DebuggerStmt: 13034 if (!updateSourceCoordNotes(pn->pn_pos.begin)) { 13035 return false; 13036 } 13037 if (!markStepBreakpoint()) { 13038 return false; 13039 } 13040 if (!emit1(JSOp::Debugger)) { 13041 return false; 13042 } 13043 break; 13044 13045 case ParseNodeKind::ClassDecl: 13046 if (!emitClass(&pn->as<ClassNode>())) { 13047 return false; 13048 } 13049 break; 13050 13051 case ParseNodeKind::NewTargetExpr: 13052 if (!emitNewTarget(&pn->as<NewTargetNode>())) { 13053 return false; 13054 } 13055 break; 13056 13057 case ParseNodeKind::ImportMetaExpr: 13058 if (!emit1(JSOp::ImportMeta)) { 13059 return false; 13060 } 13061 break; 13062 13063 case ParseNodeKind::CallImportExpr: { 13064 BinaryNode* spec = &pn->as<BinaryNode>().right()->as<BinaryNode>(); 13065 13066 if (!emitTree(spec->left())) { 13067 // [stack] specifier 13068 return false; 13069 } 13070 13071 if (!spec->right()->isKind(ParseNodeKind::PosHolder)) { 13072 // [stack] specifier options 13073 if (!emitTree(spec->right())) { 13074 return false; 13075 } 13076 } else { 13077 // [stack] specifier undefined 13078 if (!emit1(JSOp::Undefined)) { 13079 return false; 13080 } 13081 } 13082 13083 if (!emit1(JSOp::DynamicImport)) { 13084 return false; 13085 } 13086 13087 break; 13088 } 13089 13090 case ParseNodeKind::SetThis: 13091 if (!emitSetThis(&pn->as<BinaryNode>())) { 13092 return false; 13093 } 13094 break; 13095 13096 case ParseNodeKind::PropertyNameExpr: 13097 case ParseNodeKind::PosHolder: 13098 MOZ_FALLTHROUGH_ASSERT( 13099 "Should never try to emit ParseNodeKind::PosHolder or ::Property"); 13100 13101 default: 13102 MOZ_ASSERT(0); 13103 } 13104 13105 return true; 13106 } 13107 13108 static bool AllocSrcNote(FrontendContext* fc, SrcNotesVector& notes, 13109 unsigned size, unsigned* index) { 13110 size_t oldLength = notes.length(); 13111 13112 if (MOZ_UNLIKELY(oldLength + size > MaxSrcNotesLength)) { 13113 ReportAllocationOverflow(fc); 13114 return false; 13115 } 13116 13117 if (!notes.growByUninitialized(size)) { 13118 return false; 13119 } 13120 13121 *index = oldLength; 13122 return true; 13123 } 13124 13125 bool BytecodeEmitter::addTryNote(TryNoteKind kind, uint32_t stackDepth, 13126 BytecodeOffset start, BytecodeOffset end) { 13127 MOZ_ASSERT(!inPrologue()); 13128 return bytecodeSection().tryNoteList().append(kind, stackDepth, start, end); 13129 } 13130 13131 bool BytecodeEmitter::newSrcNote(SrcNoteType type, unsigned* indexp) { 13132 SrcNotesVector& notes = bytecodeSection().notes(); 13133 unsigned index; 13134 13135 /* 13136 * Compute delta from the last annotated bytecode's offset. If it's too 13137 * big to fit in sn, allocate one or more xdelta notes and reset sn. 13138 */ 13139 BytecodeOffset offset = bytecodeSection().offset(); 13140 ptrdiff_t delta = (offset - bytecodeSection().lastNoteOffset()).value(); 13141 bytecodeSection().setLastNoteOffset(offset); 13142 13143 auto allocator = [&](unsigned size) -> SrcNote* { 13144 if (!AllocSrcNote(fc, notes, size, &index)) { 13145 return nullptr; 13146 } 13147 return ¬es[index]; 13148 }; 13149 13150 if (!SrcNoteWriter::writeNote(type, delta, allocator)) { 13151 return false; 13152 } 13153 13154 if (indexp) { 13155 *indexp = index; 13156 } 13157 13158 if (type == SrcNoteType::NewLine || type == SrcNoteType::SetLine) { 13159 lastLineOnlySrcNoteIndex = index; 13160 } else { 13161 lastLineOnlySrcNoteIndex = LastSrcNoteIsNotLineOnly; 13162 } 13163 13164 return true; 13165 } 13166 13167 bool BytecodeEmitter::newSrcNote2(SrcNoteType type, ptrdiff_t offset, 13168 unsigned* indexp) { 13169 unsigned index; 13170 if (!newSrcNote(type, &index)) { 13171 return false; 13172 } 13173 if (!newSrcNoteOperand(offset)) { 13174 return false; 13175 } 13176 if (indexp) { 13177 *indexp = index; 13178 } 13179 return true; 13180 } 13181 13182 bool BytecodeEmitter::convertLastNewLineToNewLineColumn( 13183 JS::LimitedColumnNumberOneOrigin column) { 13184 SrcNotesVector& notes = bytecodeSection().notes(); 13185 MOZ_ASSERT(lastLineOnlySrcNoteIndex == notes.length() - 1); 13186 SrcNote* sn = ¬es[lastLineOnlySrcNoteIndex]; 13187 MOZ_ASSERT(sn->type() == SrcNoteType::NewLine); 13188 13189 SrcNoteWriter::convertNote(sn, SrcNoteType::NewLineColumn); 13190 if (!newSrcNoteOperand(SrcNote::NewLineColumn::toOperand(column))) { 13191 return false; 13192 } 13193 13194 lastLineOnlySrcNoteIndex = LastSrcNoteIsNotLineOnly; 13195 return true; 13196 } 13197 13198 bool BytecodeEmitter::convertLastSetLineToSetLineColumn( 13199 JS::LimitedColumnNumberOneOrigin column) { 13200 SrcNotesVector& notes = bytecodeSection().notes(); 13201 // The Line operand is either 1 byte or 4 bytes. 13202 MOZ_ASSERT(lastLineOnlySrcNoteIndex == notes.length() - 1 - 1 || 13203 lastLineOnlySrcNoteIndex == notes.length() - 1 - 4); 13204 SrcNote* sn = ¬es[lastLineOnlySrcNoteIndex]; 13205 MOZ_ASSERT(sn->type() == SrcNoteType::SetLine); 13206 13207 SrcNoteWriter::convertNote(sn, SrcNoteType::SetLineColumn); 13208 if (!newSrcNoteOperand(SrcNote::SetLineColumn::columnToOperand(column))) { 13209 return false; 13210 } 13211 13212 lastLineOnlySrcNoteIndex = LastSrcNoteIsNotLineOnly; 13213 return true; 13214 } 13215 13216 bool BytecodeEmitter::newSrcNoteOperand(ptrdiff_t operand) { 13217 if (!SrcNote::isRepresentableOperand(operand)) { 13218 reportError(nullptr, JSMSG_NEED_DIET, "script"); 13219 return false; 13220 } 13221 13222 SrcNotesVector& notes = bytecodeSection().notes(); 13223 13224 auto allocator = [&](unsigned size) -> SrcNote* { 13225 unsigned index; 13226 if (!AllocSrcNote(fc, notes, size, &index)) { 13227 return nullptr; 13228 } 13229 return ¬es[index]; 13230 }; 13231 13232 return SrcNoteWriter::writeOperand(operand, allocator); 13233 } 13234 13235 bool BytecodeEmitter::intoScriptStencil(ScriptIndex scriptIndex) { 13236 js::UniquePtr<ImmutableScriptData> immutableScriptData = 13237 createImmutableScriptData(); 13238 if (!immutableScriptData) { 13239 return false; 13240 } 13241 13242 MOZ_ASSERT(outermostScope().hasNonSyntacticScopeOnChain() == 13243 sc->hasNonSyntacticScope()); 13244 13245 auto& things = perScriptData().gcThingList().objects(); 13246 if (!compilationState.appendGCThings(fc, scriptIndex, things)) { 13247 return false; 13248 } 13249 13250 // Hand over the ImmutableScriptData instance generated by BCE. 13251 auto* sharedData = 13252 SharedImmutableScriptData::createWith(fc, std::move(immutableScriptData)); 13253 if (!sharedData) { 13254 return false; 13255 } 13256 13257 // De-duplicate the bytecode within the runtime. 13258 if (!compilationState.sharedData.addAndShare(fc, scriptIndex, sharedData)) { 13259 return false; 13260 } 13261 13262 ScriptStencil& script = compilationState.scriptData[scriptIndex]; 13263 script.setHasSharedData(); 13264 13265 // Update flags specific to functions. 13266 if (sc->isFunctionBox()) { 13267 FunctionBox* funbox = sc->asFunctionBox(); 13268 MOZ_ASSERT(&script == &funbox->functionStencil()); 13269 funbox->copyUpdatedImmutableFlags(); 13270 MOZ_ASSERT(script.isFunction()); 13271 } else { 13272 ScriptStencilExtra& scriptExtra = compilationState.scriptExtra[scriptIndex]; 13273 sc->copyScriptExtraFields(scriptExtra); 13274 } 13275 13276 return true; 13277 } 13278 13279 SelfHostedIter BytecodeEmitter::getSelfHostedIterFor( 13280 ParseNode* parseNode) const { 13281 if (emitterMode == BytecodeEmitter::SelfHosting && 13282 parseNode->isKind(ParseNodeKind::CallExpr)) { 13283 auto* callee = parseNode->as<CallNode>().callee(); 13284 if (callee->isName(TaggedParserAtomIndex::WellKnown::allowContentIter())) { 13285 return SelfHostedIter::AllowContent; 13286 } 13287 if (callee->isName( 13288 TaggedParserAtomIndex::WellKnown::allowContentIterWith())) { 13289 return SelfHostedIter::AllowContentWith; 13290 } 13291 if (callee->isName( 13292 TaggedParserAtomIndex::WellKnown::allowContentIterWithNext())) { 13293 return SelfHostedIter::AllowContentWithNext; 13294 } 13295 } 13296 13297 return SelfHostedIter::Deny; 13298 } 13299 13300 #if defined(DEBUG) || defined(JS_JITSPEW) 13301 void BytecodeEmitter::dumpAtom(TaggedParserAtomIndex index) const { 13302 parserAtoms().dump(index); 13303 } 13304 #endif