Bug Summary

File:root/firefox-clang/obj-x86_64-pc-linux-gnu/js/src/frontend/./../../../../js/src/frontend/BytecodeEmitter.cpp
Warning:line 830, column 3
Value stored to 'pc' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -O3 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name Unified_cpp_js_src_frontend0.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/js/src/frontend -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/js/src/frontend -resource-dir /usr/lib/llvm-23/lib/clang/23 -include /root/firefox-clang/config/gcc_hidden.h -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -D _GLIBCXX_ASSERTIONS=1 -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D WASM_SUPPORTS_HUGE_MEMORY -D JS_CACHEIR_SPEW -D JS_STRUCTURED_SPEW -D JS_HAS_CTYPES -D FFI_BUILDING -D EXPORT_JS_API -D MOZ_HAS_MOZGLUE -D MOZ_SUPPORT_LEAKCHECKING -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/js/src -I /root/firefox-clang/js/src -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/x86_64-linux-gnu/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16/backward -internal-isystem /usr/lib/llvm-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-error=pessimizing-move -Wno-error=large-by-value-copy=128 -Wno-error=implicit-int-float-conversion -Wno-error=thread-safety-analysis -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -Wno-character-conversion -std=gnu++20 -fdeprecated-macro -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fno-implicit-modules -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -fdiagnostics-absolute-paths -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -mllvm -dwarf-linkage-names=Abstract -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-09-01-224014-2642839-1 -x c++ Unified_cpp_js_src_frontend0.cpp
1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5/*
6 * JS bytecode generation.
7 */
8
9#include "frontend/BytecodeEmitter.h"
10
11#include "mozilla/Casting.h" // mozilla::AssertedCast
12#include "mozilla/DebugOnly.h" // mozilla::DebugOnly
13#include "mozilla/FloatingPoint.h" // mozilla::NumberEqualsInt32, mozilla::NumberIsInt32
14#include "mozilla/HashTable.h" // mozilla::HashSet
15#include "mozilla/Maybe.h" // mozilla::{Maybe,Nothing,Some}
16#include "mozilla/Saturate.h"
17#include "mozilla/Variant.h" // mozilla::AsVariant
18
19#include <algorithm>
20#include <iterator>
21#include <string.h>
22
23#include "jstypes.h" // JS_BIT
24
25#include "frontend/AbstractScopePtr.h" // ScopeIndex
26#include "frontend/BytecodeControlStructures.h" // NestableControl, BreakableControl, LabelControl, LoopControl, TryFinallyControl
27#include "frontend/CallOrNewEmitter.h" // CallOrNewEmitter
28#include "frontend/CForEmitter.h" // CForEmitter
29#include "frontend/DecoratorEmitter.h" // DecoratorEmitter
30#include "frontend/DefaultEmitter.h" // DefaultEmitter
31#include "frontend/DoWhileEmitter.h" // DoWhileEmitter
32#include "frontend/ElemOpEmitter.h" // ElemOpEmitter
33#include "frontend/EmitterScope.h" // EmitterScope
34#include "frontend/ExpressionStatementEmitter.h" // ExpressionStatementEmitter
35#include "frontend/ForInEmitter.h" // ForInEmitter
36#include "frontend/ForOfEmitter.h" // ForOfEmitter
37#include "frontend/FunctionEmitter.h" // FunctionEmitter, FunctionScriptEmitter, FunctionParamsEmitter
38#include "frontend/IfEmitter.h" // IfEmitter, InternalIfEmitter, CondEmitter
39#include "frontend/LabelEmitter.h" // LabelEmitter
40#include "frontend/LexicalScopeEmitter.h" // LexicalScopeEmitter
41#include "frontend/ModuleSharedContext.h" // ModuleSharedContext
42#include "frontend/NameAnalysisTypes.h" // PrivateNameKind
43#include "frontend/NameFunctions.h" // NameFunctions
44#include "frontend/NameOpEmitter.h" // NameOpEmitter
45#include "frontend/ObjectEmitter.h" // PropertyEmitter, ObjectEmitter, ClassEmitter
46#include "frontend/OptionalEmitter.h" // OptionalEmitter
47#include "frontend/ParseContext.h" // ParseContext::Scope
48#include "frontend/ParseNode.h" // ParseNodeKind, ParseNode and subclasses
49#include "frontend/Parser.h" // Parser
50#include "frontend/ParserAtom.h" // ParserAtomsTable, ParserAtom
51#include "frontend/PrivateOpEmitter.h" // PrivateOpEmitter
52#include "frontend/PropOpEmitter.h" // PropOpEmitter
53#include "frontend/SourceNotes.h" // SrcNote, SrcNoteType, SrcNoteWriter
54#include "frontend/SwitchEmitter.h" // SwitchEmitter
55#include "frontend/TaggedParserAtomIndexHasher.h" // TaggedParserAtomIndexHasher
56#include "frontend/TDZCheckCache.h" // TDZCheckCache
57#include "frontend/TryEmitter.h" // TryEmitter
58#include "frontend/UsingEmitter.h" // UsingEmitter
59#include "frontend/WhileEmitter.h" // WhileEmitter
60#include "js/ColumnNumber.h" // JS::LimitedColumnNumberOneOrigin, JS::ColumnNumberOffset
61#include "js/friend/ErrorMessages.h" // JSMSG_*
62#include "js/friend/StackLimits.h" // AutoCheckRecursionLimit
63#include "util/StringBuilder.h" // StringBuilder
64#include "vm/BytecodeUtil.h" // JOF_*, IsArgOp, IsLocalOp, SET_UINT24, SET_ICINDEX, BytecodeFallsThrough, BytecodeIsJumpTarget
65#include "vm/CompletionKind.h" // CompletionKind
66#include "vm/ConstantCompareOperand.h" // ConstantCompareOperand
67#include "vm/FunctionPrefixKind.h" // FunctionPrefixKind
68#include "vm/GeneratorObject.h" // AbstractGeneratorObject
69#include "vm/Opcodes.h" // JSOp, JSOpLength_*
70#include "vm/PropMap.h" // SharedPropMap::MaxPropsForNonDictionary
71#include "vm/Scope.h" // GetScopeDataTrailingNames
72#include "vm/SharedStencil.h" // ScopeNote
73#include "vm/ThrowMsgKind.h" // ThrowMsgKind
74#include "vm/TypeofEqOperand.h" // TypeofEqOperand
75
76using namespace js;
77using namespace js::frontend;
78
79using mozilla::AssertedCast;
80using mozilla::AsVariant;
81using mozilla::DebugOnly;
82using mozilla::Maybe;
83using mozilla::Nothing;
84using mozilla::NumberEqualsInt32;
85using mozilla::NumberIsInt32;
86using mozilla::Some;
87
88static bool ParseNodeRequiresSpecialLineNumberNotes(ParseNode* pn) {
89 // The few node types listed below are exceptions to the usual
90 // location-source-note-emitting code in BytecodeEmitter::emitTree().
91 // Single-line `while` loops and C-style `for` loops require careful
92 // handling to avoid strange stepping behavior.
93 // Functions usually shouldn't have location information (bug 1431202).
94
95 ParseNodeKind kind = pn->getKind();
96 return kind == ParseNodeKind::WhileStmt || kind == ParseNodeKind::ForStmt ||
97 kind == ParseNodeKind::Function;
98}
99
100static bool NeedsFieldInitializer(ParseNode* member, bool inStaticContext) {
101 // For the purposes of bytecode emission, StaticClassBlocks are treated as if
102 // they were static initializers.
103 return (member->is<StaticClassBlock>() && inStaticContext) ||
104 (member->is<ClassField>() &&
105 member->as<ClassField>().isStatic() == inStaticContext);
106}
107
108static bool NeedsAccessorInitializer(ParseNode* member, bool isStatic) {
109 if (isStatic) {
110 return false;
111 }
112 return member->is<ClassMethod>() &&
113 member->as<ClassMethod>().name().isKind(ParseNodeKind::PrivateName) &&
114 !member->as<ClassMethod>().isStatic() &&
115 member->as<ClassMethod>().accessorType() != AccessorType::None;
116}
117
118static bool ShouldSuppressBreakpointsAndSourceNotes(
119 SharedContext* sc, BytecodeEmitter::EmitterMode emitterMode) {
120 // Suppress for all self-hosting code.
121 if (emitterMode == BytecodeEmitter::EmitterMode::SelfHosting) {
122 return true;
123 }
124
125 // Suppress for synthesized class constructors.
126 if (sc->isFunctionBox()) {
127 FunctionBox* funbox = sc->asFunctionBox();
128 return funbox->isSyntheticFunction() && funbox->isClassConstructor();
129 }
130
131 return false;
132}
133
134BytecodeEmitter::BytecodeEmitter(BytecodeEmitter* parent, FrontendContext* fc,
135 SharedContext* sc,
136 const ErrorReporter& errorReporter,
137 CompilationState& compilationState,
138 EmitterMode emitterMode)
139 : sc(sc),
140 fc(fc),
141 parent(parent),
142 bytecodeSection_(fc, sc->extent().lineno,
143 JS::LimitedColumnNumberOneOrigin(sc->extent().column)),
144 perScriptData_(fc, compilationState),
145 errorReporter_(errorReporter),
146 compilationState(compilationState),
147 suppressBreakpointsAndSourceNotes(
148 ShouldSuppressBreakpointsAndSourceNotes(sc, emitterMode)),
149 emitterMode(emitterMode) {
150 MOZ_ASSERT_IF(parent, fc == parent->fc)do { if (parent) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(fc == parent->fc)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(fc == parent->fc))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("fc == parent->fc"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 150); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "fc == parent->fc" ")"); do { MOZ_CrashSequence
(__null, 150); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false); } } while (false)
;
151}
152
153BytecodeEmitter::BytecodeEmitter(BytecodeEmitter* parent, SharedContext* sc)
154 : BytecodeEmitter(parent, parent->fc, sc, parent->errorReporter_,
155 parent->compilationState, parent->emitterMode) {}
156
157BytecodeEmitter::BytecodeEmitter(FrontendContext* fc,
158 const EitherParser& parser, SharedContext* sc,
159 CompilationState& compilationState,
160 EmitterMode emitterMode)
161 : BytecodeEmitter(nullptr, fc, sc, parser.errorReporter(), compilationState,
162 emitterMode) {
163 ep_.emplace(parser);
164}
165
166void BytecodeEmitter::initFromBodyPosition(TokenPos bodyPosition) {
167 setScriptStartOffsetIfUnset(bodyPosition.begin);
168 setFunctionBodyEndPos(bodyPosition.end);
169}
170
171bool BytecodeEmitter::init() {
172 if (!parent) {
173 if (!compilationState.prepareSharedDataStorage(fc)) {
174 return false;
175 }
176 }
177 return perScriptData_.init(fc);
178}
179
180bool BytecodeEmitter::init(TokenPos bodyPosition) {
181 initFromBodyPosition(bodyPosition);
182 return init();
183}
184
185template <typename T>
186T* BytecodeEmitter::findInnermostNestableControl() const {
187 return NestableControl::findNearest<T>(innermostNestableControl);
188}
189
190template <typename T, typename Predicate /* (T*) -> bool */>
191T* BytecodeEmitter::findInnermostNestableControl(Predicate predicate) const {
192 return NestableControl::findNearest<T>(innermostNestableControl, predicate);
193}
194
195NameLocation BytecodeEmitter::lookupName(TaggedParserAtomIndex name) {
196 return innermostEmitterScope()->lookup(this, name);
197}
198
199void BytecodeEmitter::lookupPrivate(TaggedParserAtomIndex name,
200 NameLocation& loc,
201 Maybe<NameLocation>& brandLoc) {
202 innermostEmitterScope()->lookupPrivate(this, name, loc, brandLoc);
203}
204
205Maybe<NameLocation> BytecodeEmitter::locationOfNameBoundInScope(
206 TaggedParserAtomIndex name, EmitterScope* target) {
207 return innermostEmitterScope()->locationBoundInScope(name, target);
208}
209
210template <typename T>
211Maybe<NameLocation> BytecodeEmitter::locationOfNameBoundInScopeType(
212 TaggedParserAtomIndex name, EmitterScope* source) {
213 EmitterScope* aScope = source;
214 while (!aScope->scope(this).is<T>()) {
215 aScope = aScope->enclosingInFrame();
216 }
217 return source->locationBoundInScope(name, aScope);
218}
219
220bool BytecodeEmitter::markStepBreakpoint() {
221 if (skipBreakpointSrcNotes()) {
222 return true;
223 }
224
225 if (!newSrcNote(SrcNoteType::BreakpointStepSep)) {
226 return false;
227 }
228
229 // We track the location of the most recent separator for use in
230 // markSimpleBreakpoint. Note that this means that the position must already
231 // be set before markStepBreakpoint is called.
232 bytecodeSection().updateSeparatorPosition();
233
234 return true;
235}
236
237bool BytecodeEmitter::markSimpleBreakpoint() {
238 if (skipBreakpointSrcNotes()) {
239 return true;
240 }
241
242 // If a breakable call ends up being the same location as the most recent
243 // expression start, we need to skip marking it breakable in order to avoid
244 // having two breakpoints with the same line/column position.
245 // Note: This assumes that the position for the call has already been set.
246 if (!bytecodeSection().isDuplicateLocation()) {
247 if (!newSrcNote(SrcNoteType::Breakpoint)) {
248 return false;
249 }
250 }
251
252 return true;
253}
254
255bool BytecodeEmitter::emitCheck(JSOp op, ptrdiff_t delta,
256 BytecodeOffset* offset) {
257 size_t oldLength = bytecodeSection().code().length();
258 *offset = BytecodeOffset(oldLength);
259
260 size_t newLength = oldLength + size_t(delta);
261 if (MOZ_UNLIKELY(newLength > MaxBytecodeLength)(__builtin_expect(!!(newLength > MaxBytecodeLength), 0))) {
262 ReportAllocationOverflow(fc);
263 return false;
264 }
265
266 if (!bytecodeSection().code().growByUninitialized(delta)) {
267 return false;
268 }
269
270 if (BytecodeOpHasIC(op)) {
271 // Even if every bytecode op is a JOF_IC op and the function has ARGC_LIMIT
272 // arguments, numICEntries cannot overflow.
273 static_assert(MaxBytecodeLength + 1 /* this */ + ARGC_LIMIT <= UINT32_MAX(4294967295U),
274 "numICEntries must not overflow");
275 bytecodeSection().incrementNumICEntries();
276 }
277
278 return true;
279}
280
281#ifdef DEBUG1
282bool BytecodeEmitter::checkStrictOrSloppy(JSOp op) const {
283 if (IsCheckStrictOp(op) && !sc->strict()) {
284 return false;
285 }
286 if (IsCheckSloppyOp(op) && sc->strict()) {
287 return false;
288 }
289 return true;
290}
291#endif
292
293bool BytecodeEmitter::emit1(JSOp op) {
294 MOZ_ASSERT(checkStrictOrSloppy(op))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(checkStrictOrSloppy(op))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(checkStrictOrSloppy(op)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("checkStrictOrSloppy(op)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 294); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "checkStrictOrSloppy(op)" ")"); do { MOZ_CrashSequence
(__null, 294); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
295 MOZ_ASSERT(GetOpLength(op) == 1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(GetOpLength(op) == 1)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(GetOpLength(op) == 1))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("GetOpLength(op) == 1"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 295); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetOpLength(op) == 1" ")"); do { MOZ_CrashSequence
(__null, 295); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
296
297 BytecodeOffset offset;
298 if (!emitCheck(op, 1, &offset)) {
299 return false;
300 }
301
302 jsbytecode* code = bytecodeSection().code(offset);
303 code[0] = jsbytecode(op);
304 bytecodeSection().updateDepth(op, offset);
305 return true;
306}
307
308bool BytecodeEmitter::emit2(JSOp op, uint8_t op1) {
309 MOZ_ASSERT(checkStrictOrSloppy(op))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(checkStrictOrSloppy(op))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(checkStrictOrSloppy(op)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("checkStrictOrSloppy(op)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 309); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "checkStrictOrSloppy(op)" ")"); do { MOZ_CrashSequence
(__null, 309); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
310 MOZ_ASSERT(GetOpLength(op) == 2)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(GetOpLength(op) == 2)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(GetOpLength(op) == 2))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("GetOpLength(op) == 2"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 310); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetOpLength(op) == 2" ")"); do { MOZ_CrashSequence
(__null, 310); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
311
312 BytecodeOffset offset;
313 if (!emitCheck(op, 2, &offset)) {
314 return false;
315 }
316
317 jsbytecode* code = bytecodeSection().code(offset);
318 code[0] = jsbytecode(op);
319 code[1] = jsbytecode(op1);
320 bytecodeSection().updateDepth(op, offset);
321 return true;
322}
323
324bool BytecodeEmitter::emit3(JSOp op, jsbytecode op1, jsbytecode op2) {
325 MOZ_ASSERT(checkStrictOrSloppy(op))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(checkStrictOrSloppy(op))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(checkStrictOrSloppy(op)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("checkStrictOrSloppy(op)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 325); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "checkStrictOrSloppy(op)" ")"); do { MOZ_CrashSequence
(__null, 325); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
326 MOZ_ASSERT(GetOpLength(op) == 3)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(GetOpLength(op) == 3)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(GetOpLength(op) == 3))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("GetOpLength(op) == 3"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 326); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetOpLength(op) == 3" ")"); do { MOZ_CrashSequence
(__null, 326); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
327
328 /* These should filter through emitVarOp. */
329 MOZ_ASSERT(!IsArgOp(op))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsArgOp(op))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!IsArgOp(op)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!IsArgOp(op)", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 329); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsArgOp(op)"
")"); do { MOZ_CrashSequence(__null, 329); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
330 MOZ_ASSERT(!IsLocalOp(op))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsLocalOp(op))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!IsLocalOp(op)))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("!IsLocalOp(op)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 330); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!IsLocalOp(op)" ")"); do { MOZ_CrashSequence
(__null, 330); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
331
332 BytecodeOffset offset;
333 if (!emitCheck(op, 3, &offset)) {
334 return false;
335 }
336
337 jsbytecode* code = bytecodeSection().code(offset);
338 code[0] = jsbytecode(op);
339 code[1] = op1;
340 code[2] = op2;
341 bytecodeSection().updateDepth(op, offset);
342 return true;
343}
344
345bool BytecodeEmitter::emitN(JSOp op, size_t extra, BytecodeOffset* offset) {
346 MOZ_ASSERT(checkStrictOrSloppy(op))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(checkStrictOrSloppy(op))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(checkStrictOrSloppy(op)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("checkStrictOrSloppy(op)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 346); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "checkStrictOrSloppy(op)" ")"); do { MOZ_CrashSequence
(__null, 346); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
347 ptrdiff_t length = 1 + ptrdiff_t(extra);
348
349 BytecodeOffset off;
350 if (!emitCheck(op, length, &off)) {
351 return false;
352 }
353
354 jsbytecode* code = bytecodeSection().code(off);
355 code[0] = jsbytecode(op);
356 /* The remaining |extra| bytes are set by the caller */
357
358 /*
359 * Don't updateDepth if op's use-count comes from the immediate
360 * operand yet to be stored in the extra bytes after op.
361 */
362 if (CodeSpec(op).nuses >= 0) {
363 bytecodeSection().updateDepth(op, off);
364 }
365
366 if (offset) {
367 *offset = off;
368 }
369 return true;
370}
371
372bool BytecodeEmitter::emitJumpTargetOp(JSOp op, BytecodeOffset* off) {
373 MOZ_ASSERT(BytecodeIsJumpTarget(op))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(BytecodeIsJumpTarget(op))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(BytecodeIsJumpTarget(op)))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("BytecodeIsJumpTarget(op)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 373); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "BytecodeIsJumpTarget(op)" ")"); do { MOZ_CrashSequence
(__null, 373); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
374
375 // Record the current IC-entry index at start of this op.
376 uint32_t numEntries = bytecodeSection().numICEntries();
377
378 size_t n = GetOpLength(op) - 1;
379 MOZ_ASSERT(GetOpLength(op) >= 1 + ICINDEX_LEN)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(GetOpLength(op) >= 1 + ICINDEX_LEN)>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(GetOpLength(op) >= 1 + ICINDEX_LEN))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("GetOpLength(op) >= 1 + ICINDEX_LEN"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 379); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetOpLength(op) >= 1 + ICINDEX_LEN" ")"
); do { MOZ_CrashSequence(__null, 379); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
380
381 if (!emitN(op, n, off)) {
382 return false;
383 }
384
385 SET_ICINDEX(bytecodeSection().code(*off), numEntries);
386 return true;
387}
388
389bool BytecodeEmitter::emitJumpTarget(JumpTarget* target) {
390 BytecodeOffset off = bytecodeSection().offset();
391
392 // Alias consecutive jump targets.
393 if (bytecodeSection().lastTargetOffset().valid() &&
394 off == bytecodeSection().lastTargetOffset() +
395 BytecodeOffsetDiff(JSOpLength_JumpTarget)) {
396 target->offset = bytecodeSection().lastTargetOffset();
397 return true;
398 }
399
400 target->offset = off;
401 bytecodeSection().setLastTargetOffset(off);
402
403 BytecodeOffset opOff;
404 return emitJumpTargetOp(JSOp::JumpTarget, &opOff);
405}
406
407bool BytecodeEmitter::emitJumpNoFallthrough(JSOp op, JumpList* jump) {
408 BytecodeOffset offset;
409 if (!emitCheck(op, 5, &offset)) {
410 return false;
411 }
412
413 jsbytecode* code = bytecodeSection().code(offset);
414 code[0] = jsbytecode(op);
415 MOZ_ASSERT(!jump->offset.valid() ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!jump->offset.valid() || (0 <= jump->offset
.value() && jump->offset < offset))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!jump->offset.valid() || (0 <= jump->offset.value
() && jump->offset < offset)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!jump->offset.valid() || (0 <= jump->offset.value() && jump->offset < offset)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 416); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!jump->offset.valid() || (0 <= jump->offset.value() && jump->offset < offset)"
")"); do { MOZ_CrashSequence(__null, 416); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
416 (0 <= jump->offset.value() && jump->offset < offset))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!jump->offset.valid() || (0 <= jump->offset
.value() && jump->offset < offset))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!jump->offset.valid() || (0 <= jump->offset.value
() && jump->offset < offset)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!jump->offset.valid() || (0 <= jump->offset.value() && jump->offset < offset)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 416); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!jump->offset.valid() || (0 <= jump->offset.value() && jump->offset < offset)"
")"); do { MOZ_CrashSequence(__null, 416); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
417 jump->push(bytecodeSection().code(BytecodeOffset(0)), offset);
418 bytecodeSection().updateDepth(op, offset);
419 return true;
420}
421
422bool BytecodeEmitter::emitJump(JSOp op, JumpList* jump) {
423 if (!emitJumpNoFallthrough(op, jump)) {
424 return false;
425 }
426 if (BytecodeFallsThrough(op)) {
427 JumpTarget fallthrough;
428 if (!emitJumpTarget(&fallthrough)) {
429 return false;
430 }
431 }
432 return true;
433}
434
435void BytecodeEmitter::patchJumpsToTarget(JumpList jump, JumpTarget target) {
436 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!jump.offset.valid() || (0 <= jump.offset.value()
&& jump.offset <= bytecodeSection().offset()))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!jump.offset.valid() || (0 <= jump.offset.value()
&& jump.offset <= bytecodeSection().offset())))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset())"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 438); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset())"
")"); do { MOZ_CrashSequence(__null, 438); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
437 !jump.offset.valid() ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!jump.offset.valid() || (0 <= jump.offset.value()
&& jump.offset <= bytecodeSection().offset()))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!jump.offset.valid() || (0 <= jump.offset.value()
&& jump.offset <= bytecodeSection().offset())))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset())"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 438); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset())"
")"); do { MOZ_CrashSequence(__null, 438); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
438 (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset()))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!jump.offset.valid() || (0 <= jump.offset.value()
&& jump.offset <= bytecodeSection().offset()))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!jump.offset.valid() || (0 <= jump.offset.value()
&& jump.offset <= bytecodeSection().offset())))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset())"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 438); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset())"
")"); do { MOZ_CrashSequence(__null, 438); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
439 MOZ_ASSERT(0 <= target.offset.value() &&do { static_assert( mozilla::detail::AssertionConditionType<
decltype(0 <= target.offset.value() && target.offset
<= bytecodeSection().offset())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(0 <= target.offset.value(
) && target.offset <= bytecodeSection().offset()))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("0 <= target.offset.value() && target.offset <= bytecodeSection().offset()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 440); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "0 <= target.offset.value() && target.offset <= bytecodeSection().offset()"
")"); do { MOZ_CrashSequence(__null, 440); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
440 target.offset <= bytecodeSection().offset())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(0 <= target.offset.value() && target.offset
<= bytecodeSection().offset())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(0 <= target.offset.value(
) && target.offset <= bytecodeSection().offset()))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("0 <= target.offset.value() && target.offset <= bytecodeSection().offset()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 440); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "0 <= target.offset.value() && target.offset <= bytecodeSection().offset()"
")"); do { MOZ_CrashSequence(__null, 440); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
441 MOZ_ASSERT_IF(do { if (jump.offset.valid() && target.offset + BytecodeOffsetDiff
(4) <= bytecodeSection().offset()) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(BytecodeIsJumpTarget
(JSOp(*bytecodeSection().code(target.offset))))>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset
)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 444); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))"
")"); do { MOZ_CrashSequence(__null, 444); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
442 jump.offset.valid() &&do { if (jump.offset.valid() && target.offset + BytecodeOffsetDiff
(4) <= bytecodeSection().offset()) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(BytecodeIsJumpTarget
(JSOp(*bytecodeSection().code(target.offset))))>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset
)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 444); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))"
")"); do { MOZ_CrashSequence(__null, 444); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
443 target.offset + BytecodeOffsetDiff(4) <= bytecodeSection().offset(),do { if (jump.offset.valid() && target.offset + BytecodeOffsetDiff
(4) <= bytecodeSection().offset()) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(BytecodeIsJumpTarget
(JSOp(*bytecodeSection().code(target.offset))))>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset
)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 444); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))"
")"); do { MOZ_CrashSequence(__null, 444); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
444 BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset))))do { if (jump.offset.valid() && target.offset + BytecodeOffsetDiff
(4) <= bytecodeSection().offset()) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(BytecodeIsJumpTarget
(JSOp(*bytecodeSection().code(target.offset))))>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset
)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 444); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))"
")"); do { MOZ_CrashSequence(__null, 444); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
445 jump.patchAll(bytecodeSection().code(BytecodeOffset(0)), target);
446}
447
448bool BytecodeEmitter::emitJumpTargetAndPatch(JumpList jump) {
449 if (!jump.offset.valid()) {
450 return true;
451 }
452 JumpTarget target;
453 if (!emitJumpTarget(&target)) {
454 return false;
455 }
456 patchJumpsToTarget(jump, target);
457 return true;
458}
459
460bool BytecodeEmitter::emitCall(JSOp op, uint16_t argc,
461 const Maybe<uint32_t>& sourceCoordOffset) {
462 if (sourceCoordOffset.isSome()) {
463 if (!updateSourceCoordNotes(*sourceCoordOffset)) {
464 return false;
465 }
466 }
467 return emit3(op, ARGC_LO(argc), ARGC_HI(argc));
468}
469
470bool BytecodeEmitter::emitCall(JSOp op, uint16_t argc, ParseNode* pn) {
471 return emitCall(op, argc, pn ? Some(pn->pn_pos.begin) : Nothing());
472}
473
474bool BytecodeEmitter::emitDupAt(unsigned slotFromTop, unsigned count) {
475 MOZ_ASSERT(slotFromTop < unsigned(bytecodeSection().stackDepth()))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(slotFromTop < unsigned(bytecodeSection().stackDepth
()))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(slotFromTop < unsigned(bytecodeSection().stackDepth
())))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("slotFromTop < unsigned(bytecodeSection().stackDepth())",
"./../../../../js/src/frontend/BytecodeEmitter.cpp", 475); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "slotFromTop < unsigned(bytecodeSection().stackDepth())"
")"); do { MOZ_CrashSequence(__null, 475); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
476 MOZ_ASSERT(slotFromTop + 1 >= count)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(slotFromTop + 1 >= count)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(slotFromTop + 1 >= count)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("slotFromTop + 1 >= count"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 476); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "slotFromTop + 1 >= count" ")"); do { MOZ_CrashSequence
(__null, 476); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
477
478 if (slotFromTop == 0 && count == 1) {
479 return emit1(JSOp::Dup);
480 }
481
482 if (slotFromTop == 1 && count == 2) {
483 return emit1(JSOp::Dup2);
484 }
485
486 if (slotFromTop >= Bit(24)) {
487 reportError(nullptr, JSMSG_TOO_MANY_LOCALS);
488 return false;
489 }
490
491 for (unsigned i = 0; i < count; i++) {
492 BytecodeOffset off;
493 if (!emitN(JSOp::DupAt, 3, &off)) {
494 return false;
495 }
496
497 jsbytecode* pc = bytecodeSection().code(off);
498 SET_UINT24(pc, slotFromTop);
499 }
500
501 return true;
502}
503
504bool BytecodeEmitter::emitPopN(unsigned n) {
505 MOZ_ASSERT(n != 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(n != 0)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(n != 0))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("n != 0", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 505); AnnotateMozCrashReason("MOZ_ASSERT" "(" "n != 0" ")")
; do { MOZ_CrashSequence(__null, 505); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
506
507 if (n == 1) {
508 return emit1(JSOp::Pop);
509 }
510
511 // 2 JSOp::Pop instructions (2 bytes) are shorter than JSOp::PopN (3 bytes).
512 if (n == 2) {
513 return emit1(JSOp::Pop) && emit1(JSOp::Pop);
514 }
515
516 // Emit multiple ops if there are many values to pop.
517 while (n > UINT16_MAX(65535)) {
518 if (!emitUint16Operand(JSOp::PopN, UINT16_MAX(65535))) {
519 return false;
520 }
521 n -= UINT16_MAX(65535);
522 }
523 return emitUint16Operand(JSOp::PopN, n);
524}
525
526bool BytecodeEmitter::emitPickN(uint8_t n) {
527 MOZ_ASSERT(n != 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(n != 0)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(n != 0))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("n != 0", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 527); AnnotateMozCrashReason("MOZ_ASSERT" "(" "n != 0" ")")
; do { MOZ_CrashSequence(__null, 527); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
528
529 if (n == 1) {
530 return emit1(JSOp::Swap);
531 }
532
533 return emit2(JSOp::Pick, n);
534}
535
536bool BytecodeEmitter::emitUnpickN(uint8_t n) {
537 MOZ_ASSERT(n != 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(n != 0)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(n != 0))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("n != 0", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 537); AnnotateMozCrashReason("MOZ_ASSERT" "(" "n != 0" ")")
; do { MOZ_CrashSequence(__null, 537); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
538
539 if (n == 1) {
540 return emit1(JSOp::Swap);
541 }
542
543 return emit2(JSOp::Unpick, n);
544}
545
546bool BytecodeEmitter::emitCheckIsObj(CheckIsObjectKind kind) {
547 return emit2(JSOp::CheckIsObj, uint8_t(kind));
548}
549
550bool BytecodeEmitter::emitBuiltinObject(BuiltinObjectKind kind) {
551 return emit2(JSOp::BuiltinObject, uint8_t(kind));
552}
553
554/* Updates line number notes, not column notes. */
555bool BytecodeEmitter::updateLineNumberNotes(uint32_t offset) {
556 if (skipLocationSrcNotes()) {
557 return true;
558 }
559
560 const ErrorReporter& er = errorReporter();
561 std::optional<bool> onThisLineStatus =
562 er.isOnThisLine(offset, bytecodeSection().currentLine());
563 if (!onThisLineStatus.has_value()) {
564 er.errorNoOffset(JSMSG_OUT_OF_MEMORY);
565 return false;
566 }
567
568 bool onThisLine = *onThisLineStatus;
569
570 if (!onThisLine) {
571 unsigned line = er.lineAt(offset);
572 unsigned delta = line - bytecodeSection().currentLine();
573
574 // If we use a `SetLine` note below, we want it to be relative to the
575 // scripts initial line number for better chance of sharing.
576 unsigned initialLine = sc->extent().lineno;
577 MOZ_ASSERT(line >= initialLine)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(line >= initialLine)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(line >= initialLine))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("line >= initialLine"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 577); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "line >= initialLine" ")"); do { MOZ_CrashSequence
(__null, 577); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
578
579 /*
580 * Encode any change in the current source line number by using
581 * either several SrcNoteType::NewLine notes or just one
582 * SrcNoteType::SetLine note, whichever consumes less space.
583 *
584 * NB: We handle backward line number deltas (possible with for
585 * loops where the update part is emitted after the body, but its
586 * line number is <= any line number in the body) here by letting
587 * unsigned delta_ wrap to a very large number, which triggers a
588 * SrcNoteType::SetLine.
589 */
590 bytecodeSection().setCurrentLine(line, offset);
591 if (delta >= SrcNote::SetLine::lengthFor(line, initialLine)) {
592 if (!newSrcNote2(SrcNoteType::SetLine,
593 SrcNote::SetLine::toOperand(line, initialLine))) {
594 return false;
595 }
596 } else {
597 do {
598 if (!newSrcNote(SrcNoteType::NewLine)) {
599 return false;
600 }
601 } while (--delta != 0);
602 }
603
604 bytecodeSection().updateSeparatorPositionIfPresent();
605 }
606 return true;
607}
608
609/* Updates the line number and column number information in the source notes. */
610bool BytecodeEmitter::updateSourceCoordNotes(uint32_t offset) {
611 if (skipLocationSrcNotes()) {
612 return true;
613 }
614
615 if (!updateLineNumberNotes(offset)) {
616 return false;
617 }
618
619 JS::LimitedColumnNumberOneOrigin columnIndex =
620 errorReporter().columnAt(offset);
621
622 // Assert colspan is always representable.
623 static_assert((0 - ptrdiff_t(JS::LimitedColumnNumberOneOrigin::Limit)) >=
624 SrcNote::ColSpan::MinColSpan);
625 static_assert((ptrdiff_t(JS::LimitedColumnNumberOneOrigin::Limit) - 0) <=
626 SrcNote::ColSpan::MaxColSpan);
627
628 JS::ColumnNumberOffset colspan = columnIndex - bytecodeSection().lastColumn();
629
630 if (colspan != JS::ColumnNumberOffset::zero()) {
631 if (lastLineOnlySrcNoteIndex != LastSrcNoteIsNotLineOnly) {
632 MOZ_ASSERT(bytecodeSection().lastColumn() ==do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bytecodeSection().lastColumn() == JS::LimitedColumnNumberOneOrigin
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(bytecodeSection().lastColumn() == JS::LimitedColumnNumberOneOrigin
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("bytecodeSection().lastColumn() == JS::LimitedColumnNumberOneOrigin()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 633); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "bytecodeSection().lastColumn() == JS::LimitedColumnNumberOneOrigin()"
")"); do { MOZ_CrashSequence(__null, 633); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
633 JS::LimitedColumnNumberOneOrigin())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bytecodeSection().lastColumn() == JS::LimitedColumnNumberOneOrigin
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(bytecodeSection().lastColumn() == JS::LimitedColumnNumberOneOrigin
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("bytecodeSection().lastColumn() == JS::LimitedColumnNumberOneOrigin()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 633); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "bytecodeSection().lastColumn() == JS::LimitedColumnNumberOneOrigin()"
")"); do { MOZ_CrashSequence(__null, 633); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
634
635 const SrcNotesVector& notes = bytecodeSection().notes();
636 SrcNoteType type = notes[lastLineOnlySrcNoteIndex].type();
637 if (type == SrcNoteType::NewLine) {
638 if (!convertLastNewLineToNewLineColumn(columnIndex)) {
639 return false;
640 }
641 } else {
642 MOZ_ASSERT(type == SrcNoteType::SetLine)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(type == SrcNoteType::SetLine)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(type == SrcNoteType::SetLine
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"type == SrcNoteType::SetLine", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 642); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == SrcNoteType::SetLine"
")"); do { MOZ_CrashSequence(__null, 642); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
643 if (!convertLastSetLineToSetLineColumn(columnIndex)) {
644 return false;
645 }
646 }
647 } else {
648 if (!newSrcNote2(SrcNoteType::ColSpan,
649 SrcNote::ColSpan::toOperand(colspan))) {
650 return false;
651 }
652 }
653 bytecodeSection().setLastColumn(columnIndex, offset);
654 bytecodeSection().updateSeparatorPositionIfPresent();
655 }
656 return true;
657}
658
659bool BytecodeEmitter::updateSourceCoordNotesIfNonLiteral(ParseNode* node) {
660 if (node->isLiteral()) {
661 return true;
662 }
663 return updateSourceCoordNotes(node->pn_pos.begin);
664}
665
666uint32_t BytecodeEmitter::getOffsetForLoop(ParseNode* nextpn) const {
667 // Try to give the JSOp::LoopHead the same line number as the next
668 // instruction. nextpn is often a block, in which case the next instruction
669 // typically comes from the first statement inside.
670 if (nextpn->is<LexicalScopeNode>()) {
671 nextpn = nextpn->as<LexicalScopeNode>().scopeBody();
672 }
673 if (nextpn->isKind(ParseNodeKind::StatementList)) {
674 if (ParseNode* firstStatement = nextpn->as<ListNode>().head()) {
675 nextpn = firstStatement;
676 }
677 }
678
679 return nextpn->pn_pos.begin;
680}
681
682bool BytecodeEmitter::emitUint16Operand(JSOp op, uint32_t operand) {
683 MOZ_ASSERT(operand <= UINT16_MAX)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(operand <= (65535))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(operand <= (65535)))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("operand <= (65535)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 683); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "operand <= (65535)" ")"); do { MOZ_CrashSequence
(__null, 683); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
684 if (!emit3(op, UINT16_LO(operand), UINT16_HI(operand))) {
685 return false;
686 }
687 return true;
688}
689
690bool BytecodeEmitter::emitUint32Operand(JSOp op, uint32_t operand) {
691 BytecodeOffset off;
692 if (!emitN(op, 4, &off)) {
693 return false;
694 }
695 SET_UINT32(bytecodeSection().code(off), operand);
696 return true;
697}
698
699bool BytecodeEmitter::emitGoto(NestableControl* target, GotoKind kind) {
700 NonLocalExitControl nle(this, kind == GotoKind::Continue
701 ? NonLocalExitKind::Continue
702 : NonLocalExitKind::Break);
703 return nle.emitNonLocalJump(target);
704}
705
706AbstractScopePtr BytecodeEmitter::innermostScope() const {
707 return innermostEmitterScope()->scope(this);
708}
709
710ScopeIndex BytecodeEmitter::innermostScopeIndex() const {
711 return *innermostEmitterScope()->scopeIndex(this);
712}
713
714bool BytecodeEmitter::emitGCIndexOp(JSOp op, GCThingIndex index) {
715 MOZ_ASSERT(checkStrictOrSloppy(op))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(checkStrictOrSloppy(op))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(checkStrictOrSloppy(op)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("checkStrictOrSloppy(op)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 715); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "checkStrictOrSloppy(op)" ")"); do { MOZ_CrashSequence
(__null, 715); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
716
717 constexpr size_t OpLength = 1 + GCTHING_INDEX_LEN;
718 MOZ_ASSERT(GetOpLength(op) == OpLength)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(GetOpLength(op) == OpLength)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(GetOpLength(op) == OpLength)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("GetOpLength(op) == OpLength"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 718); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetOpLength(op) == OpLength" ")"); do { MOZ_CrashSequence
(__null, 718); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
719
720 BytecodeOffset offset;
721 if (!emitCheck(op, OpLength, &offset)) {
722 return false;
723 }
724
725 jsbytecode* code = bytecodeSection().code(offset);
726 code[0] = jsbytecode(op);
727 SET_GCTHING_INDEX(code, index);
728 bytecodeSection().updateDepth(op, offset);
729 return true;
730}
731
732bool BytecodeEmitter::emitAtomOp(JSOp op, TaggedParserAtomIndex atom) {
733 MOZ_ASSERT(atom)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(atom)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(atom))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("atom", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 733); AnnotateMozCrashReason("MOZ_ASSERT" "(" "atom" ")"); do
{ MOZ_CrashSequence(__null, 733); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
734
735 // .generator lookups should be emitted as JSOp::GetAliasedVar instead of
736 // JSOp::GetName etc, to bypass |with| objects on the scope chain.
737 // It's safe to emit .this lookups though because |with| objects skip
738 // those.
739 MOZ_ASSERT_IF(op == JSOp::GetName || op == JSOp::GetGName,do { if (op == JSOp::GetName || op == JSOp::GetGName) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(atom !=
TaggedParserAtomIndex::WellKnown::dot_generator_())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(atom != TaggedParserAtomIndex::WellKnown::dot_generator_()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"atom != TaggedParserAtomIndex::WellKnown::dot_generator_()",
"./../../../../js/src/frontend/BytecodeEmitter.cpp", 740); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "atom != TaggedParserAtomIndex::WellKnown::dot_generator_()"
")"); do { MOZ_CrashSequence(__null, 740); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
740 atom != TaggedParserAtomIndex::WellKnown::dot_generator_())do { if (op == JSOp::GetName || op == JSOp::GetGName) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(atom !=
TaggedParserAtomIndex::WellKnown::dot_generator_())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(atom != TaggedParserAtomIndex::WellKnown::dot_generator_()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"atom != TaggedParserAtomIndex::WellKnown::dot_generator_()",
"./../../../../js/src/frontend/BytecodeEmitter.cpp", 740); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "atom != TaggedParserAtomIndex::WellKnown::dot_generator_()"
")"); do { MOZ_CrashSequence(__null, 740); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
741
742 GCThingIndex index;
743 if (!makeAtomIndex(atom, ParserAtom::Atomize::Yes, &index)) {
744 return false;
745 }
746
747 return emitAtomOp(op, index);
748}
749
750bool BytecodeEmitter::emitAtomOp(JSOp op, GCThingIndex atomIndex) {
751 MOZ_ASSERT(JOF_OPTYPE(op) == JOF_ATOM)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(JOF_OPTYPE(op) == JOF_ATOM)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(JOF_OPTYPE(op) == JOF_ATOM))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("JOF_OPTYPE(op) == JOF_ATOM"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 751); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "JOF_OPTYPE(op) == JOF_ATOM" ")"); do { MOZ_CrashSequence
(__null, 751); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
752#ifdef DEBUG1
753 auto atom = perScriptData().gcThingList().getAtom(atomIndex);
754 MOZ_ASSERT(compilationState.parserAtoms.isInstantiatedAsJSAtom(atom))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(compilationState.parserAtoms.isInstantiatedAsJSAtom(
atom))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(compilationState.parserAtoms.isInstantiatedAsJSAtom(
atom)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("compilationState.parserAtoms.isInstantiatedAsJSAtom(atom)",
"./../../../../js/src/frontend/BytecodeEmitter.cpp", 754); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "compilationState.parserAtoms.isInstantiatedAsJSAtom(atom)"
")"); do { MOZ_CrashSequence(__null, 754); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
755#endif
756 return emitGCIndexOp(op, atomIndex);
757}
758
759bool BytecodeEmitter::emitStringOp(JSOp op, TaggedParserAtomIndex atom) {
760 MOZ_ASSERT(atom)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(atom)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(atom))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("atom", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 760); AnnotateMozCrashReason("MOZ_ASSERT" "(" "atom" ")"); do
{ MOZ_CrashSequence(__null, 760); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
761 GCThingIndex index;
762 if (!makeAtomIndex(atom, ParserAtom::Atomize::No, &index)) {
763 return false;
764 }
765
766 return emitStringOp(op, index);
767}
768
769bool BytecodeEmitter::emitStringOp(JSOp op, GCThingIndex atomIndex) {
770 MOZ_ASSERT(JOF_OPTYPE(op) == JOF_STRING)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(JOF_OPTYPE(op) == JOF_STRING)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(JOF_OPTYPE(op) == JOF_STRING
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"JOF_OPTYPE(op) == JOF_STRING", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 770); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JOF_OPTYPE(op) == JOF_STRING"
")"); do { MOZ_CrashSequence(__null, 770); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
771 return emitGCIndexOp(op, atomIndex);
772}
773
774bool BytecodeEmitter::emitInternedScopeOp(GCThingIndex index, JSOp op) {
775 MOZ_ASSERT(JOF_OPTYPE(op) == JOF_SCOPE)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(JOF_OPTYPE(op) == JOF_SCOPE)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(JOF_OPTYPE(op) == JOF_SCOPE)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("JOF_OPTYPE(op) == JOF_SCOPE"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 775); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "JOF_OPTYPE(op) == JOF_SCOPE" ")"); do { MOZ_CrashSequence
(__null, 775); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
776 MOZ_ASSERT(index < perScriptData().gcThingList().length())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(index < perScriptData().gcThingList().length())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(index < perScriptData().gcThingList().length())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("index < perScriptData().gcThingList().length()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 776); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "index < perScriptData().gcThingList().length()"
")"); do { MOZ_CrashSequence(__null, 776); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
777 return emitGCIndexOp(op, index);
778}
779
780bool BytecodeEmitter::emitInternedObjectOp(GCThingIndex index, JSOp op) {
781 MOZ_ASSERT(JOF_OPTYPE(op) == JOF_OBJECT)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(JOF_OPTYPE(op) == JOF_OBJECT)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(JOF_OPTYPE(op) == JOF_OBJECT
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"JOF_OPTYPE(op) == JOF_OBJECT", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 781); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JOF_OPTYPE(op) == JOF_OBJECT"
")"); do { MOZ_CrashSequence(__null, 781); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
782 MOZ_ASSERT(index < perScriptData().gcThingList().length())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(index < perScriptData().gcThingList().length())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(index < perScriptData().gcThingList().length())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("index < perScriptData().gcThingList().length()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 782); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "index < perScriptData().gcThingList().length()"
")"); do { MOZ_CrashSequence(__null, 782); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
783 return emitGCIndexOp(op, index);
784}
785
786bool BytecodeEmitter::emitRegExp(GCThingIndex index) {
787 return emitGCIndexOp(JSOp::RegExp, index);
788}
789
790bool BytecodeEmitter::emitLocalOp(JSOp op, uint32_t slot) {
791 MOZ_ASSERT(JOF_OPTYPE(op) != JOF_ENVCOORD)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(JOF_OPTYPE(op) != JOF_ENVCOORD)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(JOF_OPTYPE(op) != JOF_ENVCOORD
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"JOF_OPTYPE(op) != JOF_ENVCOORD", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 791); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JOF_OPTYPE(op) != JOF_ENVCOORD"
")"); do { MOZ_CrashSequence(__null, 791); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
792 MOZ_ASSERT(IsLocalOp(op))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsLocalOp(op))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsLocalOp(op)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("IsLocalOp(op)",
"./../../../../js/src/frontend/BytecodeEmitter.cpp", 792); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "IsLocalOp(op)" ")"); do { MOZ_CrashSequence
(__null, 792); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
793
794 BytecodeOffset off;
795 if (!emitN(op, LOCALNO_LEN, &off)) {
796 return false;
797 }
798
799 SET_LOCALNO(bytecodeSection().code(off), slot);
800 return true;
801}
802
803bool BytecodeEmitter::emitArgOp(JSOp op, uint16_t slot) {
804 MOZ_ASSERT(IsArgOp(op))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsArgOp(op))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsArgOp(op)))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("IsArgOp(op)", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 804); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsArgOp(op)"
")"); do { MOZ_CrashSequence(__null, 804); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
805 BytecodeOffset off;
806 if (!emitN(op, ARGNO_LEN, &off)) {
807 return false;
808 }
809
810 SET_ARGNO(bytecodeSection().code(off), slot);
811 return true;
812}
813
814bool BytecodeEmitter::emitEnvCoordOp(JSOp op, EnvironmentCoordinate ec) {
815 MOZ_ASSERT(JOF_OPTYPE(op) == JOF_ENVCOORD ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(JOF_OPTYPE(op) == JOF_ENVCOORD || JOF_OPTYPE(op) == JOF_DEBUGCOORD
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(JOF_OPTYPE(op) == JOF_ENVCOORD || JOF_OPTYPE(op) == JOF_DEBUGCOORD
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"JOF_OPTYPE(op) == JOF_ENVCOORD || JOF_OPTYPE(op) == JOF_DEBUGCOORD"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 816); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "JOF_OPTYPE(op) == JOF_ENVCOORD || JOF_OPTYPE(op) == JOF_DEBUGCOORD"
")"); do { MOZ_CrashSequence(__null, 816); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
816 JOF_OPTYPE(op) == JOF_DEBUGCOORD)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(JOF_OPTYPE(op) == JOF_ENVCOORD || JOF_OPTYPE(op) == JOF_DEBUGCOORD
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(JOF_OPTYPE(op) == JOF_ENVCOORD || JOF_OPTYPE(op) == JOF_DEBUGCOORD
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"JOF_OPTYPE(op) == JOF_ENVCOORD || JOF_OPTYPE(op) == JOF_DEBUGCOORD"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 816); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "JOF_OPTYPE(op) == JOF_ENVCOORD || JOF_OPTYPE(op) == JOF_DEBUGCOORD"
")"); do { MOZ_CrashSequence(__null, 816); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
817
818 constexpr size_t N = ENVCOORD_HOPS_LEN + ENVCOORD_SLOT_LEN;
819 MOZ_ASSERT(GetOpLength(op) == 1 + N)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(GetOpLength(op) == 1 + N)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(GetOpLength(op) == 1 + N))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("GetOpLength(op) == 1 + N"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 819); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetOpLength(op) == 1 + N" ")"); do { MOZ_CrashSequence
(__null, 819); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
820
821 BytecodeOffset off;
822 if (!emitN(op, N, &off)) {
823 return false;
824 }
825
826 jsbytecode* pc = bytecodeSection().code(off);
827 SET_ENVCOORD_HOPS(pc, ec.hops());
828 pc += ENVCOORD_HOPS_LEN;
829 SET_ENVCOORD_SLOT(pc, ec.slot());
830 pc += ENVCOORD_SLOT_LEN;
Value stored to 'pc' is never read
831 return true;
832}
833
834bool BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer) const {
835 AutoCheckRecursionLimit recursion(fc);
836 if (!recursion.check(fc)) {
837 return false;
838 }
839
840restart:
841
842 switch (pn->getKind()) {
843 // Trivial cases with no side effects.
844 case ParseNodeKind::EmptyStmt:
845 case ParseNodeKind::TrueExpr:
846 case ParseNodeKind::FalseExpr:
847 case ParseNodeKind::NullExpr:
848 case ParseNodeKind::RawUndefinedExpr:
849 case ParseNodeKind::Elision:
850 case ParseNodeKind::Generator:
851 MOZ_ASSERT(pn->is<NullaryNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<NullaryNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<NullaryNode>
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("pn->is<NullaryNode>()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 851); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<NullaryNode>()"
")"); do { MOZ_CrashSequence(__null, 851); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
852 *answer = false;
853 return true;
854
855 case ParseNodeKind::ObjectPropertyName:
856 case ParseNodeKind::PrivateName: // no side effects, unlike
857 // ParseNodeKind::Name
858 case ParseNodeKind::StringExpr:
859 case ParseNodeKind::TemplateStringExpr:
860 MOZ_ASSERT(pn->is<NameNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<NameNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<NameNode>())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("pn->is<NameNode>()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 860); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "pn->is<NameNode>()" ")"); do { MOZ_CrashSequence
(__null, 860); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
861 *answer = false;
862 return true;
863
864 case ParseNodeKind::RegExpExpr:
865 MOZ_ASSERT(pn->is<RegExpLiteral>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<RegExpLiteral>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<RegExpLiteral>
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("pn->is<RegExpLiteral>()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 865); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<RegExpLiteral>()"
")"); do { MOZ_CrashSequence(__null, 865); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
866 *answer = false;
867 return true;
868
869 case ParseNodeKind::NumberExpr:
870 MOZ_ASSERT(pn->is<NumericLiteral>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<NumericLiteral>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<NumericLiteral>
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("pn->is<NumericLiteral>()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 870); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<NumericLiteral>()"
")"); do { MOZ_CrashSequence(__null, 870); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
871 *answer = false;
872 return true;
873
874 case ParseNodeKind::BigIntExpr:
875 MOZ_ASSERT(pn->is<BigIntLiteral>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<BigIntLiteral>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<BigIntLiteral>
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("pn->is<BigIntLiteral>()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 875); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BigIntLiteral>()"
")"); do { MOZ_CrashSequence(__null, 875); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
876 *answer = false;
877 return true;
878
879 // |this| can throw in derived class constructors, including nested arrow
880 // functions or eval.
881 case ParseNodeKind::ThisExpr:
882 MOZ_ASSERT(pn->is<UnaryNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<UnaryNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<UnaryNode>()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"pn->is<UnaryNode>()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 882); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { MOZ_CrashSequence(__null, 882); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
883 *answer = sc->needsThisTDZChecks();
884 return true;
885
886 // |new.target| doesn't have any side-effects.
887 case ParseNodeKind::NewTargetExpr: {
888 MOZ_ASSERT(pn->is<NewTargetNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<NewTargetNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<NewTargetNode>
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("pn->is<NewTargetNode>()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 888); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<NewTargetNode>()"
")"); do { MOZ_CrashSequence(__null, 888); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
889 *answer = false;
890 return true;
891 }
892
893 // Trivial binary nodes with more token pos holders.
894 case ParseNodeKind::ImportMetaExpr: {
895 MOZ_ASSERT(pn->as<BinaryNode>().left()->isKind(ParseNodeKind::PosHolder))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->as<BinaryNode>().left()->isKind(ParseNodeKind
::PosHolder))>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(pn->as<BinaryNode>().left
()->isKind(ParseNodeKind::PosHolder)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("pn->as<BinaryNode>().left()->isKind(ParseNodeKind::PosHolder)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 895); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "pn->as<BinaryNode>().left()->isKind(ParseNodeKind::PosHolder)"
")"); do { MOZ_CrashSequence(__null, 895); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
896 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->as<BinaryNode>().right()->isKind(ParseNodeKind
::PosHolder))>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(pn->as<BinaryNode>().right
()->isKind(ParseNodeKind::PosHolder)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("pn->as<BinaryNode>().right()->isKind(ParseNodeKind::PosHolder)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 897); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "pn->as<BinaryNode>().right()->isKind(ParseNodeKind::PosHolder)"
")"); do { MOZ_CrashSequence(__null, 897); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
897 pn->as<BinaryNode>().right()->isKind(ParseNodeKind::PosHolder))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->as<BinaryNode>().right()->isKind(ParseNodeKind
::PosHolder))>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(pn->as<BinaryNode>().right
()->isKind(ParseNodeKind::PosHolder)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("pn->as<BinaryNode>().right()->isKind(ParseNodeKind::PosHolder)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 897); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "pn->as<BinaryNode>().right()->isKind(ParseNodeKind::PosHolder)"
")"); do { MOZ_CrashSequence(__null, 897); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
898 *answer = false;
899 return true;
900 }
901
902 case ParseNodeKind::BreakStmt:
903 MOZ_ASSERT(pn->is<BreakStatement>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<BreakStatement>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<BreakStatement>
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("pn->is<BreakStatement>()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 903); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BreakStatement>()"
")"); do { MOZ_CrashSequence(__null, 903); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
904 *answer = true;
905 return true;
906
907 case ParseNodeKind::ContinueStmt:
908 MOZ_ASSERT(pn->is<ContinueStatement>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<ContinueStatement>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<ContinueStatement
>()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("pn->is<ContinueStatement>()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 908); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<ContinueStatement>()"
")"); do { MOZ_CrashSequence(__null, 908); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
909 *answer = true;
910 return true;
911
912 case ParseNodeKind::DebuggerStmt:
913 MOZ_ASSERT(pn->is<DebuggerStatement>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<DebuggerStatement>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<DebuggerStatement
>()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("pn->is<DebuggerStatement>()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 913); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<DebuggerStatement>()"
")"); do { MOZ_CrashSequence(__null, 913); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
914 *answer = true;
915 return true;
916
917 // Watch out for getters!
918 case ParseNodeKind::OptionalDotExpr:
919 case ParseNodeKind::DotExpr:
920 case ParseNodeKind::ArgumentsLength:
921 MOZ_ASSERT(pn->is<BinaryNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<BinaryNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<BinaryNode>(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("pn->is<BinaryNode>()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 921); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { MOZ_CrashSequence(__null, 921); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
922 *answer = true;
923 return true;
924
925 // Unary cases with side effects only if the child has them.
926 case ParseNodeKind::TypeOfExpr:
927 case ParseNodeKind::VoidExpr:
928 case ParseNodeKind::NotExpr:
929 return checkSideEffects(pn->as<UnaryNode>().kid(), answer);
930
931 // Even if the name expression is effect-free, performing ToPropertyKey on
932 // it might not be effect-free:
933 //
934 // RegExp.prototype.toString = () => { throw 42; };
935 // ({ [/regex/]: 0 }); // ToPropertyKey(/regex/) throws 42
936 //
937 // function Q() {
938 // ({ [new.target]: 0 });
939 // }
940 // Q.toString = () => { throw 17; };
941 // new Q; // new.target will be Q, ToPropertyKey(Q) throws 17
942 case ParseNodeKind::ComputedName:
943 MOZ_ASSERT(pn->is<UnaryNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<UnaryNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<UnaryNode>()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"pn->is<UnaryNode>()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 943); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { MOZ_CrashSequence(__null, 943); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
944 *answer = true;
945 return true;
946
947 // Looking up or evaluating the associated name could throw.
948 case ParseNodeKind::TypeOfNameExpr:
949 MOZ_ASSERT(pn->is<UnaryNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<UnaryNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<UnaryNode>()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"pn->is<UnaryNode>()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 949); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { MOZ_CrashSequence(__null, 949); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
950 *answer = true;
951 return true;
952
953 // This unary case has side effects on the enclosing object, sure. But
954 // that's not the question this function answers: it's whether the
955 // operation may have a side effect on something *other* than the result
956 // of the overall operation in which it's embedded. The answer to that
957 // is no, because an object literal having a mutated prototype only
958 // produces a value, without affecting anything else.
959 case ParseNodeKind::MutateProto:
960 return checkSideEffects(pn->as<UnaryNode>().kid(), answer);
961
962 // Unary cases with obvious side effects.
963 case ParseNodeKind::PreIncrementExpr:
964 case ParseNodeKind::PostIncrementExpr:
965 case ParseNodeKind::PreDecrementExpr:
966 case ParseNodeKind::PostDecrementExpr:
967 case ParseNodeKind::ThrowStmt:
968 MOZ_ASSERT(pn->is<UnaryNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<UnaryNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<UnaryNode>()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"pn->is<UnaryNode>()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 968); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { MOZ_CrashSequence(__null, 968); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
969 *answer = true;
970 return true;
971
972 // These might invoke valueOf/toString, even with a subexpression without
973 // side effects! Consider |+{ valueOf: null, toString: null }|.
974 case ParseNodeKind::BitNotExpr:
975 case ParseNodeKind::PosExpr:
976 case ParseNodeKind::NegExpr:
977 MOZ_ASSERT(pn->is<UnaryNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<UnaryNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<UnaryNode>()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"pn->is<UnaryNode>()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 977); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { MOZ_CrashSequence(__null, 977); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
978 *answer = true;
979 return true;
980
981 // This invokes the (user-controllable) iterator protocol.
982 case ParseNodeKind::Spread:
983 MOZ_ASSERT(pn->is<UnaryNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<UnaryNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<UnaryNode>()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"pn->is<UnaryNode>()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 983); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { MOZ_CrashSequence(__null, 983); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
984 *answer = true;
985 return true;
986
987 case ParseNodeKind::InitialYield:
988 case ParseNodeKind::YieldStarExpr:
989 case ParseNodeKind::YieldExpr:
990 case ParseNodeKind::AwaitExpr:
991 MOZ_ASSERT(pn->is<UnaryNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<UnaryNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<UnaryNode>()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"pn->is<UnaryNode>()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 991); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { MOZ_CrashSequence(__null, 991); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
992 *answer = true;
993 return true;
994
995 // Deletion generally has side effects, even if isolated cases have none.
996 case ParseNodeKind::DeleteNameExpr:
997 case ParseNodeKind::DeletePropExpr:
998 case ParseNodeKind::DeleteElemExpr:
999 case ParseNodeKind::DeleteOptionalChainExpr:
1000 MOZ_ASSERT(pn->is<UnaryNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<UnaryNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<UnaryNode>()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"pn->is<UnaryNode>()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 1000); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { MOZ_CrashSequence(__null, 1000); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1001 *answer = true;
1002 return true;
1003
1004 // Deletion of a non-Reference expression has side effects only through
1005 // evaluating the expression.
1006 case ParseNodeKind::DeleteExpr: {
1007 ParseNode* expr = pn->as<UnaryNode>().kid();
1008 return checkSideEffects(expr, answer);
1009 }
1010
1011 case ParseNodeKind::ExpressionStmt:
1012 return checkSideEffects(pn->as<UnaryNode>().kid(), answer);
1013
1014 // Binary cases with obvious side effects.
1015 case ParseNodeKind::InitExpr:
1016 *answer = true;
1017 return true;
1018
1019 case ParseNodeKind::AssignExpr:
1020 case ParseNodeKind::AddAssignExpr:
1021 case ParseNodeKind::SubAssignExpr:
1022 case ParseNodeKind::CoalesceAssignExpr:
1023 case ParseNodeKind::OrAssignExpr:
1024 case ParseNodeKind::AndAssignExpr:
1025 case ParseNodeKind::BitOrAssignExpr:
1026 case ParseNodeKind::BitXorAssignExpr:
1027 case ParseNodeKind::BitAndAssignExpr:
1028 case ParseNodeKind::LshAssignExpr:
1029 case ParseNodeKind::RshAssignExpr:
1030 case ParseNodeKind::UrshAssignExpr:
1031 case ParseNodeKind::MulAssignExpr:
1032 case ParseNodeKind::DivAssignExpr:
1033 case ParseNodeKind::ModAssignExpr:
1034 case ParseNodeKind::PowAssignExpr:
1035 MOZ_ASSERT(pn->is<AssignmentNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<AssignmentNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<AssignmentNode>
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("pn->is<AssignmentNode>()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 1035); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<AssignmentNode>()"
")"); do { MOZ_CrashSequence(__null, 1035); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1036 *answer = true;
1037 return true;
1038
1039 case ParseNodeKind::SetThis:
1040 MOZ_ASSERT(pn->is<BinaryNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<BinaryNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<BinaryNode>(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("pn->is<BinaryNode>()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 1040); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { MOZ_CrashSequence(__null, 1040); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1041 *answer = true;
1042 return true;
1043
1044 case ParseNodeKind::StatementList:
1045 // Strict equality operations and short circuit operators are well-behaved
1046 // and perform no conversions.
1047 case ParseNodeKind::CoalesceExpr:
1048 case ParseNodeKind::OrExpr:
1049 case ParseNodeKind::AndExpr:
1050 case ParseNodeKind::StrictEqExpr:
1051 case ParseNodeKind::StrictNeExpr:
1052 // Any subexpression of a comma expression could be effectful.
1053 case ParseNodeKind::CommaExpr:
1054 MOZ_ASSERT(!pn->as<ListNode>().empty())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!pn->as<ListNode>().empty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!pn->as<ListNode>()
.empty()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!pn->as<ListNode>().empty()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 1054); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!pn->as<ListNode>().empty()"
")"); do { MOZ_CrashSequence(__null, 1054); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1055 [[fallthrough]];
1056 // Subcomponents of a literal may be effectful.
1057 case ParseNodeKind::ArrayExpr:
1058 case ParseNodeKind::ObjectExpr:
1059 for (ParseNode* item : pn->as<ListNode>().contents()) {
1060 if (!checkSideEffects(item, answer)) {
1061 return false;
1062 }
1063 if (*answer) {
1064 return true;
1065 }
1066 }
1067 return true;
1068
1069#ifdef ENABLE_DECORATORS
1070 case ParseNodeKind::DecoratorList:
1071 MOZ_CRASH("Decorators are not supported yet")do { do { } while (false); MOZ_ReportCrash("" "Decorators are not supported yet"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 1071);
AnnotateMozCrashReason("MOZ_CRASH(" "Decorators are not supported yet"
")"); do { MOZ_CrashSequence(__null, 1071); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
1072#endif
1073
1074 case ParseNodeKind::UsingDecl:
1075 case ParseNodeKind::AwaitUsingDecl:
1076 MOZ_CRASH("Using declarations are not supported yet")do { do { } while (false); MOZ_ReportCrash("" "Using declarations are not supported yet"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 1076);
AnnotateMozCrashReason("MOZ_CRASH(" "Using declarations are not supported yet"
")"); do { MOZ_CrashSequence(__null, 1076); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
1077
1078 // Most other binary operations (parsed as lists in SpiderMonkey) may
1079 // perform conversions triggering side effects. Math operations perform
1080 // ToNumber and may fail invoking invalid user-defined toString/valueOf:
1081 // |5 < { toString: null }|. |instanceof| throws if provided a
1082 // non-object constructor: |null instanceof null|. |in| throws if given
1083 // a non-object RHS: |5 in null|.
1084 case ParseNodeKind::BitOrExpr:
1085 case ParseNodeKind::BitXorExpr:
1086 case ParseNodeKind::BitAndExpr:
1087 case ParseNodeKind::EqExpr:
1088 case ParseNodeKind::NeExpr:
1089 case ParseNodeKind::LtExpr:
1090 case ParseNodeKind::LeExpr:
1091 case ParseNodeKind::GtExpr:
1092 case ParseNodeKind::GeExpr:
1093 case ParseNodeKind::InstanceOfExpr:
1094 case ParseNodeKind::InExpr:
1095 case ParseNodeKind::PrivateInExpr:
1096 case ParseNodeKind::LshExpr:
1097 case ParseNodeKind::RshExpr:
1098 case ParseNodeKind::UrshExpr:
1099 case ParseNodeKind::AddExpr:
1100 case ParseNodeKind::SubExpr:
1101 case ParseNodeKind::MulExpr:
1102 case ParseNodeKind::DivExpr:
1103 case ParseNodeKind::ModExpr:
1104 case ParseNodeKind::PowExpr:
1105 MOZ_ASSERT(pn->as<ListNode>().count() >= 2)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->as<ListNode>().count() >= 2)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(pn->as<ListNode>().count() >= 2))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("pn->as<ListNode>().count() >= 2"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 1105);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->as<ListNode>().count() >= 2"
")"); do { MOZ_CrashSequence(__null, 1105); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1106 *answer = true;
1107 return true;
1108
1109 case ParseNodeKind::PropertyDefinition:
1110 case ParseNodeKind::Case: {
1111 BinaryNode* node = &pn->as<BinaryNode>();
1112 if (!checkSideEffects(node->left(), answer)) {
1113 return false;
1114 }
1115 if (*answer) {
1116 return true;
1117 }
1118 return checkSideEffects(node->right(), answer);
1119 }
1120
1121 // More getters.
1122 case ParseNodeKind::ElemExpr:
1123 case ParseNodeKind::OptionalElemExpr:
1124 MOZ_ASSERT(pn->is<BinaryNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<BinaryNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<BinaryNode>(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("pn->is<BinaryNode>()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 1124); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { MOZ_CrashSequence(__null, 1124); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1125 *answer = true;
1126 return true;
1127
1128 // Throws if the operand is not of the right class. Can also call a private
1129 // getter.
1130 case ParseNodeKind::PrivateMemberExpr:
1131 case ParseNodeKind::OptionalPrivateMemberExpr:
1132 *answer = true;
1133 return true;
1134
1135 // These affect visible names in this code, or in other code.
1136 case ParseNodeKind::ImportDecl:
1137 case ParseNodeKind::ExportFromStmt:
1138 case ParseNodeKind::ExportDefaultStmt:
1139 MOZ_ASSERT(pn->is<BinaryNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<BinaryNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<BinaryNode>(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("pn->is<BinaryNode>()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 1139); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { MOZ_CrashSequence(__null, 1139); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1140 *answer = true;
1141 return true;
1142
1143 // Likewise.
1144 case ParseNodeKind::ExportStmt:
1145 MOZ_ASSERT(pn->is<UnaryNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<UnaryNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<UnaryNode>()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"pn->is<UnaryNode>()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 1145); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { MOZ_CrashSequence(__null, 1145); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1146 *answer = true;
1147 return true;
1148
1149 case ParseNodeKind::CallImportExpr:
1150 case ParseNodeKind::CallImportSpec:
1151 MOZ_ASSERT(pn->is<BinaryNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<BinaryNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<BinaryNode>(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("pn->is<BinaryNode>()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 1151); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { MOZ_CrashSequence(__null, 1151); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1152 *answer = true;
1153 return true;
1154
1155 // Every part of a loop might be effect-free, but looping infinitely *is*
1156 // an effect. (Language lawyer trivia: C++ says threads can be assumed
1157 // to exit or have side effects, C++14 [intro.multithread]p27, so a C++
1158 // implementation's equivalent of the below could set |*answer = false;|
1159 // if all loop sub-nodes set |*answer = false|!)
1160 case ParseNodeKind::DoWhileStmt:
1161 case ParseNodeKind::WhileStmt:
1162 case ParseNodeKind::ForStmt:
1163 MOZ_ASSERT(pn->is<BinaryNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<BinaryNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<BinaryNode>(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("pn->is<BinaryNode>()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 1163); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { MOZ_CrashSequence(__null, 1163); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1164 *answer = true;
1165 return true;
1166
1167 // Declarations affect the name set of the relevant scope.
1168 case ParseNodeKind::VarStmt:
1169 case ParseNodeKind::ConstDecl:
1170 case ParseNodeKind::LetDecl:
1171 MOZ_ASSERT(pn->is<ListNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<ListNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<ListNode>())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("pn->is<ListNode>()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 1171);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<ListNode>()"
")"); do { MOZ_CrashSequence(__null, 1171); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1172 *answer = true;
1173 return true;
1174
1175 case ParseNodeKind::IfStmt:
1176 case ParseNodeKind::ConditionalExpr: {
1177 TernaryNode* node = &pn->as<TernaryNode>();
1178 if (!checkSideEffects(node->kid1(), answer)) {
1179 return false;
1180 }
1181 if (*answer) {
1182 return true;
1183 }
1184 if (!checkSideEffects(node->kid2(), answer)) {
1185 return false;
1186 }
1187 if (*answer) {
1188 return true;
1189 }
1190 if ((pn = node->kid3())) {
1191 goto restart;
1192 }
1193 return true;
1194 }
1195
1196 // Function calls can invoke non-local code.
1197 case ParseNodeKind::NewExpr:
1198 case ParseNodeKind::CallExpr:
1199 case ParseNodeKind::OptionalCallExpr:
1200 case ParseNodeKind::TaggedTemplateExpr:
1201 case ParseNodeKind::SuperCallExpr:
1202 MOZ_ASSERT(pn->is<BinaryNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<BinaryNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<BinaryNode>(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("pn->is<BinaryNode>()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 1202); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { MOZ_CrashSequence(__null, 1202); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1203 *answer = true;
1204 return true;
1205
1206 // Function arg lists can contain arbitrary expressions. Technically
1207 // this only causes side-effects if one of the arguments does, but since
1208 // the call being made will always trigger side-effects, it isn't needed.
1209 case ParseNodeKind::Arguments:
1210 MOZ_ASSERT(pn->is<ListNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<ListNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<ListNode>())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("pn->is<ListNode>()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 1210);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<ListNode>()"
")"); do { MOZ_CrashSequence(__null, 1210); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1211 *answer = true;
1212 return true;
1213
1214 case ParseNodeKind::OptionalChain:
1215 MOZ_ASSERT(pn->is<UnaryNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<UnaryNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<UnaryNode>()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"pn->is<UnaryNode>()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 1215); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { MOZ_CrashSequence(__null, 1215); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1216 *answer = true;
1217 return true;
1218
1219 // Classes typically introduce names. Even if no name is introduced,
1220 // the heritage and/or class body (through computed property names)
1221 // usually have effects.
1222 case ParseNodeKind::ClassDecl:
1223 MOZ_ASSERT(pn->is<ClassNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<ClassNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<ClassNode>()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"pn->is<ClassNode>()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 1223); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<ClassNode>()"
")"); do { MOZ_CrashSequence(__null, 1223); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1224 *answer = true;
1225 return true;
1226
1227 // |with| calls |ToObject| on its expression and so throws if that value
1228 // is null/undefined.
1229 case ParseNodeKind::WithStmt:
1230 MOZ_ASSERT(pn->is<BinaryNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<BinaryNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<BinaryNode>(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("pn->is<BinaryNode>()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 1230); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { MOZ_CrashSequence(__null, 1230); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1231 *answer = true;
1232 return true;
1233
1234 case ParseNodeKind::ReturnStmt:
1235 MOZ_ASSERT(pn->is<BinaryNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<BinaryNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<BinaryNode>(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("pn->is<BinaryNode>()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 1235); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { MOZ_CrashSequence(__null, 1235); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1236 *answer = true;
1237 return true;
1238
1239 case ParseNodeKind::Name:
1240 MOZ_ASSERT(pn->is<NameNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<NameNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<NameNode>())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("pn->is<NameNode>()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 1240);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<NameNode>()"
")"); do { MOZ_CrashSequence(__null, 1240); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1241 *answer = true;
1242 return true;
1243
1244 // Shorthands could trigger getters: the |x| in the object literal in
1245 // |with ({ get x() { throw 42; } }) ({ x });|, for example, triggers
1246 // one. (Of course, it isn't necessary to use |with| for a shorthand to
1247 // trigger a getter.)
1248 case ParseNodeKind::Shorthand:
1249 MOZ_ASSERT(pn->is<BinaryNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<BinaryNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<BinaryNode>(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("pn->is<BinaryNode>()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 1249); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { MOZ_CrashSequence(__null, 1249); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1250 *answer = true;
1251 return true;
1252
1253 case ParseNodeKind::Function:
1254 MOZ_ASSERT(pn->is<FunctionNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<FunctionNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<FunctionNode>
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("pn->is<FunctionNode>()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 1254); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<FunctionNode>()"
")"); do { MOZ_CrashSequence(__null, 1254); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1255 /*
1256 * A named function, contrary to ES3, is no longer effectful, because
1257 * we bind its name lexically (using JSOp::Callee) instead of creating
1258 * an Object instance and binding a readonly, permanent property in it
1259 * (the object and binding can be detected and hijacked or captured).
1260 * This is a bug fix to ES3; it is fixed in ES3.1 drafts.
1261 */
1262 *answer = false;
1263 return true;
1264
1265 case ParseNodeKind::Module:
1266 *answer = false;
1267 return true;
1268
1269 case ParseNodeKind::TryStmt: {
1270 TryNode* tryNode = &pn->as<TryNode>();
1271 if (!checkSideEffects(tryNode->body(), answer)) {
1272 return false;
1273 }
1274 if (*answer) {
1275 return true;
1276 }
1277 if (LexicalScopeNode* catchScope = tryNode->catchScope()) {
1278 if (!checkSideEffects(catchScope, answer)) {
1279 return false;
1280 }
1281 if (*answer) {
1282 return true;
1283 }
1284 }
1285 if (ParseNode* finallyBlock = tryNode->finallyBlock()) {
1286 if (!checkSideEffects(finallyBlock, answer)) {
1287 return false;
1288 }
1289 }
1290 return true;
1291 }
1292
1293 case ParseNodeKind::Catch: {
1294 BinaryNode* catchClause = &pn->as<BinaryNode>();
1295 if (ParseNode* name = catchClause->left()) {
1296 if (!checkSideEffects(name, answer)) {
1297 return false;
1298 }
1299 if (*answer) {
1300 return true;
1301 }
1302 }
1303 return checkSideEffects(catchClause->right(), answer);
1304 }
1305
1306 case ParseNodeKind::SwitchStmt: {
1307 SwitchStatement* switchStmt = &pn->as<SwitchStatement>();
1308 if (!checkSideEffects(&switchStmt->discriminant(), answer)) {
1309 return false;
1310 }
1311 return *answer ||
1312 checkSideEffects(&switchStmt->lexicalForCaseList(), answer);
1313 }
1314
1315 case ParseNodeKind::LabelStmt:
1316 return checkSideEffects(pn->as<LabeledStatement>().statement(), answer);
1317
1318 case ParseNodeKind::LexicalScope:
1319 return checkSideEffects(pn->as<LexicalScopeNode>().scopeBody(), answer);
1320
1321 // We could methodically check every interpolated expression, but it's
1322 // probably not worth the trouble. Treat template strings as effect-free
1323 // only if they don't contain any substitutions.
1324 case ParseNodeKind::TemplateStringListExpr: {
1325 ListNode* list = &pn->as<ListNode>();
1326 MOZ_ASSERT(!list->empty())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!list->empty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!list->empty()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!list->empty()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 1326);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!list->empty()" ")"
); do { MOZ_CrashSequence(__null, 1326); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1327 MOZ_ASSERT((list->count() % 2) == 1,do { static_assert( mozilla::detail::AssertionConditionType<
decltype((list->count() % 2) == 1)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!((list->count() % 2) == 1)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("(list->count() % 2) == 1"
" (" "template strings must alternate template and substitution "
"parts" ")", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 1329); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(list->count() % 2) == 1"
") (" "template strings must alternate template and substitution "
"parts" ")"); do { MOZ_CrashSequence(__null, 1329); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
1328 "template strings must alternate template and substitution "do { static_assert( mozilla::detail::AssertionConditionType<
decltype((list->count() % 2) == 1)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!((list->count() % 2) == 1)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("(list->count() % 2) == 1"
" (" "template strings must alternate template and substitution "
"parts" ")", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 1329); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(list->count() % 2) == 1"
") (" "template strings must alternate template and substitution "
"parts" ")"); do { MOZ_CrashSequence(__null, 1329); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
1329 "parts")do { static_assert( mozilla::detail::AssertionConditionType<
decltype((list->count() % 2) == 1)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!((list->count() % 2) == 1)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("(list->count() % 2) == 1"
" (" "template strings must alternate template and substitution "
"parts" ")", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 1329); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(list->count() % 2) == 1"
") (" "template strings must alternate template and substitution "
"parts" ")"); do { MOZ_CrashSequence(__null, 1329); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
1330 *answer = list->count() > 1;
1331 return true;
1332 }
1333
1334 // This should be unreachable but is left as-is for now.
1335 case ParseNodeKind::ParamsBody:
1336 *answer = true;
1337 return true;
1338
1339 case ParseNodeKind::ForIn: // by ParseNodeKind::For
1340 case ParseNodeKind::ForOf: // by ParseNodeKind::For
1341 case ParseNodeKind::ForHead: // by ParseNodeKind::For
1342 case ParseNodeKind::DefaultConstructor: // by ParseNodeKind::ClassDecl
1343 case ParseNodeKind::ClassBodyScope: // by ParseNodeKind::ClassDecl
1344 case ParseNodeKind::ClassMethod: // by ParseNodeKind::ClassDecl
1345 case ParseNodeKind::ClassField: // by ParseNodeKind::ClassDecl
1346 case ParseNodeKind::ClassNames: // by ParseNodeKind::ClassDecl
1347 case ParseNodeKind::StaticClassBlock: // by ParseNodeKind::ClassDecl
1348 case ParseNodeKind::ClassMemberList: // by ParseNodeKind::ClassDecl
1349 case ParseNodeKind::ImportSpecList: // by ParseNodeKind::Import
1350 case ParseNodeKind::ImportSpec: // by ParseNodeKind::Import
1351 case ParseNodeKind::ImportNamespaceSpec: // by ParseNodeKind::Import
1352 case ParseNodeKind::ImportAttribute: // by ParseNodeKind::Import
1353 case ParseNodeKind::ImportAttributeList: // by ParseNodeKind::Import
1354 case ParseNodeKind::ImportModuleRequest: // by ParseNodeKind::Import
1355 case ParseNodeKind::ExportBatchSpecStmt: // by ParseNodeKind::Export
1356 case ParseNodeKind::ExportSpecList: // by ParseNodeKind::Export
1357 case ParseNodeKind::ExportSpec: // by ParseNodeKind::Export
1358 case ParseNodeKind::ExportNamespaceSpec: // by ParseNodeKind::Export
1359 case ParseNodeKind::CallSiteObj: // by ParseNodeKind::TaggedTemplate
1360 case ParseNodeKind::PosHolder: // by ParseNodeKind::NewTarget
1361 case ParseNodeKind::SuperBase: // by ParseNodeKind::Elem and others
1362 case ParseNodeKind::PropertyNameExpr: // by ParseNodeKind::Dot
1363 MOZ_CRASH("handled by parent nodes")do { do { } while (false); MOZ_ReportCrash("" "handled by parent nodes"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 1363);
AnnotateMozCrashReason("MOZ_CRASH(" "handled by parent nodes"
")"); do { MOZ_CrashSequence(__null, 1363); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
1364
1365 case ParseNodeKind::LastUnused:
1366 case ParseNodeKind::Limit:
1367 MOZ_CRASH("invalid node kind")do { do { } while (false); MOZ_ReportCrash("" "invalid node kind"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 1367);
AnnotateMozCrashReason("MOZ_CRASH(" "invalid node kind" ")")
; do { MOZ_CrashSequence(__null, 1367); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
1368 }
1369
1370 MOZ_CRASH(do { do { } while (false); MOZ_ReportCrash("" "invalid, unenumerated ParseNodeKind value encountered in "
"BytecodeEmitter::checkSideEffects", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 1372); AnnotateMozCrashReason("MOZ_CRASH(" "invalid, unenumerated ParseNodeKind value encountered in "
"BytecodeEmitter::checkSideEffects" ")"); do { MOZ_CrashSequence
(__null, 1372); __attribute__((nomerge)) ::abort(); } while (
false); } while (false)
1371 "invalid, unenumerated ParseNodeKind value encountered in "do { do { } while (false); MOZ_ReportCrash("" "invalid, unenumerated ParseNodeKind value encountered in "
"BytecodeEmitter::checkSideEffects", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 1372); AnnotateMozCrashReason("MOZ_CRASH(" "invalid, unenumerated ParseNodeKind value encountered in "
"BytecodeEmitter::checkSideEffects" ")"); do { MOZ_CrashSequence
(__null, 1372); __attribute__((nomerge)) ::abort(); } while (
false); } while (false)
1372 "BytecodeEmitter::checkSideEffects")do { do { } while (false); MOZ_ReportCrash("" "invalid, unenumerated ParseNodeKind value encountered in "
"BytecodeEmitter::checkSideEffects", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 1372); AnnotateMozCrashReason("MOZ_CRASH(" "invalid, unenumerated ParseNodeKind value encountered in "
"BytecodeEmitter::checkSideEffects" ")"); do { MOZ_CrashSequence
(__null, 1372); __attribute__((nomerge)) ::abort(); } while (
false); } while (false)
;
1373}
1374
1375bool BytecodeEmitter::isInLoop() const {
1376 return findInnermostNestableControl<LoopControl>();
1377}
1378
1379bool BytecodeEmitter::checkSingletonContext() const {
1380 MOZ_ASSERT_IF(sc->treatAsRunOnce(), sc->isTopLevelContext())do { if (sc->treatAsRunOnce()) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(sc->isTopLevelContext
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(sc->isTopLevelContext()))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("sc->isTopLevelContext()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 1380);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isTopLevelContext()"
")"); do { MOZ_CrashSequence(__null, 1380); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
1381 return sc->treatAsRunOnce() && !isInLoop();
1382}
1383
1384bool BytecodeEmitter::needsImplicitThis() const {
1385 // Short-circuit if there is an enclosing 'with' scope.
1386 if (sc->inWith()) {
1387 return true;
1388 }
1389
1390 // Otherwise see if the current point is under a 'with'.
1391 for (EmitterScope* es = innermostEmitterScope(); es;
1392 es = es->enclosingInFrame()) {
1393 if (es->scope(this).kind() == ScopeKind::With) {
1394 return true;
1395 }
1396 }
1397
1398 return false;
1399}
1400
1401size_t BytecodeEmitter::countThisEnvironmentHops() const {
1402 unsigned numHops = 0;
1403
1404 for (const auto* current = this; current; current = current->parent) {
1405 for (EmitterScope* es = current->innermostEmitterScope(); es;
1406 es = es->enclosingInFrame()) {
1407 if (es->scope(current).is<FunctionScope>()) {
1408 if (!es->scope(current).isArrow()) {
1409 // The Parser is responsible for marking the environment as either
1410 // closed-over or used-by-eval which ensure that is must exist.
1411 MOZ_ASSERT(es->scope(current).hasEnvironment())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(es->scope(current).hasEnvironment())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(es->scope(current).hasEnvironment()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("es->scope(current).hasEnvironment()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 1411);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "es->scope(current).hasEnvironment()"
")"); do { MOZ_CrashSequence(__null, 1411); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1412 return numHops;
1413 }
1414 }
1415 if (es->scope(current).hasEnvironment()) {
1416 numHops++;
1417 }
1418 }
1419 }
1420
1421 // The "this" environment exists outside of the compilation, but the
1422 // `ScopeContext` recorded the number of additional hops needed, so add
1423 // those in now.
1424 MOZ_ASSERT(sc->allowSuperProperty())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sc->allowSuperProperty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sc->allowSuperProperty())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("sc->allowSuperProperty()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 1424);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->allowSuperProperty()"
")"); do { MOZ_CrashSequence(__null, 1424); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1425 numHops += compilationState.scopeContext.enclosingThisEnvironmentHops;
1426 return numHops;
1427}
1428
1429bool BytecodeEmitter::emitThisEnvironmentCallee() {
1430 // Get the innermost enclosing function that has a |this| binding.
1431
1432 // Directly load callee from the frame if possible.
1433 if (sc->isFunctionBox() && !sc->asFunctionBox()->isArrow()) {
1434 return emit1(JSOp::Callee);
1435 }
1436
1437 // We have to load the callee from the environment chain.
1438 size_t numHops = countThisEnvironmentHops();
1439
1440 static_assert(
1441 ENVCOORD_HOPS_LIMIT - 1 <= UINT16_MAX(65535),
1442 "JSOp::EnvCallee operand size should match ENVCOORD_HOPS_LIMIT");
1443
1444 MOZ_ASSERT(numHops < ENVCOORD_HOPS_LIMIT - 1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(numHops < ENVCOORD_HOPS_LIMIT - 1)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(numHops < ENVCOORD_HOPS_LIMIT
- 1))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("numHops < ENVCOORD_HOPS_LIMIT - 1", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 1444); AnnotateMozCrashReason("MOZ_ASSERT" "(" "numHops < ENVCOORD_HOPS_LIMIT - 1"
")"); do { MOZ_CrashSequence(__null, 1444); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1445
1446 return emitUint16Operand(JSOp::EnvCallee, numHops);
1447}
1448
1449bool BytecodeEmitter::emitSuperBase() {
1450 if (!emitThisEnvironmentCallee()) {
1451 return false;
1452 }
1453
1454 return emit1(JSOp::SuperBase);
1455}
1456
1457void BytecodeEmitter::reportError(ParseNode* pn, unsigned errorNumber,
1458 ...) const {
1459 uint32_t offset = pn ? pn->pn_pos.begin : *scriptStartOffset;
1460
1461 va_list args;
1462 va_start(args, errorNumber)__builtin_va_start(args, errorNumber);
1463
1464 errorReporter().errorWithNotesAtVA(nullptr, AsVariant(offset), errorNumber,
1465 &args);
1466
1467 va_end(args)__builtin_va_end(args);
1468}
1469
1470void BytecodeEmitter::reportError(uint32_t offset, unsigned errorNumber,
1471 ...) const {
1472 va_list args;
1473 va_start(args, errorNumber)__builtin_va_start(args, errorNumber);
1474
1475 errorReporter().errorWithNotesAtVA(nullptr, AsVariant(offset), errorNumber,
1476 &args);
1477
1478 va_end(args)__builtin_va_end(args);
1479}
1480
1481bool BytecodeEmitter::addObjLiteralData(ObjLiteralWriter& writer,
1482 GCThingIndex* outIndex) {
1483 if (!writer.checkForDuplicatedNames(fc)) {
1484 return false;
1485 }
1486
1487 size_t len = writer.getCode().size();
1488 auto* code = compilationState.alloc.newArrayUninitialized<uint8_t>(len);
1489 if (!code) {
1490 js::ReportOutOfMemory(fc);
1491 return false;
1492 }
1493 memcpy(code, writer.getCode().data(), len);
1494
1495 ObjLiteralIndex objIndex(compilationState.objLiteralData.length());
1496 if (uint32_t(objIndex) >= TaggedScriptThingIndex::IndexLimit) {
1497 ReportAllocationOverflow(fc);
1498 return false;
1499 }
1500 if (!compilationState.objLiteralData.emplaceBack(code, len, writer.getKind(),
1501 writer.getFlags(),
1502 writer.getPropertyCount())) {
1503 js::ReportOutOfMemory(fc);
1504 return false;
1505 }
1506
1507 return perScriptData().gcThingList().append(objIndex, outIndex);
1508}
1509
1510bool BytecodeEmitter::emitPrepareIteratorResult() {
1511 constexpr JSOp op = JSOp::NewObject;
1512
1513 ObjLiteralWriter writer;
1514 writer.beginShape(op);
1515
1516 writer.setPropNameNoDuplicateCheck(parserAtoms(),
1517 TaggedParserAtomIndex::WellKnown::value());
1518 if (!writer.propWithUndefinedValue(fc)) {
1519 return false;
1520 }
1521 writer.setPropNameNoDuplicateCheck(parserAtoms(),
1522 TaggedParserAtomIndex::WellKnown::done());
1523 if (!writer.propWithUndefinedValue(fc)) {
1524 return false;
1525 }
1526
1527 GCThingIndex shape;
1528 if (!addObjLiteralData(writer, &shape)) {
1529 return false;
1530 }
1531
1532 return emitGCIndexOp(op, shape);
1533}
1534
1535bool BytecodeEmitter::emitFinishIteratorResult(bool done) {
1536 if (!emitAtomOp(JSOp::InitProp, TaggedParserAtomIndex::WellKnown::value())) {
1537 return false;
1538 }
1539 if (!emit1(done ? JSOp::True : JSOp::False)) {
1540 return false;
1541 }
1542 if (!emitAtomOp(JSOp::InitProp, TaggedParserAtomIndex::WellKnown::done())) {
1543 return false;
1544 }
1545 return true;
1546}
1547
1548bool BytecodeEmitter::emitGetNameAtLocation(TaggedParserAtomIndex name,
1549 const NameLocation& loc) {
1550 NameOpEmitter noe(this, name, loc, NameOpEmitter::Kind::Get);
1551 if (!noe.emitGet()) {
1552 return false;
1553 }
1554
1555 return true;
1556}
1557
1558bool BytecodeEmitter::emitGetName(NameNode* name) {
1559 MOZ_ASSERT(name->isKind(ParseNodeKind::Name))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(name->isKind(ParseNodeKind::Name))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(name->isKind(ParseNodeKind
::Name)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("name->isKind(ParseNodeKind::Name)", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 1559); AnnotateMozCrashReason("MOZ_ASSERT" "(" "name->isKind(ParseNodeKind::Name)"
")"); do { MOZ_CrashSequence(__null, 1559); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1560
1561 return emitGetName(name->name());
1562}
1563
1564bool BytecodeEmitter::emitGetPrivateName(NameNode* name) {
1565 MOZ_ASSERT(name->isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(name->isKind(ParseNodeKind::PrivateName))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(name->isKind(ParseNodeKind::PrivateName)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("name->isKind(ParseNodeKind::PrivateName)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 1565);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "name->isKind(ParseNodeKind::PrivateName)"
")"); do { MOZ_CrashSequence(__null, 1565); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1566 return emitGetPrivateName(name->name());
1567}
1568
1569bool BytecodeEmitter::emitGetPrivateName(TaggedParserAtomIndex nameAtom) {
1570 // The parser ensures the private name is present on the environment chain,
1571 // but its location can be Dynamic or Global when emitting debugger
1572 // eval-in-frame code.
1573 NameLocation location = lookupName(nameAtom);
1574 MOZ_ASSERT(location.kind() == NameLocation::Kind::FrameSlot ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(location.kind() == NameLocation::Kind::FrameSlot || location
.kind() == NameLocation::Kind::EnvironmentCoordinate || location
.kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation
::Kind::Global)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(location.kind() == NameLocation
::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate
|| location.kind() == NameLocation::Kind::Dynamic || location
.kind() == NameLocation::Kind::Global))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("location.kind() == NameLocation::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate || location.kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation::Kind::Global"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 1577);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "location.kind() == NameLocation::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate || location.kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation::Kind::Global"
")"); do { MOZ_CrashSequence(__null, 1577); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1575 location.kind() == NameLocation::Kind::EnvironmentCoordinate ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(location.kind() == NameLocation::Kind::FrameSlot || location
.kind() == NameLocation::Kind::EnvironmentCoordinate || location
.kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation
::Kind::Global)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(location.kind() == NameLocation
::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate
|| location.kind() == NameLocation::Kind::Dynamic || location
.kind() == NameLocation::Kind::Global))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("location.kind() == NameLocation::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate || location.kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation::Kind::Global"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 1577);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "location.kind() == NameLocation::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate || location.kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation::Kind::Global"
")"); do { MOZ_CrashSequence(__null, 1577); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1576 location.kind() == NameLocation::Kind::Dynamic ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(location.kind() == NameLocation::Kind::FrameSlot || location
.kind() == NameLocation::Kind::EnvironmentCoordinate || location
.kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation
::Kind::Global)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(location.kind() == NameLocation
::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate
|| location.kind() == NameLocation::Kind::Dynamic || location
.kind() == NameLocation::Kind::Global))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("location.kind() == NameLocation::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate || location.kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation::Kind::Global"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 1577);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "location.kind() == NameLocation::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate || location.kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation::Kind::Global"
")"); do { MOZ_CrashSequence(__null, 1577); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1577 location.kind() == NameLocation::Kind::Global)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(location.kind() == NameLocation::Kind::FrameSlot || location
.kind() == NameLocation::Kind::EnvironmentCoordinate || location
.kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation
::Kind::Global)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(location.kind() == NameLocation
::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate
|| location.kind() == NameLocation::Kind::Dynamic || location
.kind() == NameLocation::Kind::Global))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("location.kind() == NameLocation::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate || location.kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation::Kind::Global"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 1577);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "location.kind() == NameLocation::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate || location.kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation::Kind::Global"
")"); do { MOZ_CrashSequence(__null, 1577); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1578
1579 return emitGetNameAtLocation(nameAtom, location);
1580}
1581
1582bool BytecodeEmitter::emitTDZCheckIfNeeded(TaggedParserAtomIndex name,
1583 const NameLocation& loc,
1584 ValueIsOnStack isOnStack) {
1585 // Dynamic accesses have TDZ checks built into their VM code and should
1586 // never emit explicit TDZ checks.
1587 MOZ_ASSERT(loc.hasKnownSlot())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(loc.hasKnownSlot())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(loc.hasKnownSlot()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("loc.hasKnownSlot()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 1587);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "loc.hasKnownSlot()"
")"); do { MOZ_CrashSequence(__null, 1587); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1588 MOZ_ASSERT(loc.isLexical() || loc.isPrivateMethod() || loc.isSynthetic())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(loc.isLexical() || loc.isPrivateMethod() || loc.isSynthetic
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(loc.isLexical() || loc.isPrivateMethod() || loc.isSynthetic
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("loc.isLexical() || loc.isPrivateMethod() || loc.isSynthetic()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 1588);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "loc.isLexical() || loc.isPrivateMethod() || loc.isSynthetic()"
")"); do { MOZ_CrashSequence(__null, 1588); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1589
1590 // Private names are implemented as lexical bindings, but it's just an
1591 // implementation detail. Per spec there's no TDZ check when using them.
1592 if (parserAtoms().isPrivateName(name)) {
1593 return true;
1594 }
1595
1596 Maybe<MaybeCheckTDZ> check =
1597 innermostTDZCheckCache->needsTDZCheck(this, name);
1598 if (!check) {
1599 return false;
1600 }
1601
1602 // We've already emitted a check in this basic block.
1603 if (*check == DontCheckTDZ) {
1604 return true;
1605 }
1606
1607 // If the value is not on the stack, we have to load it first.
1608 if (isOnStack == ValueIsOnStack::No) {
1609 if (loc.kind() == NameLocation::Kind::FrameSlot) {
1610 if (!emitLocalOp(JSOp::GetLocal, loc.frameSlot())) {
1611 return false;
1612 }
1613 } else {
1614 if (!emitEnvCoordOp(JSOp::GetAliasedVar, loc.environmentCoordinate())) {
1615 return false;
1616 }
1617 }
1618 }
1619
1620 // Emit the lexical check.
1621 if (loc.kind() == NameLocation::Kind::FrameSlot) {
1622 if (!emitLocalOp(JSOp::CheckLexical, loc.frameSlot())) {
1623 return false;
1624 }
1625 } else {
1626 if (!emitEnvCoordOp(JSOp::CheckAliasedLexical,
1627 loc.environmentCoordinate())) {
1628 return false;
1629 }
1630 }
1631
1632 // Pop the value if needed.
1633 if (isOnStack == ValueIsOnStack::No) {
1634 if (!emit1(JSOp::Pop)) {
1635 return false;
1636 }
1637 }
1638
1639 return innermostTDZCheckCache->noteTDZCheck(this, name, DontCheckTDZ);
1640}
1641
1642bool BytecodeEmitter::emitPropLHS(NonOptionalPropertyAccessBase* prop) {
1643 MOZ_ASSERT(!prop->isSuper())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!prop->isSuper())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!prop->isSuper()))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("!prop->isSuper()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 1643);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!prop->isSuper()"
")"); do { MOZ_CrashSequence(__null, 1643); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1644
1645 ParseNode* expr = &prop->expression();
1646
1647 // Not all non-optional property accesses can be flattened (e.g. super.x or
1648 // arguments.length); use emitTree for those instead.
1649 if (!expr->is<PropertyAccess>() || expr->as<PropertyAccess>().isSuper()) {
1650 return emitTree(expr);
1651 }
1652
1653 // If the object operand is also a dotted property reference, reverse the
1654 // list linked via expression() temporarily so we can iterate over it from
1655 // the bottom up (reversing again as we go), to avoid excessive recursion.
1656 PropertyAccess* pndot = &expr->as<PropertyAccess>();
1657 ParseNode* pnup = nullptr;
1658 ParseNode* pndown;
1659 for (;;) {
1660 // Reverse pndot->expression() to point up, not down.
1661 pndown = &pndot->expression();
1662 pndot->setExpression(pnup);
1663 if (!pndown->is<PropertyAccess>() ||
1664 pndown->as<PropertyAccess>().isSuper()) {
1665 break;
1666 }
1667 pnup = pndot;
1668 pndot = &pndown->as<PropertyAccess>();
1669 }
1670
1671 // pndown is a primary expression, not a dotted property reference.
1672 if (!emitTree(pndown)) {
1673 return false;
1674 }
1675
1676 while (true) {
1677 // Walk back up the list, emitting annotated name ops.
1678 if (!emitAtomOp(JSOp::GetProp, pndot->key().atom())) {
1679 return false;
1680 }
1681
1682 // Reverse the pndot->expression() link again.
1683 pnup = pndot->maybeExpression();
1684 pndot->setExpression(pndown);
1685 pndown = pndot;
1686 if (!pnup) {
1687 break;
1688 }
1689 pndot = &pnup->as<PropertyAccess>();
1690 }
1691 return true;
1692}
1693
1694bool BytecodeEmitter::emitArgumentsLength() {
1695 if (sc->isFunctionBox() &&
1696 sc->asFunctionBox()->isEligibleForArgumentsLength() &&
1697 !sc->asFunctionBox()->needsArgsObj()) {
1698 return emit1(JSOp::ArgumentsLength);
1699 }
1700
1701 PropOpEmitter poe(this, PropOpEmitter::Kind::Get,
1702 PropOpEmitter::ObjKind::Other);
1703 if (!poe.prepareForObj()) {
1704 return false;
1705 }
1706
1707 NameOpEmitter noe(this, TaggedParserAtomIndex::WellKnown::arguments(),
1708 NameOpEmitter::Kind::Get);
1709 if (!noe.emitGet()) {
1710 return false;
1711 }
1712 return poe.emitGet(TaggedParserAtomIndex::WellKnown::length());
1713}
1714
1715bool BytecodeEmitter::emitPropIncDec(UnaryNode* incDec, ValueUsage valueUsage) {
1716 NonOptionalPropertyAccessBase* prop =
1717 &incDec->kid()->as<NonOptionalPropertyAccessBase>();
1718 bool isSuper = prop->isSuper();
1719 ParseNodeKind kind = incDec->getKind();
1720 PropOpEmitter poe(
1721 this,
1722 kind == ParseNodeKind::PostIncrementExpr
1723 ? PropOpEmitter::Kind::PostIncrement
1724 : kind == ParseNodeKind::PreIncrementExpr
1725 ? PropOpEmitter::Kind::PreIncrement
1726 : kind == ParseNodeKind::PostDecrementExpr
1727 ? PropOpEmitter::Kind::PostDecrement
1728 : PropOpEmitter::Kind::PreDecrement,
1729 isSuper ? PropOpEmitter::ObjKind::Super : PropOpEmitter::ObjKind::Other);
1730 if (!poe.prepareForObj()) {
1731 return false;
1732 }
1733 if (isSuper) {
1734 UnaryNode* base = &prop->expression().as<UnaryNode>();
1735 if (!emitGetThisForSuperBase(base)) {
1736 // [stack] THIS
1737 return false;
1738 }
1739 } else {
1740 if (!emitPropLHS(prop)) {
1741 // [stack] OBJ
1742 return false;
1743 }
1744 }
1745 if (!poe.emitIncDec(prop->key().atom(), valueUsage)) {
1746 // [stack] RESULT
1747 return false;
1748 }
1749
1750 return true;
1751}
1752
1753bool BytecodeEmitter::emitNameIncDec(UnaryNode* incDec, ValueUsage valueUsage) {
1754 MOZ_ASSERT(incDec->kid()->isKind(ParseNodeKind::Name))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(incDec->kid()->isKind(ParseNodeKind::Name))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(incDec->kid()->isKind(ParseNodeKind::Name)))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("incDec->kid()->isKind(ParseNodeKind::Name)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 1754);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "incDec->kid()->isKind(ParseNodeKind::Name)"
")"); do { MOZ_CrashSequence(__null, 1754); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1755
1756 ParseNodeKind kind = incDec->getKind();
1757 NameNode* name = &incDec->kid()->as<NameNode>();
1758 NameOpEmitter noe(this, name->atom(),
1759 kind == ParseNodeKind::PostIncrementExpr
1760 ? NameOpEmitter::Kind::PostIncrement
1761 : kind == ParseNodeKind::PreIncrementExpr
1762 ? NameOpEmitter::Kind::PreIncrement
1763 : kind == ParseNodeKind::PostDecrementExpr
1764 ? NameOpEmitter::Kind::PostDecrement
1765 : NameOpEmitter::Kind::PreDecrement);
1766 if (!noe.emitIncDec(valueUsage)) {
1767 return false;
1768 }
1769
1770 return true;
1771}
1772
1773bool BytecodeEmitter::emitElemObjAndKey(PropertyByValue* elem,
1774 ElemOpEmitter& eoe) {
1775 ParseNode* exprOrSuper = &elem->expression();
1776 ParseNode* key = &elem->key();
1777
1778 if (!eoe.prepareForObj()) {
1779 // [stack]
1780 return false;
1781 }
1782
1783 if (elem->isSuper()) {
1784 auto* base = &exprOrSuper->as<UnaryNode>();
1785 if (!emitGetThisForSuperBase(base)) {
1786 // [stack] THIS
1787 return false;
1788 }
1789 } else {
1790 if (!emitTree(exprOrSuper)) {
1791 // [stack] OBJ
1792 return false;
1793 }
1794 }
1795
1796 if (!eoe.prepareForKey()) {
1797 // [stack] # if Super
1798 // [stack] THIS? THIS
1799 // [stack] # otherwise
1800 // [stack] OBJ? OBJ
1801 return false;
1802 }
1803
1804 if (!emitTree(key)) {
1805 // [stack] # if Super
1806 // [stack] THIS? THIS KEY
1807 // [stack] # otherwise
1808 // [stack] OBJ? OBJ KEY
1809 return false;
1810 }
1811
1812 return true;
1813}
1814
1815bool BytecodeEmitter::emitElemOpBase(JSOp op) {
1816 if (!emit1(op)) {
1817 return false;
1818 }
1819
1820 return true;
1821}
1822
1823static ElemOpEmitter::Kind ConvertIncDecKind(ParseNodeKind kind) {
1824 switch (kind) {
1825 case ParseNodeKind::PostIncrementExpr:
1826 return ElemOpEmitter::Kind::PostIncrement;
1827 case ParseNodeKind::PreIncrementExpr:
1828 return ElemOpEmitter::Kind::PreIncrement;
1829 case ParseNodeKind::PostDecrementExpr:
1830 return ElemOpEmitter::Kind::PostDecrement;
1831 case ParseNodeKind::PreDecrementExpr:
1832 return ElemOpEmitter::Kind::PreDecrement;
1833 default:
1834 MOZ_CRASH("unexpected inc/dec node kind")do { do { } while (false); MOZ_ReportCrash("" "unexpected inc/dec node kind"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 1834);
AnnotateMozCrashReason("MOZ_CRASH(" "unexpected inc/dec node kind"
")"); do { MOZ_CrashSequence(__null, 1834); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
1835 }
1836}
1837
1838static PrivateOpEmitter::Kind PrivateConvertIncDecKind(ParseNodeKind kind) {
1839 switch (kind) {
1840 case ParseNodeKind::PostIncrementExpr:
1841 return PrivateOpEmitter::Kind::PostIncrement;
1842 case ParseNodeKind::PreIncrementExpr:
1843 return PrivateOpEmitter::Kind::PreIncrement;
1844 case ParseNodeKind::PostDecrementExpr:
1845 return PrivateOpEmitter::Kind::PostDecrement;
1846 case ParseNodeKind::PreDecrementExpr:
1847 return PrivateOpEmitter::Kind::PreDecrement;
1848 default:
1849 MOZ_CRASH("unexpected inc/dec node kind")do { do { } while (false); MOZ_ReportCrash("" "unexpected inc/dec node kind"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 1849);
AnnotateMozCrashReason("MOZ_CRASH(" "unexpected inc/dec node kind"
")"); do { MOZ_CrashSequence(__null, 1849); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
1850 }
1851}
1852
1853bool BytecodeEmitter::emitElemIncDec(UnaryNode* incDec, ValueUsage valueUsage) {
1854 PropertyByValue* elemExpr = &incDec->kid()->as<PropertyByValue>();
1855 bool isSuper = elemExpr->isSuper();
1856 MOZ_ASSERT(!elemExpr->key().isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!elemExpr->key().isKind(ParseNodeKind::PrivateName
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!elemExpr->key().isKind(ParseNodeKind::PrivateName
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!elemExpr->key().isKind(ParseNodeKind::PrivateName)", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 1856); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elemExpr->key().isKind(ParseNodeKind::PrivateName)"
")"); do { MOZ_CrashSequence(__null, 1856); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1857 ParseNodeKind kind = incDec->getKind();
1858 ElemOpEmitter eoe(
1859 this, ConvertIncDecKind(kind),
1860 isSuper ? ElemOpEmitter::ObjKind::Super : ElemOpEmitter::ObjKind::Other);
1861 if (!emitElemObjAndKey(elemExpr, eoe)) {
1862 // [stack] # if Super
1863 // [stack] THIS KEY
1864 // [stack] # otherwise
1865 // [stack] OBJ KEY
1866 return false;
1867 }
1868 if (!eoe.emitIncDec(valueUsage)) {
1869 // [stack] RESULT
1870 return false;
1871 }
1872
1873 return true;
1874}
1875
1876bool BytecodeEmitter::emitCallIncDec(UnaryNode* incDec) {
1877 MOZ_ASSERT(incDec->isKind(ParseNodeKind::PreIncrementExpr) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(incDec->isKind(ParseNodeKind::PreIncrementExpr) ||
incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec
->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind
(ParseNodeKind::PostDecrementExpr))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(incDec->isKind(ParseNodeKind
::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr
) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec
->isKind(ParseNodeKind::PostDecrementExpr)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind(ParseNodeKind::PostDecrementExpr)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 1880);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind(ParseNodeKind::PostDecrementExpr)"
")"); do { MOZ_CrashSequence(__null, 1880); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1878 incDec->isKind(ParseNodeKind::PostIncrementExpr) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(incDec->isKind(ParseNodeKind::PreIncrementExpr) ||
incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec
->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind
(ParseNodeKind::PostDecrementExpr))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(incDec->isKind(ParseNodeKind
::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr
) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec
->isKind(ParseNodeKind::PostDecrementExpr)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind(ParseNodeKind::PostDecrementExpr)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 1880);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind(ParseNodeKind::PostDecrementExpr)"
")"); do { MOZ_CrashSequence(__null, 1880); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1879 incDec->isKind(ParseNodeKind::PreDecrementExpr) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(incDec->isKind(ParseNodeKind::PreIncrementExpr) ||
incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec
->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind
(ParseNodeKind::PostDecrementExpr))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(incDec->isKind(ParseNodeKind
::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr
) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec
->isKind(ParseNodeKind::PostDecrementExpr)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind(ParseNodeKind::PostDecrementExpr)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 1880);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind(ParseNodeKind::PostDecrementExpr)"
")"); do { MOZ_CrashSequence(__null, 1880); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1880 incDec->isKind(ParseNodeKind::PostDecrementExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(incDec->isKind(ParseNodeKind::PreIncrementExpr) ||
incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec
->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind
(ParseNodeKind::PostDecrementExpr))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(incDec->isKind(ParseNodeKind
::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr
) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec
->isKind(ParseNodeKind::PostDecrementExpr)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind(ParseNodeKind::PostDecrementExpr)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 1880);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind(ParseNodeKind::PostDecrementExpr)"
")"); do { MOZ_CrashSequence(__null, 1880); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1881
1882 ParseNode* call = incDec->kid();
1883 MOZ_ASSERT(call->isKind(ParseNodeKind::CallExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(call->isKind(ParseNodeKind::CallExpr))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(call->isKind(ParseNodeKind::CallExpr)))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("call->isKind(ParseNodeKind::CallExpr)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 1883);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "call->isKind(ParseNodeKind::CallExpr)"
")"); do { MOZ_CrashSequence(__null, 1883); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1884 if (!emitTree(call)) {
1885 // [stack] CALLRESULT
1886 return false;
1887 }
1888
1889 // The increment/decrement has no side effects, so proceed to throw for
1890 // invalid assignment target.
1891 return emit2(JSOp::ThrowMsg, uint8_t(ThrowMsgKind::AssignToCall));
1892}
1893
1894bool BytecodeEmitter::emitPrivateIncDec(UnaryNode* incDec,
1895 ValueUsage valueUsage) {
1896 PrivateMemberAccess* privateExpr = &incDec->kid()->as<PrivateMemberAccess>();
1897 ParseNodeKind kind = incDec->getKind();
1898 PrivateOpEmitter xoe(this, PrivateConvertIncDecKind(kind),
1899 privateExpr->privateName().name());
1900 if (!emitTree(&privateExpr->expression())) {
1901 // [stack] OBJ
1902 return false;
1903 }
1904 if (!xoe.emitReference()) {
1905 // [stack] OBJ NAME
1906 return false;
1907 }
1908 if (!xoe.emitIncDec(valueUsage)) {
1909 // [stack] RESULT
1910 return false;
1911 }
1912
1913 return true;
1914}
1915
1916bool BytecodeEmitter::emitDouble(double d) {
1917 BytecodeOffset offset;
1918 if (!emitCheck(JSOp::Double, 9, &offset)) {
1919 return false;
1920 }
1921
1922 jsbytecode* code = bytecodeSection().code(offset);
1923 code[0] = jsbytecode(JSOp::Double);
1924 SET_INLINE_VALUE(code, DoubleValue(d));
1925 bytecodeSection().updateDepth(JSOp::Double, offset);
1926 return true;
1927}
1928
1929bool BytecodeEmitter::emitNumberOp(double dval) {
1930 int32_t ival;
1931 if (NumberIsInt32(dval, &ival)) {
1932 if (ival == 0) {
1933 return emit1(JSOp::Zero);
1934 }
1935 if (ival == 1) {
1936 return emit1(JSOp::One);
1937 }
1938 if ((int)(int8_t)ival == ival) {
1939 return emit2(JSOp::Int8, uint8_t(int8_t(ival)));
1940 }
1941
1942 uint32_t u = uint32_t(ival);
1943 if (u < Bit(16)) {
1944 if (!emitUint16Operand(JSOp::Uint16, u)) {
1945 return false;
1946 }
1947 } else if (u < Bit(24)) {
1948 BytecodeOffset off;
1949 if (!emitN(JSOp::Uint24, 3, &off)) {
1950 return false;
1951 }
1952 SET_UINT24(bytecodeSection().code(off), u);
1953 } else {
1954 BytecodeOffset off;
1955 if (!emitN(JSOp::Int32, 4, &off)) {
1956 return false;
1957 }
1958 SET_INT32(bytecodeSection().code(off), ival);
1959 }
1960 return true;
1961 }
1962
1963 return emitDouble(dval);
1964}
1965
1966/*
1967 * Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047.
1968 * LLVM is deciding to inline this function which uses a lot of stack space
1969 * into emitTree which is recursive and uses relatively little stack space.
1970 */
1971MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitSwitch(SwitchStatement* switchStmt) {
1972 LexicalScopeNode& lexical = switchStmt->lexicalForCaseList();
1973 MOZ_ASSERT(lexical.isKind(ParseNodeKind::LexicalScope))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(lexical.isKind(ParseNodeKind::LexicalScope))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(lexical.isKind(ParseNodeKind::LexicalScope)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("lexical.isKind(ParseNodeKind::LexicalScope)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 1973);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "lexical.isKind(ParseNodeKind::LexicalScope)"
")"); do { MOZ_CrashSequence(__null, 1973); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1974 ListNode* cases = &lexical.scopeBody()->as<ListNode>();
1975 MOZ_ASSERT(cases->isKind(ParseNodeKind::StatementList))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(cases->isKind(ParseNodeKind::StatementList))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(cases->isKind(ParseNodeKind::StatementList)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("cases->isKind(ParseNodeKind::StatementList)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 1975);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "cases->isKind(ParseNodeKind::StatementList)"
")"); do { MOZ_CrashSequence(__null, 1975); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1976
1977 SwitchEmitter se(this);
1978 if (!se.emitDiscriminant(switchStmt->discriminant().pn_pos.begin)) {
1979 return false;
1980 }
1981
1982 if (!markStepBreakpoint()) {
1983 return false;
1984 }
1985 if (!emitTree(&switchStmt->discriminant())) {
1986 return false;
1987 }
1988
1989 // Enter the scope before pushing the switch BreakableControl since all
1990 // breaks are under this scope.
1991
1992 if (!lexical.isEmptyScope()) {
1993 if (!se.emitLexical(lexical.scopeBindings())) {
1994 return false;
1995 }
1996
1997 // A switch statement may contain hoisted functions inside its
1998 // cases. The hasTopLevelFunctionDeclarations flag is propagated from the
1999 // StatementList bodies of the cases to the case list.
2000 if (cases->hasTopLevelFunctionDeclarations()) {
2001 for (ParseNode* item : cases->contents()) {
2002 CaseClause* caseClause = &item->as<CaseClause>();
2003 ListNode* statements = caseClause->statementList();
2004 if (statements->hasTopLevelFunctionDeclarations()) {
2005 if (!emitHoistedFunctionsInList(statements)) {
2006 return false;
2007 }
2008 }
2009 }
2010 }
2011 } else {
2012 MOZ_ASSERT(!cases->hasTopLevelFunctionDeclarations())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!cases->hasTopLevelFunctionDeclarations())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!cases->hasTopLevelFunctionDeclarations()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("!cases->hasTopLevelFunctionDeclarations()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 2012);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!cases->hasTopLevelFunctionDeclarations()"
")"); do { MOZ_CrashSequence(__null, 2012); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2013 }
2014
2015 SwitchEmitter::TableGenerator tableGen(this);
2016 uint32_t caseCount = cases->count() - (switchStmt->hasDefault() ? 1 : 0);
2017 if (caseCount == 0) {
2018 tableGen.finish(0);
2019 } else {
2020 for (ParseNode* item : cases->contents()) {
2021 CaseClause* caseClause = &item->as<CaseClause>();
2022 if (caseClause->isDefault()) {
2023 continue;
2024 }
2025
2026 ParseNode* caseValue = caseClause->caseExpression();
2027
2028 if (caseValue->getKind() != ParseNodeKind::NumberExpr) {
2029 tableGen.setInvalid();
2030 break;
2031 }
2032
2033 int32_t i;
2034 if (!NumberEqualsInt32(caseValue->as<NumericLiteral>().value(), &i)) {
2035 tableGen.setInvalid();
2036 break;
2037 }
2038
2039 if (!tableGen.addNumber(i)) {
2040 return false;
2041 }
2042 }
2043
2044 tableGen.finish(caseCount);
2045 }
2046
2047 if (!se.validateCaseCount(caseCount)) {
2048 return false;
2049 }
2050
2051 bool isTableSwitch = tableGen.isValid();
2052 if (isTableSwitch) {
2053 if (!se.emitTable(tableGen)) {
2054 return false;
2055 }
2056 } else {
2057 if (!se.emitCond()) {
2058 return false;
2059 }
2060
2061 // Emit code for evaluating cases and jumping to case statements.
2062 for (ParseNode* item : cases->contents()) {
2063 CaseClause* caseClause = &item->as<CaseClause>();
2064 if (caseClause->isDefault()) {
2065 continue;
2066 }
2067
2068 if (!se.prepareForCaseValue()) {
2069 return false;
2070 }
2071
2072 ParseNode* caseValue = caseClause->caseExpression();
2073 // If the expression is a literal, suppress line number emission so
2074 // that debugging works more naturally.
2075 if (!emitTree(
2076 caseValue, ValueUsage::WantValue,
2077 caseValue->isLiteral() ? SUPPRESS_LINENOTE : EMIT_LINENOTE)) {
2078 return false;
2079 }
2080
2081 if (!se.emitCaseJump()) {
2082 return false;
2083 }
2084 }
2085 }
2086
2087 // Emit code for each case's statements.
2088 for (ParseNode* item : cases->contents()) {
2089 CaseClause* caseClause = &item->as<CaseClause>();
2090 if (caseClause->isDefault()) {
2091 if (!se.emitDefaultBody()) {
2092 return false;
2093 }
2094 } else {
2095 if (isTableSwitch) {
2096 ParseNode* caseValue = caseClause->caseExpression();
2097 MOZ_ASSERT(caseValue->isKind(ParseNodeKind::NumberExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(caseValue->isKind(ParseNodeKind::NumberExpr))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(caseValue->isKind(ParseNodeKind::NumberExpr)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("caseValue->isKind(ParseNodeKind::NumberExpr)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 2097);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "caseValue->isKind(ParseNodeKind::NumberExpr)"
")"); do { MOZ_CrashSequence(__null, 2097); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2098
2099 NumericLiteral* literal = &caseValue->as<NumericLiteral>();
2100#ifdef DEBUG1
2101 // Use NumberEqualsInt32 here because switches compare using
2102 // strict equality, which will equate -0 and +0. In contrast
2103 // NumberIsInt32 would return false for -0.
2104 int32_t v;
2105 MOZ_ASSERT(mozilla::NumberEqualsInt32(literal->value(), &v))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mozilla::NumberEqualsInt32(literal->value(), &
v))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(mozilla::NumberEqualsInt32(literal->value(), &
v)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mozilla::NumberEqualsInt32(literal->value(), &v)", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 2105); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mozilla::NumberEqualsInt32(literal->value(), &v)"
")"); do { MOZ_CrashSequence(__null, 2105); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2106#endif
2107 int32_t i = int32_t(literal->value());
2108
2109 if (!se.emitCaseBody(i, tableGen)) {
2110 return false;
2111 }
2112 } else {
2113 if (!se.emitCaseBody()) {
2114 return false;
2115 }
2116 }
2117 }
2118
2119 if (!emitTree(caseClause->statementList())) {
2120 return false;
2121 }
2122 }
2123
2124 if (!se.emitEnd()) {
2125 return false;
2126 }
2127
2128 return true;
2129}
2130
2131static constexpr size_t MaxResumeIndex = BitMask(24);
2132
2133bool BytecodeEmitter::checkResumeIndexLimit() {
2134 static_assert(
2135 MaxResumeIndex < uint32_t(AbstractGeneratorObject::RESUME_INDEX_RUNNING),
2136 "resumeIndex should not include magic AbstractGeneratorObject "
2137 "resumeIndex values");
2138 static_assert(
2139 MaxResumeIndex <= INT32_MAX(2147483647) / sizeof(uintptr_t),
2140 "resumeIndex * sizeof(uintptr_t) must fit in an int32. JIT code relies "
2141 "on this when loading resume entries from BaselineScript");
2142
2143 size_t numIndices =
2144 bytecodeSection().resumeOffsetList().length() +
2145 bytecodeSection().tableSwitchOffsetList().numCaseOffsets();
2146 if (numIndices > MaxResumeIndex) {
2147 reportError(nullptr, JSMSG_TOO_MANY_RESUME_INDEXES);
2148 return false;
2149 }
2150 return true;
2151}
2152
2153bool BytecodeEmitter::allocateResumeIndex(BytecodeOffset offset,
2154 uint32_t* resumeIndex) {
2155 if (!checkResumeIndexLimit()) {
2156 return false;
2157 }
2158 *resumeIndex = bytecodeSection().resumeOffsetList().length();
2159 return bytecodeSection().resumeOffsetList().append(offset.value());
2160}
2161
2162bool BytecodeEmitter::allocateTableSwitchResumeIndexRange(
2163 mozilla::Span<BytecodeOffset> caseOffsets, BytecodeOffset switchOffset,
2164 uint32_t* firstResumeIndex) {
2165 auto& list = bytecodeSection().tableSwitchOffsetList();
2166
2167 // The final resume index depends on the number of yield and await ops in the
2168 // script, so store an index relative to the first table switch entry for now.
2169 // finishResumeOffsets adjusts it.
2170 *firstResumeIndex = list.numCaseOffsets();
2171 if (!list.appendTableSwitch(switchOffset)) {
2172 return false;
2173 }
2174
2175 for (BytecodeOffset offset : caseOffsets) {
2176 if (!checkResumeIndexLimit()) {
2177 return false;
2178 }
2179 if (!list.appendCaseOffset(offset)) {
2180 return false;
2181 }
2182 }
2183
2184 return true;
2185}
2186
2187bool BytecodeEmitter::finishResumeOffsets() {
2188 auto& resumeOffsets = bytecodeSection().resumeOffsetList();
2189 auto& tableSwitches = bytecodeSection().tableSwitchOffsetList();
2190
2191 size_t numIndices = resumeOffsets.length() + tableSwitches.numCaseOffsets();
2192 MOZ_RELEASE_ASSERT(numIndices <= MaxResumeIndex + 1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(numIndices <= MaxResumeIndex + 1)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(numIndices <= MaxResumeIndex
+ 1))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("numIndices <= MaxResumeIndex + 1", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 2192); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "numIndices <= MaxResumeIndex + 1"
")"); do { MOZ_CrashSequence(__null, 2192); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2193
2194 // Without yield/await entries, the relative indices SwitchEmitter wrote are
2195 // already the final resume indices, so there's nothing to patch.
2196 if (resumeOffsets.length() == 0) {
2197 resumeOffsets.setFrom(std::move(tableSwitches.caseOffsets));
2198 return true;
2199 }
2200
2201 // The table switch entries go after the yield and await entries.
2202 uint32_t firstTableSwitchIndex = resumeOffsets.length();
2203 if (!resumeOffsets.appendAll(tableSwitches.caseOffsets)) {
2204 return false;
2205 }
2206 for (BytecodeOffset switchOffset : tableSwitches.switchOffsets) {
2207 jsbytecode* pc = bytecodeSection().code(switchOffset);
2208 MOZ_ASSERT(JSOp(*pc) == JSOp::TableSwitch)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(JSOp(*pc) == JSOp::TableSwitch)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(JSOp(*pc) == JSOp::TableSwitch
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"JSOp(*pc) == JSOp::TableSwitch", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 2208); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JSOp(*pc) == JSOp::TableSwitch"
")"); do { MOZ_CrashSequence(__null, 2208); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2209 pc += 3 * JUMP_OFFSET_LEN;
2210 SET_RESUMEINDEX(pc, GET_RESUMEINDEX(pc) + firstTableSwitchIndex);
2211 }
2212 return true;
2213}
2214
2215bool BytecodeEmitter::emitYieldOp(JSOp op) {
2216 // ParseContext::Scope::setOwnStackSlotCount should check the fixed slot
2217 // for the following, and it should prevent using fixed slot if there are
2218 // too many bindings:
2219 // * generator or asyn function
2220 // * module code after top-level await
2221 MOZ_ASSERT(innermostEmitterScopeNoCheck()->frameSlotEnd() <=do { static_assert( mozilla::detail::AssertionConditionType<
decltype(innermostEmitterScopeNoCheck()->frameSlotEnd() <=
ParseContext::Scope::FixedSlotLimit)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(innermostEmitterScopeNoCheck
()->frameSlotEnd() <= ParseContext::Scope::FixedSlotLimit
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"innermostEmitterScopeNoCheck()->frameSlotEnd() <= ParseContext::Scope::FixedSlotLimit"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 2222);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "innermostEmitterScopeNoCheck()->frameSlotEnd() <= ParseContext::Scope::FixedSlotLimit"
")"); do { MOZ_CrashSequence(__null, 2222); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2222 ParseContext::Scope::FixedSlotLimit)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(innermostEmitterScopeNoCheck()->frameSlotEnd() <=
ParseContext::Scope::FixedSlotLimit)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(innermostEmitterScopeNoCheck
()->frameSlotEnd() <= ParseContext::Scope::FixedSlotLimit
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"innermostEmitterScopeNoCheck()->frameSlotEnd() <= ParseContext::Scope::FixedSlotLimit"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 2222);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "innermostEmitterScopeNoCheck()->frameSlotEnd() <= ParseContext::Scope::FixedSlotLimit"
")"); do { MOZ_CrashSequence(__null, 2222); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2223
2224 if (op == JSOp::FinalYieldRval) {
2225 return emit1(JSOp::FinalYieldRval);
2226 }
2227
2228 MOZ_ASSERT(op == JSOp::InitialYield || op == JSOp::Yield ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(op == JSOp::InitialYield || op == JSOp::Yield || op ==
JSOp::Await)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(op == JSOp::InitialYield || op ==
JSOp::Yield || op == JSOp::Await))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("op == JSOp::InitialYield || op == JSOp::Yield || op == JSOp::Await"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 2229);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::InitialYield || op == JSOp::Yield || op == JSOp::Await"
")"); do { MOZ_CrashSequence(__null, 2229); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2229 op == JSOp::Await)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(op == JSOp::InitialYield || op == JSOp::Yield || op ==
JSOp::Await)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(op == JSOp::InitialYield || op ==
JSOp::Yield || op == JSOp::Await))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("op == JSOp::InitialYield || op == JSOp::Yield || op == JSOp::Await"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 2229);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::InitialYield || op == JSOp::Yield || op == JSOp::Await"
")"); do { MOZ_CrashSequence(__null, 2229); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2230
2231 BytecodeOffset off;
2232 if (!emitN(op, 3, &off)) {
2233 return false;
2234 }
2235
2236 // InitialYield is always the first yield node.
2237 MOZ_ASSERT_IF(op == JSOp::InitialYield, bytecodeSection().numYields() == 0)do { if (op == JSOp::InitialYield) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(bytecodeSection(
).numYields() == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(bytecodeSection().numYields(
) == 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("bytecodeSection().numYields() == 0", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 2237); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().numYields() == 0"
")"); do { MOZ_CrashSequence(__null, 2237); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
2238
2239 if (op == JSOp::InitialYield || op == JSOp::Yield) {
2240 bytecodeSection().addNumYields();
2241 }
2242
2243 uint32_t resumeIndex;
2244 if (!allocateResumeIndex(bytecodeSection().offset(), &resumeIndex)) {
2245 return false;
2246 }
2247
2248 // InitialYield is the first resumable instruction.
2249 MOZ_ASSERT_IF(do { if (op == JSOp::InitialYield) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(resumeIndex == AbstractGeneratorObject
::RESUME_INDEX_INITIAL_YIELD)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(resumeIndex == AbstractGeneratorObject
::RESUME_INDEX_INITIAL_YIELD))), 0))) { do { } while (false);
MOZ_ReportAssertionFailure("resumeIndex == AbstractGeneratorObject::RESUME_INDEX_INITIAL_YIELD"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 2251);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "resumeIndex == AbstractGeneratorObject::RESUME_INDEX_INITIAL_YIELD"
")"); do { MOZ_CrashSequence(__null, 2251); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
2250 op == JSOp::InitialYield,do { if (op == JSOp::InitialYield) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(resumeIndex == AbstractGeneratorObject
::RESUME_INDEX_INITIAL_YIELD)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(resumeIndex == AbstractGeneratorObject
::RESUME_INDEX_INITIAL_YIELD))), 0))) { do { } while (false);
MOZ_ReportAssertionFailure("resumeIndex == AbstractGeneratorObject::RESUME_INDEX_INITIAL_YIELD"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 2251);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "resumeIndex == AbstractGeneratorObject::RESUME_INDEX_INITIAL_YIELD"
")"); do { MOZ_CrashSequence(__null, 2251); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
2251 resumeIndex == AbstractGeneratorObject::RESUME_INDEX_INITIAL_YIELD)do { if (op == JSOp::InitialYield) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(resumeIndex == AbstractGeneratorObject
::RESUME_INDEX_INITIAL_YIELD)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(resumeIndex == AbstractGeneratorObject
::RESUME_INDEX_INITIAL_YIELD))), 0))) { do { } while (false);
MOZ_ReportAssertionFailure("resumeIndex == AbstractGeneratorObject::RESUME_INDEX_INITIAL_YIELD"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 2251);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "resumeIndex == AbstractGeneratorObject::RESUME_INDEX_INITIAL_YIELD"
")"); do { MOZ_CrashSequence(__null, 2251); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
2252
2253 SET_RESUMEINDEX(bytecodeSection().code(off), resumeIndex);
2254
2255 BytecodeOffset unusedOffset;
2256 return emitJumpTargetOp(JSOp::AfterYield, &unusedOffset);
2257}
2258
2259bool BytecodeEmitter::emitPushResumeKind(GeneratorResumeKind kind) {
2260 return emit2(JSOp::ResumeKind, uint8_t(kind));
2261}
2262
2263bool BytecodeEmitter::emitSetThis(BinaryNode* setThisNode) {
2264 // ParseNodeKind::SetThis is used to update |this| after a super() call
2265 // in a derived class constructor.
2266
2267 MOZ_ASSERT(setThisNode->isKind(ParseNodeKind::SetThis))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(setThisNode->isKind(ParseNodeKind::SetThis))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(setThisNode->isKind(ParseNodeKind::SetThis)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("setThisNode->isKind(ParseNodeKind::SetThis)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 2267);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "setThisNode->isKind(ParseNodeKind::SetThis)"
")"); do { MOZ_CrashSequence(__null, 2267); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2268 MOZ_ASSERT(setThisNode->left()->isKind(ParseNodeKind::Name))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(setThisNode->left()->isKind(ParseNodeKind::Name
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(setThisNode->left()->isKind(ParseNodeKind::Name
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("setThisNode->left()->isKind(ParseNodeKind::Name)", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 2268); AnnotateMozCrashReason("MOZ_ASSERT" "(" "setThisNode->left()->isKind(ParseNodeKind::Name)"
")"); do { MOZ_CrashSequence(__null, 2268); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2269
2270 auto name = setThisNode->left()->as<NameNode>().name();
2271
2272 // The 'this' binding is not lexical, but due to super() semantics this
2273 // initialization needs to be treated as a lexical one.
2274 NameLocation loc = lookupName(name);
2275 NameLocation lexicalLoc;
2276 if (loc.kind() == NameLocation::Kind::FrameSlot) {
2277 lexicalLoc = NameLocation::FrameSlot(BindingKind::Let, loc.frameSlot());
2278 } else if (loc.kind() == NameLocation::Kind::EnvironmentCoordinate) {
2279 EnvironmentCoordinate coord = loc.environmentCoordinate();
2280 uint16_t hops = AssertedCast<uint16_t>(coord.hops());
2281 lexicalLoc = NameLocation::EnvironmentCoordinate(BindingKind::Let, hops,
2282 coord.slot());
2283 } else {
2284 MOZ_ASSERT(loc.kind() == NameLocation::Kind::Dynamic)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(loc.kind() == NameLocation::Kind::Dynamic)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(loc.kind() == NameLocation::Kind::Dynamic))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("loc.kind() == NameLocation::Kind::Dynamic"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 2284);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "loc.kind() == NameLocation::Kind::Dynamic"
")"); do { MOZ_CrashSequence(__null, 2284); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2285 lexicalLoc = loc;
2286 }
2287
2288 NameOpEmitter noe(this, name, lexicalLoc, NameOpEmitter::Kind::Initialize);
2289 if (!noe.prepareForRhs()) {
2290 // [stack]
2291 return false;
2292 }
2293
2294 // Emit the new |this| value.
2295 if (!emitTree(setThisNode->right())) {
2296 // [stack] NEWTHIS
2297 return false;
2298 }
2299
2300 // Get the original |this| and throw if we already initialized
2301 // it. Do *not* use the NameLocation argument, as that's the special
2302 // lexical location below to deal with super() semantics.
2303 if (!emitGetName(name)) {
2304 // [stack] NEWTHIS THIS
2305 return false;
2306 }
2307 if (!emit1(JSOp::CheckThisReinit)) {
2308 // [stack] NEWTHIS THIS
2309 return false;
2310 }
2311 if (!emit1(JSOp::Pop)) {
2312 // [stack] NEWTHIS
2313 return false;
2314 }
2315 if (!noe.emitAssignment()) {
2316 // [stack] NEWTHIS
2317 return false;
2318 }
2319
2320 if (!emitInitializeInstanceMembers(true)) {
2321 return false;
2322 }
2323
2324 return true;
2325}
2326
2327bool BytecodeEmitter::defineHoistedTopLevelFunctions(ParseNode* body) {
2328 MOZ_ASSERT(inPrologue())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(inPrologue())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(inPrologue()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("inPrologue()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 2328); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inPrologue()"
")"); do { MOZ_CrashSequence(__null, 2328); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2329 MOZ_ASSERT(sc->isGlobalContext() || (sc->isEvalContext() && !sc->strict()))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sc->isGlobalContext() || (sc->isEvalContext() &&
!sc->strict()))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sc->isGlobalContext() || (
sc->isEvalContext() && !sc->strict())))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("sc->isGlobalContext() || (sc->isEvalContext() && !sc->strict())"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 2329);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isGlobalContext() || (sc->isEvalContext() && !sc->strict())"
")"); do { MOZ_CrashSequence(__null, 2329); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2330 MOZ_ASSERT(body->is<LexicalScopeNode>() || body->is<ListNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(body->is<LexicalScopeNode>() || body->is
<ListNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(body->is<LexicalScopeNode
>() || body->is<ListNode>()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("body->is<LexicalScopeNode>() || body->is<ListNode>()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 2330);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "body->is<LexicalScopeNode>() || body->is<ListNode>()"
")"); do { MOZ_CrashSequence(__null, 2330); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2331
2332 if (body->is<LexicalScopeNode>()) {
2333 body = body->as<LexicalScopeNode>().scopeBody();
2334 MOZ_ASSERT(body->is<ListNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(body->is<ListNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(body->is<ListNode>(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("body->is<ListNode>()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 2334); AnnotateMozCrashReason("MOZ_ASSERT" "(" "body->is<ListNode>()"
")"); do { MOZ_CrashSequence(__null, 2334); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2335 }
2336
2337 if (!body->as<ListNode>().hasTopLevelFunctionDeclarations()) {
2338 return true;
2339 }
2340
2341 return emitHoistedFunctionsInList(&body->as<ListNode>());
2342}
2343
2344// For Global and sloppy-Eval scripts, this performs most of the steps of the
2345// spec's [GlobalDeclarationInstantiation] and [EvalDeclarationInstantiation]
2346// operations.
2347//
2348// Note that while strict-Eval is handled in the same part of the spec, it never
2349// fails for global-redeclaration checks so those scripts initialize directly in
2350// their bytecode.
2351bool BytecodeEmitter::emitDeclarationInstantiation(ParseNode* body) {
2352 if (sc->isModuleContext()) {
2353 // ES Modules have dedicated variable and lexial environments and therefore
2354 // do not have to perform redeclaration checks. We initialize their bindings
2355 // elsewhere in bytecode.
2356 return true;
2357 }
2358
2359 if (sc->isEvalContext() && sc->strict()) {
2360 // Strict Eval has a dedicated variables (and lexical) environment and
2361 // therefore does not have to perform redeclaration checks. We initialize
2362 // their bindings elsewhere in the bytecode.
2363 return true;
2364 }
2365
2366 // If we have no variables bindings, then we are done!
2367 if (sc->isGlobalContext()) {
2368 if (!sc->asGlobalContext()->bindings) {
2369 return true;
2370 }
2371 } else {
2372 MOZ_ASSERT(sc->isEvalContext())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sc->isEvalContext())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sc->isEvalContext()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("sc->isEvalContext()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 2372);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isEvalContext()"
")"); do { MOZ_CrashSequence(__null, 2372); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2373
2374 if (!sc->asEvalContext()->bindings) {
2375 return true;
2376 }
2377 }
2378
2379#if DEBUG1
2380 // There should be no emitted functions yet.
2381 for (const auto& thing : perScriptData().gcThingList().objects()) {
2382 MOZ_ASSERT(thing.isEmptyGlobalScope() || thing.isScope())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(thing.isEmptyGlobalScope() || thing.isScope())>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(thing.isEmptyGlobalScope() || thing.isScope()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("thing.isEmptyGlobalScope() || thing.isScope()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 2382);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "thing.isEmptyGlobalScope() || thing.isScope()"
")"); do { MOZ_CrashSequence(__null, 2382); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2383 }
2384#endif
2385
2386 // Emit the hoisted functions to gc-things list. There is no bytecode
2387 // generated yet to bind them.
2388 if (!defineHoistedTopLevelFunctions(body)) {
2389 return false;
2390 }
2391
2392 // Save the last GCThingIndex emitted. The hoisted functions are contained in
2393 // the gc-things list up until this point. This set of gc-things also contain
2394 // initial scopes (of which there must be at least one).
2395 MOZ_ASSERT(perScriptData().gcThingList().length() > 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(perScriptData().gcThingList().length() > 0)>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(perScriptData().gcThingList().length() > 0))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("perScriptData().gcThingList().length() > 0"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 2395);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "perScriptData().gcThingList().length() > 0"
")"); do { MOZ_CrashSequence(__null, 2395); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2396 GCThingIndex lastFun =
2397 GCThingIndex(perScriptData().gcThingList().length() - 1);
2398
2399#if DEBUG1
2400 for (const auto& thing : perScriptData().gcThingList().objects()) {
2401 MOZ_ASSERT(thing.isEmptyGlobalScope() || thing.isScope() ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(thing.isEmptyGlobalScope() || thing.isScope() || thing
.isFunction())>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(thing.isEmptyGlobalScope() || thing
.isScope() || thing.isFunction()))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("thing.isEmptyGlobalScope() || thing.isScope() || thing.isFunction()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 2402);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "thing.isEmptyGlobalScope() || thing.isScope() || thing.isFunction()"
")"); do { MOZ_CrashSequence(__null, 2402); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2402 thing.isFunction())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(thing.isEmptyGlobalScope() || thing.isScope() || thing
.isFunction())>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(thing.isEmptyGlobalScope() || thing
.isScope() || thing.isFunction()))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("thing.isEmptyGlobalScope() || thing.isScope() || thing.isFunction()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 2402);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "thing.isEmptyGlobalScope() || thing.isScope() || thing.isFunction()"
")"); do { MOZ_CrashSequence(__null, 2402); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2403 }
2404#endif
2405
2406 // Check for declaration conflicts and initialize the bindings.
2407 // NOTE: The self-hosting top-level script should not populate the builtins
2408 // directly on the GlobalObject (and instead uses JSOp::GetIntrinsic for
2409 // lookups).
2410 if (emitterMode == BytecodeEmitter::EmitterMode::Normal) {
2411 if (!emitGCIndexOp(JSOp::GlobalOrEvalDeclInstantiation, lastFun)) {
2412 return false;
2413 }
2414 }
2415
2416 return true;
2417}
2418
2419bool BytecodeEmitter::emitScript(ParseNode* body) {
2420 setScriptStartOffsetIfUnset(body->pn_pos.begin);
2421
2422 MOZ_ASSERT(inPrologue())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(inPrologue())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(inPrologue()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("inPrologue()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 2422); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inPrologue()"
")"); do { MOZ_CrashSequence(__null, 2422); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2423
2424 TDZCheckCache tdzCache(this);
2425 EmitterScope emitterScope(this);
2426 Maybe<AsyncEmitter> topLevelAwait;
2427 if (sc->isGlobalContext()) {
2428 if (!emitterScope.enterGlobal(this, sc->asGlobalContext())) {
2429 return false;
2430 }
2431 } else if (sc->isEvalContext()) {
2432 if (!emitterScope.enterEval(this, sc->asEvalContext())) {
2433 return false;
2434 }
2435 } else {
2436 MOZ_ASSERT(sc->isModuleContext())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sc->isModuleContext())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sc->isModuleContext()))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("sc->isModuleContext()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 2436);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isModuleContext()"
")"); do { MOZ_CrashSequence(__null, 2436); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2437 if (!emitterScope.enterModule(this, sc->asModuleContext())) {
2438 return false;
2439 }
2440 if (sc->asModuleContext()->isAsync()) {
2441 topLevelAwait.emplace(this);
2442 }
2443 }
2444
2445 setFunctionBodyEndPos(body->pn_pos.end);
2446
2447 bool isSloppyEval = sc->isEvalContext() && !sc->strict();
2448 if (isSloppyEval && body->is<LexicalScopeNode>() &&
2449 !body->as<LexicalScopeNode>().isEmptyScope()) {
2450 // Sloppy eval scripts may emit hoisted functions bindings with a
2451 // `JSOp::GlobalOrEvalDeclInstantiation` opcode below. If this eval needs a
2452 // top-level lexical environment, we must ensure that environment is created
2453 // before those functions are created and bound.
2454 //
2455 // This differs from the global-script case below because the global-lexical
2456 // environment exists outside the script itself. In the case of strict eval
2457 // scripts, the `emitterScope` above is already sufficient.
2458 EmitterScope lexicalEmitterScope(this);
2459 LexicalScopeNode* scope = &body->as<LexicalScopeNode>();
2460
2461 if (!lexicalEmitterScope.enterLexical(this, ScopeKind::Lexical,
2462 scope->scopeBindings())) {
2463 return false;
2464 }
2465
2466 if (!emitDeclarationInstantiation(scope->scopeBody())) {
2467 return false;
2468 }
2469
2470 switchToMain();
2471
2472 ParseNode* scopeBody = scope->scopeBody();
2473 if (!emitLexicalScopeBody(scopeBody)) {
2474 return false;
2475 }
2476
2477 if (!updateSourceCoordNotes(scopeBody->pn_pos.end)) {
2478 return false;
2479 }
2480
2481 if (!lexicalEmitterScope.leave(this)) {
2482 return false;
2483 }
2484 } else {
2485 if (!emitDeclarationInstantiation(body)) {
2486 return false;
2487 }
2488 if (topLevelAwait) {
2489 if (!topLevelAwait->prepareForModule()) {
2490 return false;
2491 }
2492 }
2493
2494 switchToMain();
2495
2496 if (!emitterScope.prepareForModuleDisposableScopeBody(this)) {
2497 return false;
2498 }
2499
2500 if (topLevelAwait) {
2501 if (!topLevelAwait->prepareForBody()) {
2502 return false;
2503 }
2504 }
2505
2506 if (!emitTree(body)) {
2507 // [stack]
2508 return false;
2509 }
2510
2511 if (!updateSourceCoordNotes(body->pn_pos.end)) {
2512 return false;
2513 }
2514 }
2515
2516 if (!emitterScope.emitModuleDisposableScopeBodyEnd(this)) {
2517 return false;
2518 }
2519
2520 if (topLevelAwait) {
2521 if (!topLevelAwait->emitEndModule()) {
2522 return false;
2523 }
2524 }
2525
2526 if (!markSimpleBreakpoint()) {
2527 return false;
2528 }
2529
2530 if (!emitReturnRval()) {
2531 return false;
2532 }
2533
2534 if (!emitterScope.leave(this)) {
2535 return false;
2536 }
2537
2538 if (!NameFunctions(fc, parserAtoms(), body)) {
2539 return false;
2540 }
2541
2542 // Create a Stencil and convert it into a JSScript.
2543 return intoScriptStencil(CompilationStencil::TopLevelIndex);
2544}
2545
2546js::UniquePtr<ImmutableScriptData>
2547BytecodeEmitter::createImmutableScriptData() {
2548 uint32_t nslots;
2549 if (!getNslots(&nslots)) {
2550 return nullptr;
2551 }
2552
2553 if (!finishResumeOffsets()) {
2554 return nullptr;
2555 }
2556
2557 bool isFunction = sc->isFunctionBox();
2558 uint16_t funLength = isFunction ? sc->asFunctionBox()->length() : 0;
2559
2560 mozilla::SaturateUint8 propertyCountEstimate = propertyAdditionEstimate;
2561
2562 // Add fields to the property count estimate.
2563 if (isFunction && sc->asFunctionBox()->useMemberInitializers()) {
2564 propertyCountEstimate +=
2565 sc->asFunctionBox()->memberInitializers().numMemberInitializers;
2566 }
2567
2568 return ImmutableScriptData::new_(
2569 fc, mainOffset(), maxFixedSlots, nslots, bodyScopeIndex,
2570 bytecodeSection().numICEntries(), isFunction, funLength,
2571 propertyCountEstimate.value(), bytecodeSection().code(),
2572 bytecodeSection().notes(), bytecodeSection().resumeOffsetList().span(),
2573 bytecodeSection().scopeNoteList().span(),
2574 bytecodeSection().tryNoteList().span());
2575}
2576
2577bool BytecodeEmitter::emitCheckIsCallable() {
2578 // This emits code to check if the value at the top of the stack is
2579 // callable. The value is left on the stack.
2580 // [stack] VAL
2581 if (!emitAtomOp(JSOp::GetIntrinsic,
2582 TaggedParserAtomIndex::WellKnown::IsCallable())) {
2583 // [stack] VAL ISCALLABLE
2584 return false;
2585 }
2586 if (!emit1(JSOp::Undefined)) {
2587 // [stack] VAL ISCALLABLE UNDEFINED
2588 return false;
2589 }
2590 if (!emitDupAt(2)) {
2591 // [stack] VAL ISCALLABLE UNDEFINED VAL
2592 return false;
2593 }
2594 return emitCall(JSOp::Call, 1);
2595 // [stack] VAL ISCALLABLE_RESULT
2596}
2597
2598bool BytecodeEmitter::getNslots(uint32_t* nslots) const {
2599 uint64_t nslots64 =
2600 maxFixedSlots + static_cast<uint64_t>(bytecodeSection().maxStackDepth());
2601 if (nslots64 > UINT32_MAX(4294967295U)) {
2602 reportError(nullptr, JSMSG_NEED_DIET, "script");
2603 return false;
2604 }
2605 *nslots = nslots64;
2606 return true;
2607}
2608
2609bool BytecodeEmitter::emitFunctionScript(FunctionNode* funNode) {
2610 MOZ_ASSERT(inPrologue())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(inPrologue())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(inPrologue()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("inPrologue()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 2610); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inPrologue()"
")"); do { MOZ_CrashSequence(__null, 2610); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2611 ParamsBodyNode* paramsBody = funNode->body();
2612 FunctionBox* funbox = sc->asFunctionBox();
2613
2614 setScriptStartOffsetIfUnset(paramsBody->pn_pos.begin);
2615
2616 // [stack]
2617
2618 FunctionScriptEmitter fse(this, funbox, Some(paramsBody->pn_pos.begin),
2619 Some(paramsBody->pn_pos.end));
2620 if (!fse.prepareForParameters()) {
2621 // [stack]
2622 return false;
2623 }
2624
2625 if (!emitFunctionFormalParameters(paramsBody)) {
2626 // [stack]
2627 return false;
2628 }
2629
2630 if (!fse.prepareForBody()) {
2631 // [stack]
2632 return false;
2633 }
2634
2635 if (!emitTree(paramsBody->body())) {
2636 // [stack]
2637 return false;
2638 }
2639
2640 if (!fse.emitEndBody()) {
2641 // [stack]
2642 return false;
2643 }
2644
2645 if (funbox->index() == CompilationStencil::TopLevelIndex) {
2646 if (!NameFunctions(fc, parserAtoms(), funNode)) {
2647 return false;
2648 }
2649 }
2650
2651 return fse.intoStencil();
2652}
2653
2654class js::frontend::DestructuringLHSRef {
2655 struct None {
2656 size_t numReferenceSlots() const { return 0; }
2657 };
2658
2659 mozilla::Variant<None, NameOpEmitter, PropOpEmitter, ElemOpEmitter,
2660 PrivateOpEmitter>
2661 emitter_ = AsVariant(None{});
2662
2663 public:
2664 template <typename T>
2665 void from(T&& emitter) {
2666 emitter_.emplace<T>(std::forward<T>(emitter));
2667 }
2668
2669 template <typename T>
2670 T& emitter() {
2671 return emitter_.as<T>();
2672 }
2673
2674 /**
2675 * Return the number of values pushed onto the stack.
2676 */
2677 size_t numReferenceSlots() const {
2678 return emitter_.match([](auto& e) { return e.numReferenceSlots(); });
2679 }
2680};
2681
2682bool BytecodeEmitter::emitDestructuringLHSRef(ParseNode* target,
2683 DestructuringFlavor flav,
2684 DestructuringLHSRef& lref) {
2685#ifdef DEBUG1
2686 int depth = bytecodeSection().stackDepth();
2687#endif
2688
2689 switch (target->getKind()) {
2690 case ParseNodeKind::ArrayExpr:
2691 case ParseNodeKind::ObjectExpr:
2692 // No need to recurse into ParseNodeKind::Array and ParseNodeKind::Object
2693 // subpatterns here, since emitSetOrInitializeDestructuring does the
2694 // recursion when setting or initializing the value.
2695 break;
2696
2697 case ParseNodeKind::Name: {
2698 auto* name = &target->as<NameNode>();
2699 NameOpEmitter noe(this, name->atom(),
2700 flav == DestructuringFlavor::Assignment
2701 ? NameOpEmitter::Kind::SimpleAssignment
2702 : NameOpEmitter::Kind::Initialize);
2703 if (!noe.prepareForRhs()) {
2704 return false;
2705 }
2706
2707 lref.from(std::move(noe));
2708 return true;
2709 }
2710
2711 case ParseNodeKind::ArgumentsLength:
2712 case ParseNodeKind::DotExpr: {
2713 NonOptionalPropertyAccessBase* prop =
2714 &target->as<NonOptionalPropertyAccessBase>();
2715 bool isSuper = prop->isSuper();
2716 PropOpEmitter poe(this, PropOpEmitter::Kind::SimpleAssignment,
2717 isSuper ? PropOpEmitter::ObjKind::Super
2718 : PropOpEmitter::ObjKind::Other);
2719 if (!poe.prepareForObj()) {
2720 return false;
2721 }
2722 if (isSuper) {
2723 UnaryNode* base = &prop->expression().as<UnaryNode>();
2724 if (!emitGetThisForSuperBase(base)) {
2725 // [stack] THIS SUPERBASE
2726 return false;
2727 }
2728 } else {
2729 if (!emitTree(&prop->expression())) {
2730 // [stack] OBJ
2731 return false;
2732 }
2733 }
2734 if (!poe.prepareForRhs()) {
2735 // [stack] # if Super
2736 // [stack] THIS SUPERBASE
2737 // [stack] # otherwise
2738 // [stack] OBJ
2739 return false;
2740 }
2741
2742 lref.from(std::move(poe));
2743 break;
2744 }
2745
2746 case ParseNodeKind::ElemExpr: {
2747 PropertyByValue* elem = &target->as<PropertyByValue>();
2748 bool isSuper = elem->isSuper();
2749 MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!elem->key().isKind(ParseNodeKind::PrivateName))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!elem->key().isKind(ParseNodeKind::PrivateName)))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!elem->key().isKind(ParseNodeKind::PrivateName)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 2749);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)"
")"); do { MOZ_CrashSequence(__null, 2749); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2750 ElemOpEmitter eoe(this, ElemOpEmitter::Kind::SimpleAssignment,
2751 isSuper ? ElemOpEmitter::ObjKind::Super
2752 : ElemOpEmitter::ObjKind::Other);
2753 if (!emitElemObjAndKey(elem, eoe)) {
2754 // [stack] # if Super
2755 // [stack] THIS KEY
2756 // [stack] # otherwise
2757 // [stack] OBJ KEY
2758 return false;
2759 }
2760 if (!eoe.prepareForRhs()) {
2761 // [stack] # if Super
2762 // [stack] THIS KEY SUPERBASE
2763 // [stack] # otherwise
2764 // [stack] OBJ KEY
2765 return false;
2766 }
2767
2768 lref.from(std::move(eoe));
2769 break;
2770 }
2771
2772 case ParseNodeKind::PrivateMemberExpr: {
2773 PrivateMemberAccess* privateExpr = &target->as<PrivateMemberAccess>();
2774 PrivateOpEmitter xoe(this, PrivateOpEmitter::Kind::SimpleAssignment,
2775 privateExpr->privateName().name());
2776 if (!emitTree(&privateExpr->expression())) {
2777 // [stack] OBJ
2778 return false;
2779 }
2780 if (!xoe.emitReference()) {
2781 // [stack] OBJ NAME
2782 return false;
2783 }
2784
2785 lref.from(std::move(xoe));
2786 break;
2787 }
2788
2789 case ParseNodeKind::CallExpr:
2790 MOZ_ASSERT_UNREACHABLE(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"Parser::reportIfNotValidSimpleAssignmentTarget " "rejects function calls as assignment "
"targets in destructuring assignments" ")", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 2793); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget "
"rejects function calls as assignment " "targets in destructuring assignments"
")"); do { MOZ_CrashSequence(__null, 2793); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2791 "Parser::reportIfNotValidSimpleAssignmentTarget "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"Parser::reportIfNotValidSimpleAssignmentTarget " "rejects function calls as assignment "
"targets in destructuring assignments" ")", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 2793); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget "
"rejects function calls as assignment " "targets in destructuring assignments"
")"); do { MOZ_CrashSequence(__null, 2793); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2792 "rejects function calls as assignment "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"Parser::reportIfNotValidSimpleAssignmentTarget " "rejects function calls as assignment "
"targets in destructuring assignments" ")", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 2793); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget "
"rejects function calls as assignment " "targets in destructuring assignments"
")"); do { MOZ_CrashSequence(__null, 2793); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2793 "targets in destructuring assignments")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"Parser::reportIfNotValidSimpleAssignmentTarget " "rejects function calls as assignment "
"targets in destructuring assignments" ")", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 2793); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget "
"rejects function calls as assignment " "targets in destructuring assignments"
")"); do { MOZ_CrashSequence(__null, 2793); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2794 break;
2795
2796 default:
2797 MOZ_CRASH("emitDestructuringLHSRef: bad lhs kind")do { do { } while (false); MOZ_ReportCrash("" "emitDestructuringLHSRef: bad lhs kind"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 2797);
AnnotateMozCrashReason("MOZ_CRASH(" "emitDestructuringLHSRef: bad lhs kind"
")"); do { MOZ_CrashSequence(__null, 2797); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
2798 }
2799
2800 MOZ_ASSERT(bytecodeSection().stackDepth() ==do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bytecodeSection().stackDepth() == depth + int(lref.numReferenceSlots
()))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(bytecodeSection().stackDepth() == depth + int(lref.numReferenceSlots
())))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("bytecodeSection().stackDepth() == depth + int(lref.numReferenceSlots())"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 2801);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == depth + int(lref.numReferenceSlots())"
")"); do { MOZ_CrashSequence(__null, 2801); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2801 depth + int(lref.numReferenceSlots()))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bytecodeSection().stackDepth() == depth + int(lref.numReferenceSlots
()))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(bytecodeSection().stackDepth() == depth + int(lref.numReferenceSlots
())))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("bytecodeSection().stackDepth() == depth + int(lref.numReferenceSlots())"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 2801);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == depth + int(lref.numReferenceSlots())"
")"); do { MOZ_CrashSequence(__null, 2801); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2802
2803 return true;
2804}
2805
2806bool BytecodeEmitter::emitSetOrInitializeDestructuring(
2807 ParseNode* target, DestructuringFlavor flav, DestructuringLHSRef& lref) {
2808 // Now emit the lvalue opcode sequence. If the lvalue is a nested
2809 // destructuring initialiser-form, call ourselves to handle it, then pop
2810 // the matched value. Otherwise emit an lvalue bytecode sequence followed
2811 // by an assignment op.
2812
2813 switch (target->getKind()) {
2814 case ParseNodeKind::ArrayExpr:
2815 case ParseNodeKind::ObjectExpr:
2816 if (!emitDestructuringOps(&target->as<ListNode>(), flav,
2817 SelfHostedIter::Deny)) {
2818 return false;
2819 }
2820 // emitDestructuringOps leaves the assigned (to-be-destructured) value on
2821 // top of the stack.
2822 break;
2823
2824 case ParseNodeKind::Name: {
2825 // The environment is already pushed by emitDestructuringLHSRef.
2826 // [stack] ENV? VAL
2827 auto& noe = lref.emitter<NameOpEmitter>();
2828
2829 if (!noe.emitAssignment()) {
2830 // [stack] VAL
2831 return false;
2832 }
2833 break;
2834 }
2835
2836 case ParseNodeKind::ArgumentsLength:
2837 case ParseNodeKind::DotExpr: {
2838 // The reference is already pushed by emitDestructuringLHSRef.
2839 // [stack] # if Super
2840 // [stack] THIS SUPERBASE VAL
2841 // [stack] # otherwise
2842 // [stack] OBJ VAL
2843 auto& poe = lref.emitter<PropOpEmitter>();
2844 auto* prop = &target->as<NonOptionalPropertyAccessBase>();
2845
2846 if (!poe.emitAssignment(prop->key().atom())) {
2847 // [stack] # VAL
2848 return false;
2849 }
2850 break;
2851 }
2852
2853 case ParseNodeKind::ElemExpr: {
2854 // The reference is already pushed by emitDestructuringLHSRef.
2855 // [stack] # if Super
2856 // [stack] THIS KEY SUPERBASE VAL
2857 // [stack] # otherwise
2858 // [stack] OBJ KEY VAL
2859 auto& eoe = lref.emitter<ElemOpEmitter>();
2860
2861 if (!eoe.emitAssignment()) {
2862 // [stack] VAL
2863 return false;
2864 }
2865 break;
2866 }
2867
2868 case ParseNodeKind::PrivateMemberExpr: {
2869 // The reference is already pushed by emitDestructuringLHSRef.
2870 // [stack] OBJ NAME VAL
2871 auto& xoe = lref.emitter<PrivateOpEmitter>();
2872
2873 if (!xoe.emitAssignment()) {
2874 // [stack] VAL
2875 return false;
2876 }
2877 break;
2878 }
2879
2880 case ParseNodeKind::CallExpr:
2881 MOZ_ASSERT_UNREACHABLE(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"Parser::reportIfNotValidSimpleAssignmentTarget " "rejects function calls as assignment "
"targets in destructuring assignments" ")", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 2884); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget "
"rejects function calls as assignment " "targets in destructuring assignments"
")"); do { MOZ_CrashSequence(__null, 2884); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2882 "Parser::reportIfNotValidSimpleAssignmentTarget "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"Parser::reportIfNotValidSimpleAssignmentTarget " "rejects function calls as assignment "
"targets in destructuring assignments" ")", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 2884); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget "
"rejects function calls as assignment " "targets in destructuring assignments"
")"); do { MOZ_CrashSequence(__null, 2884); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2883 "rejects function calls as assignment "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"Parser::reportIfNotValidSimpleAssignmentTarget " "rejects function calls as assignment "
"targets in destructuring assignments" ")", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 2884); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget "
"rejects function calls as assignment " "targets in destructuring assignments"
")"); do { MOZ_CrashSequence(__null, 2884); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2884 "targets in destructuring assignments")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"Parser::reportIfNotValidSimpleAssignmentTarget " "rejects function calls as assignment "
"targets in destructuring assignments" ")", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 2884); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget "
"rejects function calls as assignment " "targets in destructuring assignments"
")"); do { MOZ_CrashSequence(__null, 2884); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2885 break;
2886
2887 default:
2888 MOZ_CRASH("emitSetOrInitializeDestructuring: bad lhs kind")do { do { } while (false); MOZ_ReportCrash("" "emitSetOrInitializeDestructuring: bad lhs kind"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 2888);
AnnotateMozCrashReason("MOZ_CRASH(" "emitSetOrInitializeDestructuring: bad lhs kind"
")"); do { MOZ_CrashSequence(__null, 2888); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
2889 }
2890
2891 // Pop the assigned value.
2892 if (!emit1(JSOp::Pop)) {
2893 // [stack] # empty
2894 return false;
2895 }
2896
2897 return true;
2898}
2899
2900JSOp BytecodeEmitter::getIterCallOp(JSOp callOp,
2901 SelfHostedIter selfHostedIter) const {
2902 if (emitterMode == BytecodeEmitter::SelfHosting) {
2903 MOZ_ASSERT(selfHostedIter != SelfHostedIter::Deny)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(selfHostedIter != SelfHostedIter::Deny)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(selfHostedIter != SelfHostedIter::Deny))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 2903);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny"
")"); do { MOZ_CrashSequence(__null, 2903); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2904
2905 switch (callOp) {
2906 case JSOp::Call:
2907 return JSOp::CallContent;
2908 case JSOp::CallIter:
2909 return JSOp::CallContentIter;
2910 default:
2911 MOZ_CRASH("Unknown iterator call op")do { do { } while (false); MOZ_ReportCrash("" "Unknown iterator call op"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 2911);
AnnotateMozCrashReason("MOZ_CRASH(" "Unknown iterator call op"
")"); do { MOZ_CrashSequence(__null, 2911); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
2912 }
2913 }
2914
2915 return callOp;
2916}
2917
2918bool BytecodeEmitter::emitIteratorNext(
2919 const Maybe<uint32_t>& callSourceCoordOffset, IteratorKind iterKind,
2920 SelfHostedIter selfHostedIter) {
2921 MOZ_ASSERT(selfHostedIter != SelfHostedIter::Deny ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode
!= BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter
::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
" (" ".next() iteration is prohibited in self-hosted code because it"
"can run user-modifiable iteration code" ")", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 2924); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
") (" ".next() iteration is prohibited in self-hosted code because it"
"can run user-modifiable iteration code" ")"); do { MOZ_CrashSequence
(__null, 2924); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
2922 emitterMode != BytecodeEmitter::SelfHosting,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode
!= BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter
::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
" (" ".next() iteration is prohibited in self-hosted code because it"
"can run user-modifiable iteration code" ")", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 2924); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
") (" ".next() iteration is prohibited in self-hosted code because it"
"can run user-modifiable iteration code" ")"); do { MOZ_CrashSequence
(__null, 2924); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
2923 ".next() iteration is prohibited in self-hosted code because it"do { static_assert( mozilla::detail::AssertionConditionType<
decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode
!= BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter
::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
" (" ".next() iteration is prohibited in self-hosted code because it"
"can run user-modifiable iteration code" ")", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 2924); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
") (" ".next() iteration is prohibited in self-hosted code because it"
"can run user-modifiable iteration code" ")"); do { MOZ_CrashSequence
(__null, 2924); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
2924 "can run user-modifiable iteration code")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode
!= BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter
::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
" (" ".next() iteration is prohibited in self-hosted code because it"
"can run user-modifiable iteration code" ")", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 2924); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
") (" ".next() iteration is prohibited in self-hosted code because it"
"can run user-modifiable iteration code" ")"); do { MOZ_CrashSequence
(__null, 2924); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2925
2926 // [stack] ... NEXT ITER
2927 MOZ_ASSERT(bytecodeSection().stackDepth() >= 2)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bytecodeSection().stackDepth() >= 2)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(bytecodeSection().stackDepth() >= 2))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("bytecodeSection().stackDepth() >= 2"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 2927);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() >= 2"
")"); do { MOZ_CrashSequence(__null, 2927); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2928
2929 if (!emitCall(getIterCallOp(JSOp::Call, selfHostedIter), 0,
2930 callSourceCoordOffset)) {
2931 // [stack] ... RESULT
2932 return false;
2933 }
2934
2935 if (iterKind == IteratorKind::Async) {
2936 if (!emitAwaitInInnermostScope()) {
2937 // [stack] ... RESULT
2938 return false;
2939 }
2940 }
2941
2942 if (!emitCheckIsObj(CheckIsObjectKind::IteratorNext)) {
2943 // [stack] ... RESULT
2944 return false;
2945 }
2946 return true;
2947}
2948
2949bool BytecodeEmitter::emitIteratorCloseInScope(EmitterScope& currentScope,
2950 IteratorKind iterKind,
2951 CompletionKind completionKind,
2952 SelfHostedIter selfHostedIter) {
2953 MOZ_ASSERT(selfHostedIter != SelfHostedIter::Deny ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode
!= BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter
::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
" (" ".close() on iterators is prohibited in self-hosted code because "
"it can run user-modifiable iteration code" ")", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 2956); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
") (" ".close() on iterators is prohibited in self-hosted code because "
"it can run user-modifiable iteration code" ")"); do { MOZ_CrashSequence
(__null, 2956); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
2954 emitterMode != BytecodeEmitter::SelfHosting,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode
!= BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter
::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
" (" ".close() on iterators is prohibited in self-hosted code because "
"it can run user-modifiable iteration code" ")", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 2956); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
") (" ".close() on iterators is prohibited in self-hosted code because "
"it can run user-modifiable iteration code" ")"); do { MOZ_CrashSequence
(__null, 2956); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
2955 ".close() on iterators is prohibited in self-hosted code because "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode
!= BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter
::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
" (" ".close() on iterators is prohibited in self-hosted code because "
"it can run user-modifiable iteration code" ")", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 2956); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
") (" ".close() on iterators is prohibited in self-hosted code because "
"it can run user-modifiable iteration code" ")"); do { MOZ_CrashSequence
(__null, 2956); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
2956 "it can run user-modifiable iteration code")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode
!= BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter
::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
" (" ".close() on iterators is prohibited in self-hosted code because "
"it can run user-modifiable iteration code" ")", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 2956); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
") (" ".close() on iterators is prohibited in self-hosted code because "
"it can run user-modifiable iteration code" ")"); do { MOZ_CrashSequence
(__null, 2956); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2957
2958 if (iterKind == IteratorKind::Sync) {
2959 return emit2(JSOp::CloseIter, uint8_t(completionKind));
2960 }
2961
2962 // Generate inline logic corresponding to IteratorClose (ES2021 7.4.6) and
2963 // AsyncIteratorClose (ES2021 7.4.7). Steps numbers apply to both operations.
2964 //
2965 // Callers need to ensure that the iterator object is at the top of the
2966 // stack.
2967
2968 // For non-Throw completions, we emit the equivalent of:
2969 //
2970 // var returnMethod = GetMethod(iterator, "return");
2971 // if (returnMethod !== undefined) {
2972 // var innerResult = [Await] Call(returnMethod, iterator);
2973 // CheckIsObj(innerResult);
2974 // }
2975 //
2976 // Whereas for Throw completions, we emit:
2977 //
2978 // try {
2979 // var returnMethod = GetMethod(iterator, "return");
2980 // if (returnMethod !== undefined) {
2981 // [Await] Call(returnMethod, iterator);
2982 // }
2983 // } catch {}
2984
2985 Maybe<TryEmitter> tryCatch;
2986
2987 if (completionKind == CompletionKind::Throw) {
2988 tryCatch.emplace(this, TryEmitter::Kind::TryCatch,
2989 TryEmitter::ControlKind::NonSyntactic);
2990
2991 if (!tryCatch->emitTry()) {
2992 // [stack] ... ITER
2993 return false;
2994 }
2995 }
2996
2997 if (!emit1(JSOp::Dup)) {
2998 // [stack] ... ITER ITER
2999 return false;
3000 }
3001
3002 // Steps 1-2 are assertions, step 3 is implicit.
3003
3004 // Step 4.
3005 //
3006 // Get the "return" method.
3007 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::return_())) {
3008 // [stack] ... ITER RET
3009 return false;
3010 }
3011
3012 // Step 5.
3013 //
3014 // Do nothing if "return" is undefined or null.
3015 InternalIfEmitter ifReturnMethodIsDefined(this);
3016 if (!emit1(JSOp::IsNullOrUndefined)) {
3017 // [stack] ... ITER RET NULL-OR-UNDEF
3018 return false;
3019 }
3020
3021 if (!ifReturnMethodIsDefined.emitThenElse(
3022 IfEmitter::ConditionKind::Negative)) {
3023 // [stack] ... ITER RET
3024 return false;
3025 }
3026
3027 // Steps 5.c, 7.
3028 //
3029 // Call the "return" method.
3030 if (!emit1(JSOp::Swap)) {
3031 // [stack] ... RET ITER
3032 return false;
3033 }
3034
3035 if (!emitCall(getIterCallOp(JSOp::Call, selfHostedIter), 0)) {
3036 // [stack] ... RESULT
3037 return false;
3038 }
3039
3040 // 7.4.7 AsyncIteratorClose, step 5.d.
3041 if (iterKind == IteratorKind::Async) {
3042 if (completionKind != CompletionKind::Throw) {
3043 // Await clobbers rval, so save the current rval.
3044 if (!emit1(JSOp::GetRval)) {
3045 // [stack] ... RESULT RVAL
3046 return false;
3047 }
3048 if (!emit1(JSOp::Swap)) {
3049 // [stack] ... RVAL RESULT
3050 return false;
3051 }
3052 }
3053
3054 if (!emitAwaitInScope(currentScope)) {
3055 // [stack] ... RVAL? RESULT
3056 return false;
3057 }
3058
3059 if (completionKind != CompletionKind::Throw) {
3060 if (!emit1(JSOp::Swap)) {
3061 // [stack] ... RESULT RVAL
3062 return false;
3063 }
3064 if (!emit1(JSOp::SetRval)) {
3065 // [stack] ... RESULT
3066 return false;
3067 }
3068 }
3069 }
3070
3071 // Step 6 (Handled in caller).
3072
3073 // Step 8.
3074 if (completionKind != CompletionKind::Throw) {
3075 // Check that the "return" result is an object.
3076 if (!emitCheckIsObj(CheckIsObjectKind::IteratorReturn)) {
3077 // [stack] ... RESULT
3078 return false;
3079 }
3080 }
3081
3082 if (!ifReturnMethodIsDefined.emitElse()) {
3083 // [stack] ... ITER RET
3084 return false;
3085 }
3086
3087 if (!emit1(JSOp::Pop)) {
3088 // [stack] ... ITER
3089 return false;
3090 }
3091
3092 if (!ifReturnMethodIsDefined.emitEnd()) {
3093 return false;
3094 }
3095
3096 if (completionKind == CompletionKind::Throw) {
3097 if (!tryCatch->emitCatch()) {
3098 // [stack] ... ITER EXC
3099 return false;
3100 }
3101
3102 // Just ignore the exception thrown by call and await.
3103 if (!emit1(JSOp::Pop)) {
3104 // [stack] ... ITER
3105 return false;
3106 }
3107
3108 if (!tryCatch->emitEnd()) {
3109 // [stack] ... ITER
3110 return false;
3111 }
3112 }
3113
3114 // Step 9 (Handled in caller).
3115
3116 return emit1(JSOp::Pop);
3117 // [stack] ...
3118}
3119
3120bool BytecodeEmitter::emitDestructuringIteratorClose(
3121 SelfHostedIter selfHostedIter) {
3122 // [stack] ... OBJ NEXT ITER DONE
3123
3124 InternalIfEmitter ifDone(this);
3125 if (!ifDone.emitThenElse()) {
3126 // [stack] ... OBJ NEXT ITER
3127 return false;
3128 }
3129 if (!emitPopN(2)) {
3130 // [stack] ... OBJ
3131 return false;
3132 }
3133 if (!ifDone.emitElse()) {
3134 // [stack] ... OBJ NEXT ITER
3135 return false;
3136 }
3137 if (!emit1(JSOp::Swap)) {
3138 // [stack] ... OBJ ITER NEXT
3139 return false;
3140 }
3141 if (!emit1(JSOp::Pop)) {
3142 // [stack] ... OBJ ITER
3143 return false;
3144 }
3145 if (!emitIteratorCloseInInnermostScope(
3146 IteratorKind::Sync, CompletionKind::Normal, selfHostedIter)) {
3147 // [stack] ... OBJ
3148 return false;
3149 }
3150 return ifDone.emitEnd();
3151}
3152
3153template <typename InnerEmitter>
3154bool BytecodeEmitter::wrapWithDestructuringTryNote(int32_t iterDepth,
3155 InnerEmitter emitter) {
3156 MOZ_ASSERT(bytecodeSection().stackDepth() >= iterDepth)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bytecodeSection().stackDepth() >= iterDepth)>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(bytecodeSection().stackDepth() >= iterDepth))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("bytecodeSection().stackDepth() >= iterDepth"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 3156);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() >= iterDepth"
")"); do { MOZ_CrashSequence(__null, 3156); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3157#ifdef DEBUG1
3158 auto* control = findInnermostNestableControl<DestructuringControl>();
3159 MOZ_ASSERT(*control->nonLocalExitStackDepth() == iterDepth)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(*control->nonLocalExitStackDepth() == iterDepth)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(*control->nonLocalExitStackDepth() == iterDepth))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("*control->nonLocalExitStackDepth() == iterDepth"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 3159);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "*control->nonLocalExitStackDepth() == iterDepth"
")"); do { MOZ_CrashSequence(__null, 3159); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3160#endif
3161
3162 // Pad a nop at the beginning of the bytecode covered by the trynote so
3163 // that when unwinding environments, we may unwind to the scope
3164 // corresponding to the pc *before* the start, in case the first bytecode
3165 // emitted by |emitter| is the start of an inner scope. See comment above
3166 // UnwindEnvironmentToTryPc.
3167 if (!emit1(JSOp::TryDestructuring)) {
3168 return false;
3169 }
3170
3171 BytecodeOffset start = bytecodeSection().offset();
3172 if (!emitter(this)) {
3173 return false;
3174 }
3175 BytecodeOffset end = bytecodeSection().offset();
3176 if (start != end) {
3177 return addTryNote(TryNoteKind::Destructuring, iterDepth, start, end);
3178 }
3179 return true;
3180}
3181
3182bool BytecodeEmitter::emitDefault(ParseNode* defaultExpr, ParseNode* pattern) {
3183 // [stack] VALUE
3184
3185 DefaultEmitter de(this);
3186 if (!de.prepareForDefault()) {
3187 // [stack]
3188 return false;
3189 }
3190 if (!emitInitializer(defaultExpr, pattern)) {
3191 // [stack] DEFAULTVALUE
3192 return false;
3193 }
3194 if (!de.emitEnd()) {
3195 // [stack] VALUE/DEFAULTVALUE
3196 return false;
3197 }
3198 return true;
3199}
3200
3201bool BytecodeEmitter::emitAnonymousFunctionWithName(
3202 ParseNode* node, TaggedParserAtomIndex name) {
3203 MOZ_ASSERT(node->isDirectRHSAnonFunction())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(node->isDirectRHSAnonFunction())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(node->isDirectRHSAnonFunction
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("node->isDirectRHSAnonFunction()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 3203); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isDirectRHSAnonFunction()"
")"); do { MOZ_CrashSequence(__null, 3203); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3204
3205 if (node->is<FunctionNode>()) {
3206 // Function doesn't have 'name' property at this point.
3207 // Set function's name at compile time.
3208 setFunName(node->as<FunctionNode>().funbox(), name);
3209
3210 return emitTree(node);
3211 }
3212
3213 MOZ_ASSERT(node->is<ClassNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(node->is<ClassNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(node->is<ClassNode>
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("node->is<ClassNode>()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 3213); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->is<ClassNode>()"
")"); do { MOZ_CrashSequence(__null, 3213); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3214
3215 return emitClass(&node->as<ClassNode>(), ClassNameKind::InferredName, name);
3216}
3217
3218bool BytecodeEmitter::emitAnonymousFunctionWithComputedName(
3219 ParseNode* node, FunctionPrefixKind prefixKind) {
3220 MOZ_ASSERT(node->isDirectRHSAnonFunction())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(node->isDirectRHSAnonFunction())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(node->isDirectRHSAnonFunction
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("node->isDirectRHSAnonFunction()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 3220); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isDirectRHSAnonFunction()"
")"); do { MOZ_CrashSequence(__null, 3220); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3221
3222 if (node->is<FunctionNode>()) {
3223 if (!emitTree(node)) {
3224 // [stack] NAME FUN
3225 return false;
3226 }
3227 if (!emitDupAt(1)) {
3228 // [stack] NAME FUN NAME
3229 return false;
3230 }
3231 if (!emit2(JSOp::SetFunName, uint8_t(prefixKind))) {
3232 // [stack] NAME FUN
3233 return false;
3234 }
3235 return true;
3236 }
3237
3238 MOZ_ASSERT(node->is<ClassNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(node->is<ClassNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(node->is<ClassNode>
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("node->is<ClassNode>()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 3238); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->is<ClassNode>()"
")"); do { MOZ_CrashSequence(__null, 3238); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3239 MOZ_ASSERT(prefixKind == FunctionPrefixKind::None)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(prefixKind == FunctionPrefixKind::None)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(prefixKind == FunctionPrefixKind::None))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("prefixKind == FunctionPrefixKind::None"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 3239);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "prefixKind == FunctionPrefixKind::None"
")"); do { MOZ_CrashSequence(__null, 3239); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3240
3241 return emitClass(&node->as<ClassNode>(), ClassNameKind::ComputedName);
3242}
3243
3244void BytecodeEmitter::setFunName(FunctionBox* funbox,
3245 TaggedParserAtomIndex name) const {
3246 // The inferred name may already be set if this function is an interpreted
3247 // lazy function and we OOM'ed after we set the inferred name the first
3248 // time.
3249 if (funbox->hasInferredName()) {
3250 MOZ_ASSERT(!funbox->emitBytecode)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!funbox->emitBytecode)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!funbox->emitBytecode))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("!funbox->emitBytecode"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 3250);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!funbox->emitBytecode"
")"); do { MOZ_CrashSequence(__null, 3250); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3251 MOZ_ASSERT(funbox->displayAtom() == name)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(funbox->displayAtom() == name)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(funbox->displayAtom() == name
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"funbox->displayAtom() == name", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 3251); AnnotateMozCrashReason("MOZ_ASSERT" "(" "funbox->displayAtom() == name"
")"); do { MOZ_CrashSequence(__null, 3251); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3252 } else {
3253 funbox->setInferredName(name);
3254 }
3255}
3256
3257bool BytecodeEmitter::emitInitializer(ParseNode* initializer,
3258 ParseNode* pattern) {
3259 if (initializer->isDirectRHSAnonFunction()) {
3260 MOZ_ASSERT(!pattern->isInParens())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!pattern->isInParens())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!pattern->isInParens())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("!pattern->isInParens()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 3260);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!pattern->isInParens()"
")"); do { MOZ_CrashSequence(__null, 3260); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3261 auto name = pattern->as<NameNode>().name();
3262 if (!emitAnonymousFunctionWithName(initializer, name)) {
3263 return false;
3264 }
3265 } else {
3266 if (!emitTree(initializer)) {
3267 return false;
3268 }
3269 }
3270
3271 return true;
3272}
3273
3274bool BytecodeEmitter::emitDestructuringOpsArray(ListNode* pattern,
3275 DestructuringFlavor flav,
3276 SelfHostedIter selfHostedIter) {
3277 MOZ_ASSERT(pattern->isKind(ParseNodeKind::ArrayExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pattern->isKind(ParseNodeKind::ArrayExpr))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(pattern->isKind(ParseNodeKind::ArrayExpr)))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("pattern->isKind(ParseNodeKind::ArrayExpr)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 3277);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "pattern->isKind(ParseNodeKind::ArrayExpr)"
")"); do { MOZ_CrashSequence(__null, 3277); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3278 MOZ_ASSERT(bytecodeSection().stackDepth() != 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bytecodeSection().stackDepth() != 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(bytecodeSection().stackDepth
() != 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("bytecodeSection().stackDepth() != 0", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 3278); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() != 0"
")"); do { MOZ_CrashSequence(__null, 3278); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3279
3280 // Here's pseudo code for |let [a, b, , c=y, ...d] = x;|
3281 //
3282 // Lines that are annotated "covered by trynote" mean that upon throwing
3283 // an exception, IteratorClose is called on iter only if done is false.
3284 //
3285 // let x, y;
3286 // let a, b, c, d;
3287 // let iter, next, lref, result, done, value; // stack values
3288 //
3289 // // NOTE: the fast path for this example is not applicable, because of
3290 // // the spread and the assignment |c=y|, but it is documented here for a
3291 // // simpler example, |let [a,b] = x;|
3292 // //
3293 // // if (IsOptimizableArray(x)) {
3294 // // a = x[0];
3295 // // b = x[1];
3296 // // goto end: // (skip everything below)
3297 // // }
3298 //
3299 // iter = x[Symbol.iterator]();
3300 // next = iter.next;
3301 //
3302 // // ==== emitted by loop for a ====
3303 // lref = GetReference(a); // covered by trynote
3304 //
3305 // result = Call(next, iter);
3306 // done = result.done;
3307 //
3308 // if (done)
3309 // value = undefined;
3310 // else
3311 // value = result.value;
3312 //
3313 // SetOrInitialize(lref, value); // covered by trynote
3314 //
3315 // // ==== emitted by loop for b ====
3316 // lref = GetReference(b); // covered by trynote
3317 //
3318 // if (done) {
3319 // value = undefined;
3320 // } else {
3321 // result = Call(next, iter);
3322 // done = result.done;
3323 // if (done)
3324 // value = undefined;
3325 // else
3326 // value = result.value;
3327 // }
3328 //
3329 // SetOrInitialize(lref, value); // covered by trynote
3330 //
3331 // // ==== emitted by loop for elision ====
3332 // if (done) {
3333 // value = undefined;
3334 // } else {
3335 // result = Call(next, iter);
3336 // done = result.done;
3337 // if (done)
3338 // value = undefined;
3339 // else
3340 // value = result.value;
3341 // }
3342 //
3343 // // ==== emitted by loop for c ====
3344 // lref = GetReference(c); // covered by trynote
3345 //
3346 // if (done) {
3347 // value = undefined;
3348 // } else {
3349 // result = Call(next, iter);
3350 // done = result.done;
3351 // if (done)
3352 // value = undefined;
3353 // else
3354 // value = result.value;
3355 // }
3356 //
3357 // if (value === undefined)
3358 // value = y; // covered by trynote
3359 //
3360 // SetOrInitialize(lref, value); // covered by trynote
3361 //
3362 // // ==== emitted by loop for d ====
3363 // lref = GetReference(d); // covered by trynote
3364 //
3365 // if (done)
3366 // value = [];
3367 // else
3368 // value = [...iter];
3369 //
3370 // SetOrInitialize(lref, value); // covered by trynote
3371 //
3372 // // === emitted after loop ===
3373 // if (!done)
3374 // IteratorClose(iter);
3375 //
3376 // end:
3377
3378 bool isEligibleForArrayOptimizations = true;
3379 for (ParseNode* member : pattern->contents()) {
3380 switch (member->getKind()) {
3381 case ParseNodeKind::Elision:
3382 break;
3383 case ParseNodeKind::Name: {
3384 auto name = member->as<NameNode>().name();
3385 NameLocation loc = lookupName(name);
3386 if (loc.kind() != NameLocation::Kind::ArgumentSlot &&
3387 loc.kind() != NameLocation::Kind::FrameSlot &&
3388 loc.kind() != NameLocation::Kind::EnvironmentCoordinate) {
3389 isEligibleForArrayOptimizations = false;
3390 }
3391 break;
3392 }
3393 default:
3394 // Unfortunately we can't handle any recursive destructuring,
3395 // because we can't guarantee that the recursed-into parts
3396 // won't run code which invalidates our constraints. We also
3397 // cannot handle ParseNodeKind::AssignExpr for similar reasons.
3398 isEligibleForArrayOptimizations = false;
3399 break;
3400 }
3401 if (!isEligibleForArrayOptimizations) {
3402 break;
3403 }
3404 }
3405
3406 // Use an iterator to destructure the RHS, instead of index lookup. We
3407 // must leave the *original* value on the stack.
3408 if (!emit1(JSOp::Dup)) {
3409 // [stack] ... OBJ OBJ
3410 return false;
3411 }
3412
3413 Maybe<InternalIfEmitter> ifArrayOptimizable;
3414
3415 if (isEligibleForArrayOptimizations) {
3416 ifArrayOptimizable.emplace(
3417 this, BranchEmitterBase::LexicalKind::MayContainLexicalAccessInBranch);
3418
3419 if (!emit1(JSOp::Dup)) {
3420 // [stack] OBJ OBJ
3421 return false;
3422 }
3423
3424 if (!emit1(JSOp::OptimizeGetIterator)) {
3425 // [stack] OBJ OBJ IS_OPTIMIZABLE
3426 return false;
3427 }
3428
3429 if (!ifArrayOptimizable->emitThenElse()) {
3430 // [stack] OBJ OBJ
3431 return false;
3432 }
3433
3434 if (!emitAtomOp(JSOp::GetProp,
3435 TaggedParserAtomIndex::WellKnown::length())) {
3436 // [stack] OBJ LENGTH
3437 return false;
3438 }
3439
3440 if (!emit1(JSOp::Swap)) {
3441 // [stack] LENGTH OBJ
3442 return false;
3443 }
3444
3445 uint32_t idx = 0;
3446 for (ParseNode* member : pattern->contents()) {
3447 if (member->isKind(ParseNodeKind::Elision)) {
3448 idx += 1;
3449 continue;
3450 }
3451 MOZ_ASSERT(member->isKind(ParseNodeKind::Name))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(member->isKind(ParseNodeKind::Name))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(member->isKind(ParseNodeKind::Name)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("member->isKind(ParseNodeKind::Name)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 3451);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "member->isKind(ParseNodeKind::Name)"
")"); do { MOZ_CrashSequence(__null, 3451); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3452
3453 if (!emit1(JSOp::Dup)) {
3454 // [stack] LENGTH OBJ OBJ
3455 return false;
3456 }
3457
3458 if (!emitNumberOp(idx)) {
3459 // [stack] LENGTH OBJ OBJ IDX
3460 return false;
3461 }
3462
3463 if (!emit1(JSOp::Dup)) {
3464 // [stack] LENGTH OBJ OBJ IDX IDX
3465 return false;
3466 }
3467
3468 if (!emitDupAt(4)) {
3469 // [stack] LENGTH OBJ OBJ IDX IDX LENGTH
3470 return false;
3471 }
3472
3473 if (!emit1(JSOp::Lt)) {
3474 // [stack] LENGTH OBJ OBJ IDX IS_IN_DENSE_BOUNDS
3475 return false;
3476 }
3477
3478 InternalIfEmitter isInDenseBounds(this);
3479 if (!isInDenseBounds.emitThenElse()) {
3480 // [stack] LENGTH OBJ OBJ IDX
3481 return false;
3482 }
3483
3484 if (!emit1(JSOp::GetElem)) {
3485 // [stack] LENGTH OBJ VALUE
3486 return false;
3487 }
3488
3489 if (!isInDenseBounds.emitElse()) {
3490 // [stack] LENGTH OBJ OBJ IDX
3491 return false;
3492 }
3493
3494 if (!emitPopN(2)) {
3495 // [stack] LENGTH OBJ
3496 return false;
3497 }
3498
3499 if (!emit1(JSOp::Undefined)) {
3500 // [stack] LENGTH OBJ UNDEFINED
3501 return false;
3502 }
3503
3504 if (!isInDenseBounds.emitEnd()) {
3505 // [stack] LENGTH OBJ VALUE|UNDEFINED
3506 return false;
3507 }
3508
3509 DestructuringLHSRef lref;
3510 if (!emitDestructuringLHSRef(member, flav, lref)) {
3511 // [stack] LENGTH OBJ
3512 return false;
3513 }
3514
3515 if (!emitSetOrInitializeDestructuring(member, flav, lref)) {
3516 // [stack] LENGTH OBJ
3517 return false;
3518 }
3519
3520 idx += 1;
3521 }
3522
3523 if (!emit1(JSOp::Swap)) {
3524 // [stack] OBJ LENGTH
3525 return false;
3526 }
3527
3528 if (!emit1(JSOp::Pop)) {
3529 // [stack] OBJ
3530 return false;
3531 }
3532
3533 if (!ifArrayOptimizable->emitElse()) {
3534 // [stack] OBJ OBJ
3535 return false;
3536 }
3537 }
3538
3539 if (!emitIterator(selfHostedIter)) {
3540 // [stack] ... OBJ NEXT ITER
3541 return false;
3542 }
3543
3544 // For an empty pattern [], call IteratorClose unconditionally. Nothing
3545 // else needs to be done.
3546 if (!pattern->head()) {
3547 if (!emit1(JSOp::Swap)) {
3548 // [stack] ... OBJ ITER NEXT
3549 return false;
3550 }
3551 if (!emit1(JSOp::Pop)) {
3552 // [stack] ... OBJ ITER
3553 return false;
3554 }
3555
3556 if (!emitIteratorCloseInInnermostScope(
3557 IteratorKind::Sync, CompletionKind::Normal, selfHostedIter)) {
3558 // [stack] ... OBJ
3559 return false;
3560 }
3561
3562 if (ifArrayOptimizable.isSome()) {
3563 if (!ifArrayOptimizable->emitEnd()) {
3564 // [stack] OBJ
3565 return false;
3566 }
3567 }
3568
3569 return true;
3570 }
3571
3572 // Push an initial FALSE value for DONE.
3573 if (!emit1(JSOp::False)) {
3574 // [stack] ... OBJ NEXT ITER FALSE
3575 return false;
3576 }
3577
3578 // TryNoteKind::Destructuring expects the iterator and the done value
3579 // to be the second to top and the top of the stack, respectively.
3580 // IteratorClose is called upon exception only if done is false.
3581 int32_t tryNoteDepth = bytecodeSection().stackDepth();
3582
3583 // A forced return from a `yield` will jump out of the destructuring region,
3584 // so in that case DestructuringControl emits the IteratorClose after the
3585 // loop.
3586 DestructuringControl control(this, selfHostedIter);
3587 control.setNonLocalExitStackDepth(tryNoteDepth);
3588
3589 for (ParseNode* member : pattern->contents()) {
3590 bool isFirst = member == pattern->head();
3591 DebugOnly<bool> hasNext = !!member->pn_next;
3592
3593 ParseNode* subpattern;
3594 if (member->isKind(ParseNodeKind::Spread)) {
3595 subpattern = member->as<UnaryNode>().kid();
3596
3597 MOZ_ASSERT(!subpattern->isKind(ParseNodeKind::AssignExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!subpattern->isKind(ParseNodeKind::AssignExpr))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!subpattern->isKind(ParseNodeKind::AssignExpr))))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("!subpattern->isKind(ParseNodeKind::AssignExpr)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 3597);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!subpattern->isKind(ParseNodeKind::AssignExpr)"
")"); do { MOZ_CrashSequence(__null, 3597); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3598 } else {
3599 subpattern = member;
3600 }
3601
3602 ParseNode* lhsPattern = subpattern;
3603 ParseNode* pndefault = nullptr;
3604 if (subpattern->isKind(ParseNodeKind::AssignExpr)) {
3605 lhsPattern = subpattern->as<AssignmentNode>().left();
3606 pndefault = subpattern->as<AssignmentNode>().right();
3607 }
3608
3609 // Spec requires LHS reference to be evaluated first.
3610 DestructuringLHSRef lref;
3611 bool isElision = lhsPattern->isKind(ParseNodeKind::Elision);
3612 if (!isElision) {
3613 auto emitLHSRef = [lhsPattern, flav, &lref](BytecodeEmitter* bce) {
3614 return bce->emitDestructuringLHSRef(lhsPattern, flav, lref);
3615 // [stack] ... OBJ NEXT ITER DONE LREF*
3616 };
3617 if (!wrapWithDestructuringTryNote(tryNoteDepth, emitLHSRef)) {
3618 return false;
3619 }
3620 }
3621
3622 // Number of stack slots emitted for the LHS reference.
3623 size_t emitted = lref.numReferenceSlots();
3624
3625 // Pick the DONE value to the top of the stack.
3626 if (emitted) {
3627 if (!emitPickN(emitted)) {
3628 // [stack] ... OBJ NEXT ITER LREF* DONE
3629 return false;
3630 }
3631 }
3632
3633 if (isFirst) {
3634 // If this element is the first, DONE is always FALSE, so pop it.
3635 //
3636 // Non-first elements should emit if-else depending on the
3637 // member pattern, below.
3638 if (!emit1(JSOp::Pop)) {
3639 // [stack] ... OBJ NEXT ITER LREF*
3640 return false;
3641 }
3642 }
3643
3644 if (member->isKind(ParseNodeKind::Spread)) {
3645 InternalIfEmitter ifThenElse(this);
3646 if (!isFirst) {
3647 // If spread is not the first element of the pattern,
3648 // iterator can already be completed.
3649 // [stack] ... OBJ NEXT ITER LREF* DONE
3650
3651 if (!ifThenElse.emitThenElse()) {
3652 // [stack] ... OBJ NEXT ITER LREF*
3653 return false;
3654 }
3655
3656 if (!emitUint32Operand(JSOp::NewArray, 0)) {
3657 // [stack] ... OBJ NEXT ITER LREF* ARRAY
3658 return false;
3659 }
3660 if (!ifThenElse.emitElse()) {
3661 // [stack] ... OBJ NEXT ITER LREF*
3662 return false;
3663 }
3664 }
3665
3666 // If iterator is not completed, create a new array with the rest
3667 // of the iterator.
3668 if (!emitDupAt(emitted + 1, 2)) {
3669 // [stack] ... OBJ NEXT ITER LREF* NEXT ITER
3670 return false;
3671 }
3672 if (!emitUint32Operand(JSOp::NewArray, 0)) {
3673 // [stack] ... OBJ NEXT ITER LREF* NEXT ITER ARRAY
3674 return false;
3675 }
3676 if (!emitNumberOp(0)) {
3677 // [stack] ... OBJ NEXT ITER LREF* NEXT ITER ARRAY INDEX
3678 return false;
3679 }
3680 if (!emitSpread(SelfHostedIter::Deny)) {
3681 // [stack] ... OBJ NEXT ITER LREF* ARRAY INDEX
3682 return false;
3683 }
3684 if (!emit1(JSOp::Pop)) {
3685 // [stack] ... OBJ NEXT ITER LREF* ARRAY
3686 return false;
3687 }
3688
3689 if (!isFirst) {
3690 if (!ifThenElse.emitEnd()) {
3691 return false;
3692 }
3693 MOZ_ASSERT(ifThenElse.pushed() == 1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(ifThenElse.pushed() == 1)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(ifThenElse.pushed() == 1))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("ifThenElse.pushed() == 1"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 3693);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "ifThenElse.pushed() == 1"
")"); do { MOZ_CrashSequence(__null, 3693); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3694 }
3695
3696 // At this point the iterator is done. Unpick a TRUE value for DONE above
3697 // ITER.
3698 if (!emit1(JSOp::True)) {
3699 // [stack] ... OBJ NEXT ITER LREF* ARRAY TRUE
3700 return false;
3701 }
3702 if (!emitUnpickN(emitted + 1)) {
3703 // [stack] ... OBJ NEXT ITER TRUE LREF* ARRAY
3704 return false;
3705 }
3706
3707 auto emitAssignment = [lhsPattern, flav, &lref](BytecodeEmitter* bce) {
3708 return bce->emitSetOrInitializeDestructuring(lhsPattern, flav, lref);
3709 // [stack] ... OBJ NEXT ITER TRUE
3710 };
3711 if (!wrapWithDestructuringTryNote(tryNoteDepth, emitAssignment)) {
3712 return false;
3713 }
3714
3715 MOZ_ASSERT(!hasNext)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!hasNext)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!hasNext))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!hasNext", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 3715); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!hasNext" ")"
); do { MOZ_CrashSequence(__null, 3715); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3716 break;
3717 }
3718
3719 InternalIfEmitter ifAlreadyDone(this);
3720 if (!isFirst) {
3721 // [stack] ... OBJ NEXT ITER LREF* DONE
3722
3723 if (!ifAlreadyDone.emitThenElse()) {
3724 // [stack] ... OBJ NEXT ITER LREF*
3725 return false;
3726 }
3727
3728 if (!emit1(JSOp::Undefined)) {
3729 // [stack] ... OBJ NEXT ITER LREF* UNDEF
3730 return false;
3731 }
3732 if (!emit1(JSOp::NopDestructuring)) {
3733 // [stack] ... OBJ NEXT ITER LREF* UNDEF
3734 return false;
3735 }
3736
3737 // The iterator is done. Unpick a TRUE value for DONE above ITER.
3738 if (!emit1(JSOp::True)) {
3739 // [stack] ... OBJ NEXT ITER LREF* UNDEF TRUE
3740 return false;
3741 }
3742 if (!emitUnpickN(emitted + 1)) {
3743 // [stack] ... OBJ NEXT ITER TRUE LREF* UNDEF
3744 return false;
3745 }
3746
3747 if (!ifAlreadyDone.emitElse()) {
3748 // [stack] ... OBJ NEXT ITER LREF*
3749 return false;
3750 }
3751 }
3752
3753 if (!emitDupAt(emitted + 1, 2)) {
3754 // [stack] ... OBJ NEXT ITER LREF* NEXT
3755 return false;
3756 }
3757 if (!emitIteratorNext(Some(pattern->pn_pos.begin), IteratorKind::Sync,
3758 selfHostedIter)) {
3759 // [stack] ... OBJ NEXT ITER LREF* RESULT
3760 return false;
3761 }
3762 if (!emit1(JSOp::Dup)) {
3763 // [stack] ... OBJ NEXT ITER LREF* RESULT RESULT
3764 return false;
3765 }
3766 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::done())) {
3767 // [stack] ... OBJ NEXT ITER LREF* RESULT DONE
3768 return false;
3769 }
3770
3771 if (!emit1(JSOp::Dup)) {
3772 // [stack] ... OBJ NEXT ITER LREF* RESULT DONE DONE
3773 return false;
3774 }
3775 if (!emitUnpickN(emitted + 2)) {
3776 // [stack] ... OBJ NEXT ITER DONE LREF* RESULT DONE
3777 return false;
3778 }
3779
3780 InternalIfEmitter ifDone(this);
3781 if (!ifDone.emitThenElse()) {
3782 // [stack] ... OBJ NEXT ITER DONE LREF* RESULT
3783 return false;
3784 }
3785
3786 if (!emit1(JSOp::Pop)) {
3787 // [stack] ... OBJ NEXT ITER DONE LREF*
3788 return false;
3789 }
3790 if (!emit1(JSOp::Undefined)) {
3791 // [stack] ... OBJ NEXT ITER DONE LREF* UNDEF
3792 return false;
3793 }
3794 if (!emit1(JSOp::NopDestructuring)) {
3795 // [stack] ... OBJ NEXT ITER DONE LREF* UNDEF
3796 return false;
3797 }
3798
3799 if (!ifDone.emitElse()) {
3800 // [stack] ... OBJ NEXT ITER DONE LREF* RESULT
3801 return false;
3802 }
3803
3804 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::value())) {
3805 // [stack] ... OBJ NEXT ITER DONE LREF* VALUE
3806 return false;
3807 }
3808
3809 if (!ifDone.emitEnd()) {
3810 return false;
3811 }
3812 MOZ_ASSERT(ifDone.pushed() == 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(ifDone.pushed() == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(ifDone.pushed() == 0))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("ifDone.pushed() == 0"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 3812);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "ifDone.pushed() == 0"
")"); do { MOZ_CrashSequence(__null, 3812); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3813
3814 if (!isFirst) {
3815 if (!ifAlreadyDone.emitEnd()) {
3816 return false;
3817 }
3818 MOZ_ASSERT(ifAlreadyDone.pushed() == 2)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(ifAlreadyDone.pushed() == 2)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(ifAlreadyDone.pushed() == 2)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("ifAlreadyDone.pushed() == 2"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 3818);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "ifAlreadyDone.pushed() == 2"
")"); do { MOZ_CrashSequence(__null, 3818); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3819 }
3820
3821 if (pndefault) {
3822 auto emitDefault = [pndefault, lhsPattern](BytecodeEmitter* bce) {
3823 return bce->emitDefault(pndefault, lhsPattern);
3824 // [stack] ... OBJ NEXT ITER DONE LREF* VALUE
3825 };
3826
3827 if (!wrapWithDestructuringTryNote(tryNoteDepth, emitDefault)) {
3828 return false;
3829 }
3830 }
3831
3832 if (!isElision) {
3833 auto emitAssignment = [lhsPattern, flav, &lref](BytecodeEmitter* bce) {
3834 return bce->emitSetOrInitializeDestructuring(lhsPattern, flav, lref);
3835 // [stack] ... OBJ NEXT ITER DONE
3836 };
3837
3838 if (!wrapWithDestructuringTryNote(tryNoteDepth, emitAssignment)) {
3839 return false;
3840 }
3841 } else {
3842 if (!emit1(JSOp::Pop)) {
3843 // [stack] ... OBJ NEXT ITER DONE
3844 return false;
3845 }
3846 }
3847 }
3848
3849 // The last DONE value is on top of the stack. If not DONE, call
3850 // IteratorClose.
3851 // [stack] ... OBJ NEXT ITER DONE
3852 if (!control.emitEnd(this)) {
3853 // [stack] ... OBJ
3854 return false;
3855 }
3856
3857 if (ifArrayOptimizable.isSome()) {
3858 if (!ifArrayOptimizable->emitEnd()) {
3859 // [stack] OBJ
3860 return false;
3861 }
3862 }
3863
3864 return true;
3865}
3866
3867bool BytecodeEmitter::emitComputedPropertyName(UnaryNode* computedPropName) {
3868 MOZ_ASSERT(computedPropName->isKind(ParseNodeKind::ComputedName))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(computedPropName->isKind(ParseNodeKind::ComputedName
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(computedPropName->isKind(ParseNodeKind::ComputedName
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("computedPropName->isKind(ParseNodeKind::ComputedName)", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 3868); AnnotateMozCrashReason("MOZ_ASSERT" "(" "computedPropName->isKind(ParseNodeKind::ComputedName)"
")"); do { MOZ_CrashSequence(__null, 3868); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3869 return emitTree(computedPropName->kid()) && emit1(JSOp::ToPropertyKey);
3870}
3871
3872bool BytecodeEmitter::emitDestructuringOpsObject(ListNode* pattern,
3873 DestructuringFlavor flav) {
3874 MOZ_ASSERT(pattern->isKind(ParseNodeKind::ObjectExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pattern->isKind(ParseNodeKind::ObjectExpr))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(pattern->isKind(ParseNodeKind::ObjectExpr)))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("pattern->isKind(ParseNodeKind::ObjectExpr)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 3874);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "pattern->isKind(ParseNodeKind::ObjectExpr)"
")"); do { MOZ_CrashSequence(__null, 3874); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3875
3876 // [stack] ... RHS
3877 MOZ_ASSERT(bytecodeSection().stackDepth() > 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bytecodeSection().stackDepth() > 0)>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(bytecodeSection().stackDepth() > 0))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("bytecodeSection().stackDepth() > 0"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 3877);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() > 0"
")"); do { MOZ_CrashSequence(__null, 3877); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3878
3879 if (!emit1(JSOp::CheckObjCoercible)) {
3880 // [stack] ... RHS
3881 return false;
3882 }
3883
3884 // To understand why we chose '4', please see the discussion on Bug 1948959.
3885 const uint8_t estimatedRestSize = 4;
3886
3887 bool needsRestPropertyExcludedSet =
3888 pattern->count() > 1 && pattern->last()->isKind(ParseNodeKind::Spread);
3889 if (needsRestPropertyExcludedSet) {
3890 if (!emitDestructuringObjRestExclusionSet(pattern, estimatedRestSize)) {
3891 // [stack] ... RHS SET
3892 return false;
3893 }
3894
3895 if (!emit1(JSOp::Swap)) {
3896 // [stack] ... SET RHS
3897 return false;
3898 }
3899 }
3900
3901 for (ParseNode* member : pattern->contents()) {
3902 ParseNode* subpattern;
3903 bool hasKeyOnStack = false;
3904 if (member->isKind(ParseNodeKind::MutateProto) ||
3905 member->isKind(ParseNodeKind::Spread)) {
3906 subpattern = member->as<UnaryNode>().kid();
3907
3908 MOZ_ASSERT_IF(member->isKind(ParseNodeKind::Spread),do { if (member->isKind(ParseNodeKind::Spread)) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(!subpattern
->isKind(ParseNodeKind::AssignExpr))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!subpattern->isKind(ParseNodeKind
::AssignExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!subpattern->isKind(ParseNodeKind::AssignExpr)", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 3909); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!subpattern->isKind(ParseNodeKind::AssignExpr)"
")"); do { MOZ_CrashSequence(__null, 3909); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3909 !subpattern->isKind(ParseNodeKind::AssignExpr))do { if (member->isKind(ParseNodeKind::Spread)) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(!subpattern
->isKind(ParseNodeKind::AssignExpr))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!subpattern->isKind(ParseNodeKind
::AssignExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!subpattern->isKind(ParseNodeKind::AssignExpr)", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 3909); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!subpattern->isKind(ParseNodeKind::AssignExpr)"
")"); do { MOZ_CrashSequence(__null, 3909); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
3910 } else {
3911 MOZ_ASSERT(member->isKind(ParseNodeKind::PropertyDefinition) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(member->isKind(ParseNodeKind::PropertyDefinition)
|| member->isKind(ParseNodeKind::Shorthand))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(member->isKind(ParseNodeKind::PropertyDefinition) || member
->isKind(ParseNodeKind::Shorthand)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 3912);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)"
")"); do { MOZ_CrashSequence(__null, 3912); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3912 member->isKind(ParseNodeKind::Shorthand))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(member->isKind(ParseNodeKind::PropertyDefinition)
|| member->isKind(ParseNodeKind::Shorthand))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(member->isKind(ParseNodeKind::PropertyDefinition) || member
->isKind(ParseNodeKind::Shorthand)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 3912);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)"
")"); do { MOZ_CrashSequence(__null, 3912); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3913 subpattern = member->as<BinaryNode>().right();
3914
3915 // Computed property names are evaluated before the subpattern.
3916 ParseNode* key = member->as<BinaryNode>().left();
3917 if (key->isKind(ParseNodeKind::ComputedName)) {
3918 if (!emitComputedPropertyName(&key->as<UnaryNode>())) {
3919 // [stack] ... SET? RHS KEY
3920 return false;
3921 }
3922 hasKeyOnStack = true;
3923 }
3924 }
3925
3926 ParseNode* lhs = subpattern;
3927 ParseNode* pndefault = nullptr;
3928 if (subpattern->isKind(ParseNodeKind::AssignExpr)) {
3929 lhs = subpattern->as<AssignmentNode>().left();
3930 pndefault = subpattern->as<AssignmentNode>().right();
3931 }
3932
3933 // Spec requires LHS reference to be evaluated first.
3934 DestructuringLHSRef lref;
3935 if (!emitDestructuringLHSRef(lhs, flav, lref)) {
3936 // [stack] ... SET? RHS KEY? LREF*
3937 return false;
3938 }
3939
3940 // Number of stack slots emitted for the LHS reference.
3941 size_t emitted = lref.numReferenceSlots();
3942
3943 // Duplicate the value being destructured to use as a reference base.
3944 if (!emitDupAt(emitted + hasKeyOnStack)) {
3945 // [stack] ... SET? RHS KEY? LREF* RHS
3946 return false;
3947 }
3948
3949 if (member->isKind(ParseNodeKind::Spread)) {
3950 if (!updateSourceCoordNotes(member->pn_pos.begin)) {
3951 return false;
3952 }
3953
3954 if (!emit2(JSOp::NewInit, estimatedRestSize)) {
3955 // [stack] ... SET? RHS LREF* RHS TARGET
3956 return false;
3957 }
3958 if (!emit1(JSOp::Dup)) {
3959 // [stack] ... SET? RHS LREF* RHS TARGET TARGET
3960 return false;
3961 }
3962 if (!emit2(JSOp::Pick, 2)) {
3963 // [stack] ... SET? RHS LREF* TARGET TARGET RHS
3964 return false;
3965 }
3966
3967 if (needsRestPropertyExcludedSet) {
3968 if (!emit2(JSOp::Pick, emitted + 4)) {
3969 // [stack] ... RHS LREF* TARGET TARGET RHS SET
3970 return false;
3971 }
3972 }
3973
3974 CopyOption option = needsRestPropertyExcludedSet ? CopyOption::Filtered
3975 : CopyOption::Unfiltered;
3976 if (!emitCopyDataProperties(option)) {
3977 // [stack] ... RHS LREF* TARGET
3978 return false;
3979 }
3980
3981 // Destructure TARGET per this member's lhs.
3982 if (!emitSetOrInitializeDestructuring(lhs, flav, lref)) {
3983 // [stack] ... RHS
3984 return false;
3985 }
3986
3987 MOZ_ASSERT(member == pattern->last(), "Rest property is always last")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(member == pattern->last())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(member == pattern->last()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"member == pattern->last()" " (" "Rest property is always last"
")", "./../../../../js/src/frontend/BytecodeEmitter.cpp", 3987
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "member == pattern->last()"
") (" "Rest property is always last" ")"); do { MOZ_CrashSequence
(__null, 3987); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3988 break;
3989 }
3990
3991 // Now push the property value currently being matched, which is the value
3992 // of the current property name "label" on the left of a colon in the object
3993 // initialiser.
3994 if (member->isKind(ParseNodeKind::MutateProto)) {
3995 if (!emitAtomOp(JSOp::GetProp,
3996 TaggedParserAtomIndex::WellKnown::proto_())) {
3997 // [stack] ... SET? RHS LREF* PROP
3998 return false;
3999 }
4000 } else {
4001 MOZ_ASSERT(member->isKind(ParseNodeKind::PropertyDefinition) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(member->isKind(ParseNodeKind::PropertyDefinition)
|| member->isKind(ParseNodeKind::Shorthand))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(member->isKind(ParseNodeKind::PropertyDefinition) || member
->isKind(ParseNodeKind::Shorthand)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 4002);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)"
")"); do { MOZ_CrashSequence(__null, 4002); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4002 member->isKind(ParseNodeKind::Shorthand))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(member->isKind(ParseNodeKind::PropertyDefinition)
|| member->isKind(ParseNodeKind::Shorthand))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(member->isKind(ParseNodeKind::PropertyDefinition) || member
->isKind(ParseNodeKind::Shorthand)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 4002);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)"
")"); do { MOZ_CrashSequence(__null, 4002); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4003
4004 ParseNode* key = member->as<BinaryNode>().left();
4005 if (key->isKind(ParseNodeKind::ObjectPropertyName) ||
4006 key->isKind(ParseNodeKind::StringExpr)) {
4007 if (!emitAtomOp(JSOp::GetProp, key->as<NameNode>().atom())) {
4008 // [stack] ... SET? RHS LREF* PROP
4009 return false;
4010 }
4011 } else {
4012 if (key->isKind(ParseNodeKind::NumberExpr)) {
4013 if (!emitNumberOp(key->as<NumericLiteral>().value())) {
4014 // [stack]... SET? RHS LREF* RHS KEY
4015 return false;
4016 }
4017 } else {
4018 // Otherwise this is a computed property name. BigInt keys are parsed
4019 // as (synthetic) computed property names, too.
4020 MOZ_ASSERT(key->isKind(ParseNodeKind::ComputedName))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(key->isKind(ParseNodeKind::ComputedName))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(key->isKind(ParseNodeKind::ComputedName)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("key->isKind(ParseNodeKind::ComputedName)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 4020);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::ComputedName)"
")"); do { MOZ_CrashSequence(__null, 4020); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4021 MOZ_ASSERT(hasKeyOnStack)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(hasKeyOnStack)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(hasKeyOnStack))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("hasKeyOnStack",
"./../../../../js/src/frontend/BytecodeEmitter.cpp", 4021); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "hasKeyOnStack" ")"); do { MOZ_CrashSequence
(__null, 4021); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4022
4023 if (!emit2(JSOp::Pick, emitted + 1)) {
4024 // [stack] ... SET? RHS LREF* RHS KEY
4025 return false;
4026 }
4027
4028 // Add the computed property key to the exclusion set.
4029 if (needsRestPropertyExcludedSet) {
4030 if (!emitDupAt(emitted + 3)) {
4031 // [stack] ... SET RHS LREF* RHS KEY SET
4032 return false;
4033 }
4034 if (!emitDupAt(1)) {
4035 // [stack] ... SET RHS LREF* RHS KEY SET KEY
4036 return false;
4037 }
4038 if (!emit1(JSOp::Undefined)) {
4039 // [stack] ... SET RHS LREF* RHS KEY SET KEY UNDEFINED
4040 return false;
4041 }
4042 if (!emit1(JSOp::InitElem)) {
4043 // [stack] ... SET RHS LREF* RHS KEY SET
4044 return false;
4045 }
4046 if (!emit1(JSOp::Pop)) {
4047 // [stack] ... SET RHS LREF* RHS KEY
4048 return false;
4049 }
4050 }
4051 }
4052
4053 // Get the property value.
4054 if (!emitElemOpBase(JSOp::GetElem)) {
4055 // [stack] ... SET? RHS LREF* PROP
4056 return false;
4057 }
4058 }
4059 }
4060
4061 if (pndefault) {
4062 if (!emitDefault(pndefault, lhs)) {
4063 // [stack] ... SET? RHS LREF* VALUE
4064 return false;
4065 }
4066 }
4067
4068 // Destructure PROP per this member's lhs.
4069 if (!emitSetOrInitializeDestructuring(lhs, flav, lref)) {
4070 // [stack] ... SET? RHS
4071 return false;
4072 }
4073 }
4074
4075 return true;
4076}
4077
4078static bool IsDestructuringRestExclusionSetObjLiteralCompatible(
4079 ListNode* pattern) {
4080 uint32_t propCount = 0;
4081 for (ParseNode* member : pattern->contents()) {
4082 if (member->isKind(ParseNodeKind::Spread)) {
4083 MOZ_ASSERT(!member->pn_next, "unexpected trailing element after spread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!member->pn_next)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!member->pn_next))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("!member->pn_next"
" (" "unexpected trailing element after spread" ")", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 4083); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!member->pn_next"
") (" "unexpected trailing element after spread" ")"); do { MOZ_CrashSequence
(__null, 4083); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4084 break;
4085 }
4086
4087 propCount++;
4088
4089 if (member->isKind(ParseNodeKind::MutateProto)) {
4090 continue;
4091 }
4092
4093 ParseNode* key = member->as<BinaryNode>().left();
4094 if (key->isKind(ParseNodeKind::ObjectPropertyName) ||
4095 key->isKind(ParseNodeKind::StringExpr)) {
4096 continue;
4097 }
4098
4099 // Number and BigInt keys aren't yet supported. Computed property names need
4100 // to be added dynamically.
4101 MOZ_ASSERT(key->isKind(ParseNodeKind::NumberExpr) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(key->isKind(ParseNodeKind::NumberExpr) || key->
isKind(ParseNodeKind::BigIntExpr) || key->isKind(ParseNodeKind
::ComputedName))>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(key->isKind(ParseNodeKind::
NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr) || key
->isKind(ParseNodeKind::ComputedName)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr) || key->isKind(ParseNodeKind::ComputedName)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 4103);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr) || key->isKind(ParseNodeKind::ComputedName)"
")"); do { MOZ_CrashSequence(__null, 4103); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4102 key->isKind(ParseNodeKind::BigIntExpr) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(key->isKind(ParseNodeKind::NumberExpr) || key->
isKind(ParseNodeKind::BigIntExpr) || key->isKind(ParseNodeKind
::ComputedName))>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(key->isKind(ParseNodeKind::
NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr) || key
->isKind(ParseNodeKind::ComputedName)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr) || key->isKind(ParseNodeKind::ComputedName)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 4103);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr) || key->isKind(ParseNodeKind::ComputedName)"
")"); do { MOZ_CrashSequence(__null, 4103); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4103 key->isKind(ParseNodeKind::ComputedName))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(key->isKind(ParseNodeKind::NumberExpr) || key->
isKind(ParseNodeKind::BigIntExpr) || key->isKind(ParseNodeKind
::ComputedName))>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(key->isKind(ParseNodeKind::
NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr) || key
->isKind(ParseNodeKind::ComputedName)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr) || key->isKind(ParseNodeKind::ComputedName)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 4103);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr) || key->isKind(ParseNodeKind::ComputedName)"
")"); do { MOZ_CrashSequence(__null, 4103); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4104 return false;
4105 }
4106
4107 if (propCount > SharedPropMap::MaxPropsForNonDictionary) {
4108 // JSOp::NewObject cannot accept dictionary-mode objects.
4109 return false;
4110 }
4111
4112 return true;
4113}
4114
4115bool BytecodeEmitter::emitDestructuringObjRestExclusionSet(
4116 ListNode* pattern, uint8_t estimatedRestSize) {
4117 MOZ_ASSERT(pattern->isKind(ParseNodeKind::ObjectExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pattern->isKind(ParseNodeKind::ObjectExpr))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(pattern->isKind(ParseNodeKind::ObjectExpr)))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("pattern->isKind(ParseNodeKind::ObjectExpr)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 4117);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "pattern->isKind(ParseNodeKind::ObjectExpr)"
")"); do { MOZ_CrashSequence(__null, 4117); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4118 MOZ_ASSERT(pattern->last()->isKind(ParseNodeKind::Spread))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pattern->last()->isKind(ParseNodeKind::Spread)
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(pattern->last()->isKind(ParseNodeKind::Spread)
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"pattern->last()->isKind(ParseNodeKind::Spread)", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 4118); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pattern->last()->isKind(ParseNodeKind::Spread)"
")"); do { MOZ_CrashSequence(__null, 4118); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4119
4120 // See if we can use ObjLiteral to construct the exclusion set object.
4121 if (IsDestructuringRestExclusionSetObjLiteralCompatible(pattern)) {
4122 if (!emitDestructuringRestExclusionSetObjLiteral(pattern)) {
4123 // [stack] OBJ
4124 return false;
4125 }
4126 } else {
4127 // Take the slow but sure way and start off with a blank object.
4128 if (!emit2(JSOp::NewInit, estimatedRestSize)) {
4129 // [stack] OBJ
4130 return false;
4131 }
4132 }
4133
4134 for (ParseNode* member : pattern->contents()) {
4135 if (member->isKind(ParseNodeKind::Spread)) {
4136 MOZ_ASSERT(!member->pn_next, "unexpected trailing element after spread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!member->pn_next)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!member->pn_next))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("!member->pn_next"
" (" "unexpected trailing element after spread" ")", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 4136); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!member->pn_next"
") (" "unexpected trailing element after spread" ")"); do { MOZ_CrashSequence
(__null, 4136); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4137 break;
4138 }
4139
4140 TaggedParserAtomIndex pnatom;
4141 if (member->isKind(ParseNodeKind::MutateProto)) {
4142 pnatom = TaggedParserAtomIndex::WellKnown::proto_();
4143 } else {
4144 ParseNode* key = member->as<BinaryNode>().left();
4145 if (key->isKind(ParseNodeKind::ObjectPropertyName) ||
4146 key->isKind(ParseNodeKind::StringExpr)) {
4147 pnatom = key->as<NameNode>().atom();
4148 } else if (key->isKind(ParseNodeKind::NumberExpr)) {
4149 if (!emitNumberOp(key->as<NumericLiteral>().value())) {
4150 return false;
4151 }
4152 } else {
4153 // Otherwise this is a computed property name which needs to be added
4154 // dynamically. BigInt keys are parsed as (synthetic) computed property
4155 // names, too.
4156 MOZ_ASSERT(key->isKind(ParseNodeKind::ComputedName))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(key->isKind(ParseNodeKind::ComputedName))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(key->isKind(ParseNodeKind::ComputedName)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("key->isKind(ParseNodeKind::ComputedName)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 4156);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::ComputedName)"
")"); do { MOZ_CrashSequence(__null, 4156); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4157 continue;
4158 }
4159 }
4160
4161 // Initialize elements with |undefined|.
4162 if (!emit1(JSOp::Undefined)) {
4163 return false;
4164 }
4165
4166 if (!pnatom) {
4167 if (!emit1(JSOp::InitElem)) {
4168 return false;
4169 }
4170 } else {
4171 if (!emitAtomOp(JSOp::InitProp, pnatom)) {
4172 return false;
4173 }
4174 }
4175 }
4176
4177 return true;
4178}
4179
4180bool BytecodeEmitter::emitDestructuringOps(ListNode* pattern,
4181 DestructuringFlavor flav,
4182 SelfHostedIter selfHostedIter) {
4183 if (pattern->isKind(ParseNodeKind::ArrayExpr)) {
4184 return emitDestructuringOpsArray(pattern, flav, selfHostedIter);
4185 }
4186 return emitDestructuringOpsObject(pattern, flav);
4187}
4188
4189bool BytecodeEmitter::emitTemplateString(ListNode* templateString) {
4190 bool pushedString = false;
4191
4192 for (ParseNode* item : templateString->contents()) {
4193 bool isString = (item->getKind() == ParseNodeKind::StringExpr ||
4194 item->getKind() == ParseNodeKind::TemplateStringExpr);
4195
4196 // Skip empty strings. These are very common: a template string like
4197 // `${a}${b}` has three empty strings and without this optimization
4198 // we'd emit four JSOp::Add operations instead of just one.
4199 if (isString && item->as<NameNode>().atom() ==
4200 TaggedParserAtomIndex::WellKnown::empty()) {
4201 continue;
4202 }
4203
4204 if (!isString) {
4205 // We update source notes before emitting the expression
4206 if (!updateSourceCoordNotes(item->pn_pos.begin)) {
4207 return false;
4208 }
4209 }
4210
4211 if (!emitTree(item)) {
4212 return false;
4213 }
4214
4215 if (!isString) {
4216 // We need to convert the expression to a string
4217 if (!emit1(JSOp::ToString)) {
4218 return false;
4219 }
4220 }
4221
4222 if (pushedString) {
4223 // We've pushed two strings onto the stack. Add them together, leaving
4224 // just one.
4225 if (!emit1(JSOp::Add)) {
4226 return false;
4227 }
4228 } else {
4229 pushedString = true;
4230 }
4231 }
4232
4233 if (!pushedString) {
4234 // All strings were empty, this can happen for something like `${""}`.
4235 // Just push an empty string.
4236 if (!emitStringOp(JSOp::String,
4237 TaggedParserAtomIndex::WellKnown::empty())) {
4238 return false;
4239 }
4240 }
4241
4242 return true;
4243}
4244
4245bool BytecodeEmitter::emitDeclarationList(ListNode* declList) {
4246 for (ParseNode* decl : declList->contents()) {
4247 ParseNode* pattern;
4248 ParseNode* initializer;
4249 if (decl->isKind(ParseNodeKind::Name)) {
4250 pattern = decl;
4251 initializer = nullptr;
4252 } else {
4253 AssignmentNode* assignNode = &decl->as<AssignmentNode>();
4254 pattern = assignNode->left();
4255 initializer = assignNode->right();
4256 }
4257
4258 if (pattern->isKind(ParseNodeKind::Name)) {
4259 // initializer can be null here.
4260 if (!emitSingleDeclaration(declList, &pattern->as<NameNode>(),
4261 initializer)) {
4262 return false;
4263 }
4264 } else {
4265 MOZ_ASSERT(pattern->isKind(ParseNodeKind::ArrayExpr) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pattern->isKind(ParseNodeKind::ArrayExpr) || pattern
->isKind(ParseNodeKind::ObjectExpr))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pattern->isKind(ParseNodeKind
::ArrayExpr) || pattern->isKind(ParseNodeKind::ObjectExpr)
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"pattern->isKind(ParseNodeKind::ArrayExpr) || pattern->isKind(ParseNodeKind::ObjectExpr)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 4266);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "pattern->isKind(ParseNodeKind::ArrayExpr) || pattern->isKind(ParseNodeKind::ObjectExpr)"
")"); do { MOZ_CrashSequence(__null, 4266); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4266 pattern->isKind(ParseNodeKind::ObjectExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pattern->isKind(ParseNodeKind::ArrayExpr) || pattern
->isKind(ParseNodeKind::ObjectExpr))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pattern->isKind(ParseNodeKind
::ArrayExpr) || pattern->isKind(ParseNodeKind::ObjectExpr)
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"pattern->isKind(ParseNodeKind::ArrayExpr) || pattern->isKind(ParseNodeKind::ObjectExpr)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 4266);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "pattern->isKind(ParseNodeKind::ArrayExpr) || pattern->isKind(ParseNodeKind::ObjectExpr)"
")"); do { MOZ_CrashSequence(__null, 4266); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4267 MOZ_ASSERT(initializer != nullptr)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(initializer != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(initializer != nullptr))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("initializer != nullptr"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 4267);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "initializer != nullptr"
")"); do { MOZ_CrashSequence(__null, 4267); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4268
4269 if (!updateSourceCoordNotes(initializer->pn_pos.begin)) {
4270 return false;
4271 }
4272 if (!markStepBreakpoint()) {
4273 return false;
4274 }
4275 if (!emitTree(initializer)) {
4276 return false;
4277 }
4278
4279 if (!emitDestructuringOps(&pattern->as<ListNode>(),
4280 DestructuringFlavor::Declaration,
4281 getSelfHostedIterFor(initializer))) {
4282 return false;
4283 }
4284
4285 if (!emit1(JSOp::Pop)) {
4286 return false;
4287 }
4288 }
4289 }
4290 return true;
4291}
4292
4293bool BytecodeEmitter::emitSingleDeclaration(ListNode* declList, NameNode* decl,
4294 ParseNode* initializer) {
4295 MOZ_ASSERT(decl->isKind(ParseNodeKind::Name))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(decl->isKind(ParseNodeKind::Name))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(decl->isKind(ParseNodeKind
::Name)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("decl->isKind(ParseNodeKind::Name)", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 4295); AnnotateMozCrashReason("MOZ_ASSERT" "(" "decl->isKind(ParseNodeKind::Name)"
")"); do { MOZ_CrashSequence(__null, 4295); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4296
4297 // Nothing to do for initializer-less 'var' declarations, as there's no TDZ.
4298 if (!initializer && declList->isKind(ParseNodeKind::VarStmt)) {
4299 return true;
4300 }
4301
4302 auto nameAtom = decl->name();
4303 NameOpEmitter noe(this, nameAtom, NameOpEmitter::Kind::Initialize);
4304 if (!noe.prepareForRhs()) {
4305 // [stack] ENV?
4306 return false;
4307 }
4308 if (!initializer) {
4309 // Lexical declarations are initialized to undefined without an
4310 // initializer.
4311 MOZ_ASSERT(declList->isKind(ParseNodeKind::LetDecl),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(declList->isKind(ParseNodeKind::LetDecl))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(declList->isKind(ParseNodeKind::LetDecl)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("declList->isKind(ParseNodeKind::LetDecl)"
" (" "var declarations without initializers handled above, "
"and const declarations must have initializers" ")", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 4313); AnnotateMozCrashReason("MOZ_ASSERT" "(" "declList->isKind(ParseNodeKind::LetDecl)"
") (" "var declarations without initializers handled above, "
"and const declarations must have initializers" ")"); do { MOZ_CrashSequence
(__null, 4313); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
4312 "var declarations without initializers handled above, "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(declList->isKind(ParseNodeKind::LetDecl))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(declList->isKind(ParseNodeKind::LetDecl)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("declList->isKind(ParseNodeKind::LetDecl)"
" (" "var declarations without initializers handled above, "
"and const declarations must have initializers" ")", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 4313); AnnotateMozCrashReason("MOZ_ASSERT" "(" "declList->isKind(ParseNodeKind::LetDecl)"
") (" "var declarations without initializers handled above, "
"and const declarations must have initializers" ")"); do { MOZ_CrashSequence
(__null, 4313); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
4313 "and const declarations must have initializers")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(declList->isKind(ParseNodeKind::LetDecl))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(declList->isKind(ParseNodeKind::LetDecl)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("declList->isKind(ParseNodeKind::LetDecl)"
" (" "var declarations without initializers handled above, "
"and const declarations must have initializers" ")", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 4313); AnnotateMozCrashReason("MOZ_ASSERT" "(" "declList->isKind(ParseNodeKind::LetDecl)"
") (" "var declarations without initializers handled above, "
"and const declarations must have initializers" ")"); do { MOZ_CrashSequence
(__null, 4313); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4314 if (!emit1(JSOp::Undefined)) {
4315 // [stack] ENV? UNDEF
4316 return false;
4317 }
4318 } else {
4319 MOZ_ASSERT(initializer)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(initializer)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(initializer))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("initializer", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 4319); AnnotateMozCrashReason("MOZ_ASSERT" "(" "initializer"
")"); do { MOZ_CrashSequence(__null, 4319); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4320
4321 if (!updateSourceCoordNotes(initializer->pn_pos.begin)) {
4322 return false;
4323 }
4324 if (!markStepBreakpoint()) {
4325 return false;
4326 }
4327 if (!emitInitializer(initializer, decl)) {
4328 // [stack] ENV? V
4329 return false;
4330 }
4331 }
4332
4333 if (declList->isKind(ParseNodeKind::UsingDecl)) {
4334 if (!innermostEmitterScope()->prepareForDisposableAssignment(
4335 UsingHint::Sync)) {
4336 // [stack] ENV? V
4337 return false;
4338 }
4339 } else if (declList->isKind(ParseNodeKind::AwaitUsingDecl)) {
4340 if (!innermostEmitterScope()->prepareForDisposableAssignment(
4341 UsingHint::Async)) {
4342 // [stack] ENV? V
4343 return false;
4344 }
4345 }
4346
4347 if (!noe.emitAssignment()) {
4348 // [stack] V
4349 return false;
4350 }
4351
4352 if (!emit1(JSOp::Pop)) {
4353 // [stack]
4354 return false;
4355 }
4356
4357 return true;
4358}
4359
4360bool BytecodeEmitter::emitAssignmentRhs(
4361 ParseNode* rhs, TaggedParserAtomIndex anonFunctionName) {
4362 if (rhs->isDirectRHSAnonFunction()) {
4363 if (anonFunctionName) {
4364 return emitAnonymousFunctionWithName(rhs, anonFunctionName);
4365 }
4366 return emitAnonymousFunctionWithComputedName(rhs, FunctionPrefixKind::None);
4367 }
4368 return emitTree(rhs);
4369}
4370
4371// The RHS value to assign is already on the stack, i.e., the next enumeration
4372// value in a for-in or for-of loop. Offset is the location in the stack of the
4373// already-emitted rhs. If we emitted a JSOp::BindUnqualifiedName or
4374// JSOp::BindUnqualifiedGName, then the scope is on the top of the stack and we
4375// need to dig one deeper to get the right RHS value.
4376bool BytecodeEmitter::emitAssignmentRhs(uint8_t offset) {
4377 if (offset != 1) {
4378 return emitPickN(offset - 1);
4379 }
4380
4381 return true;
4382}
4383
4384static inline JSOp CompoundAssignmentParseNodeKindToJSOp(ParseNodeKind pnk) {
4385 switch (pnk) {
4386 case ParseNodeKind::InitExpr:
4387 return JSOp::Nop;
4388 case ParseNodeKind::AssignExpr:
4389 return JSOp::Nop;
4390 case ParseNodeKind::AddAssignExpr:
4391 return JSOp::Add;
4392 case ParseNodeKind::SubAssignExpr:
4393 return JSOp::Sub;
4394 case ParseNodeKind::BitOrAssignExpr:
4395 return JSOp::BitOr;
4396 case ParseNodeKind::BitXorAssignExpr:
4397 return JSOp::BitXor;
4398 case ParseNodeKind::BitAndAssignExpr:
4399 return JSOp::BitAnd;
4400 case ParseNodeKind::LshAssignExpr:
4401 return JSOp::Lsh;
4402 case ParseNodeKind::RshAssignExpr:
4403 return JSOp::Rsh;
4404 case ParseNodeKind::UrshAssignExpr:
4405 return JSOp::Ursh;
4406 case ParseNodeKind::MulAssignExpr:
4407 return JSOp::Mul;
4408 case ParseNodeKind::DivAssignExpr:
4409 return JSOp::Div;
4410 case ParseNodeKind::ModAssignExpr:
4411 return JSOp::Mod;
4412 case ParseNodeKind::PowAssignExpr:
4413 return JSOp::Pow;
4414 case ParseNodeKind::CoalesceAssignExpr:
4415 case ParseNodeKind::OrAssignExpr:
4416 case ParseNodeKind::AndAssignExpr:
4417 // Short-circuit assignment operators are handled elsewhere.
4418 [[fallthrough]];
4419 default:
4420 MOZ_CRASH("unexpected compound assignment op")do { do { } while (false); MOZ_ReportCrash("" "unexpected compound assignment op"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 4420);
AnnotateMozCrashReason("MOZ_CRASH(" "unexpected compound assignment op"
")"); do { MOZ_CrashSequence(__null, 4420); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
4421 }
4422}
4423
4424bool BytecodeEmitter::emitAssignmentOrInit(ParseNodeKind kind, ParseNode* lhs,
4425 ParseNode* rhs) {
4426 JSOp compoundOp = CompoundAssignmentParseNodeKindToJSOp(kind);
4427 bool isCompound = compoundOp != JSOp::Nop;
4428 bool isInit = kind == ParseNodeKind::InitExpr;
4429
4430 // We estimate the number of properties this could create
4431 // if used as constructor merely by counting this.foo = assignment
4432 // or init expressions;
4433 //
4434 // This currently doesn't handle this[x] = foo;
4435 if (isInit || kind == ParseNodeKind::AssignExpr) {
4436 if (lhs->isKind(ParseNodeKind::DotExpr)) {
4437 if (lhs->as<PropertyAccess>().expression().isKind(
4438 ParseNodeKind::ThisExpr)) {
4439 propertyAdditionEstimate++;
4440 }
4441 }
4442 }
4443
4444 MOZ_ASSERT_IF(isInit, lhs->isKind(ParseNodeKind::DotExpr) ||do { if (isInit) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(lhs->isKind(ParseNodeKind::DotExpr) || lhs->
isKind(ParseNodeKind::ElemExpr) || lhs->isKind(ParseNodeKind
::PrivateMemberExpr))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(lhs->isKind(ParseNodeKind
::DotExpr) || lhs->isKind(ParseNodeKind::ElemExpr) || lhs->
isKind(ParseNodeKind::PrivateMemberExpr)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("lhs->isKind(ParseNodeKind::DotExpr) || lhs->isKind(ParseNodeKind::ElemExpr) || lhs->isKind(ParseNodeKind::PrivateMemberExpr)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 4446);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "lhs->isKind(ParseNodeKind::DotExpr) || lhs->isKind(ParseNodeKind::ElemExpr) || lhs->isKind(ParseNodeKind::PrivateMemberExpr)"
")"); do { MOZ_CrashSequence(__null, 4446); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4445 lhs->isKind(ParseNodeKind::ElemExpr) ||do { if (isInit) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(lhs->isKind(ParseNodeKind::DotExpr) || lhs->
isKind(ParseNodeKind::ElemExpr) || lhs->isKind(ParseNodeKind
::PrivateMemberExpr))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(lhs->isKind(ParseNodeKind
::DotExpr) || lhs->isKind(ParseNodeKind::ElemExpr) || lhs->
isKind(ParseNodeKind::PrivateMemberExpr)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("lhs->isKind(ParseNodeKind::DotExpr) || lhs->isKind(ParseNodeKind::ElemExpr) || lhs->isKind(ParseNodeKind::PrivateMemberExpr)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 4446);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "lhs->isKind(ParseNodeKind::DotExpr) || lhs->isKind(ParseNodeKind::ElemExpr) || lhs->isKind(ParseNodeKind::PrivateMemberExpr)"
")"); do { MOZ_CrashSequence(__null, 4446); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4446 lhs->isKind(ParseNodeKind::PrivateMemberExpr))do { if (isInit) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(lhs->isKind(ParseNodeKind::DotExpr) || lhs->
isKind(ParseNodeKind::ElemExpr) || lhs->isKind(ParseNodeKind
::PrivateMemberExpr))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(lhs->isKind(ParseNodeKind
::DotExpr) || lhs->isKind(ParseNodeKind::ElemExpr) || lhs->
isKind(ParseNodeKind::PrivateMemberExpr)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("lhs->isKind(ParseNodeKind::DotExpr) || lhs->isKind(ParseNodeKind::ElemExpr) || lhs->isKind(ParseNodeKind::PrivateMemberExpr)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 4446);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "lhs->isKind(ParseNodeKind::DotExpr) || lhs->isKind(ParseNodeKind::ElemExpr) || lhs->isKind(ParseNodeKind::PrivateMemberExpr)"
")"); do { MOZ_CrashSequence(__null, 4446); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4447
4448 // |name| is used within NameOpEmitter, so its lifetime must surpass |noe|.
4449 TaggedParserAtomIndex name;
4450
4451 Maybe<NameOpEmitter> noe;
4452 Maybe<PropOpEmitter> poe;
4453 Maybe<ElemOpEmitter> eoe;
4454 Maybe<PrivateOpEmitter> xoe;
4455
4456 // Deal with non-name assignments.
4457 uint8_t offset = 1;
4458
4459 // Purpose of anonFunctionName:
4460 //
4461 // In normal name assignments (`f = function(){}`), an anonymous function gets
4462 // an inferred name based on the left-hand side name node.
4463 //
4464 // In normal property assignments (`obj.x = function(){}`), the anonymous
4465 // function does not have a computed name, and rhs->isDirectRHSAnonFunction()
4466 // will be false (and anonFunctionName will not be used). However, in field
4467 // initializers (`class C { x = function(){} }`), field initialization is
4468 // implemented via a property or elem assignment (where we are now), and
4469 // rhs->isDirectRHSAnonFunction() is set - so we'll assign the name of the
4470 // function.
4471 TaggedParserAtomIndex anonFunctionName;
4472
4473 switch (lhs->getKind()) {
4474 case ParseNodeKind::Name: {
4475 name = lhs->as<NameNode>().name();
4476 anonFunctionName = name;
4477 noe.emplace(this, name,
4478 isCompound ? NameOpEmitter::Kind::CompoundAssignment
4479 : NameOpEmitter::Kind::SimpleAssignment);
4480 break;
4481 }
4482 case ParseNodeKind::ArgumentsLength:
4483 case ParseNodeKind::DotExpr: {
4484 NonOptionalPropertyAccessBase* prop =
4485 &lhs->as<NonOptionalPropertyAccessBase>();
4486 bool isSuper = prop->isSuper();
4487 poe.emplace(this,
4488 isCompound ? PropOpEmitter::Kind::CompoundAssignment
4489 : isInit ? PropOpEmitter::Kind::PropInit
4490 : PropOpEmitter::Kind::SimpleAssignment,
4491 isSuper ? PropOpEmitter::ObjKind::Super
4492 : PropOpEmitter::ObjKind::Other);
4493 if (!poe->prepareForObj()) {
4494 return false;
4495 }
4496 anonFunctionName = prop->name();
4497 if (isSuper) {
4498 UnaryNode* base = &prop->expression().as<UnaryNode>();
4499 if (!emitGetThisForSuperBase(base)) {
4500 // [stack] THIS SUPERBASE
4501 return false;
4502 }
4503 // SUPERBASE is pushed onto THIS later in poe->emitGet below.
4504 offset += 2;
4505 } else {
4506 if (!emitTree(&prop->expression())) {
4507 // [stack] OBJ
4508 return false;
4509 }
4510 offset += 1;
4511 }
4512 break;
4513 }
4514 case ParseNodeKind::ElemExpr: {
4515 PropertyByValue* elem = &lhs->as<PropertyByValue>();
4516 bool isSuper = elem->isSuper();
4517 MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!elem->key().isKind(ParseNodeKind::PrivateName))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!elem->key().isKind(ParseNodeKind::PrivateName)))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!elem->key().isKind(ParseNodeKind::PrivateName)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 4517);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)"
")"); do { MOZ_CrashSequence(__null, 4517); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4518 eoe.emplace(this,
4519 isCompound ? ElemOpEmitter::Kind::CompoundAssignment
4520 : isInit ? ElemOpEmitter::Kind::PropInit
4521 : ElemOpEmitter::Kind::SimpleAssignment,
4522 isSuper ? ElemOpEmitter::ObjKind::Super
4523 : ElemOpEmitter::ObjKind::Other);
4524 if (!emitElemObjAndKey(elem, *eoe)) {
4525 // [stack] # if Super
4526 // [stack] THIS KEY
4527 // [stack] # otherwise
4528 // [stack] OBJ KEY
4529 return false;
4530 }
4531 if (isSuper) {
4532 // SUPERBASE is pushed onto KEY in eoe->emitGet below.
4533 offset += 3;
4534 } else {
4535 offset += 2;
4536 }
4537 break;
4538 }
4539 case ParseNodeKind::PrivateMemberExpr: {
4540 PrivateMemberAccess* privateExpr = &lhs->as<PrivateMemberAccess>();
4541 xoe.emplace(this,
4542 isCompound ? PrivateOpEmitter::Kind::CompoundAssignment
4543 : isInit ? PrivateOpEmitter::Kind::PropInit
4544 : PrivateOpEmitter::Kind::SimpleAssignment,
4545 privateExpr->privateName().name());
4546 if (!emitTree(&privateExpr->expression())) {
4547 // [stack] OBJ
4548 return false;
4549 }
4550 if (!xoe->emitReference()) {
4551 // [stack] OBJ KEY
4552 return false;
4553 }
4554 offset += xoe->numReferenceSlots();
4555 break;
4556 }
4557 case ParseNodeKind::ArrayExpr:
4558 case ParseNodeKind::ObjectExpr:
4559 break;
4560 case ParseNodeKind::CallExpr:
4561 if (!emitTree(lhs)) {
4562 return false;
4563 }
4564
4565 // Assignment to function calls is forbidden, but we have to make the
4566 // call first. Now we can throw.
4567 if (!emit2(JSOp::ThrowMsg, uint8_t(ThrowMsgKind::AssignToCall))) {
4568 return false;
4569 }
4570
4571 // Rebalance the stack to placate stack-depth assertions.
4572 if (!emit1(JSOp::Pop)) {
4573 return false;
4574 }
4575 break;
4576 default:
4577 MOZ_ASSERT(0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(0)>::isValid, "invalid assertion condition"); if (
(__builtin_expect(!!(!(!!(0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("0", "./../../../../js/src/frontend/BytecodeEmitter.cpp", 4577
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0" ")"); do { MOZ_CrashSequence
(__null, 4577); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4578 }
4579
4580 if (isCompound) {
4581 MOZ_ASSERT(rhs)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(rhs)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(rhs))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("rhs", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 4581); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rhs" ")"); do
{ MOZ_CrashSequence(__null, 4581); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
4582 switch (lhs->getKind()) {
4583 case ParseNodeKind::ArgumentsLength:
4584 case ParseNodeKind::DotExpr: {
4585 NonOptionalPropertyAccessBase* prop =
4586 &lhs->as<NonOptionalPropertyAccessBase>();
4587 if (!poe->emitGet(prop->key().atom())) {
4588 // [stack] # if Super
4589 // [stack] THIS SUPERBASE PROP
4590 // [stack] # otherwise
4591 // [stack] OBJ PROP
4592 return false;
4593 }
4594 break;
4595 }
4596 case ParseNodeKind::ElemExpr: {
4597 if (!eoe->emitGet()) {
4598 // [stack] KEY THIS OBJ ELEM
4599 return false;
4600 }
4601 break;
4602 }
4603 case ParseNodeKind::PrivateMemberExpr: {
4604 if (!xoe->emitGet()) {
4605 // [stack] OBJ KEY VALUE
4606 return false;
4607 }
4608 break;
4609 }
4610 case ParseNodeKind::CallExpr:
4611 // We just emitted a JSOp::ThrowMsg and popped the call's return
4612 // value. Push a random value to make sure the stack depth is
4613 // correct.
4614 if (!emit1(JSOp::Null)) {
4615 // [stack] NULL
4616 return false;
4617 }
4618 break;
4619 default:;
4620 }
4621 }
4622
4623 switch (lhs->getKind()) {
4624 case ParseNodeKind::Name:
4625 if (!noe->prepareForRhs()) {
4626 // [stack] ENV? VAL?
4627 return false;
4628 }
4629 offset += noe->emittedBindOp();
4630 break;
4631 case ParseNodeKind::ArgumentsLength:
4632 case ParseNodeKind::DotExpr:
4633 if (!poe->prepareForRhs()) {
4634 // [stack] # if Simple Assignment with Super
4635 // [stack] THIS SUPERBASE
4636 // [stack] # if Simple Assignment with other
4637 // [stack] OBJ
4638 // [stack] # if Compound Assignment with Super
4639 // [stack] THIS SUPERBASE PROP
4640 // [stack] # if Compound Assignment with other
4641 // [stack] OBJ PROP
4642 return false;
4643 }
4644 break;
4645 case ParseNodeKind::ElemExpr:
4646 if (!eoe->prepareForRhs()) {
4647 // [stack] # if Simple Assignment with Super
4648 // [stack] THIS KEY SUPERBASE
4649 // [stack] # if Simple Assignment with other
4650 // [stack] OBJ KEY
4651 // [stack] # if Compound Assignment with Super
4652 // [stack] THIS KEY SUPERBASE ELEM
4653 // [stack] # if Compound Assignment with other
4654 // [stack] OBJ KEY ELEM
4655 return false;
4656 }
4657 break;
4658 case ParseNodeKind::PrivateMemberExpr:
4659 // no stack adjustment needed
4660 break;
4661 default:
4662 break;
4663 }
4664
4665 if (rhs) {
4666 if (!emitAssignmentRhs(rhs, anonFunctionName)) {
4667 // [stack] ... VAL? RHS
4668 return false;
4669 }
4670 } else {
4671 // Assumption: Things with pre-emitted RHS values never need to be named.
4672 if (!emitAssignmentRhs(offset)) {
4673 // [stack] ... VAL? RHS
4674 return false;
4675 }
4676 }
4677
4678 /* If += etc., emit the binary operator with a hint for the decompiler. */
4679 if (isCompound) {
4680 if (!emit1(compoundOp)) {
4681 // [stack] ... VAL
4682 return false;
4683 }
4684 if (!emit1(JSOp::NopIsAssignOp)) {
4685 // [stack] ... VAL
4686 return false;
4687 }
4688 }
4689
4690 /* Finally, emit the specialized assignment bytecode. */
4691 switch (lhs->getKind()) {
4692 case ParseNodeKind::Name: {
4693 if (!noe->emitAssignment()) {
4694 // [stack] VAL
4695 return false;
4696 }
4697 break;
4698 }
4699 case ParseNodeKind::ArgumentsLength:
4700 case ParseNodeKind::DotExpr: {
4701 NonOptionalPropertyAccessBase* prop =
4702 &lhs->as<NonOptionalPropertyAccessBase>();
4703 if (!poe->emitAssignment(prop->key().atom())) {
4704 // [stack] VAL
4705 return false;
4706 }
4707 break;
4708 }
4709 case ParseNodeKind::CallExpr:
4710 // We threw above, so nothing to do here.
4711 break;
4712 case ParseNodeKind::ElemExpr: {
4713 if (!eoe->emitAssignment()) {
4714 // [stack] VAL
4715 return false;
4716 }
4717 break;
4718 }
4719 case ParseNodeKind::PrivateMemberExpr:
4720 if (!xoe->emitAssignment()) {
4721 // [stack] VAL
4722 return false;
4723 }
4724 break;
4725 case ParseNodeKind::ArrayExpr:
4726 case ParseNodeKind::ObjectExpr: {
4727 auto selfHostedIter =
4728 rhs ? getSelfHostedIterFor(rhs) : SelfHostedIter::Deny;
4729 if (!emitDestructuringOps(&lhs->as<ListNode>(),
4730 DestructuringFlavor::Assignment,
4731 selfHostedIter)) {
4732 return false;
4733 }
4734 break;
4735 }
4736 default:
4737 MOZ_ASSERT(0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(0)>::isValid, "invalid assertion condition"); if (
(__builtin_expect(!!(!(!!(0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("0", "./../../../../js/src/frontend/BytecodeEmitter.cpp", 4737
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0" ")"); do { MOZ_CrashSequence
(__null, 4737); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4738 }
4739 return true;
4740}
4741
4742bool BytecodeEmitter::emitShortCircuitAssignment(AssignmentNode* node) {
4743 TDZCheckCache tdzCache(this);
4744
4745 JSOp op;
4746 switch (node->getKind()) {
4747 case ParseNodeKind::CoalesceAssignExpr:
4748 op = JSOp::Coalesce;
4749 break;
4750 case ParseNodeKind::OrAssignExpr:
4751 op = JSOp::Or;
4752 break;
4753 case ParseNodeKind::AndAssignExpr:
4754 op = JSOp::And;
4755 break;
4756 default:
4757 MOZ_CRASH("Unexpected ParseNodeKind")do { do { } while (false); MOZ_ReportCrash("" "Unexpected ParseNodeKind"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 4757);
AnnotateMozCrashReason("MOZ_CRASH(" "Unexpected ParseNodeKind"
")"); do { MOZ_CrashSequence(__null, 4757); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
4758 }
4759
4760 ParseNode* lhs = node->left();
4761 ParseNode* rhs = node->right();
4762
4763 // |name| is used within NameOpEmitter, so its lifetime must surpass |noe|.
4764 TaggedParserAtomIndex name;
4765
4766 // Select the appropriate emitter based on the left-hand side.
4767 Maybe<NameOpEmitter> noe;
4768 Maybe<PropOpEmitter> poe;
4769 Maybe<ElemOpEmitter> eoe;
4770 Maybe<PrivateOpEmitter> xoe;
4771
4772 int32_t depth = bytecodeSection().stackDepth();
4773
4774 // Number of values pushed onto the stack in addition to the lhs value.
4775 int32_t numPushed;
4776
4777 // Evaluate the left-hand side expression and compute any stack values needed
4778 // for the assignment.
4779 switch (lhs->getKind()) {
4780 case ParseNodeKind::Name: {
4781 name = lhs->as<NameNode>().name();
4782 noe.emplace(this, name, NameOpEmitter::Kind::CompoundAssignment);
4783
4784 if (!noe->prepareForRhs()) {
4785 // [stack] ENV? LHS
4786 return false;
4787 }
4788
4789 numPushed = noe->emittedBindOp();
4790 break;
4791 }
4792 case ParseNodeKind::ArgumentsLength:
4793 case ParseNodeKind::DotExpr: {
4794 NonOptionalPropertyAccessBase* prop =
4795 &lhs->as<NonOptionalPropertyAccessBase>();
4796 bool isSuper = prop->isSuper();
4797
4798 poe.emplace(this, PropOpEmitter::Kind::CompoundAssignment,
4799 isSuper ? PropOpEmitter::ObjKind::Super
4800 : PropOpEmitter::ObjKind::Other);
4801
4802 if (!poe->prepareForObj()) {
4803 return false;
4804 }
4805
4806 if (isSuper) {
4807 UnaryNode* base = &prop->expression().as<UnaryNode>();
4808 if (!emitGetThisForSuperBase(base)) {
4809 // [stack] THIS SUPERBASE
4810 return false;
4811 }
4812 } else {
4813 if (!emitTree(&prop->expression())) {
4814 // [stack] OBJ
4815 return false;
4816 }
4817 }
4818
4819 if (!poe->emitGet(prop->key().atom())) {
4820 // [stack] # if Super
4821 // [stack] THIS SUPERBASE LHS
4822 // [stack] # otherwise
4823 // [stack] OBJ LHS
4824 return false;
4825 }
4826
4827 if (!poe->prepareForRhs()) {
4828 // [stack] # if Super
4829 // [stack] THIS SUPERBASE LHS
4830 // [stack] # otherwise
4831 // [stack] OBJ LHS
4832 return false;
4833 }
4834
4835 numPushed = 1 + isSuper;
4836 break;
4837 }
4838
4839 case ParseNodeKind::ElemExpr: {
4840 PropertyByValue* elem = &lhs->as<PropertyByValue>();
4841 bool isSuper = elem->isSuper();
4842 MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!elem->key().isKind(ParseNodeKind::PrivateName))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!elem->key().isKind(ParseNodeKind::PrivateName)))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!elem->key().isKind(ParseNodeKind::PrivateName)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 4842);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)"
")"); do { MOZ_CrashSequence(__null, 4842); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4843 eoe.emplace(this, ElemOpEmitter::Kind::CompoundAssignment,
4844 isSuper ? ElemOpEmitter::ObjKind::Super
4845 : ElemOpEmitter::ObjKind::Other);
4846
4847 if (!emitElemObjAndKey(elem, *eoe)) {
4848 // [stack] # if Super
4849 // [stack] THIS KEY
4850 // [stack] # otherwise
4851 // [stack] OBJ KEY
4852 return false;
4853 }
4854
4855 if (!eoe->emitGet()) {
4856 // [stack] # if Super
4857 // [stack] THIS KEY SUPERBASE LHS
4858 // [stack] # otherwise
4859 // [stack] OBJ KEY LHS
4860 return false;
4861 }
4862
4863 if (!eoe->prepareForRhs()) {
4864 // [stack] # if Super
4865 // [stack] THIS KEY SUPERBASE LHS
4866 // [stack] # otherwise
4867 // [stack] OBJ KEY LHS
4868 return false;
4869 }
4870
4871 numPushed = 2 + isSuper;
4872 break;
4873 }
4874
4875 case ParseNodeKind::PrivateMemberExpr: {
4876 PrivateMemberAccess* privateExpr = &lhs->as<PrivateMemberAccess>();
4877 xoe.emplace(this, PrivateOpEmitter::Kind::CompoundAssignment,
4878 privateExpr->privateName().name());
4879 if (!emitTree(&privateExpr->expression())) {
4880 // [stack] OBJ
4881 return false;
4882 }
4883 if (!xoe->emitReference()) {
4884 // [stack] OBJ NAME
4885 return false;
4886 }
4887 if (!xoe->emitGet()) {
4888 // [stack] OBJ NAME LHS
4889 return false;
4890 }
4891 numPushed = xoe->numReferenceSlots();
4892 break;
4893 }
4894
4895 default:
4896 MOZ_CRASH()do { do { } while (false); MOZ_ReportCrash("" , "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 4896); AnnotateMozCrashReason("MOZ_CRASH(" ")"); do { MOZ_CrashSequence
(__null, 4896); __attribute__((nomerge)) ::abort(); } while (
false); } while (false)
;
4897 }
4898
4899 MOZ_ASSERT(bytecodeSection().stackDepth() == depth + numPushed + 1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bytecodeSection().stackDepth() == depth + numPushed +
1)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(bytecodeSection().stackDepth() == depth + numPushed +
1))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("bytecodeSection().stackDepth() == depth + numPushed + 1", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 4899); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == depth + numPushed + 1"
")"); do { MOZ_CrashSequence(__null, 4899); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4900
4901 // Test for the short-circuit condition.
4902 JumpList jump;
4903 if (!emitJump(op, &jump)) {
4904 // [stack] ... LHS
4905 return false;
4906 }
4907
4908 // The short-circuit condition wasn't fulfilled, pop the left-hand side value
4909 // which was kept on the stack.
4910 if (!emit1(JSOp::Pop)) {
4911 // [stack] ...
4912 return false;
4913 }
4914
4915 if (!emitAssignmentRhs(rhs, name)) {
4916 // [stack] ... RHS
4917 return false;
4918 }
4919
4920 // Perform the actual assignment.
4921 switch (lhs->getKind()) {
4922 case ParseNodeKind::Name: {
4923 if (!noe->emitAssignment()) {
4924 // [stack] RHS
4925 return false;
4926 }
4927 break;
4928 }
4929 case ParseNodeKind::ArgumentsLength:
4930 case ParseNodeKind::DotExpr: {
4931 NonOptionalPropertyAccessBase* prop =
4932 &lhs->as<NonOptionalPropertyAccessBase>();
4933
4934 if (!poe->emitAssignment(prop->key().atom())) {
4935 // [stack] RHS
4936 return false;
4937 }
4938 break;
4939 }
4940
4941 case ParseNodeKind::ElemExpr: {
4942 if (!eoe->emitAssignment()) {
4943 // [stack] RHS
4944 return false;
4945 }
4946 break;
4947 }
4948
4949 case ParseNodeKind::PrivateMemberExpr:
4950 if (!xoe->emitAssignment()) {
4951 // [stack] RHS
4952 return false;
4953 }
4954 break;
4955
4956 default:
4957 MOZ_CRASH()do { do { } while (false); MOZ_ReportCrash("" , "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 4957); AnnotateMozCrashReason("MOZ_CRASH(" ")"); do { MOZ_CrashSequence
(__null, 4957); __attribute__((nomerge)) ::abort(); } while (
false); } while (false)
;
4958 }
4959
4960 MOZ_ASSERT(bytecodeSection().stackDepth() == depth + 1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bytecodeSection().stackDepth() == depth + 1)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(bytecodeSection().stackDepth() == depth + 1))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("bytecodeSection().stackDepth() == depth + 1"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 4960);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == depth + 1"
")"); do { MOZ_CrashSequence(__null, 4960); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4961
4962 // Join with the short-circuit jump and pop anything left on the stack.
4963 if (numPushed > 0) {
4964 JumpList jumpAroundPop;
4965 if (!emitJump(JSOp::Goto, &jumpAroundPop)) {
4966 // [stack] RHS
4967 return false;
4968 }
4969
4970 if (!emitJumpTargetAndPatch(jump)) {
4971 // [stack] ... LHS
4972 return false;
4973 }
4974
4975 // Reconstruct the stack depth after the jump.
4976 bytecodeSection().setStackDepth(depth + 1 + numPushed);
4977
4978 // Move the left-hand side value to the bottom and pop the rest.
4979 if (!emitUnpickN(numPushed)) {
4980 // [stack] LHS ...
4981 return false;
4982 }
4983 if (!emitPopN(numPushed)) {
4984 // [stack] LHS
4985 return false;
4986 }
4987
4988 if (!emitJumpTargetAndPatch(jumpAroundPop)) {
4989 // [stack] LHS | RHS
4990 return false;
4991 }
4992 } else {
4993 if (!emitJumpTargetAndPatch(jump)) {
4994 // [stack] LHS | RHS
4995 return false;
4996 }
4997 }
4998
4999 MOZ_ASSERT(bytecodeSection().stackDepth() == depth + 1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bytecodeSection().stackDepth() == depth + 1)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(bytecodeSection().stackDepth() == depth + 1))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("bytecodeSection().stackDepth() == depth + 1"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 4999);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == depth + 1"
")"); do { MOZ_CrashSequence(__null, 4999); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5000
5001 return true;
5002}
5003
5004bool BytecodeEmitter::emitCallSiteObjectArray(ObjLiteralWriter& writer,
5005 ListNode* cookedOrRaw,
5006 ParseNode* head, uint32_t count) {
5007 DebugOnly<size_t> idx = 0;
5008 for (ParseNode* pn : cookedOrRaw->contentsFrom(head)) {
5009 MOZ_ASSERT(pn->isKind(ParseNodeKind::TemplateStringExpr) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->isKind(ParseNodeKind::TemplateStringExpr) || pn
->isKind(ParseNodeKind::RawUndefinedExpr))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->isKind(ParseNodeKind::
TemplateStringExpr) || pn->isKind(ParseNodeKind::RawUndefinedExpr
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("pn->isKind(ParseNodeKind::TemplateStringExpr) || pn->isKind(ParseNodeKind::RawUndefinedExpr)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 5010);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->isKind(ParseNodeKind::TemplateStringExpr) || pn->isKind(ParseNodeKind::RawUndefinedExpr)"
")"); do { MOZ_CrashSequence(__null, 5010); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5010 pn->isKind(ParseNodeKind::RawUndefinedExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->isKind(ParseNodeKind::TemplateStringExpr) || pn
->isKind(ParseNodeKind::RawUndefinedExpr))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->isKind(ParseNodeKind::
TemplateStringExpr) || pn->isKind(ParseNodeKind::RawUndefinedExpr
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("pn->isKind(ParseNodeKind::TemplateStringExpr) || pn->isKind(ParseNodeKind::RawUndefinedExpr)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 5010);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->isKind(ParseNodeKind::TemplateStringExpr) || pn->isKind(ParseNodeKind::RawUndefinedExpr)"
")"); do { MOZ_CrashSequence(__null, 5010); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5011
5012 if (!emitObjLiteralValue(writer, pn)) {
5013 return false;
5014 }
5015 idx++;
5016 }
5017 MOZ_ASSERT(idx == count)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(idx == count)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(idx == count))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("idx == count", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 5017); AnnotateMozCrashReason("MOZ_ASSERT" "(" "idx == count"
")"); do { MOZ_CrashSequence(__null, 5017); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5018
5019 return true;
5020}
5021
5022bool BytecodeEmitter::emitCallSiteObject(CallSiteNode* callSiteObj) {
5023 constexpr JSOp op = JSOp::CallSiteObj;
5024
5025 // The first element of a call-site node is the raw-values list. Skip over it.
5026 ListNode* raw = callSiteObj->rawNodes();
5027 MOZ_ASSERT(raw->isKind(ParseNodeKind::ArrayExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(raw->isKind(ParseNodeKind::ArrayExpr))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(raw->isKind(ParseNodeKind::ArrayExpr)))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("raw->isKind(ParseNodeKind::ArrayExpr)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 5027);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "raw->isKind(ParseNodeKind::ArrayExpr)"
")"); do { MOZ_CrashSequence(__null, 5027); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5028 ParseNode* head = callSiteObj->head()->pn_next;
5029
5030 uint32_t count = callSiteObj->count() - 1;
5031 MOZ_ASSERT(count == raw->count())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(count == raw->count())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(count == raw->count()))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("count == raw->count()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 5031);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "count == raw->count()"
")"); do { MOZ_CrashSequence(__null, 5031); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5032
5033 ObjLiteralWriter writer;
5034 writer.beginCallSiteObj(op);
5035 writer.beginDenseArrayElements();
5036
5037 // Write elements of the two arrays: the 'cooked' values followed by the
5038 // 'raw' values.
5039 MOZ_RELEASE_ASSERT(count < UINT32_MAX / 2,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(count < (4294967295U) / 2)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(count < (4294967295U) / 2
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"count < (4294967295U) / 2" " (" "Number of elements for both arrays must fit in uint32_t"
")", "./../../../../js/src/frontend/BytecodeEmitter.cpp", 5040
); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "count < (4294967295U) / 2"
") (" "Number of elements for both arrays must fit in uint32_t"
")"); do { MOZ_CrashSequence(__null, 5040); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5040 "Number of elements for both arrays must fit in uint32_t")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(count < (4294967295U) / 2)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(count < (4294967295U) / 2
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"count < (4294967295U) / 2" " (" "Number of elements for both arrays must fit in uint32_t"
")", "./../../../../js/src/frontend/BytecodeEmitter.cpp", 5040
); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "count < (4294967295U) / 2"
") (" "Number of elements for both arrays must fit in uint32_t"
")"); do { MOZ_CrashSequence(__null, 5040); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5041 if (!emitCallSiteObjectArray(writer, callSiteObj, head, count)) {
5042 return false;
5043 }
5044 if (!emitCallSiteObjectArray(writer, raw, raw->head(), count)) {
5045 return false;
5046 }
5047
5048 GCThingIndex cookedIndex;
5049 if (!addObjLiteralData(writer, &cookedIndex)) {
5050 return false;
5051 }
5052
5053 MOZ_ASSERT(sc->hasCallSiteObj())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sc->hasCallSiteObj())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sc->hasCallSiteObj()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("sc->hasCallSiteObj()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 5053);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->hasCallSiteObj()"
")"); do { MOZ_CrashSequence(__null, 5053); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5054
5055 return emitInternedObjectOp(cookedIndex, op);
5056}
5057
5058bool BytecodeEmitter::emitCatch(BinaryNode* catchClause) {
5059 // We must be nested under a try-finally statement.
5060 MOZ_ASSERT(innermostNestableControl->is<TryFinallyControl>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(innermostNestableControl->is<TryFinallyControl
>())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(innermostNestableControl->is<TryFinallyControl
>()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("innermostNestableControl->is<TryFinallyControl>()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 5060);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "innermostNestableControl->is<TryFinallyControl>()"
")"); do { MOZ_CrashSequence(__null, 5060); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5061
5062 ParseNode* param = catchClause->left();
5063 if (!param) {
5064 // Catch parameter was omitted; just discard the exception.
5065 if (!emit1(JSOp::Pop)) {
5066 return false;
5067 }
5068 } else {
5069 switch (param->getKind()) {
5070 case ParseNodeKind::ArrayExpr:
5071 case ParseNodeKind::ObjectExpr:
5072 if (!emitDestructuringOps(&param->as<ListNode>(),
5073 DestructuringFlavor::Declaration,
5074 SelfHostedIter::Deny)) {
5075 return false;
5076 }
5077 if (!emit1(JSOp::Pop)) {
5078 return false;
5079 }
5080 break;
5081
5082 case ParseNodeKind::Name:
5083 if (!emitLexicalInitialization(&param->as<NameNode>())) {
5084 return false;
5085 }
5086 if (!emit1(JSOp::Pop)) {
5087 return false;
5088 }
5089 break;
5090
5091 default:
5092 MOZ_ASSERT(0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(0)>::isValid, "invalid assertion condition"); if (
(__builtin_expect(!!(!(!!(0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("0", "./../../../../js/src/frontend/BytecodeEmitter.cpp", 5092
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0" ")"); do { MOZ_CrashSequence
(__null, 5092); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
5093 }
5094 }
5095
5096 /* Emit the catch body. */
5097 return emitTree(catchClause->right());
5098}
5099
5100// Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See the
5101// comment on EmitSwitch.
5102MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitTry(TryNode* tryNode) {
5103 LexicalScopeNode* catchScope = tryNode->catchScope();
5104 ParseNode* finallyNode = tryNode->finallyBlock();
5105
5106 TryEmitter::Kind kind;
5107 if (catchScope) {
5108 if (finallyNode) {
5109 kind = TryEmitter::Kind::TryCatchFinally;
5110 } else {
5111 kind = TryEmitter::Kind::TryCatch;
5112 }
5113 } else {
5114 MOZ_ASSERT(finallyNode)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(finallyNode)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(finallyNode))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("finallyNode", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 5114); AnnotateMozCrashReason("MOZ_ASSERT" "(" "finallyNode"
")"); do { MOZ_CrashSequence(__null, 5114); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5115 kind = TryEmitter::Kind::TryFinally;
5116 }
5117 TryEmitter tryCatch(this, kind, TryEmitter::ControlKind::Syntactic);
5118
5119 if (!tryCatch.emitTry()) {
5120 return false;
5121 }
5122
5123 if (!emitTree(tryNode->body())) {
5124 return false;
5125 }
5126
5127 // If this try has a catch block, emit it.
5128 if (catchScope) {
5129 // The emitted code for a catch block looks like:
5130 //
5131 // [pushlexicalenv] only if any local aliased
5132 // exception
5133 // setlocal 0; pop assign or possibly destructure exception
5134 // < catch block contents >
5135 // debugleaveblock
5136 // [poplexicalenv] only if any local aliased
5137 // if there is a finally block:
5138 // goto <finally>
5139 // [jump target for returning from finally]
5140 // goto <after finally>
5141 if (!tryCatch.emitCatch()) {
5142 return false;
5143 }
5144
5145 // Emit the lexical scope and catch body.
5146 if (!emitTree(catchScope)) {
5147 return false;
5148 }
5149 }
5150
5151 // Emit the finally handler, if there is one.
5152 if (finallyNode) {
5153 if (!tryCatch.emitFinally(Some(finallyNode->pn_pos.begin))) {
5154 return false;
5155 }
5156
5157 if (!emitTree(finallyNode)) {
5158 return false;
5159 }
5160 }
5161
5162 if (!tryCatch.emitEnd()) {
5163 return false;
5164 }
5165
5166 return true;
5167}
5168
5169[[nodiscard]] bool BytecodeEmitter::emitJumpToFinally(JumpList* jump,
5170 uint32_t idx) {
5171 // Push the continuation index.
5172 if (!emitNumberOp(idx)) {
5173 return false;
5174 }
5175
5176 // Push |exception_stack|.
5177 if (!emit1(JSOp::Null)) {
5178 return false;
5179 }
5180
5181 // Push |throwing|.
5182 if (!emit1(JSOp::False)) {
5183 return false;
5184 }
5185
5186 // Jump to the finally block.
5187 if (!emitJumpNoFallthrough(JSOp::Goto, jump)) {
5188 return false;
5189 }
5190
5191 return true;
5192}
5193
5194bool BytecodeEmitter::emitIf(TernaryNode* ifNode) {
5195 IfEmitter ifThenElse(this);
5196
5197 if (!ifThenElse.emitIf(Some(ifNode->kid1()->pn_pos.begin))) {
5198 return false;
5199 }
5200
5201if_again:
5202 ParseNode* testNode = ifNode->kid1();
5203 auto conditionKind = IfEmitter::ConditionKind::Positive;
5204 if (testNode->isKind(ParseNodeKind::NotExpr)) {
5205 testNode = testNode->as<UnaryNode>().kid();
5206 conditionKind = IfEmitter::ConditionKind::Negative;
5207 }
5208
5209 if (!markStepBreakpoint()) {
5210 return false;
5211 }
5212
5213 // Emit code for the condition before pushing stmtInfo.
5214 // NOTE: NotExpr of testNode may be unwrapped, and in that case the negation
5215 // is handled by conditionKind.
5216 if (!emitTree(testNode)) {
5217 return false;
5218 }
5219
5220 ParseNode* elseNode = ifNode->kid3();
5221 if (elseNode) {
5222 if (!ifThenElse.emitThenElse(conditionKind)) {
5223 return false;
5224 }
5225 } else {
5226 if (!ifThenElse.emitThen(conditionKind)) {
5227 return false;
5228 }
5229 }
5230
5231 /* Emit code for the then part. */
5232 if (!emitTree(ifNode->kid2())) {
5233 return false;
5234 }
5235
5236 if (elseNode) {
5237 if (elseNode->isKind(ParseNodeKind::IfStmt)) {
5238 ifNode = &elseNode->as<TernaryNode>();
5239
5240 if (!ifThenElse.emitElseIf(Some(ifNode->kid1()->pn_pos.begin))) {
5241 return false;
5242 }
5243
5244 goto if_again;
5245 }
5246
5247 if (!ifThenElse.emitElse()) {
5248 return false;
5249 }
5250
5251 /* Emit code for the else part. */
5252 if (!emitTree(elseNode)) {
5253 return false;
5254 }
5255 }
5256
5257 if (!ifThenElse.emitEnd()) {
5258 return false;
5259 }
5260
5261 return true;
5262}
5263
5264bool BytecodeEmitter::emitHoistedFunctionsInList(ListNode* stmtList) {
5265 MOZ_ASSERT(stmtList->hasTopLevelFunctionDeclarations())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(stmtList->hasTopLevelFunctionDeclarations())>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(stmtList->hasTopLevelFunctionDeclarations()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("stmtList->hasTopLevelFunctionDeclarations()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 5265);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "stmtList->hasTopLevelFunctionDeclarations()"
")"); do { MOZ_CrashSequence(__null, 5265); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5266
5267 // We can call this multiple times for sloppy eval scopes.
5268 if (stmtList->emittedTopLevelFunctionDeclarations()) {
5269 return true;
5270 }
5271
5272 stmtList->setEmittedTopLevelFunctionDeclarations();
5273
5274 for (ParseNode* stmt : stmtList->contents()) {
5275 ParseNode* maybeFun = stmt;
5276
5277 if (!sc->strict()) {
5278 while (maybeFun->isKind(ParseNodeKind::LabelStmt)) {
5279 maybeFun = maybeFun->as<LabeledStatement>().statement();
5280 }
5281 }
5282
5283 if (maybeFun->is<FunctionNode>() &&
5284 maybeFun->as<FunctionNode>().functionIsHoisted()) {
5285 if (!emitTree(maybeFun)) {
5286 return false;
5287 }
5288 }
5289 }
5290
5291 return true;
5292}
5293
5294bool BytecodeEmitter::emitLexicalScopeBody(
5295 ParseNode* body, EmitLineNumberNote emitLineNote /* = EMIT_LINENOTE */) {
5296 if (body->isKind(ParseNodeKind::StatementList) &&
5297 body->as<ListNode>().hasTopLevelFunctionDeclarations()) {
5298 // This block contains function statements whose definitions are
5299 // hoisted to the top of the block. Emit these as a separate pass
5300 // before the rest of the block.
5301 if (!emitHoistedFunctionsInList(&body->as<ListNode>())) {
5302 return false;
5303 }
5304 }
5305
5306 // Line notes were updated by emitLexicalScope or emitScript.
5307 return emitTree(body, ValueUsage::WantValue, emitLineNote);
5308}
5309
5310// Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See
5311// the comment on emitSwitch.
5312MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitLexicalScope(
5313 LexicalScopeNode* lexicalScope) {
5314 LexicalScopeEmitter lse(this);
5315
5316 ParseNode* body = lexicalScope->scopeBody();
5317 if (lexicalScope->isEmptyScope()) {
5318 if (!lse.emitEmptyScope()) {
5319 return false;
5320 }
5321
5322 if (!emitLexicalScopeBody(body)) {
5323 return false;
5324 }
5325
5326 if (!lse.emitEnd()) {
5327 return false;
5328 }
5329
5330 return true;
5331 }
5332
5333 // We are about to emit some bytecode for what the spec calls "declaration
5334 // instantiation". Assign these instructions to the opening `{` of the
5335 // block. (Using the location of each declaration we're instantiating is
5336 // too weird when stepping in the debugger.)
5337 if (!ParseNodeRequiresSpecialLineNumberNotes(body)) {
5338 if (!updateSourceCoordNotes(lexicalScope->pn_pos.begin)) {
5339 return false;
5340 }
5341 }
5342
5343 ScopeKind kind;
5344 if (body->isKind(ParseNodeKind::Catch)) {
5345 BinaryNode* catchNode = &body->as<BinaryNode>();
5346 kind =
5347 (!catchNode->left() || catchNode->left()->isKind(ParseNodeKind::Name))
5348 ? ScopeKind::SimpleCatch
5349 : ScopeKind::Catch;
5350 } else {
5351 kind = lexicalScope->kind();
5352 }
5353
5354 BlockKind blockKind = BlockKind::Other;
5355 if (body->isKind(ParseNodeKind::ForStmt) &&
5356 body->as<ForNode>().head()->isKind(ParseNodeKind::ForOf)) {
5357 MOZ_ASSERT(kind == ScopeKind::Lexical)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(kind == ScopeKind::Lexical)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(kind == ScopeKind::Lexical))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("kind == ScopeKind::Lexical"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 5357);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "kind == ScopeKind::Lexical"
")"); do { MOZ_CrashSequence(__null, 5357); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5358 blockKind = BlockKind::ForOf;
5359 }
5360
5361 if (!lse.emitScope(kind, lexicalScope->scopeBindings(), blockKind)) {
5362 return false;
5363 }
5364
5365 if (body->isKind(ParseNodeKind::ForStmt)) {
5366 // for loops need to emit JSOp::FreshenLexicalEnv/JSOp::RecreateLexicalEnv
5367 // if there are lexical declarations in the head. Signal this by passing a
5368 // non-nullptr lexical scope.
5369 if (!emitFor(&body->as<ForNode>(), &lse.emitterScope())) {
5370 return false;
5371 }
5372 } else {
5373 if (!emitLexicalScopeBody(body, SUPPRESS_LINENOTE)) {
5374 return false;
5375 }
5376 }
5377
5378 if (!lse.emitEnd()) {
5379 return false;
5380 }
5381 return true;
5382}
5383
5384bool BytecodeEmitter::emitWith(BinaryNode* withNode) {
5385 // Ensure that the column of the 'with' is set properly.
5386 if (!updateSourceCoordNotes(withNode->left()->pn_pos.begin)) {
5387 return false;
5388 }
5389
5390 if (!markStepBreakpoint()) {
5391 return false;
5392 }
5393
5394 if (!emitTree(withNode->left())) {
5395 return false;
5396 }
5397
5398 EmitterScope emitterScope(this);
5399 if (!emitterScope.enterWith(this)) {
5400 return false;
5401 }
5402
5403 if (!emitTree(withNode->right())) {
5404 return false;
5405 }
5406
5407 return emitterScope.leave(this);
5408}
5409
5410bool BytecodeEmitter::emitCopyDataProperties(CopyOption option) {
5411 DebugOnly<int32_t> depth = bytecodeSection().stackDepth();
5412
5413 uint32_t argc;
5414 if (option == CopyOption::Filtered) {
5415 MOZ_ASSERT(depth > 2)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(depth > 2)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(depth > 2))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("depth > 2", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 5415); AnnotateMozCrashReason("MOZ_ASSERT" "(" "depth > 2"
")"); do { MOZ_CrashSequence(__null, 5415); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5416 // [stack] TARGET SOURCE SET
5417 argc = 3;
5418
5419 if (!emitAtomOp(JSOp::GetIntrinsic,
5420 TaggedParserAtomIndex::WellKnown::CopyDataProperties())) {
5421 // [stack] TARGET SOURCE SET COPYDATAPROPERTIES
5422 return false;
5423 }
5424 } else {
5425 MOZ_ASSERT(depth > 1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(depth > 1)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(depth > 1))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("depth > 1", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 5425); AnnotateMozCrashReason("MOZ_ASSERT" "(" "depth > 1"
")"); do { MOZ_CrashSequence(__null, 5425); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5426 // [stack] TARGET SOURCE
5427 argc = 2;
5428
5429 if (!emitAtomOp(
5430 JSOp::GetIntrinsic,
5431 TaggedParserAtomIndex::WellKnown::CopyDataPropertiesUnfiltered())) {
5432 // [stack] TARGET SOURCE COPYDATAPROPERTIES
5433 return false;
5434 }
5435 }
5436
5437 if (!emit1(JSOp::Undefined)) {
5438 // [stack] TARGET SOURCE SET? COPYDATAPROPERTIES
5439 // UNDEFINED
5440 return false;
5441 }
5442 if (!emit2(JSOp::Pick, argc + 1)) {
5443 // [stack] SOURCE SET? COPYDATAPROPERTIES UNDEFINED
5444 // TARGET
5445 return false;
5446 }
5447 if (!emit2(JSOp::Pick, argc + 1)) {
5448 // [stack] SET? COPYDATAPROPERTIES UNDEFINED TARGET
5449 // SOURCE
5450 return false;
5451 }
5452 if (option == CopyOption::Filtered) {
5453 if (!emit2(JSOp::Pick, argc + 1)) {
5454 // [stack] COPYDATAPROPERTIES UNDEFINED TARGET SOURCE SET
5455 return false;
5456 }
5457 }
5458 // Callee is always self-hosted instrinsic, and cannot be content function.
5459 if (!emitCall(JSOp::CallIgnoresRv, argc)) {
5460 // [stack] IGNORED
5461 return false;
5462 }
5463
5464 if (!emit1(JSOp::Pop)) {
5465 // [stack]
5466 return false;
5467 }
5468
5469 MOZ_ASSERT(depth - int(argc) == bytecodeSection().stackDepth())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(depth - int(argc) == bytecodeSection().stackDepth())
>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(depth - int(argc) == bytecodeSection().stackDepth())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("depth - int(argc) == bytecodeSection().stackDepth()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 5469);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "depth - int(argc) == bytecodeSection().stackDepth()"
")"); do { MOZ_CrashSequence(__null, 5469); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5470 return true;
5471}
5472
5473bool BytecodeEmitter::emitBigIntOp(BigIntLiteral* bigint) {
5474 GCThingIndex index;
5475 if (!perScriptData().gcThingList().append(bigint, &index)) {
5476 return false;
5477 }
5478 return emitGCIndexOp(JSOp::BigInt, index);
5479}
5480
5481bool BytecodeEmitter::emitIterable(ParseNode* value,
5482 SelfHostedIter selfHostedIter,
5483 IteratorKind iterKind) {
5484 MOZ_ASSERT(getSelfHostedIterFor(value) == selfHostedIter)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(getSelfHostedIterFor(value) == selfHostedIter)>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(getSelfHostedIterFor(value) == selfHostedIter))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("getSelfHostedIterFor(value) == selfHostedIter"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 5484);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "getSelfHostedIterFor(value) == selfHostedIter"
")"); do { MOZ_CrashSequence(__null, 5484); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5485
5486 if (!emitTree(value)) {
5487 // [stack] ITERABLE
5488 return false;
5489 }
5490
5491 switch (selfHostedIter) {
5492 case SelfHostedIter::Deny:
5493 case SelfHostedIter::AllowContent:
5494 // [stack] ITERABLE
5495 return true;
5496
5497 case SelfHostedIter::AllowContentWith: {
5498 // This is the following case:
5499 //
5500 // for (const nextValue of allowContentIterWith(items, usingIterator)) {
5501 //
5502 // `items` is emitted by `emitTree(value)` above, and the result is on the
5503 // stack as ITERABLE.
5504 // `usingIterator` is the value of `items[Symbol.iterator]`, that's
5505 // already retrieved.
5506 ListNode* argsList = value->as<CallNode>().args();
5507 MOZ_ASSERT_IF(iterKind == IteratorKind::Sync, argsList->count() == 2)do { if (iterKind == IteratorKind::Sync) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(argsList
->count() == 2)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(argsList->count() == 2)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 2"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 5507);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2"
")"); do { MOZ_CrashSequence(__null, 5507); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
5508 MOZ_ASSERT_IF(iterKind == IteratorKind::Async, argsList->count() == 3)do { if (iterKind == IteratorKind::Async) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(argsList
->count() == 3)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(argsList->count() == 3)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 3"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 5508);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 3"
")"); do { MOZ_CrashSequence(__null, 5508); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
5509
5510 if (!emitTree(argsList->head()->pn_next)) {
5511 // [stack] ITERABLE ITERFN
5512 return false;
5513 }
5514
5515 // Async iterator has two possible iterators: An async iterator and a sync
5516 // iterator.
5517 if (iterKind == IteratorKind::Async) {
5518 if (!emitTree(argsList->head()->pn_next->pn_next)) {
5519 // [stack] ITERABLE ASYNC_ITERFN SYNC_ITERFN
5520 return false;
5521 }
5522 }
5523
5524 // [stack] ITERABLE ASYNC_ITERFN? SYNC_ITERFN
5525 return true;
5526 }
5527
5528 case SelfHostedIter::AllowContentWithNext: {
5529 // This is the following case:
5530 //
5531 // for (const nextValue of allowContentIterWithNext(iterator, next)) {
5532 //
5533 // `iterator` is emitted by `emitTree(value)` above, and the result is on
5534 // the stack as ITER.
5535 // `next` is the value of `iterator.next`, that's already retrieved.
5536 ListNode* argsList = value->as<CallNode>().args();
5537 MOZ_ASSERT(argsList->count() == 2)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(argsList->count() == 2)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(argsList->count() == 2)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 2"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 5537);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2"
")"); do { MOZ_CrashSequence(__null, 5537); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5538
5539 if (!emitTree(argsList->head()->pn_next)) {
5540 // [stack] ITER NEXT
5541 return false;
5542 }
5543
5544 if (!emit1(JSOp::Swap)) {
5545 // [stack] NEXT ITER
5546 return false;
5547 }
5548
5549 // [stack] NEXT ITER
5550 return true;
5551 }
5552 }
5553
5554 MOZ_CRASH("invalid self-hosted iteration kind")do { do { } while (false); MOZ_ReportCrash("" "invalid self-hosted iteration kind"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 5554);
AnnotateMozCrashReason("MOZ_CRASH(" "invalid self-hosted iteration kind"
")"); do { MOZ_CrashSequence(__null, 5554); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
5555}
5556
5557bool BytecodeEmitter::emitIterator(SelfHostedIter selfHostedIter) {
5558 MOZ_ASSERT(selfHostedIter != SelfHostedIter::Deny ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode
!= BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter
::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
" (" "[Symbol.iterator]() call is prohibited in self-hosted code "
"because it can run user-modifiable iteration code" ")", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 5561); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
") (" "[Symbol.iterator]() call is prohibited in self-hosted code "
"because it can run user-modifiable iteration code" ")"); do
{ MOZ_CrashSequence(__null, 5561); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
5559 emitterMode != BytecodeEmitter::SelfHosting,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode
!= BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter
::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
" (" "[Symbol.iterator]() call is prohibited in self-hosted code "
"because it can run user-modifiable iteration code" ")", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 5561); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
") (" "[Symbol.iterator]() call is prohibited in self-hosted code "
"because it can run user-modifiable iteration code" ")"); do
{ MOZ_CrashSequence(__null, 5561); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
5560 "[Symbol.iterator]() call is prohibited in self-hosted code "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode
!= BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter
::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
" (" "[Symbol.iterator]() call is prohibited in self-hosted code "
"because it can run user-modifiable iteration code" ")", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 5561); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
") (" "[Symbol.iterator]() call is prohibited in self-hosted code "
"because it can run user-modifiable iteration code" ")"); do
{ MOZ_CrashSequence(__null, 5561); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
5561 "because it can run user-modifiable iteration code")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode
!= BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter
::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
" (" "[Symbol.iterator]() call is prohibited in self-hosted code "
"because it can run user-modifiable iteration code" ")", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 5561); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
") (" "[Symbol.iterator]() call is prohibited in self-hosted code "
"because it can run user-modifiable iteration code" ")"); do
{ MOZ_CrashSequence(__null, 5561); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
5562
5563 if (selfHostedIter == SelfHostedIter::AllowContentWithNext) {
5564 // [stack] NEXT ITER
5565
5566 // Nothing to do, stack already contains the iterator and its `next` method.
5567 return true;
5568 }
5569
5570 if (selfHostedIter != SelfHostedIter::AllowContentWith) {
5571 // [stack] OBJ
5572
5573 // Convert iterable to iterator.
5574 if (!emit1(JSOp::Dup)) {
5575 // [stack] OBJ OBJ
5576 return false;
5577 }
5578 if (!emit2(JSOp::Symbol, uint8_t(JS::SymbolCode::iterator))) {
5579 // [stack] OBJ OBJ @@ITERATOR
5580 return false;
5581 }
5582 if (!emitElemOpBase(JSOp::GetElem)) {
5583 // [stack] OBJ ITERFN
5584 return false;
5585 }
5586 }
5587
5588 if (!emit1(JSOp::Swap)) {
5589 // [stack] ITERFN OBJ
5590 return false;
5591 }
5592 if (!emitCall(getIterCallOp(JSOp::CallIter, selfHostedIter), 0)) {
5593 // [stack] ITER
5594 return false;
5595 }
5596 if (!emitCheckIsObj(CheckIsObjectKind::GetIterator)) {
5597 // [stack] ITER
5598 return false;
5599 }
5600 if (!emit1(JSOp::Dup)) {
5601 // [stack] ITER ITER
5602 return false;
5603 }
5604 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::next())) {
5605 // [stack] ITER NEXT
5606 return false;
5607 }
5608 if (!emit1(JSOp::Swap)) {
5609 // [stack] NEXT ITER
5610 return false;
5611 }
5612 return true;
5613}
5614
5615bool BytecodeEmitter::emitAsyncIterator(SelfHostedIter selfHostedIter) {
5616 MOZ_ASSERT(selfHostedIter != SelfHostedIter::AllowContentWithNext)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(selfHostedIter != SelfHostedIter::AllowContentWithNext
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(selfHostedIter != SelfHostedIter::AllowContentWithNext
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"selfHostedIter != SelfHostedIter::AllowContentWithNext", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 5616); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::AllowContentWithNext"
")"); do { MOZ_CrashSequence(__null, 5616); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5617 MOZ_ASSERT(selfHostedIter != SelfHostedIter::Deny ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode
!= BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter
::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
" (" "[Symbol.asyncIterator]() call is prohibited in self-hosted code "
"because it can run user-modifiable iteration code" ")", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 5620); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
") (" "[Symbol.asyncIterator]() call is prohibited in self-hosted code "
"because it can run user-modifiable iteration code" ")"); do
{ MOZ_CrashSequence(__null, 5620); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
5618 emitterMode != BytecodeEmitter::SelfHosting,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode
!= BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter
::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
" (" "[Symbol.asyncIterator]() call is prohibited in self-hosted code "
"because it can run user-modifiable iteration code" ")", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 5620); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
") (" "[Symbol.asyncIterator]() call is prohibited in self-hosted code "
"because it can run user-modifiable iteration code" ")"); do
{ MOZ_CrashSequence(__null, 5620); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
5619 "[Symbol.asyncIterator]() call is prohibited in self-hosted code "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode
!= BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter
::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
" (" "[Symbol.asyncIterator]() call is prohibited in self-hosted code "
"because it can run user-modifiable iteration code" ")", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 5620); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
") (" "[Symbol.asyncIterator]() call is prohibited in self-hosted code "
"because it can run user-modifiable iteration code" ")"); do
{ MOZ_CrashSequence(__null, 5620); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
5620 "because it can run user-modifiable iteration code")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode
!= BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter
::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
" (" "[Symbol.asyncIterator]() call is prohibited in self-hosted code "
"because it can run user-modifiable iteration code" ")", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 5620); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
") (" "[Symbol.asyncIterator]() call is prohibited in self-hosted code "
"because it can run user-modifiable iteration code" ")"); do
{ MOZ_CrashSequence(__null, 5620); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
5621
5622 if (selfHostedIter != SelfHostedIter::AllowContentWith) {
5623 // [stack] OBJ
5624
5625 // Convert iterable to iterator.
5626 if (!emit1(JSOp::Dup)) {
5627 // [stack] OBJ OBJ
5628 return false;
5629 }
5630 if (!emit2(JSOp::Symbol, uint8_t(JS::SymbolCode::asyncIterator))) {
5631 // [stack] OBJ OBJ @@ASYNCITERATOR
5632 return false;
5633 }
5634 if (!emitElemOpBase(JSOp::GetElem)) {
5635 // [stack] OBJ ASYNC_ITERFN
5636 return false;
5637 }
5638 } else {
5639 // [stack] OBJ ASYNC_ITERFN SYNC_ITERFN
5640
5641 if (!emitElemOpBase(JSOp::Swap)) {
5642 // [stack] OBJ SYNC_ITERFN ASYNC_ITERFN
5643 return false;
5644 }
5645 }
5646
5647 InternalIfEmitter ifAsyncIterIsUndefined(this);
5648 if (!emit1(JSOp::IsNullOrUndefined)) {
5649 // [stack] OBJ SYNC_ITERFN? ASYNC_ITERFN NULL-OR-UNDEF
5650 return false;
5651 }
5652 if (!ifAsyncIterIsUndefined.emitThenElse()) {
5653 // [stack] OBJ SYNC_ITERFN? ASYNC_ITERFN
5654 return false;
5655 }
5656
5657 if (!emit1(JSOp::Pop)) {
5658 // [stack] OBJ SYNC_ITERFN?
5659 return false;
5660 }
5661
5662 if (selfHostedIter != SelfHostedIter::AllowContentWith) {
5663 if (!emit1(JSOp::Dup)) {
5664 // [stack] OBJ OBJ
5665 return false;
5666 }
5667 if (!emit2(JSOp::Symbol, uint8_t(JS::SymbolCode::iterator))) {
5668 // [stack] OBJ OBJ @@ITERATOR
5669 return false;
5670 }
5671 if (!emitElemOpBase(JSOp::GetElem)) {
5672 // [stack] OBJ SYNC_ITERFN
5673 return false;
5674 }
5675 } else {
5676 // [stack] OBJ SYNC_ITERFN
5677 }
5678
5679 if (!emit1(JSOp::Swap)) {
5680 // [stack] SYNC_ITERFN OBJ
5681 return false;
5682 }
5683 if (!emitCall(getIterCallOp(JSOp::CallIter, selfHostedIter), 0)) {
5684 // [stack] ITER
5685 return false;
5686 }
5687 if (!emitCheckIsObj(CheckIsObjectKind::GetIterator)) {
5688 // [stack] ITER
5689 return false;
5690 }
5691
5692 if (!emit1(JSOp::Dup)) {
5693 // [stack] ITER ITER
5694 return false;
5695 }
5696 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::next())) {
5697 // [stack] ITER SYNCNEXT
5698 return false;
5699 }
5700
5701 if (!emit1(JSOp::ToAsyncIter)) {
5702 // [stack] ITER
5703 return false;
5704 }
5705
5706 if (!ifAsyncIterIsUndefined.emitElse()) {
5707 // [stack] OBJ SYNC_ITERFN? ASYNC_ITERFN
5708 return false;
5709 }
5710
5711 if (selfHostedIter == SelfHostedIter::AllowContentWith) {
5712 if (!emit1(JSOp::Swap)) {
5713 // [stack] OBJ ASYNC_ITERFN SYNC_ITERFN
5714 return false;
5715 }
5716 if (!emit1(JSOp::Pop)) {
5717 // [stack] OBJ ASYNC_ITERFN
5718 return false;
5719 }
5720 }
5721
5722 if (!emit1(JSOp::Swap)) {
5723 // [stack] ASYNC_ITERFN OBJ
5724 return false;
5725 }
5726 if (!emitCall(getIterCallOp(JSOp::CallIter, selfHostedIter), 0)) {
5727 // [stack] ITER
5728 return false;
5729 }
5730 if (!emitCheckIsObj(CheckIsObjectKind::GetAsyncIterator)) {
5731 // [stack] ITER
5732 return false;
5733 }
5734
5735 if (!ifAsyncIterIsUndefined.emitEnd()) {
5736 // [stack] ITER
5737 return false;
5738 }
5739
5740 if (!emit1(JSOp::Dup)) {
5741 // [stack] ITER ITER
5742 return false;
5743 }
5744 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::next())) {
5745 // [stack] ITER NEXT
5746 return false;
5747 }
5748 if (!emit1(JSOp::Swap)) {
5749 // [stack] NEXT ITER
5750 return false;
5751 }
5752
5753 return true;
5754}
5755
5756bool BytecodeEmitter::emitSpread(SelfHostedIter selfHostedIter) {
5757 LoopControl loopInfo(this, StatementKind::Spread);
5758
5759 if (!loopInfo.emitLoopHead(this, Nothing())) {
5760 // [stack] NEXT ITER ARR I
5761 return false;
5762 }
5763
5764 {
5765#ifdef DEBUG1
5766 auto loopDepth = bytecodeSection().stackDepth();
5767#endif
5768
5769 // Spread operations can't contain |continue|, so don't bother setting loop
5770 // and enclosing "update" offsets, as we do with for-loops.
5771
5772 if (!emitDupAt(3, 2)) {
5773 // [stack] NEXT ITER ARR I NEXT ITER
5774 return false;
5775 }
5776 if (!emitIteratorNext(Nothing(), IteratorKind::Sync, selfHostedIter)) {
5777 // [stack] NEXT ITER ARR I RESULT
5778 return false;
5779 }
5780 if (!emit1(JSOp::Dup)) {
5781 // [stack] NEXT ITER ARR I RESULT RESULT
5782 return false;
5783 }
5784 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::done())) {
5785 // [stack] NEXT ITER ARR I RESULT DONE
5786 return false;
5787 }
5788 if (!emitJump(JSOp::JumpIfTrue, &loopInfo.breaks)) {
5789 // [stack] NEXT ITER ARR I RESULT
5790 return false;
5791 }
5792
5793 // Emit code to assign result.value to the iteration variable.
5794 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::value())) {
5795 // [stack] NEXT ITER ARR I VALUE
5796 return false;
5797 }
5798 if (!emit1(JSOp::InitElemInc)) {
5799 // [stack] NEXT ITER ARR I
5800 return false;
5801 }
5802
5803 if (!loopInfo.emitLoopEnd(this, JSOp::Goto, TryNoteKind::ForOf)) {
5804 // [stack] NEXT ITER ARR I
5805 return false;
5806 }
5807
5808 MOZ_ASSERT(bytecodeSection().stackDepth() == loopDepth)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bytecodeSection().stackDepth() == loopDepth)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(bytecodeSection().stackDepth() == loopDepth))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("bytecodeSection().stackDepth() == loopDepth"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 5808);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == loopDepth"
")"); do { MOZ_CrashSequence(__null, 5808); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5809 }
5810
5811 // When we leave the loop body and jump to this point, the result value is
5812 // still on the stack. Account for that by updating the stack depth
5813 // manually.
5814 bytecodeSection().setStackDepth(bytecodeSection().stackDepth() + 1);
5815
5816 // No continues should occur in spreads.
5817 MOZ_ASSERT(!loopInfo.continues.offset.valid())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!loopInfo.continues.offset.valid())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!loopInfo.continues.offset.valid
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!loopInfo.continues.offset.valid()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 5817); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!loopInfo.continues.offset.valid()"
")"); do { MOZ_CrashSequence(__null, 5817); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5818
5819 if (!emit2(JSOp::Pick, 4)) {
5820 // [stack] ITER ARR I RESULT NEXT
5821 return false;
5822 }
5823 if (!emit2(JSOp::Pick, 4)) {
5824 // [stack] ARR I RESULT NEXT ITER
5825 return false;
5826 }
5827
5828 return emitPopN(3);
5829 // [stack] ARR I
5830}
5831
5832bool BytecodeEmitter::emitInitializeForInOrOfTarget(TernaryNode* forHead) {
5833 MOZ_ASSERT(forHead->isKind(ParseNodeKind::ForIn) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(forHead->isKind(ParseNodeKind::ForIn) || forHead->
isKind(ParseNodeKind::ForOf))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(forHead->isKind(ParseNodeKind
::ForIn) || forHead->isKind(ParseNodeKind::ForOf)))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("forHead->isKind(ParseNodeKind::ForIn) || forHead->isKind(ParseNodeKind::ForOf)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 5834);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "forHead->isKind(ParseNodeKind::ForIn) || forHead->isKind(ParseNodeKind::ForOf)"
")"); do { MOZ_CrashSequence(__null, 5834); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5834 forHead->isKind(ParseNodeKind::ForOf))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(forHead->isKind(ParseNodeKind::ForIn) || forHead->
isKind(ParseNodeKind::ForOf))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(forHead->isKind(ParseNodeKind
::ForIn) || forHead->isKind(ParseNodeKind::ForOf)))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("forHead->isKind(ParseNodeKind::ForIn) || forHead->isKind(ParseNodeKind::ForOf)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 5834);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "forHead->isKind(ParseNodeKind::ForIn) || forHead->isKind(ParseNodeKind::ForOf)"
")"); do { MOZ_CrashSequence(__null, 5834); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5835
5836 MOZ_ASSERT(bytecodeSection().stackDepth() >= 1,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bytecodeSection().stackDepth() >= 1)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(bytecodeSection().stackDepth() >= 1))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("bytecodeSection().stackDepth() >= 1"
" (" "must have a per-iteration value for initializing" ")",
"./../../../../js/src/frontend/BytecodeEmitter.cpp", 5837); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() >= 1" ") ("
"must have a per-iteration value for initializing" ")"); do {
MOZ_CrashSequence(__null, 5837); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
5837 "must have a per-iteration value for initializing")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bytecodeSection().stackDepth() >= 1)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(bytecodeSection().stackDepth() >= 1))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("bytecodeSection().stackDepth() >= 1"
" (" "must have a per-iteration value for initializing" ")",
"./../../../../js/src/frontend/BytecodeEmitter.cpp", 5837); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() >= 1" ") ("
"must have a per-iteration value for initializing" ")"); do {
MOZ_CrashSequence(__null, 5837); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
5838
5839 ParseNode* target = forHead->kid1();
5840 MOZ_ASSERT(!forHead->kid2())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!forHead->kid2())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!forHead->kid2()))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("!forHead->kid2()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 5840);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!forHead->kid2()"
")"); do { MOZ_CrashSequence(__null, 5840); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5841
5842 // If the for-in/of loop didn't have a variable declaration, per-loop
5843 // initialization is just assigning the iteration value to a target
5844 // expression.
5845 if (!target->is<DeclarationListNode>()) {
5846 return emitAssignmentOrInit(ParseNodeKind::AssignExpr, target, nullptr);
5847 // [stack] ... ITERVAL
5848 }
5849
5850 // Otherwise, per-loop initialization is (possibly) declaration
5851 // initialization. If the declaration is a lexical declaration, it must be
5852 // initialized. If the declaration is a variable declaration, an
5853 // assignment to that name (which does *not* necessarily assign to the
5854 // variable!) must be generated.
5855
5856 auto* declarationList = &target->as<DeclarationListNode>();
5857 if (!updateSourceCoordNotes(declarationList->pn_pos.begin)) {
5858 return false;
5859 }
5860
5861 target = declarationList->singleBinding();
5862
5863 NameNode* nameNode = nullptr;
5864 if (target->isKind(ParseNodeKind::Name)) {
5865 nameNode = &target->as<NameNode>();
5866 } else if (target->isKind(ParseNodeKind::AssignExpr)) {
5867 BinaryNode* assignNode = &target->as<BinaryNode>();
5868 if (assignNode->left()->is<NameNode>()) {
5869 nameNode = &assignNode->left()->as<NameNode>();
5870 }
5871 }
5872
5873 if (nameNode) {
5874 auto nameAtom = nameNode->name();
5875 NameOpEmitter noe(this, nameAtom, NameOpEmitter::Kind::Initialize);
5876 if (!noe.prepareForRhs()) {
5877 return false;
5878 }
5879 if (noe.emittedBindOp()) {
5880 // Per-iteration initialization in for-in/of loops computes the
5881 // iteration value *before* initializing. Thus the initializing
5882 // value may be buried under a bind-specific value on the stack.
5883 // Swap it to the top of the stack.
5884 MOZ_ASSERT(bytecodeSection().stackDepth() >= 2)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bytecodeSection().stackDepth() >= 2)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(bytecodeSection().stackDepth() >= 2))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("bytecodeSection().stackDepth() >= 2"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 5884);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() >= 2"
")"); do { MOZ_CrashSequence(__null, 5884); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5885 if (!emit1(JSOp::Swap)) {
5886 return false;
5887 }
5888 } else {
5889 // In cases of emitting a frame slot or environment slot,
5890 // nothing needs be done.
5891 MOZ_ASSERT(bytecodeSection().stackDepth() >= 1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bytecodeSection().stackDepth() >= 1)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(bytecodeSection().stackDepth() >= 1))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("bytecodeSection().stackDepth() >= 1"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 5891);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() >= 1"
")"); do { MOZ_CrashSequence(__null, 5891); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5892 }
5893
5894 if (declarationList->isKind(ParseNodeKind::UsingDecl)) {
5895 if (!innermostEmitterScope()->prepareForDisposableAssignment(
5896 UsingHint::Sync)) {
5897 // [stack] ENV? V
5898 return false;
5899 }
5900 } else if (declarationList->isKind(ParseNodeKind::AwaitUsingDecl)) {
5901 if (!innermostEmitterScope()->prepareForDisposableAssignment(
5902 UsingHint::Async)) {
5903 // [stack] ENV? V
5904 return false;
5905 }
5906 }
5907
5908 if (!noe.emitAssignment()) {
5909 return false;
5910 }
5911
5912 // The caller handles removing the iteration value from the stack.
5913 return true;
5914 }
5915
5916 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!target->isKind(ParseNodeKind::AssignExpr))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!target->isKind(ParseNodeKind::AssignExpr)))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("!target->isKind(ParseNodeKind::AssignExpr)"
" (" "for-in/of loop destructuring declarations can't have initializers"
")", "./../../../../js/src/frontend/BytecodeEmitter.cpp", 5918
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!target->isKind(ParseNodeKind::AssignExpr)"
") (" "for-in/of loop destructuring declarations can't have initializers"
")"); do { MOZ_CrashSequence(__null, 5918); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5917 !target->isKind(ParseNodeKind::AssignExpr),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!target->isKind(ParseNodeKind::AssignExpr))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!target->isKind(ParseNodeKind::AssignExpr)))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("!target->isKind(ParseNodeKind::AssignExpr)"
" (" "for-in/of loop destructuring declarations can't have initializers"
")", "./../../../../js/src/frontend/BytecodeEmitter.cpp", 5918
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!target->isKind(ParseNodeKind::AssignExpr)"
") (" "for-in/of loop destructuring declarations can't have initializers"
")"); do { MOZ_CrashSequence(__null, 5918); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5918 "for-in/of loop destructuring declarations can't have initializers")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!target->isKind(ParseNodeKind::AssignExpr))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!target->isKind(ParseNodeKind::AssignExpr)))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("!target->isKind(ParseNodeKind::AssignExpr)"
" (" "for-in/of loop destructuring declarations can't have initializers"
")", "./../../../../js/src/frontend/BytecodeEmitter.cpp", 5918
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!target->isKind(ParseNodeKind::AssignExpr)"
") (" "for-in/of loop destructuring declarations can't have initializers"
")"); do { MOZ_CrashSequence(__null, 5918); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5919
5920 MOZ_ASSERT(target->isKind(ParseNodeKind::ArrayExpr) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(target->isKind(ParseNodeKind::ArrayExpr) || target
->isKind(ParseNodeKind::ObjectExpr))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(target->isKind(ParseNodeKind
::ArrayExpr) || target->isKind(ParseNodeKind::ObjectExpr))
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("target->isKind(ParseNodeKind::ArrayExpr) || target->isKind(ParseNodeKind::ObjectExpr)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 5921);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "target->isKind(ParseNodeKind::ArrayExpr) || target->isKind(ParseNodeKind::ObjectExpr)"
")"); do { MOZ_CrashSequence(__null, 5921); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5921 target->isKind(ParseNodeKind::ObjectExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(target->isKind(ParseNodeKind::ArrayExpr) || target
->isKind(ParseNodeKind::ObjectExpr))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(target->isKind(ParseNodeKind
::ArrayExpr) || target->isKind(ParseNodeKind::ObjectExpr))
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("target->isKind(ParseNodeKind::ArrayExpr) || target->isKind(ParseNodeKind::ObjectExpr)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 5921);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "target->isKind(ParseNodeKind::ArrayExpr) || target->isKind(ParseNodeKind::ObjectExpr)"
")"); do { MOZ_CrashSequence(__null, 5921); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5922 return emitDestructuringOps(&target->as<ListNode>(),
5923 DestructuringFlavor::Declaration,
5924 SelfHostedIter::Deny);
5925}
5926
5927bool BytecodeEmitter::emitForOf(ForNode* forOfLoop,
5928 const EmitterScope* headLexicalEmitterScope) {
5929 MOZ_ASSERT(forOfLoop->isKind(ParseNodeKind::ForStmt))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(forOfLoop->isKind(ParseNodeKind::ForStmt))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(forOfLoop->isKind(ParseNodeKind::ForStmt)))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("forOfLoop->isKind(ParseNodeKind::ForStmt)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 5929);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfLoop->isKind(ParseNodeKind::ForStmt)"
")"); do { MOZ_CrashSequence(__null, 5929); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5930
5931 TernaryNode* forOfHead = forOfLoop->head();
5932 MOZ_ASSERT(forOfHead->isKind(ParseNodeKind::ForOf))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(forOfHead->isKind(ParseNodeKind::ForOf))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(forOfHead->isKind(ParseNodeKind::ForOf)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("forOfHead->isKind(ParseNodeKind::ForOf)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 5932);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfHead->isKind(ParseNodeKind::ForOf)"
")"); do { MOZ_CrashSequence(__null, 5932); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5933
5934 unsigned iflags = forOfLoop->iflags();
5935 IteratorKind iterKind =
5936 (iflags & JSITER_FORAWAITOF0x80) ? IteratorKind::Async : IteratorKind::Sync;
5937 MOZ_ASSERT_IF(iterKind == IteratorKind::Async, sc->isSuspendableContext())do { if (iterKind == IteratorKind::Async) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(sc->
isSuspendableContext())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sc->isSuspendableContext(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("sc->isSuspendableContext()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 5937); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isSuspendableContext()"
")"); do { MOZ_CrashSequence(__null, 5937); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
5938 MOZ_ASSERT_IF(iterKind == IteratorKind::Async,do { if (iterKind == IteratorKind::Async) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(sc->
asSuspendableContext()->isAsync())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sc->asSuspendableContext(
)->isAsync()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("sc->asSuspendableContext()->isAsync()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 5939); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->asSuspendableContext()->isAsync()"
")"); do { MOZ_CrashSequence(__null, 5939); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
5939 sc->asSuspendableContext()->isAsync())do { if (iterKind == IteratorKind::Async) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(sc->
asSuspendableContext()->isAsync())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sc->asSuspendableContext(
)->isAsync()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("sc->asSuspendableContext()->isAsync()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 5939); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->asSuspendableContext()->isAsync()"
")"); do { MOZ_CrashSequence(__null, 5939); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
5940
5941 ParseNode* forHeadExpr = forOfHead->kid3();
5942
5943 // Certain builtins (e.g. Array.from) are implemented in self-hosting
5944 // as for-of loops.
5945 auto selfHostedIter = getSelfHostedIterFor(forHeadExpr);
5946 ForOfEmitter::HeadUsingDeclarationKind headUsingDeclKind =
5947 ForOfEmitter::HeadUsingDeclarationKind::None;
5948 if (forOfHead->kid1()->isKind(ParseNodeKind::UsingDecl)) {
5949 headUsingDeclKind = ForOfEmitter::HeadUsingDeclarationKind::Sync;
5950 } else if (forOfHead->kid1()->isKind(ParseNodeKind::AwaitUsingDecl)) {
5951 headUsingDeclKind = ForOfEmitter::HeadUsingDeclarationKind::Async;
5952 }
5953
5954 ForOfEmitter forOf(this, headLexicalEmitterScope, selfHostedIter, iterKind,
5955 headUsingDeclKind);
5956
5957 if (!forOf.emitIterated()) {
5958 // [stack]
5959 return false;
5960 }
5961
5962 if (!updateSourceCoordNotes(forHeadExpr->pn_pos.begin)) {
5963 return false;
5964 }
5965 if (!markStepBreakpoint()) {
5966 return false;
5967 }
5968 if (!emitIterable(forHeadExpr, selfHostedIter, iterKind)) {
5969 // [stack] ITERABLE
5970 return false;
5971 }
5972
5973 if (headLexicalEmitterScope) {
5974 DebugOnly<ParseNode*> forOfTarget = forOfHead->kid1();
5975 MOZ_ASSERT(forOfTarget->isKind(ParseNodeKind::LetDecl) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget
->isKind(ParseNodeKind::ConstDecl) || forOfTarget->isKind
(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind
::AwaitUsingDecl))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(forOfTarget->isKind(ParseNodeKind
::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl
) || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget
->isKind(ParseNodeKind::AwaitUsingDecl)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl) || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 5978);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl) || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)"
")"); do { MOZ_CrashSequence(__null, 5978); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5976 forOfTarget->isKind(ParseNodeKind::ConstDecl) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget
->isKind(ParseNodeKind::ConstDecl) || forOfTarget->isKind
(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind
::AwaitUsingDecl))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(forOfTarget->isKind(ParseNodeKind
::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl
) || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget
->isKind(ParseNodeKind::AwaitUsingDecl)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl) || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 5978);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl) || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)"
")"); do { MOZ_CrashSequence(__null, 5978); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5977 forOfTarget->isKind(ParseNodeKind::UsingDecl) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget
->isKind(ParseNodeKind::ConstDecl) || forOfTarget->isKind
(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind
::AwaitUsingDecl))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(forOfTarget->isKind(ParseNodeKind
::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl
) || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget
->isKind(ParseNodeKind::AwaitUsingDecl)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl) || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 5978);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl) || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)"
")"); do { MOZ_CrashSequence(__null, 5978); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5978 forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget
->isKind(ParseNodeKind::ConstDecl) || forOfTarget->isKind
(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind
::AwaitUsingDecl))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(forOfTarget->isKind(ParseNodeKind
::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl
) || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget
->isKind(ParseNodeKind::AwaitUsingDecl)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl) || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 5978);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl) || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)"
")"); do { MOZ_CrashSequence(__null, 5978); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5979 }
5980
5981 if (!forOf.emitInitialize(forOfHead->pn_pos.begin)) {
5982 // [stack] NEXT ITER VALUE
5983 return false;
5984 }
5985
5986 if (!emitInitializeForInOrOfTarget(forOfHead)) {
5987 // [stack] NEXT ITER VALUE
5988 return false;
5989 }
5990
5991 if (!forOf.emitBody()) {
5992 // [stack] NEXT ITER UNDEF
5993 return false;
5994 }
5995
5996 // Perform the loop body.
5997 ParseNode* forBody = forOfLoop->body();
5998 if (!emitTree(forBody)) {
5999 // [stack] NEXT ITER UNDEF
6000 return false;
6001 }
6002
6003 if (!forOf.emitEnd(forHeadExpr->pn_pos.begin)) {
6004 // [stack]
6005 return false;
6006 }
6007
6008 return true;
6009}
6010
6011bool BytecodeEmitter::emitForIn(ForNode* forInLoop,
6012 const EmitterScope* headLexicalEmitterScope) {
6013 TernaryNode* forInHead = forInLoop->head();
6014 MOZ_ASSERT(forInHead->isKind(ParseNodeKind::ForIn))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(forInHead->isKind(ParseNodeKind::ForIn))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(forInHead->isKind(ParseNodeKind::ForIn)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("forInHead->isKind(ParseNodeKind::ForIn)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 6014);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInHead->isKind(ParseNodeKind::ForIn)"
")"); do { MOZ_CrashSequence(__null, 6014); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6015
6016 ForInEmitter forIn(this, headLexicalEmitterScope);
6017
6018 // Annex B: Evaluate the var-initializer expression if present.
6019 // |for (var i = initializer in expr) { ... }|
6020 ParseNode* forInTarget = forInHead->kid1();
6021 if (forInTarget->is<DeclarationListNode>()) {
6022 auto* declarationList = &forInTarget->as<DeclarationListNode>();
6023
6024 ParseNode* decl = declarationList->singleBinding();
6025 if (decl->isKind(ParseNodeKind::AssignExpr)) {
6026 BinaryNode* assignNode = &decl->as<BinaryNode>();
6027 if (assignNode->left()->is<NameNode>()) {
6028 NameNode* nameNode = &assignNode->left()->as<NameNode>();
6029 ParseNode* initializer = assignNode->right();
6030 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(forInTarget->isKind(ParseNodeKind::VarStmt))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(forInTarget->isKind(ParseNodeKind::VarStmt)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("forInTarget->isKind(ParseNodeKind::VarStmt)"
" (" "for-in initializers are only permitted for |var| declarations"
")", "./../../../../js/src/frontend/BytecodeEmitter.cpp", 6032
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInTarget->isKind(ParseNodeKind::VarStmt)"
") (" "for-in initializers are only permitted for |var| declarations"
")"); do { MOZ_CrashSequence(__null, 6032); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6031 forInTarget->isKind(ParseNodeKind::VarStmt),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(forInTarget->isKind(ParseNodeKind::VarStmt))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(forInTarget->isKind(ParseNodeKind::VarStmt)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("forInTarget->isKind(ParseNodeKind::VarStmt)"
" (" "for-in initializers are only permitted for |var| declarations"
")", "./../../../../js/src/frontend/BytecodeEmitter.cpp", 6032
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInTarget->isKind(ParseNodeKind::VarStmt)"
") (" "for-in initializers are only permitted for |var| declarations"
")"); do { MOZ_CrashSequence(__null, 6032); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6032 "for-in initializers are only permitted for |var| declarations")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(forInTarget->isKind(ParseNodeKind::VarStmt))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(forInTarget->isKind(ParseNodeKind::VarStmt)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("forInTarget->isKind(ParseNodeKind::VarStmt)"
" (" "for-in initializers are only permitted for |var| declarations"
")", "./../../../../js/src/frontend/BytecodeEmitter.cpp", 6032
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInTarget->isKind(ParseNodeKind::VarStmt)"
") (" "for-in initializers are only permitted for |var| declarations"
")"); do { MOZ_CrashSequence(__null, 6032); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6033
6034 if (!updateSourceCoordNotes(decl->pn_pos.begin)) {
6035 return false;
6036 }
6037
6038 auto nameAtom = nameNode->name();
6039 NameOpEmitter noe(this, nameAtom, NameOpEmitter::Kind::Initialize);
6040 if (!noe.prepareForRhs()) {
6041 return false;
6042 }
6043 if (!emitInitializer(initializer, nameNode)) {
6044 return false;
6045 }
6046 if (!noe.emitAssignment()) {
6047 return false;
6048 }
6049
6050 // Pop the initializer.
6051 if (!emit1(JSOp::Pop)) {
6052 return false;
6053 }
6054 }
6055 }
6056 }
6057
6058 if (!forIn.emitIterated()) {
6059 // [stack]
6060 return false;
6061 }
6062
6063 // Evaluate the expression being iterated.
6064 ParseNode* expr = forInHead->kid3();
6065
6066 if (!updateSourceCoordNotes(expr->pn_pos.begin)) {
6067 return false;
6068 }
6069 if (!markStepBreakpoint()) {
6070 return false;
6071 }
6072 if (!emitTree(expr)) {
6073 // [stack] EXPR
6074 return false;
6075 }
6076
6077 MOZ_ASSERT(forInLoop->iflags() == 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(forInLoop->iflags() == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(forInLoop->iflags() == 0)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("forInLoop->iflags() == 0"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 6077);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInLoop->iflags() == 0"
")"); do { MOZ_CrashSequence(__null, 6077); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6078
6079 MOZ_ASSERT_IF(headLexicalEmitterScope,do { if (headLexicalEmitterScope) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(forInTarget->
isKind(ParseNodeKind::LetDecl) || forInTarget->isKind(ParseNodeKind
::ConstDecl))>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(forInTarget->isKind(ParseNodeKind
::LetDecl) || forInTarget->isKind(ParseNodeKind::ConstDecl
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("forInTarget->isKind(ParseNodeKind::LetDecl) || forInTarget->isKind(ParseNodeKind::ConstDecl)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 6081);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInTarget->isKind(ParseNodeKind::LetDecl) || forInTarget->isKind(ParseNodeKind::ConstDecl)"
")"); do { MOZ_CrashSequence(__null, 6081); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
6080 forInTarget->isKind(ParseNodeKind::LetDecl) ||do { if (headLexicalEmitterScope) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(forInTarget->
isKind(ParseNodeKind::LetDecl) || forInTarget->isKind(ParseNodeKind
::ConstDecl))>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(forInTarget->isKind(ParseNodeKind
::LetDecl) || forInTarget->isKind(ParseNodeKind::ConstDecl
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("forInTarget->isKind(ParseNodeKind::LetDecl) || forInTarget->isKind(ParseNodeKind::ConstDecl)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 6081);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInTarget->isKind(ParseNodeKind::LetDecl) || forInTarget->isKind(ParseNodeKind::ConstDecl)"
")"); do { MOZ_CrashSequence(__null, 6081); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
6081 forInTarget->isKind(ParseNodeKind::ConstDecl))do { if (headLexicalEmitterScope) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(forInTarget->
isKind(ParseNodeKind::LetDecl) || forInTarget->isKind(ParseNodeKind
::ConstDecl))>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(forInTarget->isKind(ParseNodeKind
::LetDecl) || forInTarget->isKind(ParseNodeKind::ConstDecl
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("forInTarget->isKind(ParseNodeKind::LetDecl) || forInTarget->isKind(ParseNodeKind::ConstDecl)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 6081);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInTarget->isKind(ParseNodeKind::LetDecl) || forInTarget->isKind(ParseNodeKind::ConstDecl)"
")"); do { MOZ_CrashSequence(__null, 6081); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
6082
6083 if (!forIn.emitInitialize()) {
6084 // [stack] ITER ITERVAL
6085 return false;
6086 }
6087
6088 if (!emitInitializeForInOrOfTarget(forInHead)) {
6089 // [stack] ITER ITERVAL
6090 return false;
6091 }
6092
6093 if (!forIn.emitBody()) {
6094 // [stack] ITER ITERVAL
6095 return false;
6096 }
6097
6098 // Perform the loop body.
6099 ParseNode* forBody = forInLoop->body();
6100 if (!emitTree(forBody)) {
6101 // [stack] ITER ITERVAL
6102 return false;
6103 }
6104
6105 if (!forIn.emitEnd(forInHead->pn_pos.begin)) {
6106 // [stack]
6107 return false;
6108 }
6109
6110 return true;
6111}
6112
6113/* C-style `for (init; cond; update) ...` loop. */
6114bool BytecodeEmitter::emitCStyleFor(
6115 ForNode* forNode, const EmitterScope* headLexicalEmitterScope) {
6116 TernaryNode* forHead = forNode->head();
6117 ParseNode* forBody = forNode->body();
6118 ParseNode* init = forHead->kid1();
6119 ParseNode* cond = forHead->kid2();
6120 ParseNode* update = forHead->kid3();
6121 bool isLet = init && init->isKind(ParseNodeKind::LetDecl);
6122
6123 CForEmitter cfor(this, isLet ? headLexicalEmitterScope : nullptr);
6124
6125 if (!cfor.emitInit(init ? Some(init->pn_pos.begin) : Nothing())) {
6126 // [stack]
6127 return false;
6128 }
6129
6130 // If the head of this for-loop declared any lexical variables, the parser
6131 // wrapped this ParseNodeKind::For node in a ParseNodeKind::LexicalScope
6132 // representing the implicit scope of those variables. By the time we get
6133 // here, we have already entered that scope. So far, so good.
6134 if (init) {
6135 // Emit the `init` clause, whether it's an expression or a variable
6136 // declaration. (The loop variables were hoisted into an enclosing
6137 // scope, but we still need to emit code for the initializers.)
6138 if (init->is<DeclarationListNode>()) {
6139 MOZ_ASSERT(!init->as<DeclarationListNode>().empty())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!init->as<DeclarationListNode>().empty())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!init->as<DeclarationListNode>().empty())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("!init->as<DeclarationListNode>().empty()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 6139);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!init->as<DeclarationListNode>().empty()"
")"); do { MOZ_CrashSequence(__null, 6139); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6140
6141 if (!emitTree(init)) {
6142 // [stack]
6143 return false;
6144 }
6145 } else {
6146 if (!updateSourceCoordNotes(init->pn_pos.begin)) {
6147 return false;
6148 }
6149 if (!markStepBreakpoint()) {
6150 return false;
6151 }
6152
6153 // 'init' is an expression, not a declaration. emitTree left its
6154 // value on the stack.
6155 if (!emitTree(init, ValueUsage::IgnoreValue)) {
6156 // [stack] VAL
6157 return false;
6158 }
6159 if (!emit1(JSOp::Pop)) {
6160 // [stack]
6161 return false;
6162 }
6163 }
6164 }
6165
6166 if (!cfor.emitCond(cond ? Some(cond->pn_pos.begin) : Nothing())) {
6167 // [stack]
6168 return false;
6169 }
6170
6171 if (cond) {
6172 if (!updateSourceCoordNotes(cond->pn_pos.begin)) {
6173 return false;
6174 }
6175 if (!markStepBreakpoint()) {
6176 return false;
6177 }
6178 if (!emitTree(cond)) {
6179 // [stack] VAL
6180 return false;
6181 }
6182 }
6183
6184 if (!cfor.emitBody(cond ? CForEmitter::Cond::Present
6185 : CForEmitter::Cond::Missing)) {
6186 // [stack]
6187 return false;
6188 }
6189
6190 if (!emitTree(forBody)) {
6191 // [stack]
6192 return false;
6193 }
6194
6195 if (!cfor.emitUpdate(
6196 update ? CForEmitter::Update::Present : CForEmitter::Update::Missing,
6197 update ? Some(update->pn_pos.begin) : Nothing())) {
6198 // [stack]
6199 return false;
6200 }
6201
6202 // Check for update code to do before the condition (if any).
6203 if (update) {
6204 if (!updateSourceCoordNotes(update->pn_pos.begin)) {
6205 return false;
6206 }
6207 if (!markStepBreakpoint()) {
6208 return false;
6209 }
6210 if (!emitTree(update, ValueUsage::IgnoreValue)) {
6211 // [stack] VAL
6212 return false;
6213 }
6214 }
6215
6216 if (!cfor.emitEnd(forNode->pn_pos.begin)) {
6217 // [stack]
6218 return false;
6219 }
6220
6221 return true;
6222}
6223
6224bool BytecodeEmitter::emitFor(ForNode* forNode,
6225 const EmitterScope* headLexicalEmitterScope) {
6226 if (forNode->head()->isKind(ParseNodeKind::ForHead)) {
6227 return emitCStyleFor(forNode, headLexicalEmitterScope);
6228 }
6229
6230 if (!updateLineNumberNotes(forNode->pn_pos.begin)) {
6231 return false;
6232 }
6233
6234 if (forNode->head()->isKind(ParseNodeKind::ForIn)) {
6235 return emitForIn(forNode, headLexicalEmitterScope);
6236 }
6237
6238 MOZ_ASSERT(forNode->head()->isKind(ParseNodeKind::ForOf))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(forNode->head()->isKind(ParseNodeKind::ForOf))
>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(forNode->head()->isKind(ParseNodeKind::ForOf))
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("forNode->head()->isKind(ParseNodeKind::ForOf)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 6238);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "forNode->head()->isKind(ParseNodeKind::ForOf)"
")"); do { MOZ_CrashSequence(__null, 6238); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6239 return emitForOf(forNode, headLexicalEmitterScope);
6240}
6241
6242MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitFunction(
6243 FunctionNode* funNode, bool needsProto /* = false */) {
6244 FunctionBox* funbox = funNode->funbox();
6245
6246 // [stack]
6247
6248 FunctionEmitter fe(this, funbox, funNode->syntaxKind(),
6249 funNode->functionIsHoisted()
6250 ? FunctionEmitter::IsHoisted::Yes
6251 : FunctionEmitter::IsHoisted::No);
6252
6253 // |wasEmittedByEnclosingScript| flag is set to true once the function has
6254 // been emitted. Function definitions that need hoisting to the top of the
6255 // function will be seen by emitFunction in two places.
6256 if (funbox->wasEmittedByEnclosingScript()) {
6257 if (!fe.emitAgain()) {
6258 // [stack]
6259 return false;
6260 }
6261 MOZ_ASSERT(funNode->functionIsHoisted())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(funNode->functionIsHoisted())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(funNode->functionIsHoisted
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("funNode->functionIsHoisted()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 6261); AnnotateMozCrashReason("MOZ_ASSERT" "(" "funNode->functionIsHoisted()"
")"); do { MOZ_CrashSequence(__null, 6261); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6262 } else {
6263 MOZ_ASSERT(funbox->isInterpreted())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(funbox->isInterpreted())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(funbox->isInterpreted()))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("funbox->isInterpreted()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 6263);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "funbox->isInterpreted()"
")"); do { MOZ_CrashSequence(__null, 6263); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6264 if (!funbox->emitBytecode) {
6265 return fe.emitLazy();
6266 // [stack] FUN?
6267 }
6268
6269 if (!fe.prepareForNonLazy()) {
6270 // [stack]
6271 return false;
6272 }
6273
6274 BytecodeEmitter bce2(this, funbox);
6275 if (!bce2.init(funNode->pn_pos)) {
6276 return false;
6277 }
6278
6279 /* We measured the max scope depth when we parsed the function. */
6280 if (!bce2.emitFunctionScript(funNode)) {
6281 return false;
6282 }
6283
6284 if (!fe.emitNonLazyEnd()) {
6285 // [stack] FUN?
6286 return false;
6287 }
6288 }
6289
6290 // Track the last emitted top-level self-hosted function, so that intrinsics
6291 // can adjust attributes at parse time.
6292 //
6293 // NOTE: We also disallow lambda functions in the top-level body. This is done
6294 // to simplify handling of the self-hosted stencil. Within normal function
6295 // declarations there are no such restrictions.
6296 if (emitterMode == EmitterMode::SelfHosting) {
6297 if (sc->isTopLevelContext()) {
6298 MOZ_ASSERT(!funbox->isLambda())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!funbox->isLambda())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!funbox->isLambda()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!funbox->isLambda()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 6298);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!funbox->isLambda()"
")"); do { MOZ_CrashSequence(__null, 6298); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6299 MOZ_ASSERT(funbox->explicitName())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(funbox->explicitName())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(funbox->explicitName())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("funbox->explicitName()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 6299);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "funbox->explicitName()"
")"); do { MOZ_CrashSequence(__null, 6299); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6300 prevSelfHostedTopLevelFunction = funbox;
6301 }
6302 }
6303
6304 return true;
6305}
6306
6307bool BytecodeEmitter::emitDo(BinaryNode* doNode) {
6308 ParseNode* bodyNode = doNode->left();
6309
6310 DoWhileEmitter doWhile(this);
6311 if (!doWhile.emitBody(doNode->pn_pos.begin, getOffsetForLoop(bodyNode))) {
6312 return false;
6313 }
6314
6315 if (!emitTree(bodyNode)) {
6316 return false;
6317 }
6318
6319 if (!doWhile.emitCond()) {
6320 return false;
6321 }
6322
6323 ParseNode* condNode = doNode->right();
6324 if (!updateSourceCoordNotes(condNode->pn_pos.begin)) {
6325 return false;
6326 }
6327 if (!markStepBreakpoint()) {
6328 return false;
6329 }
6330 if (!emitTree(condNode)) {
6331 return false;
6332 }
6333
6334 if (!doWhile.emitEnd()) {
6335 return false;
6336 }
6337
6338 return true;
6339}
6340
6341bool BytecodeEmitter::emitWhile(BinaryNode* whileNode) {
6342 ParseNode* bodyNode = whileNode->right();
6343
6344 WhileEmitter wh(this);
6345
6346 ParseNode* condNode = whileNode->left();
6347 if (!wh.emitCond(whileNode->pn_pos.begin, getOffsetForLoop(condNode),
6348 whileNode->pn_pos.end)) {
6349 return false;
6350 }
6351
6352 if (!updateSourceCoordNotes(condNode->pn_pos.begin)) {
6353 return false;
6354 }
6355 if (!markStepBreakpoint()) {
6356 return false;
6357 }
6358 if (!emitTree(condNode)) {
6359 return false;
6360 }
6361
6362 if (!wh.emitBody()) {
6363 return false;
6364 }
6365 if (!emitTree(bodyNode)) {
6366 return false;
6367 }
6368
6369 if (!wh.emitEnd()) {
6370 return false;
6371 }
6372
6373 return true;
6374}
6375
6376bool BytecodeEmitter::emitBreak(TaggedParserAtomIndex label) {
6377 BreakableControl* target;
6378 if (label) {
6379 // Any statement with the matching label may be the break target.
6380 auto hasSameLabel = [label](LabelControl* labelControl) {
6381 return labelControl->label() == label;
6382 };
6383 target = findInnermostNestableControl<LabelControl>(hasSameLabel);
6384 } else {
6385 auto isNotLabel = [](BreakableControl* control) {
6386 return !control->is<LabelControl>();
6387 };
6388 target = findInnermostNestableControl<BreakableControl>(isNotLabel);
6389 }
6390
6391 return emitGoto(target, GotoKind::Break);
6392}
6393
6394bool BytecodeEmitter::emitContinue(TaggedParserAtomIndex label) {
6395 LoopControl* target = nullptr;
6396 if (label) {
6397 // Find the loop statement enclosed by the matching label.
6398 NestableControl* control = innermostNestableControl;
6399 while (!control->is<LabelControl>() ||
6400 control->as<LabelControl>().label() != label) {
6401 if (control->is<LoopControl>()) {
6402 target = &control->as<LoopControl>();
6403 }
6404 control = control->enclosing();
6405 }
6406 } else {
6407 target = findInnermostNestableControl<LoopControl>();
6408 }
6409 return emitGoto(target, GotoKind::Continue);
6410}
6411
6412bool BytecodeEmitter::emitGetFunctionThis(NameNode* thisName) {
6413 MOZ_ASSERT(sc->hasFunctionThisBinding())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sc->hasFunctionThisBinding())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sc->hasFunctionThisBinding
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("sc->hasFunctionThisBinding()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 6413); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->hasFunctionThisBinding()"
")"); do { MOZ_CrashSequence(__null, 6413); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6414 MOZ_ASSERT(thisName->isName(TaggedParserAtomIndex::WellKnown::dot_this_()))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(thisName->isName(TaggedParserAtomIndex::WellKnown
::dot_this_()))>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(thisName->isName(TaggedParserAtomIndex
::WellKnown::dot_this_())))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("thisName->isName(TaggedParserAtomIndex::WellKnown::dot_this_())"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 6414);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "thisName->isName(TaggedParserAtomIndex::WellKnown::dot_this_())"
")"); do { MOZ_CrashSequence(__null, 6414); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6415
6416 if (!updateLineNumberNotes(thisName->pn_pos.begin)) {
6417 return false;
6418 }
6419
6420 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_this_())) {
6421 // [stack] THIS
6422 return false;
6423 }
6424 if (sc->needsThisTDZChecks()) {
6425 if (!emit1(JSOp::CheckThis)) {
6426 // [stack] THIS
6427 return false;
6428 }
6429 }
6430
6431 return true;
6432}
6433
6434bool BytecodeEmitter::emitGetThisForSuperBase(UnaryNode* superBase) {
6435 MOZ_ASSERT(superBase->isKind(ParseNodeKind::SuperBase))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(superBase->isKind(ParseNodeKind::SuperBase))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(superBase->isKind(ParseNodeKind::SuperBase)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("superBase->isKind(ParseNodeKind::SuperBase)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 6435);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "superBase->isKind(ParseNodeKind::SuperBase)"
")"); do { MOZ_CrashSequence(__null, 6435); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6436 NameNode* nameNode = &superBase->kid()->as<NameNode>();
6437 return emitGetFunctionThis(nameNode);
6438 // [stack] THIS
6439}
6440
6441bool BytecodeEmitter::emitThisLiteral(ThisLiteral* pn) {
6442 if (ParseNode* kid = pn->kid()) {
6443 NameNode* thisName = &kid->as<NameNode>();
6444 return emitGetFunctionThis(thisName);
6445 // [stack] THIS
6446 }
6447
6448 if (sc->thisBinding() == ThisBinding::Module) {
6449 return emit1(JSOp::Undefined);
6450 // [stack] UNDEF
6451 }
6452
6453 MOZ_ASSERT(sc->thisBinding() == ThisBinding::Global)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sc->thisBinding() == ThisBinding::Global)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(sc->thisBinding() == ThisBinding::Global))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("sc->thisBinding() == ThisBinding::Global"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 6453);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->thisBinding() == ThisBinding::Global"
")"); do { MOZ_CrashSequence(__null, 6453); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6454
6455 MOZ_ASSERT(outermostScope().hasNonSyntacticScopeOnChain() ==do { static_assert( mozilla::detail::AssertionConditionType<
decltype(outermostScope().hasNonSyntacticScopeOnChain() == sc
->hasNonSyntacticScope())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(outermostScope().hasNonSyntacticScopeOnChain
() == sc->hasNonSyntacticScope()))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("outermostScope().hasNonSyntacticScopeOnChain() == sc->hasNonSyntacticScope()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 6456);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "outermostScope().hasNonSyntacticScopeOnChain() == sc->hasNonSyntacticScope()"
")"); do { MOZ_CrashSequence(__null, 6456); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6456 sc->hasNonSyntacticScope())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(outermostScope().hasNonSyntacticScopeOnChain() == sc
->hasNonSyntacticScope())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(outermostScope().hasNonSyntacticScopeOnChain
() == sc->hasNonSyntacticScope()))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("outermostScope().hasNonSyntacticScopeOnChain() == sc->hasNonSyntacticScope()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 6456);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "outermostScope().hasNonSyntacticScopeOnChain() == sc->hasNonSyntacticScope()"
")"); do { MOZ_CrashSequence(__null, 6456); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6457 if (sc->hasNonSyntacticScope()) {
6458 return emit1(JSOp::NonSyntacticGlobalThis);
6459 // [stack] THIS
6460 }
6461
6462 return emit1(JSOp::GlobalThis);
6463 // [stack] THIS
6464}
6465
6466bool BytecodeEmitter::emitCheckDerivedClassConstructorReturn() {
6467 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(lookupName(TaggedParserAtomIndex::WellKnown::dot_this_
()).hasKnownSlot())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(lookupName(TaggedParserAtomIndex
::WellKnown::dot_this_()).hasKnownSlot()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("lookupName(TaggedParserAtomIndex::WellKnown::dot_this_()).hasKnownSlot()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 6468);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "lookupName(TaggedParserAtomIndex::WellKnown::dot_this_()).hasKnownSlot()"
")"); do { MOZ_CrashSequence(__null, 6468); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6468 lookupName(TaggedParserAtomIndex::WellKnown::dot_this_()).hasKnownSlot())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(lookupName(TaggedParserAtomIndex::WellKnown::dot_this_
()).hasKnownSlot())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(lookupName(TaggedParserAtomIndex
::WellKnown::dot_this_()).hasKnownSlot()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("lookupName(TaggedParserAtomIndex::WellKnown::dot_this_()).hasKnownSlot()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 6468);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "lookupName(TaggedParserAtomIndex::WellKnown::dot_this_()).hasKnownSlot()"
")"); do { MOZ_CrashSequence(__null, 6468); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6469 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_this_())) {
6470 return false;
6471 }
6472 if (!emit1(JSOp::CheckReturn)) {
6473 return false;
6474 }
6475 if (!emit1(JSOp::SetRval)) {
6476 return false;
6477 }
6478 return true;
6479}
6480
6481bool BytecodeEmitter::emitNewTarget() {
6482 MOZ_ASSERT(sc->allowNewTarget())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sc->allowNewTarget())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sc->allowNewTarget()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("sc->allowNewTarget()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 6482);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->allowNewTarget()"
")"); do { MOZ_CrashSequence(__null, 6482); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6483
6484 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_newTarget_())) {
6485 // [stack] NEW.TARGET
6486 return false;
6487 }
6488 return true;
6489}
6490
6491bool BytecodeEmitter::emitNewTarget(NewTargetNode* pn) {
6492 MOZ_ASSERT(pn->newTargetName()->isName(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->newTargetName()->isName( TaggedParserAtomIndex
::WellKnown::dot_newTarget_()))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->newTargetName()->isName
( TaggedParserAtomIndex::WellKnown::dot_newTarget_())))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("pn->newTargetName()->isName( TaggedParserAtomIndex::WellKnown::dot_newTarget_())"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 6493);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->newTargetName()->isName( TaggedParserAtomIndex::WellKnown::dot_newTarget_())"
")"); do { MOZ_CrashSequence(__null, 6493); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6493 TaggedParserAtomIndex::WellKnown::dot_newTarget_()))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->newTargetName()->isName( TaggedParserAtomIndex
::WellKnown::dot_newTarget_()))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->newTargetName()->isName
( TaggedParserAtomIndex::WellKnown::dot_newTarget_())))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("pn->newTargetName()->isName( TaggedParserAtomIndex::WellKnown::dot_newTarget_())"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 6493);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->newTargetName()->isName( TaggedParserAtomIndex::WellKnown::dot_newTarget_())"
")"); do { MOZ_CrashSequence(__null, 6493); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6494
6495 return emitNewTarget();
6496}
6497
6498bool BytecodeEmitter::emitNewTarget(CallNode* pn) {
6499 MOZ_ASSERT(pn->callOp() == JSOp::SuperCall ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->callOp() == JSOp::SuperCall || pn->callOp(
) == JSOp::SpreadSuperCall)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->callOp() == JSOp::SuperCall
|| pn->callOp() == JSOp::SpreadSuperCall))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("pn->callOp() == JSOp::SuperCall || pn->callOp() == JSOp::SpreadSuperCall"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 6500);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->callOp() == JSOp::SuperCall || pn->callOp() == JSOp::SpreadSuperCall"
")"); do { MOZ_CrashSequence(__null, 6500); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6500 pn->callOp() == JSOp::SpreadSuperCall)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->callOp() == JSOp::SuperCall || pn->callOp(
) == JSOp::SpreadSuperCall)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->callOp() == JSOp::SuperCall
|| pn->callOp() == JSOp::SpreadSuperCall))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("pn->callOp() == JSOp::SuperCall || pn->callOp() == JSOp::SpreadSuperCall"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 6500);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->callOp() == JSOp::SuperCall || pn->callOp() == JSOp::SpreadSuperCall"
")"); do { MOZ_CrashSequence(__null, 6500); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6501
6502 // The parser is responsible for marking the "new.target" binding as being
6503 // implicitly used in super() calls.
6504 return emitNewTarget();
6505}
6506
6507bool BytecodeEmitter::emitReturn(UnaryNode* returnNode) {
6508 if (!updateSourceCoordNotes(returnNode->pn_pos.begin)) {
6509 return false;
6510 }
6511
6512 if (!markStepBreakpoint()) {
6513 return false;
6514 }
6515
6516 /* Push a return value */
6517 if (ParseNode* expr = returnNode->kid()) {
6518 if (!emitTree(expr)) {
6519 return false;
6520 }
6521
6522 if (sc->asSuspendableContext()->isAsync() &&
6523 sc->asSuspendableContext()->isGenerator()) {
6524 if (!emitAwaitInInnermostScope()) {
6525 return false;
6526 }
6527 }
6528 } else {
6529 /* No explicit return value provided */
6530 if (!emit1(JSOp::Undefined)) {
6531 return false;
6532 }
6533 }
6534
6535 // We know functionBodyEndPos is set because "return" is only
6536 // valid in a function, and so we've passed through
6537 // emitFunctionScript.
6538 if (!updateSourceCoordNotes(*functionBodyEndPos)) {
6539 return false;
6540 }
6541
6542 /*
6543 * The return value is currently on the stack. We would like to
6544 * generate JSOp::Return, but if we have work to do before returning,
6545 * we will instead generate JSOp::SetRval / JSOp::RetRval.
6546 *
6547 * We don't know whether we will need fixup code until after calling
6548 * prepareForNonLocalJumpToOutermost, so we start by generating
6549 * JSOp::SetRval, then mutate it to JSOp::Return in finishReturn if it
6550 * wasn't needed.
6551 */
6552 BytecodeOffset setRvalOffset = bytecodeSection().offset();
6553 if (!emit1(JSOp::SetRval)) {
6554 return false;
6555 }
6556
6557 NonLocalExitControl nle(this, NonLocalExitKind::Return);
6558 return nle.emitReturn(setRvalOffset);
6559}
6560
6561bool BytecodeEmitter::finishReturn(BytecodeOffset setRvalOffset) {
6562 // The return value is currently in rval. Depending on the current function,
6563 // we may have to do additional work before returning:
6564 // - Derived class constructors must check if the return value is an object.
6565 // - Generators and async functions must do a final yield.
6566 // - Non-async generators must return the value as an iterator result:
6567 // { value: <rval>, done: true }
6568 // - Non-generator async functions must resolve the function's result promise
6569 // with the value.
6570 //
6571 // If we have not generated any code since the SetRval that stored the return
6572 // value, we can also optimize the bytecode by rewriting that SetRval as a
6573 // JSOp::Return. See |emitReturn| above.
6574
6575 bool isDerivedClassConstructor =
6576 sc->isFunctionBox() && sc->asFunctionBox()->isDerivedClassConstructor();
6577 bool needsFinalYield =
6578 sc->isFunctionBox() && sc->asFunctionBox()->needsFinalYield();
6579 bool isSimpleReturn =
6580 setRvalOffset.valid() &&
6581 setRvalOffset + BytecodeOffsetDiff(JSOpLength_SetRval) ==
6582 bytecodeSection().offset();
6583
6584 if (isDerivedClassConstructor) {
6585 MOZ_ASSERT(!needsFinalYield)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!needsFinalYield)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!needsFinalYield))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("!needsFinalYield"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 6585);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!needsFinalYield" ")"
); do { MOZ_CrashSequence(__null, 6585); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6586 if (!emitJump(JSOp::Goto, &endOfDerivedClassConstructorBody)) {
6587 return false;
6588 }
6589 return true;
6590 }
6591
6592 if (needsFinalYield) {
6593 // A forced return from a `yield` expression can have extra values on the
6594 // expression stack. Pop them here.
6595 int32_t nvalues = bytecodeSection().stackDepth();
6596 if (nvalues > 0 && !emitPopN(nvalues)) {
6597 return false;
6598 }
6599 if (!emitJump(JSOp::Goto, &finalYields)) {
6600 return false;
6601 }
6602 return true;
6603 }
6604
6605 if (isSimpleReturn) {
6606 MOZ_ASSERT(JSOp(bytecodeSection().code()[setRvalOffset.value()]) ==do { static_assert( mozilla::detail::AssertionConditionType<
decltype(JSOp(bytecodeSection().code()[setRvalOffset.value()]
) == JSOp::SetRval)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(JSOp(bytecodeSection().code(
)[setRvalOffset.value()]) == JSOp::SetRval))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("JSOp(bytecodeSection().code()[setRvalOffset.value()]) == JSOp::SetRval"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 6607);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "JSOp(bytecodeSection().code()[setRvalOffset.value()]) == JSOp::SetRval"
")"); do { MOZ_CrashSequence(__null, 6607); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6607 JSOp::SetRval)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(JSOp(bytecodeSection().code()[setRvalOffset.value()]
) == JSOp::SetRval)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(JSOp(bytecodeSection().code(
)[setRvalOffset.value()]) == JSOp::SetRval))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("JSOp(bytecodeSection().code()[setRvalOffset.value()]) == JSOp::SetRval"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 6607);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "JSOp(bytecodeSection().code()[setRvalOffset.value()]) == JSOp::SetRval"
")"); do { MOZ_CrashSequence(__null, 6607); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6608 bytecodeSection().code()[setRvalOffset.value()] = jsbytecode(JSOp::Return);
6609 return true;
6610 }
6611
6612 // Nothing special needs to be done.
6613 return emitReturnRval();
6614}
6615
6616bool BytecodeEmitter::emitCheckYieldResumeKind() {
6617 // The bytecode below relies on Next being falsy and Throw/Return being
6618 // truthy.
6619 static_assert(uint8_t(GeneratorResumeKind::Next) == 0);
6620 static_assert(uint8_t(GeneratorResumeKind::Throw) != 0);
6621 static_assert(uint8_t(GeneratorResumeKind::Return) != 0);
6622
6623 const int32_t startDepth = bytecodeSection().stackDepth();
6624 // [stack] RVAL RESUMEKIND
6625
6626 if (!emit1(JSOp::Dup)) {
6627 // [stack] RVAL RESUMEKIND RESUMEKIND
6628 return false;
6629 }
6630 InternalIfEmitter ifNotNext(this);
6631 if (!ifNotNext.emitThen()) {
6632 // [stack] RVAL RESUMEKIND
6633 return false;
6634 }
6635
6636 // Handle Throw and Return.
6637 if (!emitPushResumeKind(GeneratorResumeKind::Throw)) {
6638 // [stack] RVAL RESUMEKIND THROW
6639 return false;
6640 }
6641 if (!emit1(JSOp::StrictEq)) {
6642 // [stack] RVAL (RESUMEKIND==Throw)
6643 return false;
6644 }
6645 InternalIfEmitter ifThrow(this);
6646 if (!ifThrow.emitThen()) {
6647 // [stack] RVAL
6648 return false;
6649 }
6650 if (!emit1(JSOp::Throw)) {
6651 // [stack]
6652 return false;
6653 }
6654 bytecodeSection().setStackDepth(startDepth - 1);
6655 if (!ifThrow.emitEnd()) {
6656 // [stack] RVAL
6657 return false;
6658 }
6659 if (!emit1(JSOp::SetRval)) {
6660 // [stack]
6661 return false;
6662 }
6663 {
6664 NonLocalExitControl nle(this, NonLocalExitKind::Return);
6665 if (!nle.emitReturn()) {
6666 return false;
6667 }
6668 }
6669
6670 bytecodeSection().setStackDepth(startDepth);
6671 if (!ifNotNext.emitEnd()) {
6672 // [stack] RVAL RESUMEKIND
6673 return false;
6674 }
6675 if (!emit1(JSOp::Pop)) {
6676 // [stack] RVAL
6677 return false;
6678 }
6679 return true;
6680}
6681
6682bool BytecodeEmitter::emitCheckAwaitResumeKind() {
6683 // An `await` is only resumed by a promise reaction, so we don't have to
6684 // handle the Return resume kind here, only Next and Throw.
6685 // See https://tc39.es/ecma262/#await.
6686
6687 // The bytecode below relies on Next being falsy and Throw being truthy.
6688 static_assert(uint8_t(GeneratorResumeKind::Next) == 0);
6689 static_assert(uint8_t(GeneratorResumeKind::Throw) != 0);
6690
6691 const int32_t startDepth = bytecodeSection().stackDepth();
6692 // [stack] RVAL RESUMEKIND
6693
6694 InternalIfEmitter ifThrow(this);
6695 if (!ifThrow.emitThen()) {
6696 // [stack] RVAL
6697 return false;
6698 }
6699 if (!emit1(JSOp::Throw)) {
6700 // [stack]
6701 return false;
6702 }
6703 bytecodeSection().setStackDepth(startDepth - 1);
6704 if (!ifThrow.emitEnd()) {
6705 // [stack] RVAL
6706 return false;
6707 }
6708 return true;
6709}
6710
6711bool BytecodeEmitter::emitGetDotGeneratorInScope(EmitterScope& currentScope) {
6712 if (!sc->isFunction() && sc->isModuleContext() &&
6713 sc->asModuleContext()->isAsync()) {
6714 NameLocation loc = *locationOfNameBoundInScopeType<ModuleScope>(
6715 TaggedParserAtomIndex::WellKnown::dot_generator_(), &currentScope);
6716 return emitGetNameAtLocation(
6717 TaggedParserAtomIndex::WellKnown::dot_generator_(), loc);
6718 }
6719 NameLocation loc = *locationOfNameBoundInScopeType<FunctionScope>(
6720 TaggedParserAtomIndex::WellKnown::dot_generator_(), &currentScope);
6721 return emitGetNameAtLocation(
6722 TaggedParserAtomIndex::WellKnown::dot_generator_(), loc);
6723}
6724
6725bool BytecodeEmitter::emitInitialYield(UnaryNode* yieldNode) {
6726 if (!emitTree(yieldNode->kid())) {
6727 return false;
6728 }
6729
6730 if (!emitYieldOp(JSOp::InitialYield)) {
6731 // [stack] RVAL RESUMEKIND
6732 return false;
6733 }
6734 if (!emitCheckYieldResumeKind()) {
6735 // [stack] RVAL
6736 return false;
6737 }
6738 if (!emit1(JSOp::Pop)) {
6739 // [stack]
6740 return false;
6741 }
6742
6743 return true;
6744}
6745
6746bool BytecodeEmitter::emitYield(UnaryNode* yieldNode) {
6747 MOZ_ASSERT(sc->isFunctionBox())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sc->isFunctionBox())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sc->isFunctionBox()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("sc->isFunctionBox()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 6747);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isFunctionBox()"
")"); do { MOZ_CrashSequence(__null, 6747); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6748 MOZ_ASSERT(sc->asFunctionBox()->isGenerator())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sc->asFunctionBox()->isGenerator())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(sc->asFunctionBox()->isGenerator()))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("sc->asFunctionBox()->isGenerator()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 6748);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->asFunctionBox()->isGenerator()"
")"); do { MOZ_CrashSequence(__null, 6748); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6749 MOZ_ASSERT(yieldNode->isKind(ParseNodeKind::YieldExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(yieldNode->isKind(ParseNodeKind::YieldExpr))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(yieldNode->isKind(ParseNodeKind::YieldExpr)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("yieldNode->isKind(ParseNodeKind::YieldExpr)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 6749);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "yieldNode->isKind(ParseNodeKind::YieldExpr)"
")"); do { MOZ_CrashSequence(__null, 6749); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6750
6751 bool needsIteratorResult = sc->asFunctionBox()->needsIteratorResult();
6752 if (needsIteratorResult) {
6753 if (!emitPrepareIteratorResult()) {
6754 // [stack] ITEROBJ
6755 return false;
6756 }
6757 }
6758 if (ParseNode* expr = yieldNode->kid()) {
6759 if (!emitTree(expr)) {
6760 // [stack] ITEROBJ? VAL
6761 return false;
6762 }
6763 } else {
6764 if (!emit1(JSOp::Undefined)) {
6765 // [stack] ITEROBJ? UNDEFINED
6766 return false;
6767 }
6768 }
6769
6770 if (sc->asSuspendableContext()->isAsync()) {
6771 MOZ_ASSERT(!needsIteratorResult)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!needsIteratorResult)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!needsIteratorResult))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("!needsIteratorResult"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 6771);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!needsIteratorResult"
")"); do { MOZ_CrashSequence(__null, 6771); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6772 if (!emitAwaitInInnermostScope()) {
6773 // [stack] RESULT
6774 return false;
6775 }
6776 }
6777
6778 if (needsIteratorResult) {
6779 if (!emitFinishIteratorResult(false)) {
6780 // [stack] ITEROBJ
6781 return false;
6782 }
6783 }
6784
6785 if (!emitGetDotGeneratorInInnermostScope()) {
6786 // [stack] # if needsIteratorResult
6787 // [stack] ITEROBJ .GENERATOR
6788 // [stack] # else
6789 // [stack] RESULT .GENERATOR
6790 return false;
6791 }
6792
6793 if (!emitYieldOp(JSOp::Yield)) {
6794 // [stack] YIELDRESULT RESUMEKIND
6795 return false;
6796 }
6797
6798 if (!emitCheckYieldResumeKind()) {
6799 // [stack] YIELDRESULT
6800 return false;
6801 }
6802
6803 return true;
6804}
6805
6806bool BytecodeEmitter::emitAwaitInInnermostScope(UnaryNode* awaitNode) {
6807 MOZ_ASSERT(sc->isSuspendableContext())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sc->isSuspendableContext())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sc->isSuspendableContext(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("sc->isSuspendableContext()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 6807); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isSuspendableContext()"
")"); do { MOZ_CrashSequence(__null, 6807); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6808 MOZ_ASSERT(awaitNode->isKind(ParseNodeKind::AwaitExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(awaitNode->isKind(ParseNodeKind::AwaitExpr))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(awaitNode->isKind(ParseNodeKind::AwaitExpr)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("awaitNode->isKind(ParseNodeKind::AwaitExpr)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 6808);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "awaitNode->isKind(ParseNodeKind::AwaitExpr)"
")"); do { MOZ_CrashSequence(__null, 6808); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6809
6810 if (!emitTree(awaitNode->kid())) {
6811 return false;
6812 }
6813 return emitAwaitInInnermostScope();
6814}
6815
6816bool BytecodeEmitter::emitAwaitInScope(EmitterScope& currentScope) {
6817 // Emit the CanSkipAwait fast path if this is a function script. The await
6818 // can't be skipped for modules: during InnerModuleEvaluation, we must yield
6819 // execution so other modules in the same module graph can run.
6820 mozilla::Maybe<InternalIfEmitter> ifCanSkip;
6821 if (sc->isFunctionBox()) {
6822 if (!emit1(JSOp::CanSkipAwait)) {
6823 // [stack] VALUE CANSKIP
6824 return false;
6825 }
6826
6827 if (!emit1(JSOp::MaybeExtractAwaitValue)) {
6828 // [stack] VALUE_OR_RESOLVED CANSKIP
6829 return false;
6830 }
6831
6832 ifCanSkip.emplace(this);
6833 if (!ifCanSkip->emitThen(IfEmitter::ConditionKind::Negative)) {
6834 // [stack] VALUE_OR_RESOLVED
6835 return false;
6836 }
6837 }
6838
6839 if (sc->asSuspendableContext()->needsPromiseResult()) {
6840 if (!emitGetDotGeneratorInScope(currentScope)) {
6841 // [stack] VALUE GENERATOR
6842 return false;
6843 }
6844 if (!emit1(JSOp::AsyncAwait)) {
6845 // [stack] PROMISE
6846 return false;
6847 }
6848 }
6849
6850 if (!emitGetDotGeneratorInScope(currentScope)) {
6851 // [stack] VALUE|PROMISE GENERATOR
6852 return false;
6853 }
6854 if (!emitYieldOp(JSOp::Await)) {
6855 // [stack] RESOLVED RESUMEKIND
6856 return false;
6857 }
6858 if (!emitCheckAwaitResumeKind()) {
6859 // [stack] RESOLVED
6860 return false;
6861 }
6862
6863 if (ifCanSkip.isSome()) {
6864 if (!ifCanSkip->emitEnd()) {
6865 return false;
6866 }
6867 MOZ_ASSERT(ifCanSkip->popped() == 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(ifCanSkip->popped() == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(ifCanSkip->popped() == 0)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("ifCanSkip->popped() == 0"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 6867);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "ifCanSkip->popped() == 0"
")"); do { MOZ_CrashSequence(__null, 6867); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6868 }
6869
6870 return true;
6871}
6872
6873// ES2019 draft rev 49b781ec80117b60f73327ef3054703a3111e40c
6874// 14.4.14 Runtime Semantics: Evaluation
6875// YieldExpression : yield* AssignmentExpression
6876bool BytecodeEmitter::emitYieldStar(ParseNode* iter) {
6877 MOZ_ASSERT(getSelfHostedIterFor(iter) == SelfHostedIter::Deny,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(getSelfHostedIterFor(iter) == SelfHostedIter::Deny)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(getSelfHostedIterFor(iter) == SelfHostedIter::Deny))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("getSelfHostedIterFor(iter) == SelfHostedIter::Deny"
" (" "yield* is prohibited in self-hosted code because it can run "
"user-modifiable iteration code" ")", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 6879); AnnotateMozCrashReason("MOZ_ASSERT" "(" "getSelfHostedIterFor(iter) == SelfHostedIter::Deny"
") (" "yield* is prohibited in self-hosted code because it can run "
"user-modifiable iteration code" ")"); do { MOZ_CrashSequence
(__null, 6879); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
6878 "yield* is prohibited in self-hosted code because it can run "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(getSelfHostedIterFor(iter) == SelfHostedIter::Deny)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(getSelfHostedIterFor(iter) == SelfHostedIter::Deny))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("getSelfHostedIterFor(iter) == SelfHostedIter::Deny"
" (" "yield* is prohibited in self-hosted code because it can run "
"user-modifiable iteration code" ")", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 6879); AnnotateMozCrashReason("MOZ_ASSERT" "(" "getSelfHostedIterFor(iter) == SelfHostedIter::Deny"
") (" "yield* is prohibited in self-hosted code because it can run "
"user-modifiable iteration code" ")"); do { MOZ_CrashSequence
(__null, 6879); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
6879 "user-modifiable iteration code")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(getSelfHostedIterFor(iter) == SelfHostedIter::Deny)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(getSelfHostedIterFor(iter) == SelfHostedIter::Deny))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("getSelfHostedIterFor(iter) == SelfHostedIter::Deny"
" (" "yield* is prohibited in self-hosted code because it can run "
"user-modifiable iteration code" ")", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 6879); AnnotateMozCrashReason("MOZ_ASSERT" "(" "getSelfHostedIterFor(iter) == SelfHostedIter::Deny"
") (" "yield* is prohibited in self-hosted code because it can run "
"user-modifiable iteration code" ")"); do { MOZ_CrashSequence
(__null, 6879); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6880
6881 MOZ_ASSERT(sc->isSuspendableContext())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sc->isSuspendableContext())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sc->isSuspendableContext(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("sc->isSuspendableContext()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 6881); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isSuspendableContext()"
")"); do { MOZ_CrashSequence(__null, 6881); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6882 MOZ_ASSERT(sc->asSuspendableContext()->isGenerator())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sc->asSuspendableContext()->isGenerator())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(sc->asSuspendableContext()->isGenerator()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("sc->asSuspendableContext()->isGenerator()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 6882);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->asSuspendableContext()->isGenerator()"
")"); do { MOZ_CrashSequence(__null, 6882); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6883
6884 // Step 1.
6885 IteratorKind iterKind = sc->asSuspendableContext()->isAsync()
6886 ? IteratorKind::Async
6887 : IteratorKind::Sync;
6888 // Steps 2-5.
6889 if (!emitTree(iter)) {
6890 // [stack] ITERABLE
6891 return false;
6892 }
6893 if (iterKind == IteratorKind::Async) {
6894 if (!emitAsyncIterator(SelfHostedIter::Deny)) {
6895 // [stack] NEXT ITER
6896 return false;
6897 }
6898 } else {
6899 if (!emitIterator(SelfHostedIter::Deny)) {
6900 // [stack] NEXT ITER
6901 return false;
6902 }
6903 }
6904
6905 // Step 6.
6906 // Start with NormalCompletion(undefined).
6907 if (!emit1(JSOp::Undefined)) {
6908 // [stack] NEXT ITER RECEIVED
6909 return false;
6910 }
6911 if (!emitPushResumeKind(GeneratorResumeKind::Next)) {
6912 // [stack] NEXT ITER RECEIVED RESUMEKIND
6913 return false;
6914 }
6915
6916 const int32_t startDepth = bytecodeSection().stackDepth();
6917 MOZ_ASSERT(startDepth >= 4)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(startDepth >= 4)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(startDepth >= 4))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("startDepth >= 4"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 6917);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "startDepth >= 4"
")"); do { MOZ_CrashSequence(__null, 6917); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6918
6919 // Step 7 is a loop.
6920 LoopControl loopInfo(this, StatementKind::YieldStar);
6921 if (!loopInfo.emitLoopHead(this, Nothing())) {
6922 // [stack] NEXT ITER RECEIVED RESUMEKIND
6923 return false;
6924 }
6925
6926 // Step 7.a. Check for Normal completion.
6927 if (!emit1(JSOp::Dup)) {
6928 // [stack] NEXT ITER RECEIVED RESUMEKIND RESUMEKIND
6929 return false;
6930 }
6931 if (!emitPushResumeKind(GeneratorResumeKind::Next)) {
6932 // [stack] NEXT ITER RECEIVED RESUMEKIND RESUMEKIND NORMAL
6933 return false;
6934 }
6935 if (!emit1(JSOp::StrictEq)) {
6936 // [stack] NEXT ITER RECEIVED RESUMEKIND IS_NORMAL
6937 return false;
6938 }
6939
6940 InternalIfEmitter ifKind(this);
6941 if (!ifKind.emitThenElse()) {
6942 // [stack] NEXT ITER RECEIVED RESUMEKIND
6943 return false;
6944 }
6945 {
6946 if (!emit1(JSOp::Pop)) {
6947 // [stack] NEXT ITER RECEIVED
6948 return false;
6949 }
6950
6951 // Step 7.a.i.
6952 // result = iter.next(received)
6953 if (!emit2(JSOp::Unpick, 2)) {
6954 // [stack] RECEIVED NEXT ITER
6955 return false;
6956 }
6957 if (!emit1(JSOp::Dup2)) {
6958 // [stack] RECEIVED NEXT ITER NEXT ITER
6959 return false;
6960 }
6961 if (!emit2(JSOp::Pick, 4)) {
6962 // [stack] NEXT ITER NEXT ITER RECEIVED
6963 return false;
6964 }
6965 if (!emitCall(JSOp::Call, 1, iter)) {
6966 // [stack] NEXT ITER RESULT
6967 return false;
6968 }
6969
6970 // Step 7.a.ii.
6971 if (iterKind == IteratorKind::Async) {
6972 if (!emitAwaitInInnermostScope()) {
6973 // [stack] NEXT ITER RESULT
6974 return false;
6975 }
6976 }
6977
6978 // Step 7.a.iii.
6979 if (!emitCheckIsObj(CheckIsObjectKind::IteratorNext)) {
6980 // [stack] NEXT ITER RESULT
6981 return false;
6982 }
6983
6984 // Bytecode for steps 7.a.iv-vii is emitted after the ifKind if-else because
6985 // it's shared with other branches.
6986 }
6987
6988 // Step 7.b. Check for Throw completion.
6989 if (!ifKind.emitElseIf(Nothing())) {
6990 // [stack] NEXT ITER RECEIVED RESUMEKIND
6991 return false;
6992 }
6993 if (!emit1(JSOp::Dup)) {
6994 // [stack] NEXT ITER RECEIVED RESUMEKIND RESUMEKIND
6995 return false;
6996 }
6997 if (!emitPushResumeKind(GeneratorResumeKind::Throw)) {
6998 // [stack] NEXT ITER RECEIVED RESUMEKIND RESUMEKIND THROW
6999 return false;
7000 }
7001 if (!emit1(JSOp::StrictEq)) {
7002 // [stack] NEXT ITER RECEIVED RESUMEKIND IS_THROW
7003 return false;
7004 }
7005 if (!ifKind.emitThenElse()) {
7006 // [stack] NEXT ITER RECEIVED RESUMEKIND
7007 return false;
7008 }
7009 {
7010 if (!emit1(JSOp::Pop)) {
7011 // [stack] NEXT ITER RECEIVED
7012 return false;
7013 }
7014 // Step 7.b.i.
7015 if (!emitDupAt(1)) {
7016 // [stack] NEXT ITER RECEIVED ITER
7017 return false;
7018 }
7019 if (!emit1(JSOp::Dup)) {
7020 // [stack] NEXT ITER RECEIVED ITER ITER
7021 return false;
7022 }
7023 if (!emitAtomOp(JSOp::GetProp,
7024 TaggedParserAtomIndex::WellKnown::throw_())) {
7025 // [stack] NEXT ITER RECEIVED ITER THROW
7026 return false;
7027 }
7028
7029 // Step 7.b.ii.
7030 InternalIfEmitter ifThrowMethodIsNotDefined(this);
7031 if (!emit1(JSOp::IsNullOrUndefined)) {
7032 // [stack] NEXT ITER RECEIVED ITER THROW NULL-OR-UNDEF
7033 return false;
7034 }
7035
7036 if (!ifThrowMethodIsNotDefined.emitThenElse(
7037 IfEmitter::ConditionKind::Negative)) {
7038 // [stack] NEXT ITER RECEIVED ITER THROW
7039 return false;
7040 }
7041
7042 // Step 7.b.ii.1.
7043 // RESULT = ITER.throw(EXCEPTION)
7044 if (!emit1(JSOp::Swap)) {
7045 // [stack] NEXT ITER RECEIVED THROW ITER
7046 return false;
7047 }
7048 if (!emit2(JSOp::Pick, 2)) {
7049 // [stack] NEXT ITER THROW ITER RECEIVED
7050 return false;
7051 }
7052 if (!emitCall(JSOp::Call, 1, iter)) {
7053 // [stack] NEXT ITER RESULT
7054 return false;
7055 }
7056
7057 // Step 7.b.ii.2.
7058 if (iterKind == IteratorKind::Async) {
7059 if (!emitAwaitInInnermostScope()) {
7060 // [stack] NEXT ITER RESULT
7061 return false;
7062 }
7063 }
7064
7065 // Step 7.b.ii.4.
7066 if (!emitCheckIsObj(CheckIsObjectKind::IteratorThrow)) {
7067 // [stack] NEXT ITER RESULT
7068 return false;
7069 }
7070
7071 // Bytecode for steps 7.b.ii.5-8 is emitted after the ifKind if-else because
7072 // it's shared with other branches.
7073
7074 // Step 7.b.iii.
7075 if (!ifThrowMethodIsNotDefined.emitElse()) {
7076 // [stack] NEXT ITER RECEIVED ITER THROW
7077 return false;
7078 }
7079 if (!emit1(JSOp::Pop)) {
7080 // [stack] NEXT ITER RECEIVED ITER
7081 return false;
7082 }
7083
7084 // Steps 7.b.iii.1-4.
7085 //
7086 // If the iterator does not have a "throw" method, it calls IteratorClose
7087 // and then throws a TypeError.
7088 if (!emitIteratorCloseInInnermostScope(iterKind, CompletionKind::Normal,
7089 SelfHostedIter::Deny)) {
7090 // [stack] NEXT ITER RECEIVED ITER
7091 return false;
7092 }
7093 // Steps 7.b.iii.5-6.
7094 if (!emit2(JSOp::ThrowMsg, uint8_t(ThrowMsgKind::IteratorNoThrow))) {
7095 // [stack] NEXT ITER RECEIVED ITER
7096 // [stack] # throw
7097 return false;
7098 }
7099
7100 if (!ifThrowMethodIsNotDefined.emitEnd()) {
7101 return false;
7102 }
7103 }
7104
7105 // Step 7.c. It must be a Return completion.
7106 if (!ifKind.emitElse()) {
7107 // [stack] NEXT ITER RECEIVED RESUMEKIND
7108 return false;
7109 }
7110 {
7111 if (!emit1(JSOp::Pop)) {
7112 // [stack] NEXT ITER RECEIVED
7113 return false;
7114 }
7115
7116 // Step 7.c.i.
7117 //
7118 // Call iterator.return() for receiving a "forced return" completion from
7119 // the generator.
7120
7121 // Step 7.c.ii.
7122 //
7123 // Get the "return" method.
7124 if (!emitDupAt(1)) {
7125 // [stack] NEXT ITER RECEIVED ITER
7126 return false;
7127 }
7128 if (!emit1(JSOp::Dup)) {
7129 // [stack] NEXT ITER RECEIVED ITER ITER
7130 return false;
7131 }
7132 if (!emitAtomOp(JSOp::GetProp,
7133 TaggedParserAtomIndex::WellKnown::return_())) {
7134 // [stack] NEXT ITER RECEIVED ITER RET
7135 return false;
7136 }
7137
7138 // Step 7.c.iii.
7139 //
7140 // Do nothing if "return" is undefined or null.
7141 InternalIfEmitter ifReturnMethodIsDefined(this);
7142 if (!emit1(JSOp::IsNullOrUndefined)) {
7143 // [stack] NEXT ITER RECEIVED ITER RET NULL-OR-UNDEF
7144 return false;
7145 }
7146
7147 // Step 7.c.iv.
7148 //
7149 // Call "return" with the argument passed to Generator.prototype.return.
7150 if (!ifReturnMethodIsDefined.emitThenElse(
7151 IfEmitter::ConditionKind::Negative)) {
7152 // [stack] NEXT ITER RECEIVED ITER RET
7153 return false;
7154 }
7155 if (!emit1(JSOp::Swap)) {
7156 // [stack] NEXT ITER RECEIVED RET ITER
7157 return false;
7158 }
7159 if (!emit2(JSOp::Pick, 2)) {
7160 // [stack] NEXT ITER RET ITER RECEIVED
7161 return false;
7162 }
7163 if (!emitCall(JSOp::Call, 1)) {
7164 // [stack] NEXT ITER RESULT
7165 return false;
7166 }
7167
7168 // Step 7.c.v.
7169 if (iterKind == IteratorKind::Async) {
7170 if (!emitAwaitInInnermostScope()) {
7171 // [stack] NEXT ITER RESULT
7172 return false;
7173 }
7174 }
7175
7176 // Step 7.c.vi.
7177 if (!emitCheckIsObj(CheckIsObjectKind::IteratorReturn)) {
7178 // [stack] NEXT ITER RESULT
7179 return false;
7180 }
7181
7182 // Check if the returned object from iterator.return() is done. If not,
7183 // continue yielding.
7184
7185 // Steps 7.c.vii-viii.
7186 InternalIfEmitter ifReturnDone(this);
7187 if (!emit1(JSOp::Dup)) {
7188 // [stack] NEXT ITER RESULT RESULT
7189 return false;
7190 }
7191 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::done())) {
7192 // [stack] NEXT ITER RESULT DONE
7193 return false;
7194 }
7195 if (!ifReturnDone.emitThenElse()) {
7196 // [stack] NEXT ITER RESULT
7197 return false;
7198 }
7199
7200 // Step 7.c.viii.1.
7201 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::value())) {
7202 // [stack] NEXT ITER VALUE
7203 return false;
7204 }
7205 if (!ifReturnDone.emitElse()) {
7206 // [stack] NEXT ITER RESULT
7207 return false;
7208 }
7209
7210 // Jump to continue label for steps 7.c.ix-x.
7211 if (!emitJump(JSOp::Goto, &loopInfo.continues)) {
7212 // [stack] NEXT ITER RESULT
7213 return false;
7214 }
7215
7216 if (!ifReturnDone.emitEnd()) {
7217 // [stack] NEXT ITER VALUE
7218 return false;
7219 }
7220
7221 // Step 7.c.iii.
7222 if (!ifReturnMethodIsDefined.emitElse()) {
7223 // [stack] NEXT ITER RECEIVED ITER RET
7224 return false;
7225 }
7226 if (!emitPopN(2)) {
7227 // [stack] NEXT ITER RECEIVED
7228 return false;
7229 }
7230 if (iterKind == IteratorKind::Async) {
7231 // Step 7.c.iii.1.
7232 if (!emitAwaitInInnermostScope()) {
7233 // [stack] NEXT ITER RECEIVED
7234 return false;
7235 }
7236 }
7237 if (!ifReturnMethodIsDefined.emitEnd()) {
7238 // [stack] NEXT ITER RECEIVED
7239 return false;
7240 }
7241
7242 // Perform a "forced generator return".
7243 //
7244 // Step 7.c.iii.2.
7245 // Step 7.c.viii.2.
7246 if (!emit1(JSOp::SetRval)) {
7247 // [stack] NEXT ITER
7248 return false;
7249 }
7250 {
7251 NonLocalExitControl nle(this, NonLocalExitKind::Return);
7252 if (!nle.emitReturn()) {
7253 return false;
7254 }
7255 }
7256 bytecodeSection().setStackDepth(startDepth - 1);
7257 }
7258
7259 if (!ifKind.emitEnd()) {
7260 // [stack] NEXT ITER RESULT
7261 return false;
7262 }
7263
7264 // Shared tail for Normal/Throw completions.
7265 //
7266 // Steps 7.a.iv-v.
7267 // Steps 7.b.ii.5-6.
7268 //
7269 // [stack] NEXT ITER RESULT
7270
7271 // if (result.done) break;
7272 if (!emit1(JSOp::Dup)) {
7273 // [stack] NEXT ITER RESULT RESULT
7274 return false;
7275 }
7276 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::done())) {
7277 // [stack] NEXT ITER RESULT DONE
7278 return false;
7279 }
7280 if (!emitJump(JSOp::JumpIfTrue, &loopInfo.breaks)) {
7281 // [stack] NEXT ITER RESULT
7282 return false;
7283 }
7284
7285 // Steps 7.a.vi-vii.
7286 // Steps 7.b.ii.7-8.
7287 // Steps 7.c.ix-x.
7288 if (!loopInfo.emitContinueTarget(this)) {
7289 // [stack] NEXT ITER RESULT
7290 return false;
7291 }
7292 if (iterKind == IteratorKind::Async) {
7293 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::value())) {
7294 // [stack] NEXT ITER RESULT
7295 return false;
7296 }
7297 }
7298 if (!emitGetDotGeneratorInInnermostScope()) {
7299 // [stack] NEXT ITER RESULT GENOBJ
7300 return false;
7301 }
7302 if (!emitYieldOp(JSOp::Yield)) {
7303 // [stack] NEXT ITER RVAL RESUMEKIND
7304 return false;
7305 }
7306 if (!loopInfo.emitLoopEnd(this, JSOp::Goto, TryNoteKind::Loop)) {
7307 // [stack] NEXT ITER RVAL RESUMEKIND
7308 return false;
7309 }
7310
7311 // Jumps to this point have 3 (instead of 4) values on the stack.
7312 MOZ_ASSERT(bytecodeSection().stackDepth() == startDepth)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bytecodeSection().stackDepth() == startDepth)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(bytecodeSection().stackDepth() == startDepth))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("bytecodeSection().stackDepth() == startDepth"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 7312);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == startDepth"
")"); do { MOZ_CrashSequence(__null, 7312); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7313 bytecodeSection().setStackDepth(startDepth - 1);
7314
7315 // [stack] NEXT ITER RESULT
7316
7317 // Step 7.a.v.1.
7318 // Step 7.b.ii.6.a.
7319 //
7320 // result.value
7321 if (!emit2(JSOp::Unpick, 2)) {
7322 // [stack] RESULT NEXT ITER
7323 return false;
7324 }
7325 if (!emitPopN(2)) {
7326 // [stack] RESULT
7327 return false;
7328 }
7329 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::value())) {
7330 // [stack] VALUE
7331 return false;
7332 }
7333
7334 MOZ_ASSERT(bytecodeSection().stackDepth() == startDepth - 3)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bytecodeSection().stackDepth() == startDepth - 3)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(bytecodeSection().stackDepth() == startDepth - 3))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("bytecodeSection().stackDepth() == startDepth - 3"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 7334);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == startDepth - 3"
")"); do { MOZ_CrashSequence(__null, 7334); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7335
7336 return true;
7337}
7338
7339bool BytecodeEmitter::emitStatementList(ListNode* stmtList) {
7340 for (ParseNode* stmt : stmtList->contents()) {
7341 if (!emitTree(stmt)) {
7342 return false;
7343 }
7344 }
7345 return true;
7346}
7347
7348bool BytecodeEmitter::emitExpressionStatement(UnaryNode* exprStmt) {
7349 MOZ_ASSERT(exprStmt->isKind(ParseNodeKind::ExpressionStmt))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(exprStmt->isKind(ParseNodeKind::ExpressionStmt))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(exprStmt->isKind(ParseNodeKind::ExpressionStmt)))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("exprStmt->isKind(ParseNodeKind::ExpressionStmt)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 7349);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "exprStmt->isKind(ParseNodeKind::ExpressionStmt)"
")"); do { MOZ_CrashSequence(__null, 7349); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7350
7351 /*
7352 * Top-level or called-from-a-native JS_Execute/EvaluateScript,
7353 * debugger, and eval frames may need the value of the ultimate
7354 * expression statement as the script's result, despite the fact
7355 * that it appears useless to the compiler.
7356 *
7357 * API users may also set the ReadOnlyCompileOptions::noScriptRval option when
7358 * calling JS_Compile* to suppress JSOp::SetRval.
7359 */
7360 bool wantval = false;
7361 bool useful = false;
7362 if (sc->isTopLevelContext()) {
7363 useful = wantval = !sc->noScriptRval();
7364 }
7365
7366 /* Don't eliminate expressions with side effects. */
7367 ParseNode* expr = exprStmt->kid();
7368 if (!useful) {
7369 if (!checkSideEffects(expr, &useful)) {
7370 return false;
7371 }
7372
7373 /*
7374 * Don't eliminate apparently useless expressions if they are labeled
7375 * expression statements. The startOffset() test catches the case
7376 * where we are nesting in emitTree for a labeled compound statement.
7377 */
7378 if (innermostNestableControl &&
7379 innermostNestableControl->is<LabelControl>() &&
7380 innermostNestableControl->as<LabelControl>().startOffset() >=
7381 bytecodeSection().offset()) {
7382 useful = true;
7383 }
7384 }
7385
7386 if (useful) {
7387 ValueUsage valueUsage =
7388 wantval ? ValueUsage::WantValue : ValueUsage::IgnoreValue;
7389 ExpressionStatementEmitter ese(this, valueUsage);
7390 if (!ese.prepareForExpr(exprStmt->pn_pos.begin)) {
7391 return false;
7392 }
7393 if (!markStepBreakpoint()) {
7394 return false;
7395 }
7396 if (!emitTree(expr, valueUsage)) {
7397 return false;
7398 }
7399 if (!ese.emitEnd()) {
7400 return false;
7401 }
7402 }
7403
7404 return true;
7405}
7406
7407bool BytecodeEmitter::emitDeleteName(UnaryNode* deleteNode) {
7408 MOZ_ASSERT(deleteNode->isKind(ParseNodeKind::DeleteNameExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(deleteNode->isKind(ParseNodeKind::DeleteNameExpr)
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(deleteNode->isKind(ParseNodeKind::DeleteNameExpr)
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"deleteNode->isKind(ParseNodeKind::DeleteNameExpr)", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 7408); AnnotateMozCrashReason("MOZ_ASSERT" "(" "deleteNode->isKind(ParseNodeKind::DeleteNameExpr)"
")"); do { MOZ_CrashSequence(__null, 7408); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7409
7410 NameNode* nameExpr = &deleteNode->kid()->as<NameNode>();
7411 MOZ_ASSERT(nameExpr->isKind(ParseNodeKind::Name))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(nameExpr->isKind(ParseNodeKind::Name))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(nameExpr->isKind(ParseNodeKind::Name)))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("nameExpr->isKind(ParseNodeKind::Name)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 7411);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "nameExpr->isKind(ParseNodeKind::Name)"
")"); do { MOZ_CrashSequence(__null, 7411); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7412
7413 return emitAtomOp(JSOp::DelName, nameExpr->atom());
7414}
7415
7416bool BytecodeEmitter::emitDeleteProperty(UnaryNode* deleteNode) {
7417 MOZ_ASSERT(deleteNode->isKind(ParseNodeKind::DeletePropExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(deleteNode->isKind(ParseNodeKind::DeletePropExpr)
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(deleteNode->isKind(ParseNodeKind::DeletePropExpr)
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"deleteNode->isKind(ParseNodeKind::DeletePropExpr)", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 7417); AnnotateMozCrashReason("MOZ_ASSERT" "(" "deleteNode->isKind(ParseNodeKind::DeletePropExpr)"
")"); do { MOZ_CrashSequence(__null, 7417); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7418
7419 NonOptionalPropertyAccessBase* propExpr =
7420 &deleteNode->kid()->as<NonOptionalPropertyAccessBase>();
7421 PropOpEmitter poe(this, PropOpEmitter::Kind::Delete,
7422 propExpr->isSuper() ? PropOpEmitter::ObjKind::Super
7423 : PropOpEmitter::ObjKind::Other);
7424
7425 if (!poe.prepareForObj()) {
7426 return false;
7427 }
7428
7429 if (propExpr->isSuper()) {
7430 // The expression |delete super.foo;| has to evaluate |super.foo|, which
7431 // could throw if |this| hasn't yet been set by a |super(...)| call.
7432 auto* base = &propExpr->expression().as<UnaryNode>();
7433 if (!emitGetThisForSuperBase(base)) {
7434 // [stack] THIS
7435 return false;
7436 }
7437 } else {
7438 if (!emitPropLHS(propExpr)) {
7439 // [stack] OBJ
7440 return false;
7441 }
7442 }
7443
7444 if (!poe.emitDelete(propExpr->key().atom())) {
7445 // [stack] # if Super
7446 // [stack] THIS
7447 // [stack] # otherwise
7448 // [stack] SUCCEEDED
7449 return false;
7450 }
7451
7452 return true;
7453}
7454
7455bool BytecodeEmitter::emitDeleteElement(UnaryNode* deleteNode) {
7456 MOZ_ASSERT(deleteNode->isKind(ParseNodeKind::DeleteElemExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(deleteNode->isKind(ParseNodeKind::DeleteElemExpr)
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(deleteNode->isKind(ParseNodeKind::DeleteElemExpr)
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"deleteNode->isKind(ParseNodeKind::DeleteElemExpr)", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 7456); AnnotateMozCrashReason("MOZ_ASSERT" "(" "deleteNode->isKind(ParseNodeKind::DeleteElemExpr)"
")"); do { MOZ_CrashSequence(__null, 7456); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7457
7458 auto* elemExpr = &deleteNode->kid()->as<PropertyByValue>();
7459 bool isSuper = elemExpr->isSuper();
7460 MOZ_ASSERT(!elemExpr->key().isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!elemExpr->key().isKind(ParseNodeKind::PrivateName
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!elemExpr->key().isKind(ParseNodeKind::PrivateName
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!elemExpr->key().isKind(ParseNodeKind::PrivateName)", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 7460); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elemExpr->key().isKind(ParseNodeKind::PrivateName)"
")"); do { MOZ_CrashSequence(__null, 7460); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7461 ElemOpEmitter eoe(
7462 this, ElemOpEmitter::Kind::Delete,
7463 isSuper ? ElemOpEmitter::ObjKind::Super : ElemOpEmitter::ObjKind::Other);
7464
7465 if (!emitElemObjAndKey(elemExpr, eoe)) {
7466 // [stack] # if Super
7467 // [stack] THIS KEY
7468 // [stack] # otherwise
7469 // [stack] OBJ KEY
7470 return false;
7471 }
7472
7473 if (!eoe.emitDelete()) {
7474 // [stack] # if Super
7475 // [stack] THIS
7476 // [stack] # otherwise
7477 // [stack] SUCCEEDED
7478 return false;
7479 }
7480
7481 return true;
7482}
7483
7484bool BytecodeEmitter::emitDeleteExpression(UnaryNode* deleteNode) {
7485 MOZ_ASSERT(deleteNode->isKind(ParseNodeKind::DeleteExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(deleteNode->isKind(ParseNodeKind::DeleteExpr))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(deleteNode->isKind(ParseNodeKind::DeleteExpr)))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("deleteNode->isKind(ParseNodeKind::DeleteExpr)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 7485);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "deleteNode->isKind(ParseNodeKind::DeleteExpr)"
")"); do { MOZ_CrashSequence(__null, 7485); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7486
7487 ParseNode* expression = deleteNode->kid();
7488
7489 // If useless, just emit JSOp::True; otherwise convert |delete <expr>| to
7490 // effectively |<expr>, true|.
7491 bool useful = false;
7492 if (!checkSideEffects(expression, &useful)) {
7493 return false;
7494 }
7495
7496 if (useful) {
7497 if (!emitTree(expression)) {
7498 return false;
7499 }
7500 if (!emit1(JSOp::Pop)) {
7501 return false;
7502 }
7503 }
7504
7505 return emit1(JSOp::True);
7506}
7507
7508bool BytecodeEmitter::emitDeleteOptionalChain(UnaryNode* deleteNode) {
7509 MOZ_ASSERT(deleteNode->isKind(ParseNodeKind::DeleteOptionalChainExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(deleteNode->isKind(ParseNodeKind::DeleteOptionalChainExpr
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(deleteNode->isKind(ParseNodeKind::DeleteOptionalChainExpr
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("deleteNode->isKind(ParseNodeKind::DeleteOptionalChainExpr)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 7509);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "deleteNode->isKind(ParseNodeKind::DeleteOptionalChainExpr)"
")"); do { MOZ_CrashSequence(__null, 7509); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7510
7511 OptionalEmitter oe(this, bytecodeSection().stackDepth());
7512
7513 ParseNode* kid = deleteNode->kid();
7514 switch (kid->getKind()) {
7515 case ParseNodeKind::ElemExpr:
7516 case ParseNodeKind::OptionalElemExpr: {
7517 auto* elemExpr = &kid->as<PropertyByValueBase>();
7518 if (!emitDeleteElementInOptChain(elemExpr, oe)) {
7519 // [stack] # If shortcircuit
7520 // [stack] UNDEFINED-OR-NULL
7521 // [stack] # otherwise
7522 // [stack] SUCCEEDED
7523 return false;
7524 }
7525
7526 break;
7527 }
7528 case ParseNodeKind::ArgumentsLength:
7529 case ParseNodeKind::DotExpr:
7530 case ParseNodeKind::OptionalDotExpr: {
7531 auto* propExpr = &kid->as<PropertyAccessBase>();
7532 if (!emitDeletePropertyInOptChain(propExpr, oe)) {
7533 // [stack] # If shortcircuit
7534 // [stack] UNDEFINED-OR-NULL
7535 // [stack] # otherwise
7536 // [stack] SUCCEEDED
7537 return false;
7538 }
7539 break;
7540 }
7541 default:
7542 MOZ_ASSERT_UNREACHABLE("Unrecognized optional delete ParseNodeKind")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"Unrecognized optional delete ParseNodeKind" ")", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 7542); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Unrecognized optional delete ParseNodeKind"
")"); do { MOZ_CrashSequence(__null, 7542); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7543 }
7544
7545 if (!oe.emitOptionalJumpTarget(JSOp::True)) {
7546 // [stack] # If shortcircuit
7547 // [stack] TRUE
7548 // [stack] # otherwise
7549 // [stack] SUCCEEDED
7550 return false;
7551 }
7552
7553 return true;
7554}
7555
7556bool BytecodeEmitter::emitDeletePropertyInOptChain(PropertyAccessBase* propExpr,
7557 OptionalEmitter& oe) {
7558 MOZ_ASSERT(!propExpr->isSuper())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!propExpr->isSuper())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!propExpr->isSuper()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!propExpr->isSuper()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 7558);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!propExpr->isSuper()"
")"); do { MOZ_CrashSequence(__null, 7558); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7559 PropOpEmitter poe(this, PropOpEmitter::Kind::Delete,
7560 PropOpEmitter::ObjKind::Other);
7561
7562 if (!poe.prepareForObj()) {
7563 // [stack]
7564 return false;
7565 }
7566 if (!emitOptionalTree(&propExpr->expression(), oe)) {
7567 // [stack] OBJ
7568 return false;
7569 }
7570 if (propExpr->isKind(ParseNodeKind::OptionalDotExpr)) {
7571 if (!oe.emitJumpShortCircuit()) {
7572 // [stack] # if Jump
7573 // [stack] UNDEFINED-OR-NULL
7574 // [stack] # otherwise
7575 // [stack] OBJ
7576 return false;
7577 }
7578 }
7579
7580 if (!poe.emitDelete(propExpr->key().atom())) {
7581 // [stack] SUCCEEDED
7582 return false;
7583 }
7584
7585 return true;
7586}
7587
7588bool BytecodeEmitter::emitDeleteElementInOptChain(PropertyByValueBase* elemExpr,
7589 OptionalEmitter& oe) {
7590 MOZ_ASSERT_IF(elemExpr->is<PropertyByValue>(),do { if (elemExpr->is<PropertyByValue>()) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(!elemExpr
->as<PropertyByValue>().isSuper())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!elemExpr->as<PropertyByValue
>().isSuper()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!elemExpr->as<PropertyByValue>().isSuper()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 7591); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elemExpr->as<PropertyByValue>().isSuper()"
")"); do { MOZ_CrashSequence(__null, 7591); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
7591 !elemExpr->as<PropertyByValue>().isSuper())do { if (elemExpr->is<PropertyByValue>()) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(!elemExpr
->as<PropertyByValue>().isSuper())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!elemExpr->as<PropertyByValue
>().isSuper()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!elemExpr->as<PropertyByValue>().isSuper()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 7591); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elemExpr->as<PropertyByValue>().isSuper()"
")"); do { MOZ_CrashSequence(__null, 7591); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
7592 ElemOpEmitter eoe(this, ElemOpEmitter::Kind::Delete,
7593 ElemOpEmitter::ObjKind::Other);
7594
7595 if (!eoe.prepareForObj()) {
7596 // [stack]
7597 return false;
7598 }
7599
7600 if (!emitOptionalTree(&elemExpr->expression(), oe)) {
7601 // [stack] OBJ
7602 return false;
7603 }
7604
7605 if (elemExpr->isKind(ParseNodeKind::OptionalElemExpr)) {
7606 if (!oe.emitJumpShortCircuit()) {
7607 // [stack] # if Jump
7608 // [stack] UNDEFINED-OR-NULL
7609 // [stack] # otherwise
7610 // [stack] OBJ
7611 return false;
7612 }
7613 }
7614
7615 if (!eoe.prepareForKey()) {
7616 // [stack] OBJ
7617 return false;
7618 }
7619
7620 if (!emitTree(&elemExpr->key())) {
7621 // [stack] OBJ KEY
7622 return false;
7623 }
7624
7625 if (!eoe.emitDelete()) {
7626 // [stack] SUCCEEDED
7627 return false;
7628 }
7629
7630 return true;
7631}
7632
7633bool BytecodeEmitter::emitDebugCheckSelfHosted() {
7634 // [stack] CALLEE
7635
7636#ifdef DEBUG1
7637 if (!emit1(JSOp::DebugCheckSelfHosted)) {
7638 // [stack] CALLEE
7639 return false;
7640 }
7641#endif
7642
7643 return true;
7644}
7645
7646bool BytecodeEmitter::emitSelfHostedCallFunction(CallNode* callNode, JSOp op) {
7647 // Special-casing of callFunction to emit bytecode that directly
7648 // invokes the callee with the correct |this| object and arguments.
7649 // callFunction(fun, thisArg, arg0, arg1) thus becomes:
7650 // - emit lookup for fun
7651 // - emit lookup for thisArg
7652 // - emit lookups for arg0, arg1
7653 //
7654 // argc is set to the amount of actually emitted args and the
7655 // emitting of args below is disabled by setting emitArgs to false.
7656 NameNode* calleeNode = &callNode->callee()->as<NameNode>();
7657 ListNode* argsList = callNode->args();
7658
7659 MOZ_ASSERT(argsList->count() >= 2)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(argsList->count() >= 2)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(argsList->count() >= 2
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"argsList->count() >= 2", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 7659); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() >= 2"
")"); do { MOZ_CrashSequence(__null, 7659); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7660
7661 MOZ_ASSERT(callNode->callOp() == JSOp::Call)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(callNode->callOp() == JSOp::Call)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(callNode->callOp() == JSOp
::Call))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("callNode->callOp() == JSOp::Call", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 7661); AnnotateMozCrashReason("MOZ_ASSERT" "(" "callNode->callOp() == JSOp::Call"
")"); do { MOZ_CrashSequence(__null, 7661); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7662
7663 bool constructing =
7664 calleeNode->name() ==
7665 TaggedParserAtomIndex::WellKnown::constructContentFunction();
7666 ParseNode* funNode = argsList->head();
7667
7668 if (!emitTree(funNode)) {
7669 // [stack] CALLEE
7670 return false;
7671 }
7672
7673#ifdef DEBUG1
7674 MOZ_ASSERT(op == JSOp::Call || op == JSOp::CallContent ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(op == JSOp::Call || op == JSOp::CallContent || op ==
JSOp::NewContent)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(op == JSOp::Call || op == JSOp
::CallContent || op == JSOp::NewContent))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("op == JSOp::Call || op == JSOp::CallContent || op == JSOp::NewContent"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 7675);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::Call || op == JSOp::CallContent || op == JSOp::NewContent"
")"); do { MOZ_CrashSequence(__null, 7675); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7675 op == JSOp::NewContent)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(op == JSOp::Call || op == JSOp::CallContent || op ==
JSOp::NewContent)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(op == JSOp::Call || op == JSOp
::CallContent || op == JSOp::NewContent))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("op == JSOp::Call || op == JSOp::CallContent || op == JSOp::NewContent"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 7675);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::Call || op == JSOp::CallContent || op == JSOp::NewContent"
")"); do { MOZ_CrashSequence(__null, 7675); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7676 if (op == JSOp::Call) {
7677 if (!emitDebugCheckSelfHosted()) {
7678 // [stack] CALLEE
7679 return false;
7680 }
7681 }
7682#endif
7683
7684 ParseNode* thisOrNewTarget = funNode->pn_next;
7685 if (constructing) {
7686 // Save off the new.target value, but here emit a proper |this| for a
7687 // constructing call.
7688 if (!emit1(JSOp::IsConstructing)) {
7689 // [stack] CALLEE IS_CONSTRUCTING
7690 return false;
7691 }
7692 } else {
7693 // It's |this|, emit it.
7694 if (!emitTree(thisOrNewTarget)) {
7695 // [stack] CALLEE THIS
7696 return false;
7697 }
7698 }
7699
7700 for (ParseNode* argpn : argsList->contentsFrom(thisOrNewTarget->pn_next)) {
7701 if (!emitTree(argpn)) {
7702 // [stack] CALLEE ... ARGS...
7703 return false;
7704 }
7705 }
7706
7707 if (constructing) {
7708 if (!emitTree(thisOrNewTarget)) {
7709 // [stack] CALLEE IS_CONSTRUCTING ARGS... NEW.TARGET
7710 return false;
7711 }
7712 }
7713
7714 uint32_t argc = argsList->count() - 2;
7715 if (!emitCall(op, argc)) {
7716 // [stack] RVAL
7717 return false;
7718 }
7719
7720 return true;
7721}
7722
7723bool BytecodeEmitter::emitSelfHostedResumeGenerator(CallNode* callNode) {
7724 ListNode* argsList = callNode->args();
7725
7726 // Syntax: resumeGenerator(gen, value, 'next'|'throw'|'return')
7727 MOZ_ASSERT(argsList->count() == 3)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(argsList->count() == 3)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(argsList->count() == 3)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 3"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 7727);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 3"
")"); do { MOZ_CrashSequence(__null, 7727); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7728
7729 ParseNode* genNode = argsList->head();
7730 if (!emitTree(genNode)) {
7731 // [stack] GENERATOR
7732 return false;
7733 }
7734
7735 ParseNode* valNode = genNode->pn_next;
7736 if (!emitTree(valNode)) {
7737 // [stack] GENERATOR VALUE
7738 return false;
7739 }
7740
7741 ParseNode* kindNode = valNode->pn_next;
7742 MOZ_ASSERT(kindNode->isKind(ParseNodeKind::StringExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(kindNode->isKind(ParseNodeKind::StringExpr))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(kindNode->isKind(ParseNodeKind::StringExpr)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("kindNode->isKind(ParseNodeKind::StringExpr)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 7742);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "kindNode->isKind(ParseNodeKind::StringExpr)"
")"); do { MOZ_CrashSequence(__null, 7742); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7743 GeneratorResumeKind kind =
7744 ParserAtomToResumeKind(kindNode->as<NameNode>().atom());
7745 MOZ_ASSERT(!kindNode->pn_next)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!kindNode->pn_next)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!kindNode->pn_next))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("!kindNode->pn_next"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 7745);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!kindNode->pn_next"
")"); do { MOZ_CrashSequence(__null, 7745); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7746
7747 if (!emitPushResumeKind(kind)) {
7748 // [stack] GENERATOR VALUE RESUMEKIND
7749 return false;
7750 }
7751
7752 if (!emit1(JSOp::Resume)) {
7753 // [stack] RVAL
7754 return false;
7755 }
7756
7757 return true;
7758}
7759
7760bool BytecodeEmitter::emitSelfHostedAllowContentIter(CallNode* callNode) {
7761 ListNode* argsList = callNode->args();
7762
7763 MOZ_ASSERT(argsList->count() == 1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(argsList->count() == 1)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(argsList->count() == 1)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 1"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 7763);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1"
")"); do { MOZ_CrashSequence(__null, 7763); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7764
7765 // We're just here as a sentinel. Pass the value through directly.
7766 return emitTree(argsList->head());
7767}
7768
7769bool BytecodeEmitter::emitSelfHostedAllowContentIterWith(CallNode* callNode) {
7770 ListNode* argsList = callNode->args();
7771
7772 MOZ_ASSERT(argsList->count() == 2 || argsList->count() == 3)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(argsList->count() == 2 || argsList->count() ==
3)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(argsList->count() == 2 || argsList->count() ==
3))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("argsList->count() == 2 || argsList->count() == 3", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 7772); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2 || argsList->count() == 3"
")"); do { MOZ_CrashSequence(__null, 7772); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7773
7774 // We're just here as a sentinel. Pass the value through directly.
7775 return emitTree(argsList->head());
7776}
7777
7778bool BytecodeEmitter::emitSelfHostedAllowContentIterWithNext(
7779 CallNode* callNode) {
7780 ListNode* argsList = callNode->args();
7781
7782 MOZ_ASSERT(argsList->count() == 2)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(argsList->count() == 2)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(argsList->count() == 2)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 2"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 7782);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2"
")"); do { MOZ_CrashSequence(__null, 7782); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7783
7784 // We're just here as a sentinel. Pass the value through directly.
7785 return emitTree(argsList->head());
7786}
7787
7788bool BytecodeEmitter::emitSelfHostedDefineDataProperty(CallNode* callNode) {
7789 ListNode* argsList = callNode->args();
7790
7791 // Only optimize when 3 arguments are passed.
7792 MOZ_ASSERT(argsList->count() == 3)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(argsList->count() == 3)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(argsList->count() == 3)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 3"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 7792);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 3"
")"); do { MOZ_CrashSequence(__null, 7792); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7793
7794 ParseNode* objNode = argsList->head();
7795 if (!emitTree(objNode)) {
7796 return false;
7797 }
7798
7799 ParseNode* idNode = objNode->pn_next;
7800 if (!emitTree(idNode)) {
7801 return false;
7802 }
7803
7804 ParseNode* valNode = idNode->pn_next;
7805 if (!emitTree(valNode)) {
7806 return false;
7807 }
7808
7809 // This will leave the object on the stack instead of pushing |undefined|,
7810 // but that's fine because the self-hosted code doesn't use the return
7811 // value.
7812 return emit1(JSOp::InitElem);
7813}
7814
7815bool BytecodeEmitter::emitSelfHostedHasOwn(CallNode* callNode) {
7816 ListNode* argsList = callNode->args();
7817
7818 MOZ_ASSERT(argsList->count() == 2)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(argsList->count() == 2)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(argsList->count() == 2)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 2"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 7818);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2"
")"); do { MOZ_CrashSequence(__null, 7818); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7819
7820 ParseNode* idNode = argsList->head();
7821 if (!emitTree(idNode)) {
7822 return false;
7823 }
7824
7825 ParseNode* objNode = idNode->pn_next;
7826 if (!emitTree(objNode)) {
7827 return false;
7828 }
7829
7830 return emit1(JSOp::HasOwn);
7831}
7832
7833bool BytecodeEmitter::emitSelfHostedGetPropertySuper(CallNode* callNode) {
7834 ListNode* argsList = callNode->args();
7835
7836 MOZ_ASSERT(argsList->count() == 3)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(argsList->count() == 3)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(argsList->count() == 3)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 3"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 7836);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 3"
")"); do { MOZ_CrashSequence(__null, 7836); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7837
7838 ParseNode* objNode = argsList->head();
7839 ParseNode* idNode = objNode->pn_next;
7840 ParseNode* receiverNode = idNode->pn_next;
7841
7842 if (!emitTree(receiverNode)) {
7843 return false;
7844 }
7845
7846 if (!emitTree(idNode)) {
7847 return false;
7848 }
7849
7850 if (!emitTree(objNode)) {
7851 return false;
7852 }
7853
7854 return emitElemOpBase(JSOp::GetElemSuper);
7855}
7856
7857bool BytecodeEmitter::emitSelfHostedToNumeric(CallNode* callNode) {
7858 ListNode* argsList = callNode->args();
7859
7860 MOZ_ASSERT(argsList->count() == 1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(argsList->count() == 1)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(argsList->count() == 1)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 1"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 7860);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1"
")"); do { MOZ_CrashSequence(__null, 7860); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7861
7862 ParseNode* argNode = argsList->head();
7863
7864 if (!emitTree(argNode)) {
7865 return false;
7866 }
7867
7868 return emit1(JSOp::ToNumeric);
7869}
7870
7871bool BytecodeEmitter::emitSelfHostedToString(CallNode* callNode) {
7872 ListNode* argsList = callNode->args();
7873
7874 MOZ_ASSERT(argsList->count() == 1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(argsList->count() == 1)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(argsList->count() == 1)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 1"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 7874);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1"
")"); do { MOZ_CrashSequence(__null, 7874); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7875
7876 ParseNode* argNode = argsList->head();
7877
7878 if (!emitTree(argNode)) {
7879 return false;
7880 }
7881
7882 return emit1(JSOp::ToString);
7883}
7884
7885bool BytecodeEmitter::emitSelfHostedIsNullOrUndefined(CallNode* callNode) {
7886 ListNode* argsList = callNode->args();
7887
7888 MOZ_ASSERT(argsList->count() == 1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(argsList->count() == 1)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(argsList->count() == 1)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 1"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 7888);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1"
")"); do { MOZ_CrashSequence(__null, 7888); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7889
7890 ParseNode* argNode = argsList->head();
7891
7892 if (!emitTree(argNode)) {
7893 // [stack] ARG
7894 return false;
7895 }
7896 if (!emit1(JSOp::IsNullOrUndefined)) {
7897 // [stack] ARG IS_NULL_OR_UNDEF
7898 return false;
7899 }
7900 if (!emit1(JSOp::Swap)) {
7901 // [stack] IS_NULL_OR_UNDEF ARG
7902 return false;
7903 }
7904 if (!emit1(JSOp::Pop)) {
7905 // [stack] IS_NULL_OR_UNDEF
7906 return false;
7907 }
7908 return true;
7909}
7910
7911bool BytecodeEmitter::emitSelfHostedIteratorClose(CallNode* callNode) {
7912 ListNode* argsList = callNode->args();
7913 MOZ_ASSERT(argsList->count() == 1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(argsList->count() == 1)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(argsList->count() == 1)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 1"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 7913);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1"
")"); do { MOZ_CrashSequence(__null, 7913); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7914
7915 ParseNode* argNode = argsList->head();
7916 if (!emitTree(argNode)) {
7917 // [stack] ARG
7918 return false;
7919 }
7920
7921 if (!emit2(JSOp::CloseIter, uint8_t(CompletionKind::Normal))) {
7922 // [stack]
7923 return false;
7924 }
7925
7926 // This is still a call node, so we must generate a stack value.
7927 if (!emit1(JSOp::Undefined)) {
7928 // [stack] RVAL
7929 return false;
7930 }
7931
7932 return true;
7933}
7934
7935bool BytecodeEmitter::emitSelfHostedGetBuiltinConstructorOrPrototype(
7936 CallNode* callNode, bool isConstructor) {
7937 ListNode* argsList = callNode->args();
7938
7939 MOZ_ASSERT(argsList->count() == 1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(argsList->count() == 1)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(argsList->count() == 1)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 1"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 7939);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1"
")"); do { MOZ_CrashSequence(__null, 7939); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7940
7941 ParseNode* argNode = argsList->head();
7942
7943 if (!argNode->isKind(ParseNodeKind::StringExpr)) {
7944 reportError(callNode, JSMSG_UNEXPECTED_TYPE, "built-in name",
7945 "not a string constant");
7946 return false;
7947 }
7948
7949 auto name = argNode->as<NameNode>().atom();
7950
7951 BuiltinObjectKind kind;
7952 if (isConstructor) {
7953 kind = BuiltinConstructorForName(name);
7954 } else {
7955 kind = BuiltinPrototypeForName(name);
7956 }
7957
7958 if (kind == BuiltinObjectKind::None) {
7959 reportError(callNode, JSMSG_UNEXPECTED_TYPE, "built-in name",
7960 "not a valid built-in");
7961 return false;
7962 }
7963
7964 return emitBuiltinObject(kind);
7965}
7966
7967bool BytecodeEmitter::emitSelfHostedGetBuiltinConstructor(CallNode* callNode) {
7968 return emitSelfHostedGetBuiltinConstructorOrPrototype(
7969 callNode, /* isConstructor = */ true);
7970}
7971
7972bool BytecodeEmitter::emitSelfHostedGetBuiltinPrototype(CallNode* callNode) {
7973 return emitSelfHostedGetBuiltinConstructorOrPrototype(
7974 callNode, /* isConstructor = */ false);
7975}
7976
7977JS::SymbolCode ParserAtomToSymbolCode(TaggedParserAtomIndex atom) {
7978 // NOTE: This is a linear search, but the set of entries is quite small and
7979 // this is only used for initial self-hosted parse.
7980#define MATCH_WELL_KNOWN_SYMBOL(NAME) \
7981 if (atom == TaggedParserAtomIndex::WellKnown::NAME()) { \
7982 return JS::SymbolCode::NAME; \
7983 }
7984 JS_FOR_EACH_WELL_KNOWN_SYMBOL(MATCH_WELL_KNOWN_SYMBOL)MATCH_WELL_KNOWN_SYMBOL(isConcatSpreadable) MATCH_WELL_KNOWN_SYMBOL
(iterator) MATCH_WELL_KNOWN_SYMBOL(match) MATCH_WELL_KNOWN_SYMBOL
(replace) MATCH_WELL_KNOWN_SYMBOL(search) MATCH_WELL_KNOWN_SYMBOL
(species) MATCH_WELL_KNOWN_SYMBOL(hasInstance) MATCH_WELL_KNOWN_SYMBOL
(split) MATCH_WELL_KNOWN_SYMBOL(toPrimitive) MATCH_WELL_KNOWN_SYMBOL
(toStringTag) MATCH_WELL_KNOWN_SYMBOL(unscopables) MATCH_WELL_KNOWN_SYMBOL
(asyncIterator) MATCH_WELL_KNOWN_SYMBOL(matchAll) MATCH_WELL_KNOWN_SYMBOL
(dispose) MATCH_WELL_KNOWN_SYMBOL(asyncDispose)
7985#undef MATCH_WELL_KNOWN_SYMBOL
7986
7987 return JS::SymbolCode::Limit;
7988}
7989
7990bool BytecodeEmitter::emitSelfHostedGetBuiltinSymbol(CallNode* callNode) {
7991 ListNode* argsList = callNode->args();
7992
7993 MOZ_ASSERT(argsList->count() == 1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(argsList->count() == 1)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(argsList->count() == 1)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 1"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 7993);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1"
")"); do { MOZ_CrashSequence(__null, 7993); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7994
7995 ParseNode* argNode = argsList->head();
7996
7997 if (!argNode->isKind(ParseNodeKind::StringExpr)) {
7998 reportError(callNode, JSMSG_UNEXPECTED_TYPE, "built-in name",
7999 "not a string constant");
8000 return false;
8001 }
8002
8003 auto name = argNode->as<NameNode>().atom();
8004
8005 JS::SymbolCode code = ParserAtomToSymbolCode(name);
8006 if (code == JS::SymbolCode::Limit) {
8007 reportError(callNode, JSMSG_UNEXPECTED_TYPE, "built-in name",
8008 "not a valid built-in");
8009 return false;
8010 }
8011
8012 return emit2(JSOp::Symbol, uint8_t(code));
8013}
8014
8015bool BytecodeEmitter::emitSelfHostedArgumentsLength(CallNode* callNode) {
8016 MOZ_ASSERT(!sc->asFunctionBox()->needsArgsObj())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!sc->asFunctionBox()->needsArgsObj())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!sc->asFunctionBox()->needsArgsObj()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!sc->asFunctionBox()->needsArgsObj()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 8016);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sc->asFunctionBox()->needsArgsObj()"
")"); do { MOZ_CrashSequence(__null, 8016); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8017 sc->asFunctionBox()->setUsesArgumentsIntrinsics();
8018
8019 MOZ_ASSERT(callNode->args()->count() == 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(callNode->args()->count() == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(callNode->args()->count
() == 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("callNode->args()->count() == 0", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 8019); AnnotateMozCrashReason("MOZ_ASSERT" "(" "callNode->args()->count() == 0"
")"); do { MOZ_CrashSequence(__null, 8019); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8020
8021 return emit1(JSOp::ArgumentsLength);
8022}
8023
8024bool BytecodeEmitter::emitSelfHostedGetArgument(CallNode* callNode) {
8025 MOZ_ASSERT(!sc->asFunctionBox()->needsArgsObj())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!sc->asFunctionBox()->needsArgsObj())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!sc->asFunctionBox()->needsArgsObj()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!sc->asFunctionBox()->needsArgsObj()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 8025);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sc->asFunctionBox()->needsArgsObj()"
")"); do { MOZ_CrashSequence(__null, 8025); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8026 sc->asFunctionBox()->setUsesArgumentsIntrinsics();
8027
8028 ListNode* argsList = callNode->args();
8029 MOZ_ASSERT(argsList->count() == 1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(argsList->count() == 1)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(argsList->count() == 1)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 1"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 8029);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1"
")"); do { MOZ_CrashSequence(__null, 8029); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8030
8031 ParseNode* argNode = argsList->head();
8032 if (!emitTree(argNode)) {
8033 return false;
8034 }
8035
8036 return emit1(JSOp::GetActualArg);
8037}
8038
8039#ifdef DEBUG1
8040void BytecodeEmitter::assertSelfHostedExpectedTopLevel(ParseNode* node) {
8041 // The function argument is expected to be a simple binding/function name.
8042 // Eg. `function foo() { }; SpecialIntrinsic(foo)`
8043 MOZ_ASSERT(node->isKind(ParseNodeKind::Name),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(node->isKind(ParseNodeKind::Name))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(node->isKind(ParseNodeKind
::Name)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("node->isKind(ParseNodeKind::Name)" " (" "argument must be a function name"
")", "./../../../../js/src/frontend/BytecodeEmitter.cpp", 8044
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::Name)"
") (" "argument must be a function name" ")"); do { MOZ_CrashSequence
(__null, 8044); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
8044 "argument must be a function name")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(node->isKind(ParseNodeKind::Name))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(node->isKind(ParseNodeKind
::Name)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("node->isKind(ParseNodeKind::Name)" " (" "argument must be a function name"
")", "./../../../../js/src/frontend/BytecodeEmitter.cpp", 8044
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::Name)"
") (" "argument must be a function name" ")"); do { MOZ_CrashSequence
(__null, 8044); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
8045 TaggedParserAtomIndex targetName = node->as<NameNode>().name();
8046
8047 // The special intrinsics must follow the target functions definition. A
8048 // simple assert is fine here since any hoisted function will cause a non-null
8049 // value to be set here.
8050 MOZ_ASSERT(prevSelfHostedTopLevelFunction)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(prevSelfHostedTopLevelFunction)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(prevSelfHostedTopLevelFunction
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"prevSelfHostedTopLevelFunction", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 8050); AnnotateMozCrashReason("MOZ_ASSERT" "(" "prevSelfHostedTopLevelFunction"
")"); do { MOZ_CrashSequence(__null, 8050); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8051
8052 // The target function must match the most recently defined top-level
8053 // self-hosted function.
8054 MOZ_ASSERT(prevSelfHostedTopLevelFunction->explicitName() == targetName,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(prevSelfHostedTopLevelFunction->explicitName() ==
targetName)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(prevSelfHostedTopLevelFunction->
explicitName() == targetName))), 0))) { do { } while (false);
MOZ_ReportAssertionFailure("prevSelfHostedTopLevelFunction->explicitName() == targetName"
" (" "selfhost decorator must immediately follow target function"
")", "./../../../../js/src/frontend/BytecodeEmitter.cpp", 8055
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "prevSelfHostedTopLevelFunction->explicitName() == targetName"
") (" "selfhost decorator must immediately follow target function"
")"); do { MOZ_CrashSequence(__null, 8055); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8055 "selfhost decorator must immediately follow target function")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(prevSelfHostedTopLevelFunction->explicitName() ==
targetName)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(prevSelfHostedTopLevelFunction->
explicitName() == targetName))), 0))) { do { } while (false);
MOZ_ReportAssertionFailure("prevSelfHostedTopLevelFunction->explicitName() == targetName"
" (" "selfhost decorator must immediately follow target function"
")", "./../../../../js/src/frontend/BytecodeEmitter.cpp", 8055
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "prevSelfHostedTopLevelFunction->explicitName() == targetName"
") (" "selfhost decorator must immediately follow target function"
")"); do { MOZ_CrashSequence(__null, 8055); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8056}
8057#endif
8058
8059bool BytecodeEmitter::emitSelfHostedSetIsInlinableLargeFunction(
8060 CallNode* callNode) {
8061#ifdef DEBUG1
8062 ListNode* argsList = callNode->args();
8063
8064 MOZ_ASSERT(argsList->count() == 1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(argsList->count() == 1)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(argsList->count() == 1)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 1"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 8064);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1"
")"); do { MOZ_CrashSequence(__null, 8064); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8065
8066 assertSelfHostedExpectedTopLevel(argsList->head());
8067#endif
8068
8069 MOZ_ASSERT(prevSelfHostedTopLevelFunction->isInitialCompilation)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(prevSelfHostedTopLevelFunction->isInitialCompilation
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(prevSelfHostedTopLevelFunction->isInitialCompilation
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"prevSelfHostedTopLevelFunction->isInitialCompilation", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 8069); AnnotateMozCrashReason("MOZ_ASSERT" "(" "prevSelfHostedTopLevelFunction->isInitialCompilation"
")"); do { MOZ_CrashSequence(__null, 8069); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8070 prevSelfHostedTopLevelFunction->setIsInlinableLargeFunction();
8071
8072 // This is still a call node, so we must generate a stack value.
8073 return emit1(JSOp::Undefined);
8074}
8075
8076bool BytecodeEmitter::emitSelfHostedSetCanonicalName(CallNode* callNode) {
8077 ListNode* argsList = callNode->args();
8078
8079 MOZ_ASSERT(argsList->count() == 2)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(argsList->count() == 2)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(argsList->count() == 2)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 2"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 8079);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2"
")"); do { MOZ_CrashSequence(__null, 8079); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8080
8081#ifdef DEBUG1
8082 assertSelfHostedExpectedTopLevel(argsList->head());
8083#endif
8084
8085 ParseNode* nameNode = argsList->last();
8086 MOZ_ASSERT(nameNode->isKind(ParseNodeKind::StringExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(nameNode->isKind(ParseNodeKind::StringExpr))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(nameNode->isKind(ParseNodeKind::StringExpr)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("nameNode->isKind(ParseNodeKind::StringExpr)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 8086);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "nameNode->isKind(ParseNodeKind::StringExpr)"
")"); do { MOZ_CrashSequence(__null, 8086); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8087 TaggedParserAtomIndex specName = nameNode->as<NameNode>().atom();
8088 // Canonical name must be atomized.
8089 compilationState.parserAtoms.markUsedByStencil(specName,
8090 ParserAtom::Atomize::Yes);
8091
8092 // Store the canonical name for instantiation.
8093 prevSelfHostedTopLevelFunction->functionStencil().setSelfHostedCanonicalName(
8094 specName);
8095
8096 return emit1(JSOp::Undefined);
8097}
8098
8099#ifdef DEBUG1
8100void BytecodeEmitter::assertSelfHostedUnsafeGetReservedSlot(
8101 ListNode* argsList) {
8102 MOZ_ASSERT(argsList->count() == 2)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(argsList->count() == 2)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(argsList->count() == 2)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 2"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 8102);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2"
")"); do { MOZ_CrashSequence(__null, 8102); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8103
8104 ParseNode* objNode = argsList->head();
8105 ParseNode* slotNode = objNode->pn_next;
8106
8107 // Ensure that the slot argument is fixed, this is required by the JITs.
8108 MOZ_ASSERT(slotNode->isKind(ParseNodeKind::NumberExpr),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(slotNode->isKind(ParseNodeKind::NumberExpr))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(slotNode->isKind(ParseNodeKind::NumberExpr)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("slotNode->isKind(ParseNodeKind::NumberExpr)"
" (" "slot argument must be a constant" ")", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 8109); AnnotateMozCrashReason("MOZ_ASSERT" "(" "slotNode->isKind(ParseNodeKind::NumberExpr)"
") (" "slot argument must be a constant" ")"); do { MOZ_CrashSequence
(__null, 8109); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
8109 "slot argument must be a constant")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(slotNode->isKind(ParseNodeKind::NumberExpr))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(slotNode->isKind(ParseNodeKind::NumberExpr)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("slotNode->isKind(ParseNodeKind::NumberExpr)"
" (" "slot argument must be a constant" ")", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 8109); AnnotateMozCrashReason("MOZ_ASSERT" "(" "slotNode->isKind(ParseNodeKind::NumberExpr)"
") (" "slot argument must be a constant" ")"); do { MOZ_CrashSequence
(__null, 8109); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
8110}
8111
8112void BytecodeEmitter::assertSelfHostedUnsafeSetReservedSlot(
8113 ListNode* argsList) {
8114 MOZ_ASSERT(argsList->count() == 3)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(argsList->count() == 3)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(argsList->count() == 3)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 3"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 8114);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 3"
")"); do { MOZ_CrashSequence(__null, 8114); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8115
8116 ParseNode* objNode = argsList->head();
8117 ParseNode* slotNode = objNode->pn_next;
8118
8119 // Ensure that the slot argument is fixed, this is required by the JITs.
8120 MOZ_ASSERT(slotNode->isKind(ParseNodeKind::NumberExpr),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(slotNode->isKind(ParseNodeKind::NumberExpr))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(slotNode->isKind(ParseNodeKind::NumberExpr)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("slotNode->isKind(ParseNodeKind::NumberExpr)"
" (" "slot argument must be a constant" ")", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 8121); AnnotateMozCrashReason("MOZ_ASSERT" "(" "slotNode->isKind(ParseNodeKind::NumberExpr)"
") (" "slot argument must be a constant" ")"); do { MOZ_CrashSequence
(__null, 8121); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
8121 "slot argument must be a constant")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(slotNode->isKind(ParseNodeKind::NumberExpr))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(slotNode->isKind(ParseNodeKind::NumberExpr)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("slotNode->isKind(ParseNodeKind::NumberExpr)"
" (" "slot argument must be a constant" ")", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 8121); AnnotateMozCrashReason("MOZ_ASSERT" "(" "slotNode->isKind(ParseNodeKind::NumberExpr)"
") (" "slot argument must be a constant" ")"); do { MOZ_CrashSequence
(__null, 8121); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
8122}
8123#endif
8124
8125/* A version of emitCalleeAndThis for the optional cases:
8126 * * a?.()
8127 * * a?.b()
8128 * * a?.["b"]()
8129 * * (a?.b)()
8130 * * a?.#b()
8131 *
8132 * See emitCallOrNew and emitOptionalCall for more context.
8133 */
8134bool BytecodeEmitter::emitOptionalCalleeAndThis(ParseNode* callee,
8135 CallNode* call,
8136 CallOrNewEmitter& cone,
8137 OptionalEmitter& oe) {
8138 AutoCheckRecursionLimit recursion(fc);
8139 if (!recursion.check(fc)) {
8140 return false;
8141 }
8142
8143 switch (ParseNodeKind kind = callee->getKind()) {
8144 case ParseNodeKind::Name: {
8145 auto name = callee->as<NameNode>().name();
8146 if (!cone.emitNameCallee(name)) {
8147 // [stack] CALLEE THIS
8148 return false;
8149 }
8150 break;
8151 }
8152
8153 case ParseNodeKind::OptionalDotExpr: {
8154 MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(emitterMode != BytecodeEmitter::SelfHosting)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(emitterMode != BytecodeEmitter::SelfHosting))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("emitterMode != BytecodeEmitter::SelfHosting"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 8154);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode != BytecodeEmitter::SelfHosting"
")"); do { MOZ_CrashSequence(__null, 8154); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8155 OptionalPropertyAccess* prop = &callee->as<OptionalPropertyAccess>();
8156 bool isSuper = false;
8157
8158 PropOpEmitter& poe = cone.prepareForPropCallee(isSuper);
8159 if (!emitOptionalDotExpression(prop, poe, isSuper, oe)) {
8160 // [stack] CALLEE THIS
8161 return false;
8162 }
8163 break;
8164 }
8165 case ParseNodeKind::ArgumentsLength: {
8166 MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(emitterMode != BytecodeEmitter::SelfHosting)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(emitterMode != BytecodeEmitter::SelfHosting))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("emitterMode != BytecodeEmitter::SelfHosting"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 8166);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode != BytecodeEmitter::SelfHosting"
")"); do { MOZ_CrashSequence(__null, 8166); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8167 if (!cone.prepareForOtherCallee()) {
8168 return false;
8169 }
8170 if (!emitArgumentsLength()) {
8171 // [stack] ARGUMENTS_LENGTH
8172 return false;
8173 }
8174 break;
8175 }
8176 case ParseNodeKind::DotExpr: {
8177 MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(emitterMode != BytecodeEmitter::SelfHosting)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(emitterMode != BytecodeEmitter::SelfHosting))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("emitterMode != BytecodeEmitter::SelfHosting"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 8177);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode != BytecodeEmitter::SelfHosting"
")"); do { MOZ_CrashSequence(__null, 8177); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8178 PropertyAccess* prop = &callee->as<PropertyAccess>();
8179 bool isSuper = prop->isSuper();
8180
8181 PropOpEmitter& poe = cone.prepareForPropCallee(isSuper);
8182 if (!emitOptionalDotExpression(prop, poe, isSuper, oe)) {
8183 // [stack] CALLEE THIS
8184 return false;
8185 }
8186 break;
8187 }
8188
8189 case ParseNodeKind::OptionalElemExpr: {
8190 OptionalPropertyByValue* elem = &callee->as<OptionalPropertyByValue>();
8191 bool isSuper = false;
8192 MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!elem->key().isKind(ParseNodeKind::PrivateName))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!elem->key().isKind(ParseNodeKind::PrivateName)))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!elem->key().isKind(ParseNodeKind::PrivateName)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 8192);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)"
")"); do { MOZ_CrashSequence(__null, 8192); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8193 ElemOpEmitter& eoe = cone.prepareForElemCallee(isSuper);
8194 if (!emitOptionalElemExpression(elem, eoe, isSuper, oe)) {
8195 // [stack] CALLEE THIS
8196 return false;
8197 }
8198 break;
8199 }
8200 case ParseNodeKind::ElemExpr: {
8201 PropertyByValue* elem = &callee->as<PropertyByValue>();
8202 bool isSuper = elem->isSuper();
8203 MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!elem->key().isKind(ParseNodeKind::PrivateName))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!elem->key().isKind(ParseNodeKind::PrivateName)))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!elem->key().isKind(ParseNodeKind::PrivateName)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 8203);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)"
")"); do { MOZ_CrashSequence(__null, 8203); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8204 ElemOpEmitter& eoe = cone.prepareForElemCallee(isSuper);
8205 if (!emitOptionalElemExpression(elem, eoe, isSuper, oe)) {
8206 // [stack] CALLEE THIS
8207 return false;
8208 }
8209 break;
8210 }
8211
8212 case ParseNodeKind::PrivateMemberExpr:
8213 case ParseNodeKind::OptionalPrivateMemberExpr: {
8214 PrivateMemberAccessBase* privateExpr =
8215 &callee->as<PrivateMemberAccessBase>();
8216 PrivateOpEmitter& xoe =
8217 cone.prepareForPrivateCallee(privateExpr->privateName().name());
8218 if (!emitOptionalPrivateExpression(privateExpr, xoe, oe)) {
8219 // [stack] CALLEE THIS
8220 return false;
8221 }
8222 break;
8223 }
8224
8225 case ParseNodeKind::Function:
8226 if (!cone.prepareForFunctionCallee()) {
8227 return false;
8228 }
8229 if (!emitOptionalTree(callee, oe)) {
8230 // [stack] CALLEE
8231 return false;
8232 }
8233 break;
8234
8235 case ParseNodeKind::OptionalChain: {
8236 return emitCalleeAndThisForOptionalChain(&callee->as<UnaryNode>(), call,
8237 cone);
8238 }
8239
8240 default:
8241 MOZ_RELEASE_ASSERT(kind != ParseNodeKind::SuperBase)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(kind != ParseNodeKind::SuperBase)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(kind != ParseNodeKind::SuperBase
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"kind != ParseNodeKind::SuperBase", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 8241); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "kind != ParseNodeKind::SuperBase"
")"); do { MOZ_CrashSequence(__null, 8241); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8242
8243 if (!cone.prepareForOtherCallee()) {
8244 return false;
8245 }
8246 if (!emitOptionalTree(callee, oe)) {
8247 // [stack] CALLEE
8248 return false;
8249 }
8250 break;
8251 }
8252
8253 if (!cone.emitThis()) {
8254 // [stack] CALLEE THIS
8255 return false;
8256 }
8257
8258 return true;
8259}
8260
8261bool BytecodeEmitter::emitCalleeAndThis(ParseNode* callee, CallNode* maybeCall,
8262 CallOrNewEmitter& cone) {
8263 MOZ_ASSERT_IF(maybeCall, maybeCall->callee() == callee)do { if (maybeCall) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(maybeCall->callee() == callee)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(maybeCall->callee() == callee
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"maybeCall->callee() == callee", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 8263); AnnotateMozCrashReason("MOZ_ASSERT" "(" "maybeCall->callee() == callee"
")"); do { MOZ_CrashSequence(__null, 8263); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
8264
8265 switch (callee->getKind()) {
8266 case ParseNodeKind::Name: {
8267 auto name = callee->as<NameNode>().name();
8268 if (!cone.emitNameCallee(name)) {
8269 // [stack] CALLEE THIS?
8270 return false;
8271 }
8272 break;
8273 }
8274 case ParseNodeKind::ArgumentsLength: {
8275 MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(emitterMode != BytecodeEmitter::SelfHosting)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(emitterMode != BytecodeEmitter::SelfHosting))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("emitterMode != BytecodeEmitter::SelfHosting"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 8275);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode != BytecodeEmitter::SelfHosting"
")"); do { MOZ_CrashSequence(__null, 8275); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8276 if (!cone.prepareForOtherCallee()) {
8277 return false;
8278 }
8279 if (!emitArgumentsLength()) {
8280 // [stack] ARGUMENTS_LENGTH
8281 return false;
8282 }
8283 break;
8284 }
8285 case ParseNodeKind::DotExpr: {
8286 MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(emitterMode != BytecodeEmitter::SelfHosting)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(emitterMode != BytecodeEmitter::SelfHosting))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("emitterMode != BytecodeEmitter::SelfHosting"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 8286);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode != BytecodeEmitter::SelfHosting"
")"); do { MOZ_CrashSequence(__null, 8286); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8287 PropertyAccess* prop = &callee->as<PropertyAccess>();
8288 bool isSuper = prop->isSuper();
8289
8290 PropOpEmitter& poe = cone.prepareForPropCallee(isSuper);
8291 if (!poe.prepareForObj()) {
8292 return false;
8293 }
8294 if (isSuper) {
8295 UnaryNode* base = &prop->expression().as<UnaryNode>();
8296 if (!emitGetThisForSuperBase(base)) {
8297 // [stack] THIS
8298 return false;
8299 }
8300 } else {
8301 if (!emitPropLHS(prop)) {
8302 // [stack] OBJ
8303 return false;
8304 }
8305 }
8306 if (!poe.emitGet(prop->key().atom())) {
8307 // [stack] CALLEE THIS?
8308 return false;
8309 }
8310
8311 break;
8312 }
8313 case ParseNodeKind::ElemExpr: {
8314 MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(emitterMode != BytecodeEmitter::SelfHosting)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(emitterMode != BytecodeEmitter::SelfHosting))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("emitterMode != BytecodeEmitter::SelfHosting"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 8314);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode != BytecodeEmitter::SelfHosting"
")"); do { MOZ_CrashSequence(__null, 8314); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8315 PropertyByValue* elem = &callee->as<PropertyByValue>();
8316 bool isSuper = elem->isSuper();
8317 MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!elem->key().isKind(ParseNodeKind::PrivateName))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!elem->key().isKind(ParseNodeKind::PrivateName)))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!elem->key().isKind(ParseNodeKind::PrivateName)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 8317);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)"
")"); do { MOZ_CrashSequence(__null, 8317); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8318 ElemOpEmitter& eoe = cone.prepareForElemCallee(isSuper);
8319 if (!emitElemObjAndKey(elem, eoe)) {
8320 // [stack] # if Super
8321 // [stack] THIS? THIS KEY
8322 // [stack] # otherwise
8323 // [stack] OBJ? OBJ KEY
8324 return false;
8325 }
8326 if (!eoe.emitGet()) {
8327 // [stack] CALLEE THIS?
8328 return false;
8329 }
8330
8331 break;
8332 }
8333 case ParseNodeKind::PrivateMemberExpr: {
8334 MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(emitterMode != BytecodeEmitter::SelfHosting)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(emitterMode != BytecodeEmitter::SelfHosting))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("emitterMode != BytecodeEmitter::SelfHosting"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 8334);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode != BytecodeEmitter::SelfHosting"
")"); do { MOZ_CrashSequence(__null, 8334); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8335 PrivateMemberAccessBase* privateExpr =
8336 &callee->as<PrivateMemberAccessBase>();
8337 PrivateOpEmitter& xoe =
8338 cone.prepareForPrivateCallee(privateExpr->privateName().name());
8339 if (!emitTree(&privateExpr->expression())) {
8340 // [stack] OBJ
8341 return false;
8342 }
8343 if (!xoe.emitReference()) {
8344 // [stack] OBJ NAME
8345 return false;
8346 }
8347 if (!xoe.emitGetForCallOrNew()) {
8348 // [stack] CALLEE THIS
8349 return false;
8350 }
8351
8352 break;
8353 }
8354 case ParseNodeKind::Function:
8355 if (!cone.prepareForFunctionCallee()) {
8356 return false;
8357 }
8358 if (!emitTree(callee)) {
8359 // [stack] CALLEE
8360 return false;
8361 }
8362 break;
8363 case ParseNodeKind::SuperBase:
8364 MOZ_ASSERT(maybeCall)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(maybeCall)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(maybeCall))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("maybeCall", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 8364); AnnotateMozCrashReason("MOZ_ASSERT" "(" "maybeCall" ")"
); do { MOZ_CrashSequence(__null, 8364); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8365 MOZ_ASSERT(maybeCall->isKind(ParseNodeKind::SuperCallExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(maybeCall->isKind(ParseNodeKind::SuperCallExpr))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(maybeCall->isKind(ParseNodeKind::SuperCallExpr)))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("maybeCall->isKind(ParseNodeKind::SuperCallExpr)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 8365);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "maybeCall->isKind(ParseNodeKind::SuperCallExpr)"
")"); do { MOZ_CrashSequence(__null, 8365); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8366 MOZ_ASSERT(callee->isKind(ParseNodeKind::SuperBase))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(callee->isKind(ParseNodeKind::SuperBase))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(callee->isKind(ParseNodeKind::SuperBase)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("callee->isKind(ParseNodeKind::SuperBase)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 8366);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "callee->isKind(ParseNodeKind::SuperBase)"
")"); do { MOZ_CrashSequence(__null, 8366); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8367 if (!cone.emitSuperCallee()) {
8368 // [stack] CALLEE IsConstructing
8369 return false;
8370 }
8371 break;
8372 case ParseNodeKind::OptionalChain: {
8373 MOZ_ASSERT(maybeCall)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(maybeCall)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(maybeCall))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("maybeCall", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 8373); AnnotateMozCrashReason("MOZ_ASSERT" "(" "maybeCall" ")"
); do { MOZ_CrashSequence(__null, 8373); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8374 return emitCalleeAndThisForOptionalChain(&callee->as<UnaryNode>(),
8375 maybeCall, cone);
8376 }
8377 default:
8378 if (!cone.prepareForOtherCallee()) {
8379 return false;
8380 }
8381 if (!emitTree(callee)) {
8382 return false;
8383 }
8384 break;
8385 }
8386
8387 if (!cone.emitThis()) {
8388 // [stack] CALLEE THIS
8389 return false;
8390 }
8391
8392 return true;
8393}
8394
8395ParseNode* BytecodeEmitter::getCoordNode(ParseNode* callNode,
8396 ParseNode* calleeNode, JSOp op,
8397 ListNode* argsList) const {
8398 ParseNode* coordNode = callNode;
8399 if (op == JSOp::Call || op == JSOp::SpreadCall) {
8400 // Default to using the location of the `(` itself.
8401 // obj[expr]() // expression
8402 // ^ // column coord
8403 coordNode = argsList;
8404
8405 switch (calleeNode->getKind()) {
8406 case ParseNodeKind::ArgumentsLength:
8407 case ParseNodeKind::DotExpr:
8408 // Use the position of a property access identifier.
8409 //
8410 // obj().aprop() // expression
8411 // ^ // column coord
8412 //
8413 // Note: Because of the constant folding logic in FoldElement,
8414 // this case also applies for constant string properties.
8415 //
8416 // obj()['aprop']() // expression
8417 // ^ // column coord
8418 coordNode = &calleeNode->as<NonOptionalPropertyAccessBase>().key();
8419 break;
8420 case ParseNodeKind::Name: {
8421 // Use the start of callee name unless it is at a separator
8422 // or has no args.
8423 //
8424 // 2 + obj() // expression
8425 // ^ // column coord
8426 //
8427 if (argsList->empty() ||
8428 !bytecodeSection().atSeparator(calleeNode->pn_pos.begin)) {
8429 // Use the start of callee names.
8430 coordNode = calleeNode;
8431 }
8432 break;
8433 }
8434
8435 default:
8436 break;
8437 }
8438 }
8439 return coordNode;
8440}
8441
8442bool BytecodeEmitter::emitArguments(ListNode* argsList, bool isCall,
8443 bool isSpread, CallOrNewEmitter& cone) {
8444 uint32_t argc = argsList->count();
8445 if (argc >= ARGC_LIMIT) {
8446 reportError(argsList,
8447 isCall ? JSMSG_TOO_MANY_FUN_ARGS : JSMSG_TOO_MANY_CON_ARGS);
8448 return false;
8449 }
8450 if (!isSpread) {
8451 if (!cone.prepareForNonSpreadArguments()) {
8452 // [stack] CALLEE THIS
8453 return false;
8454 }
8455 for (ParseNode* arg : argsList->contents()) {
8456 if (!updateSourceCoordNotesIfNonLiteral(arg)) {
8457 return false;
8458 }
8459 if (!emitTree(arg)) {
8460 // [stack] CALLEE THIS ARG*
8461 return false;
8462 }
8463 }
8464 } else if (cone.wantSpreadOperand()) {
8465 auto* spreadNode = &argsList->head()->as<UnaryNode>();
8466 if (!updateSourceCoordNotesIfNonLiteral(spreadNode->kid())) {
8467 return false;
8468 }
8469 if (!emitTree(spreadNode->kid())) {
8470 // [stack] CALLEE THIS ARG0
8471 return false;
8472 }
8473
8474 if (!cone.emitSpreadArgumentsTest()) {
8475 // [stack] CALLEE THIS ARG0
8476 return false;
8477 }
8478
8479 if (cone.wantSpreadIteration()) {
8480 if (!emitSpreadIntoArray(spreadNode)) {
8481 // [stack] CALLEE THIS ARR
8482 return false;
8483 }
8484 }
8485
8486 if (!cone.emitSpreadArgumentsTestEnd()) {
8487 // [stack] CALLEE THIS ARR
8488 return false;
8489 }
8490 } else {
8491 if (!cone.prepareForSpreadArguments()) {
8492 // [stack] CALLEE THIS
8493 return false;
8494 }
8495 if (!emitArray(argsList)) {
8496 // [stack] CALLEE THIS ARR
8497 return false;
8498 }
8499 }
8500
8501 return true;
8502}
8503
8504bool BytecodeEmitter::emitOptionalCall(CallNode* callNode, OptionalEmitter& oe,
8505 ValueUsage valueUsage) {
8506 /*
8507 * A modified version of emitCallOrNew that handles optional calls.
8508 *
8509 * These include the following:
8510 * a?.()
8511 * a.b?.()
8512 * a.["b"]?.()
8513 * (a?.b)?.()
8514 *
8515 * See CallOrNewEmitter for more context.
8516 */
8517 ParseNode* calleeNode = callNode->callee();
8518 ListNode* argsList = callNode->args();
8519 bool isSpread = IsSpreadOp(callNode->callOp());
8520 JSOp op = callNode->callOp();
8521 uint32_t argc = argsList->count();
8522 bool isOptimizableSpread = isSpread && argc == 1;
8523
8524 CallOrNewEmitter cone(this, op,
8525 isOptimizableSpread
8526 ? CallOrNewEmitter::ArgumentsKind::SingleSpread
8527 : CallOrNewEmitter::ArgumentsKind::Other,
8528 valueUsage);
8529
8530 ParseNode* coordNode = getCoordNode(callNode, calleeNode, op, argsList);
8531
8532 if (!emitOptionalCalleeAndThis(calleeNode, callNode, cone, oe)) {
8533 // [stack] CALLEE THIS
8534 return false;
8535 }
8536
8537 if (callNode->isKind(ParseNodeKind::OptionalCallExpr)) {
8538 if (!oe.emitJumpShortCircuitForCall()) {
8539 // [stack] CALLEE THIS
8540 return false;
8541 }
8542 }
8543
8544 if (!emitArguments(argsList, /* isCall = */ true, isSpread, cone)) {
8545 // [stack] CALLEE THIS ARGS...
8546 return false;
8547 }
8548
8549 if (!cone.emitEnd(argc, coordNode->pn_pos.begin)) {
8550 // [stack] RVAL
8551 return false;
8552 }
8553
8554 return true;
8555}
8556
8557bool BytecodeEmitter::emitSelfHostedDisposeResources(CallNode* callNode,
8558 DisposalKind kind) {
8559 ListNode* argsList = callNode->args();
8560 MOZ_ASSERT(argsList->count() == 2)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(argsList->count() == 2)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(argsList->count() == 2)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 2"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 8560);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2"
")"); do { MOZ_CrashSequence(__null, 8560); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8561
8562 ParseNode* resourcesNode = argsList->head();
8563 ParseNode* countNode = resourcesNode->pn_next;
8564
8565 DisposalEmitter de(this, bool(kind));
8566
8567 if (!emit1(JSOp::False)) {
8568 // [stack] THROWING
8569 return false;
8570 }
8571
8572 if (!emit1(JSOp::Undefined)) {
8573 // [stack] THROWING UNDEF
8574 return false;
8575 }
8576
8577 if (!de.prepareForDisposeCapability()) {
8578 // [stack] RVAL? NEEDS-AWAIT? HAS-AWAITED? THROWING UNDEF
8579 return false;
8580 }
8581
8582 if (!emitTree(resourcesNode)) {
8583 // [stack] RVAL? NEEDS-AWAIT? HAS-AWAITED? THROWING UNDEF RESOURCES
8584 return false;
8585 }
8586
8587 if (!emitTree(countNode)) {
8588 // [stack] RVAL? NEEDS-AWAIT? HAS-AWAITED? THROWING UNDEF RESOURCES COUNT
8589 return false;
8590 }
8591
8592 if (!de.emitEnd(*innermostEmitterScope())) {
8593 // [stack] EXC THROWING
8594 return false;
8595 }
8596
8597 // [stack] EXC THROWING
8598
8599 InternalIfEmitter ifThrow(this);
8600
8601 if (!ifThrow.emitThenElse()) {
8602 // [stack] EXC
8603 return false;
8604 }
8605
8606 if (!emit1(JSOp::Throw)) {
8607 // [stack]
8608 return false;
8609 }
8610
8611 if (!ifThrow.emitElse()) {
8612 // [stack] EXC
8613 return false;
8614 }
8615
8616 if (!emit1(JSOp::Pop)) {
8617 // [stack]
8618 return false;
8619 }
8620
8621 if (!ifThrow.emitEnd()) {
8622 // [stack]
8623 return false;
8624 }
8625
8626 if (!emit1(JSOp::Undefined)) {
8627 // [stack] RVAL
8628 return false;
8629 }
8630
8631 return true;
8632}
8633
8634bool BytecodeEmitter::emitCallOrNew(CallNode* callNode, ValueUsage valueUsage) {
8635 /*
8636 * Emit callable invocation or operator new (constructor call) code.
8637 * First, emit code for the left operand to evaluate the callable or
8638 * constructable object expression.
8639 *
8640 * Then (or in a call case that has no explicit reference-base
8641 * object) we emit JSOp::Undefined to produce the undefined |this|
8642 * value required for calls (which non-strict mode functions
8643 * will box into the global object).
8644 */
8645 bool isCall = callNode->isKind(ParseNodeKind::CallExpr) ||
8646 callNode->isKind(ParseNodeKind::TaggedTemplateExpr);
8647 ParseNode* calleeNode = callNode->callee();
8648 ListNode* argsList = callNode->args();
8649 JSOp op = callNode->callOp();
8650
8651 if (calleeNode->isKind(ParseNodeKind::Name) &&
8652 emitterMode == BytecodeEmitter::SelfHosting && op == JSOp::Call) {
8653 // Calls to "callFunction", "callContentFunction", or "resumeGenerator" in
8654 // self-hosted code generate inline bytecode.
8655 //
8656 // NOTE: The list of special instruction names has to be kept in sync with
8657 // "js/src/builtin/.eslintrc.js".
8658 auto calleeName = calleeNode->as<NameNode>().name();
8659 if (calleeName == TaggedParserAtomIndex::WellKnown::callFunction()) {
8660 return emitSelfHostedCallFunction(callNode, JSOp::Call);
8661 }
8662 if (calleeName == TaggedParserAtomIndex::WellKnown::callContentFunction()) {
8663 return emitSelfHostedCallFunction(callNode, JSOp::CallContent);
8664 }
8665 if (calleeName ==
8666 TaggedParserAtomIndex::WellKnown::constructContentFunction()) {
8667 return emitSelfHostedCallFunction(callNode, JSOp::NewContent);
8668 }
8669 if (calleeName == TaggedParserAtomIndex::WellKnown::resumeGenerator()) {
8670 return emitSelfHostedResumeGenerator(callNode);
8671 }
8672 if (calleeName == TaggedParserAtomIndex::WellKnown::allowContentIter()) {
8673 return emitSelfHostedAllowContentIter(callNode);
8674 }
8675 if (calleeName ==
8676 TaggedParserAtomIndex::WellKnown::allowContentIterWith()) {
8677 return emitSelfHostedAllowContentIterWith(callNode);
8678 }
8679 if (calleeName ==
8680 TaggedParserAtomIndex::WellKnown::allowContentIterWithNext()) {
8681 return emitSelfHostedAllowContentIterWithNext(callNode);
8682 }
8683 if (calleeName == TaggedParserAtomIndex::WellKnown::DefineDataProperty() &&
8684 argsList->count() == 3) {
8685 return emitSelfHostedDefineDataProperty(callNode);
8686 }
8687 if (calleeName == TaggedParserAtomIndex::WellKnown::hasOwn()) {
8688 return emitSelfHostedHasOwn(callNode);
8689 }
8690 if (calleeName == TaggedParserAtomIndex::WellKnown::getPropertySuper()) {
8691 return emitSelfHostedGetPropertySuper(callNode);
8692 }
8693 if (calleeName == TaggedParserAtomIndex::WellKnown::ToNumeric()) {
8694 return emitSelfHostedToNumeric(callNode);
8695 }
8696 if (calleeName == TaggedParserAtomIndex::WellKnown::ToString()) {
8697 return emitSelfHostedToString(callNode);
8698 }
8699 if (calleeName ==
8700 TaggedParserAtomIndex::WellKnown::GetBuiltinConstructor()) {
8701 return emitSelfHostedGetBuiltinConstructor(callNode);
8702 }
8703 if (calleeName == TaggedParserAtomIndex::WellKnown::GetBuiltinPrototype()) {
8704 return emitSelfHostedGetBuiltinPrototype(callNode);
8705 }
8706 if (calleeName == TaggedParserAtomIndex::WellKnown::GetBuiltinSymbol()) {
8707 return emitSelfHostedGetBuiltinSymbol(callNode);
8708 }
8709 if (calleeName == TaggedParserAtomIndex::WellKnown::ArgumentsLength()) {
8710 return emitSelfHostedArgumentsLength(callNode);
8711 }
8712 if (calleeName == TaggedParserAtomIndex::WellKnown::GetArgument()) {
8713 return emitSelfHostedGetArgument(callNode);
8714 }
8715 if (calleeName ==
8716 TaggedParserAtomIndex::WellKnown::SetIsInlinableLargeFunction()) {
8717 return emitSelfHostedSetIsInlinableLargeFunction(callNode);
8718 }
8719 if (calleeName == TaggedParserAtomIndex::WellKnown::SetCanonicalName()) {
8720 return emitSelfHostedSetCanonicalName(callNode);
8721 }
8722 if (calleeName == TaggedParserAtomIndex::WellKnown::IsNullOrUndefined()) {
8723 return emitSelfHostedIsNullOrUndefined(callNode);
8724 }
8725 if (calleeName == TaggedParserAtomIndex::WellKnown::IteratorClose()) {
8726 return emitSelfHostedIteratorClose(callNode);
8727 }
8728 if (calleeName ==
8729 TaggedParserAtomIndex::WellKnown::DisposeResourcesAsync()) {
8730 return emitSelfHostedDisposeResources(callNode, DisposalKind::Async);
8731 }
8732 if (calleeName ==
8733 TaggedParserAtomIndex::WellKnown::DisposeResourcesSync()) {
8734 return emitSelfHostedDisposeResources(callNode, DisposalKind::Sync);
8735 }
8736#ifdef DEBUG1
8737 if (calleeName ==
8738 TaggedParserAtomIndex::WellKnown::UnsafeGetReservedSlot() ||
8739 calleeName == TaggedParserAtomIndex::WellKnown::
8740 UnsafeGetObjectFromReservedSlot() ||
8741 calleeName == TaggedParserAtomIndex::WellKnown::
8742 UnsafeGetInt32FromReservedSlot() ||
8743 calleeName == TaggedParserAtomIndex::WellKnown::
8744 UnsafeGetStringFromReservedSlot()) {
8745 // Make sure that this call is correct, but don't emit any special code.
8746 assertSelfHostedUnsafeGetReservedSlot(argsList);
8747 }
8748 if (calleeName ==
8749 TaggedParserAtomIndex::WellKnown::UnsafeSetReservedSlot()) {
8750 // Make sure that this call is correct, but don't emit any special code.
8751 assertSelfHostedUnsafeSetReservedSlot(argsList);
8752 }
8753#endif
8754 // Fall through
8755 }
8756
8757 uint32_t argc = argsList->count();
8758 bool isSpread = IsSpreadOp(op);
8759 bool isOptimizableSpread = isSpread && argc == 1;
8760 bool isDefaultDerivedClassConstructor =
8761 sc->isFunctionBox() && sc->asFunctionBox()->isDerivedClassConstructor() &&
8762 sc->asFunctionBox()->isSyntheticFunction();
8763 MOZ_ASSERT_IF(isDefaultDerivedClassConstructor, isOptimizableSpread)do { if (isDefaultDerivedClassConstructor) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(isOptimizableSpread
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(isOptimizableSpread))), 0))) { do { } while (false);
MOZ_ReportAssertionFailure("isOptimizableSpread", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 8763); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isOptimizableSpread"
")"); do { MOZ_CrashSequence(__null, 8763); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
8764 CallOrNewEmitter cone(
8765 this, op,
8766 isOptimizableSpread
8767 ? isDefaultDerivedClassConstructor
8768 ? CallOrNewEmitter::ArgumentsKind::PassthroughRest
8769 : CallOrNewEmitter::ArgumentsKind::SingleSpread
8770 : CallOrNewEmitter::ArgumentsKind::Other,
8771 valueUsage);
8772
8773 if (!emitCalleeAndThis(calleeNode, callNode, cone)) {
8774 // [stack] CALLEE THIS
8775 return false;
8776 }
8777 if (!emitArguments(argsList, isCall, isSpread, cone)) {
8778 // [stack] CALLEE THIS ARGS...
8779 return false;
8780 }
8781
8782 // Push new.target for construct calls.
8783 if (IsConstructOp(op)) {
8784 if (op == JSOp::SuperCall || op == JSOp::SpreadSuperCall) {
8785 if (!emitNewTarget(callNode)) {
8786 // [stack] CALLEE THIS ARGS.. NEW.TARGET
8787 return false;
8788 }
8789 } else {
8790 // Repush the callee as new.target
8791 uint32_t effectiveArgc = isSpread ? 1 : argc;
8792 if (!emitDupAt(effectiveArgc + 1)) {
8793 // [stack] CALLEE THIS ARGS.. CALLEE
8794 return false;
8795 }
8796 }
8797 }
8798
8799 ParseNode* coordNode = getCoordNode(callNode, calleeNode, op, argsList);
8800
8801 if (!cone.emitEnd(argc, coordNode->pn_pos.begin)) {
8802 // [stack] RVAL
8803 return false;
8804 }
8805
8806 return true;
8807}
8808
8809// This list must be kept in the same order in several places:
8810// - The binary operators in ParseNode.h ,
8811// - the binary operators in TokenKind.h
8812// - the precedence list in Parser.cpp
8813static const JSOp ParseNodeKindToJSOp[] = {
8814 // Some binary ops require special code generation (PrivateIn);
8815 // these should not use BinaryOpParseNodeKindToJSOp. This table fills those
8816 // slots with Nops to make the rest of the table lookup work.
8817 JSOp::Coalesce, JSOp::Or, JSOp::And, JSOp::BitOr, JSOp::BitXor,
8818 JSOp::BitAnd, JSOp::StrictEq, JSOp::Eq, JSOp::StrictNe, JSOp::Ne,
8819 JSOp::Lt, JSOp::Le, JSOp::Gt, JSOp::Ge, JSOp::Instanceof,
8820 JSOp::In, JSOp::Nop, JSOp::Lsh, JSOp::Rsh, JSOp::Ursh,
8821 JSOp::Add, JSOp::Sub, JSOp::Mul, JSOp::Div, JSOp::Mod,
8822 JSOp::Pow};
8823
8824static inline JSOp BinaryOpParseNodeKindToJSOp(ParseNodeKind pnk) {
8825 MOZ_ASSERT(pnk >= ParseNodeKind::BinOpFirst)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pnk >= ParseNodeKind::BinOpFirst)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pnk >= ParseNodeKind::BinOpFirst
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"pnk >= ParseNodeKind::BinOpFirst", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 8825); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pnk >= ParseNodeKind::BinOpFirst"
")"); do { MOZ_CrashSequence(__null, 8825); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8826 MOZ_ASSERT(pnk <= ParseNodeKind::BinOpLast)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pnk <= ParseNodeKind::BinOpLast)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pnk <= ParseNodeKind::BinOpLast
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"pnk <= ParseNodeKind::BinOpLast", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 8826); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pnk <= ParseNodeKind::BinOpLast"
")"); do { MOZ_CrashSequence(__null, 8826); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8827 int parseNodeFirst = size_t(ParseNodeKind::BinOpFirst);
8828#ifdef DEBUG1
8829 int jsopArraySize = std::size(ParseNodeKindToJSOp);
8830 int parseNodeKindListSize =
8831 size_t(ParseNodeKind::BinOpLast) - parseNodeFirst + 1;
8832 MOZ_ASSERT(jsopArraySize == parseNodeKindListSize)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(jsopArraySize == parseNodeKindListSize)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(jsopArraySize == parseNodeKindListSize))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("jsopArraySize == parseNodeKindListSize"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 8832);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "jsopArraySize == parseNodeKindListSize"
")"); do { MOZ_CrashSequence(__null, 8832); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8833 // Ensure we don't use this to find an op for a parse node
8834 // requiring special emission rules.
8835 MOZ_ASSERT(ParseNodeKindToJSOp[size_t(pnk) - parseNodeFirst] != JSOp::Nop)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(ParseNodeKindToJSOp[size_t(pnk) - parseNodeFirst] !=
JSOp::Nop)>::isValid, "invalid assertion condition"); if (
(__builtin_expect(!!(!(!!(ParseNodeKindToJSOp[size_t(pnk) - parseNodeFirst
] != JSOp::Nop))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("ParseNodeKindToJSOp[size_t(pnk) - parseNodeFirst] != JSOp::Nop"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 8835);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "ParseNodeKindToJSOp[size_t(pnk) - parseNodeFirst] != JSOp::Nop"
")"); do { MOZ_CrashSequence(__null, 8835); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8836#endif
8837 return ParseNodeKindToJSOp[size_t(pnk) - parseNodeFirst];
8838}
8839
8840bool BytecodeEmitter::emitRightAssociative(ListNode* node) {
8841 // ** is the only right-associative operator.
8842 MOZ_ASSERT(node->isKind(ParseNodeKind::PowExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(node->isKind(ParseNodeKind::PowExpr))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(node->isKind(ParseNodeKind::PowExpr)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("node->isKind(ParseNodeKind::PowExpr)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 8842);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::PowExpr)"
")"); do { MOZ_CrashSequence(__null, 8842); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8843
8844 // Right-associative operator chain.
8845 for (ParseNode* subexpr : node->contents()) {
8846 if (!updateSourceCoordNotesIfNonLiteral(subexpr)) {
8847 return false;
8848 }
8849 if (!emitTree(subexpr)) {
8850 return false;
8851 }
8852 }
8853 for (uint32_t i = 0; i < node->count() - 1; i++) {
8854 if (!emit1(JSOp::Pow)) {
8855 return false;
8856 }
8857 }
8858 return true;
8859}
8860
8861Maybe<ConstantCompareOperand>
8862BytecodeEmitter::parseNodeToConstantCompareOperand(ParseNode* constant) {
8863 switch (constant->getKind()) {
8864 case ParseNodeKind::NumberExpr: {
8865 double d = constant->as<NumericLiteral>().value();
8866 int32_t ival;
8867 if (NumberEqualsInt32(d, &ival)) {
8868 if (ConstantCompareOperand::CanEncodeInt32ValueAsOperand(ival)) {
8869 return Some(ConstantCompareOperand(int8_t(ival)));
8870 }
8871 }
8872 return Nothing();
8873 }
8874 case ParseNodeKind::TrueExpr:
8875 case ParseNodeKind::FalseExpr:
8876 return Some(
8877 ConstantCompareOperand(constant->isKind(ParseNodeKind::TrueExpr)));
8878 case ParseNodeKind::NullExpr:
8879 return Some(
8880 ConstantCompareOperand(ConstantCompareOperand::EncodedType::Null));
8881 case ParseNodeKind::RawUndefinedExpr:
8882 return Some(ConstantCompareOperand(
8883 ConstantCompareOperand::EncodedType::Undefined));
8884 case ParseNodeKind::Name: {
8885 MOZ_ASSERT(constant->as<NameNode>().name() ==do { static_assert( mozilla::detail::AssertionConditionType<
decltype(constant->as<NameNode>().name() == TaggedParserAtomIndex
::WellKnown::undefined())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(constant->as<NameNode>
().name() == TaggedParserAtomIndex::WellKnown::undefined())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("constant->as<NameNode>().name() == TaggedParserAtomIndex::WellKnown::undefined()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 8886);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "constant->as<NameNode>().name() == TaggedParserAtomIndex::WellKnown::undefined()"
")"); do { MOZ_CrashSequence(__null, 8886); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8886 TaggedParserAtomIndex::WellKnown::undefined())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(constant->as<NameNode>().name() == TaggedParserAtomIndex
::WellKnown::undefined())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(constant->as<NameNode>
().name() == TaggedParserAtomIndex::WellKnown::undefined())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("constant->as<NameNode>().name() == TaggedParserAtomIndex::WellKnown::undefined()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 8886);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "constant->as<NameNode>().name() == TaggedParserAtomIndex::WellKnown::undefined()"
")"); do { MOZ_CrashSequence(__null, 8886); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8887 NameLocation loc = lookupName(constant->as<NameNode>().name());
8888 switch (loc.kind()) {
8889 case NameLocation::Kind::Global:
8890 if (!sc->hasNonSyntacticScope()) {
8891 return Some(ConstantCompareOperand(
8892 ConstantCompareOperand::EncodedType::Undefined));
8893 }
8894 return Nothing();
8895 case NameLocation::Kind::Intrinsic:
8896 return Some(ConstantCompareOperand(
8897 ConstantCompareOperand::EncodedType::Undefined));
8898 default:
8899 return Nothing();
8900 }
8901 }
8902 default:
8903 return Nothing();
8904 }
8905}
8906
8907bool BytecodeEmitter::tryEmitConstantEq(ListNode* node, JSOp op,
8908 bool* emitted) {
8909 // We ignore long chains of === or !==, we
8910 // only optimise cases a === b or a !== b
8911 if (node->count() != 2) {
8912 *emitted = false;
8913 return true;
8914 }
8915
8916 JSOp constantOp;
8917 switch (op) {
8918 case JSOp::StrictEq:
8919 constantOp = JSOp::StrictConstantEq;
8920 break;
8921 case JSOp::StrictNe:
8922 constantOp = JSOp::StrictConstantNe;
8923 break;
8924 default:
8925 *emitted = false;
8926 return true;
8927 }
8928
8929 ParseNode* left = node->head();
8930 ParseNode* right = node->head()->pn_next;
8931
8932 ParseNode* expressionNode;
8933 ParseNode* constantNode;
8934 if (left->isConstant() || left->isUndefinedLiteral()) {
8935 expressionNode = right;
8936 constantNode = left;
8937 } else if (right->isConstant() || right->isUndefinedLiteral()) {
8938 expressionNode = left;
8939 constantNode = right;
8940 } else {
8941 *emitted = false;
8942 return true;
8943 }
8944
8945 Maybe<ConstantCompareOperand> operand =
8946 parseNodeToConstantCompareOperand(constantNode);
8947 if (operand.isNothing()) {
8948 *emitted = false;
8949 return true;
8950 }
8951
8952 if (!emitTree(expressionNode)) {
8953 return false;
8954 }
8955
8956 if (!emitUint16Operand(constantOp, operand->rawValue())) {
8957 return false;
8958 }
8959
8960 *emitted = true;
8961 return true;
8962}
8963
8964bool BytecodeEmitter::emitLeftAssociative(ListNode* node) {
8965 JSOp op = BinaryOpParseNodeKindToJSOp(node->getKind());
8966 bool constantEqEmitted = false;
8967 if (!tryEmitConstantEq(node, op, &constantEqEmitted)) {
8968 return false;
8969 }
8970 if (constantEqEmitted) {
8971 return true;
8972 }
8973 // Left-associative operator chain.
8974 if (!emitTree(node->head())) {
8975 return false;
8976 }
8977 ParseNode* nextExpr = node->head()->pn_next;
8978 do {
8979 if (!updateSourceCoordNotesIfNonLiteral(nextExpr)) {
8980 return false;
8981 }
8982 if (!emitTree(nextExpr)) {
8983 return false;
8984 }
8985 if (!emit1(op)) {
8986 return false;
8987 }
8988 } while ((nextExpr = nextExpr->pn_next));
8989 return true;
8990}
8991
8992bool BytecodeEmitter::emitPrivateInExpr(ListNode* node) {
8993 MOZ_ASSERT(node->head()->isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(node->head()->isKind(ParseNodeKind::PrivateName
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(node->head()->isKind(ParseNodeKind::PrivateName
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("node->head()->isKind(ParseNodeKind::PrivateName)", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 8993); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->head()->isKind(ParseNodeKind::PrivateName)"
")"); do { MOZ_CrashSequence(__null, 8993); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8994
8995 NameNode& privateNameNode = node->head()->as<NameNode>();
8996 TaggedParserAtomIndex privateName = privateNameNode.name();
8997
8998 PrivateOpEmitter xoe(this, PrivateOpEmitter::Kind::ErgonomicBrandCheck,
8999 privateName);
9000
9001 ParseNode* valueNode = node->head()->pn_next;
9002 MOZ_ASSERT(valueNode->pn_next == nullptr)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(valueNode->pn_next == nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(valueNode->pn_next == nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"valueNode->pn_next == nullptr", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 9002); AnnotateMozCrashReason("MOZ_ASSERT" "(" "valueNode->pn_next == nullptr"
")"); do { MOZ_CrashSequence(__null, 9002); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9003
9004 if (!emitTree(valueNode)) {
9005 // [stack] OBJ
9006 return false;
9007 }
9008
9009 if (!xoe.emitReference()) {
9010 // [stack] OBJ BRAND if private method
9011 // [stack] OBJ NAME if private field or accessor.
9012 return false;
9013 }
9014
9015 if (!xoe.emitBrandCheck()) {
9016 // [stack] OBJ BRAND BOOL if private method
9017 // [stack] OBJ NAME BOOL if private field or accessor.
9018 return false;
9019 }
9020
9021 if (!emitUnpickN(2)) {
9022 // [stack] BOOL OBJ BRAND if private method
9023 // [stack] BOOL OBJ NAME if private field or accessor.
9024 return false;
9025 }
9026
9027 if (!emitPopN(2)) {
9028 // [stack] BOOL
9029 return false;
9030 }
9031
9032 return true;
9033}
9034
9035/*
9036 * Special `emitTree` for Optional Chaining case.
9037 * Examples of this are `emitOptionalChain`, `emitDeleteOptionalChain` and
9038 * `emitCalleeAndThisForOptionalChain`.
9039 */
9040bool BytecodeEmitter::emitOptionalTree(
9041 ParseNode* pn, OptionalEmitter& oe,
9042 ValueUsage valueUsage /* = ValueUsage::WantValue */) {
9043 AutoCheckRecursionLimit recursion(fc);
9044 if (!recursion.check(fc)) {
9045 return false;
9046 }
9047 ParseNodeKind kind = pn->getKind();
9048 switch (kind) {
9049 case ParseNodeKind::OptionalDotExpr: {
9050 OptionalPropertyAccess* prop = &pn->as<OptionalPropertyAccess>();
9051 bool isSuper = false;
9052 PropOpEmitter poe(this, PropOpEmitter::Kind::Get,
9053 PropOpEmitter::ObjKind::Other);
9054 if (!emitOptionalDotExpression(prop, poe, isSuper, oe)) {
9055 return false;
9056 }
9057 break;
9058 }
9059 case ParseNodeKind::ArgumentsLength: {
9060 // Emit via emitArgumentsLength to handle elided arguments bindings;
9061 // emitOptionalDotExpression would instead emit a plain GetName of
9062 // |arguments|.
9063 if (!emitArgumentsLength()) {
9064 return false;
9065 }
9066 break;
9067 }
9068 case ParseNodeKind::DotExpr: {
9069 PropertyAccess* prop = &pn->as<PropertyAccess>();
9070 bool isSuper = prop->isSuper();
9071 PropOpEmitter poe(this, PropOpEmitter::Kind::Get,
9072 isSuper ? PropOpEmitter::ObjKind::Super
9073 : PropOpEmitter::ObjKind::Other);
9074 if (!emitOptionalDotExpression(prop, poe, isSuper, oe)) {
9075 return false;
9076 }
9077 break;
9078 }
9079
9080 case ParseNodeKind::OptionalElemExpr: {
9081 OptionalPropertyByValue* elem = &pn->as<OptionalPropertyByValue>();
9082 bool isSuper = false;
9083 MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!elem->key().isKind(ParseNodeKind::PrivateName))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!elem->key().isKind(ParseNodeKind::PrivateName)))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!elem->key().isKind(ParseNodeKind::PrivateName)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 9083);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)"
")"); do { MOZ_CrashSequence(__null, 9083); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9084 ElemOpEmitter eoe(this, ElemOpEmitter::Kind::Get,
9085 ElemOpEmitter::ObjKind::Other);
9086
9087 if (!emitOptionalElemExpression(elem, eoe, isSuper, oe)) {
9088 return false;
9089 }
9090 break;
9091 }
9092 case ParseNodeKind::ElemExpr: {
9093 PropertyByValue* elem = &pn->as<PropertyByValue>();
9094 bool isSuper = elem->isSuper();
9095 MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!elem->key().isKind(ParseNodeKind::PrivateName))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!elem->key().isKind(ParseNodeKind::PrivateName)))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!elem->key().isKind(ParseNodeKind::PrivateName)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 9095);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)"
")"); do { MOZ_CrashSequence(__null, 9095); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9096 ElemOpEmitter eoe(this, ElemOpEmitter::Kind::Get,
9097 isSuper ? ElemOpEmitter::ObjKind::Super
9098 : ElemOpEmitter::ObjKind::Other);
9099
9100 if (!emitOptionalElemExpression(elem, eoe, isSuper, oe)) {
9101 return false;
9102 }
9103 break;
9104 }
9105 case ParseNodeKind::PrivateMemberExpr:
9106 case ParseNodeKind::OptionalPrivateMemberExpr: {
9107 PrivateMemberAccessBase* privateExpr = &pn->as<PrivateMemberAccessBase>();
9108 PrivateOpEmitter xoe(this, PrivateOpEmitter::Kind::Get,
9109 privateExpr->privateName().name());
9110 if (!emitOptionalPrivateExpression(privateExpr, xoe, oe)) {
9111 return false;
9112 }
9113 break;
9114 }
9115 case ParseNodeKind::CallExpr:
9116 case ParseNodeKind::OptionalCallExpr:
9117 if (!emitOptionalCall(&pn->as<CallNode>(), oe, valueUsage)) {
9118 return false;
9119 }
9120 break;
9121 // List of accepted ParseNodeKinds that might appear only at the beginning
9122 // of an Optional Chain.
9123 // For example, a taggedTemplateExpr node might occur if we have
9124 // `test`?.b, with `test` as the taggedTemplateExpr ParseNode.
9125 default:
9126#ifdef DEBUG1
9127 // https://tc39.es/ecma262/#sec-primary-expression
9128 bool isPrimaryExpression =
9129 kind == ParseNodeKind::ThisExpr || kind == ParseNodeKind::Name ||
9130 kind == ParseNodeKind::PrivateName ||
9131 kind == ParseNodeKind::NullExpr || kind == ParseNodeKind::TrueExpr ||
9132 kind == ParseNodeKind::FalseExpr ||
9133 kind == ParseNodeKind::NumberExpr ||
9134 kind == ParseNodeKind::BigIntExpr ||
9135 kind == ParseNodeKind::StringExpr ||
9136 kind == ParseNodeKind::ArrayExpr ||
9137 kind == ParseNodeKind::ObjectExpr ||
9138 kind == ParseNodeKind::Function || kind == ParseNodeKind::ClassDecl ||
9139 kind == ParseNodeKind::RegExpExpr ||
9140 kind == ParseNodeKind::TemplateStringExpr ||
9141 kind == ParseNodeKind::TemplateStringListExpr ||
9142 kind == ParseNodeKind::RawUndefinedExpr || pn->isInParens();
9143
9144 // https://tc39.es/ecma262/#sec-left-hand-side-expressions
9145 bool isMemberExpression = isPrimaryExpression ||
9146 kind == ParseNodeKind::TaggedTemplateExpr ||
9147 kind == ParseNodeKind::NewExpr ||
9148 kind == ParseNodeKind::NewTargetExpr ||
9149 kind == ParseNodeKind::ImportMetaExpr;
9150
9151 bool isCallExpression = kind == ParseNodeKind::SetThis ||
9152 kind == ParseNodeKind::CallImportExpr;
9153
9154 MOZ_ASSERT(isMemberExpression || isCallExpression,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(isMemberExpression || isCallExpression)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(isMemberExpression || isCallExpression))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("isMemberExpression || isCallExpression"
" (" "Unknown ParseNodeKind for OptionalChain" ")", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 9155); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isMemberExpression || isCallExpression"
") (" "Unknown ParseNodeKind for OptionalChain" ")"); do { MOZ_CrashSequence
(__null, 9155); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
9155 "Unknown ParseNodeKind for OptionalChain")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(isMemberExpression || isCallExpression)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(isMemberExpression || isCallExpression))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("isMemberExpression || isCallExpression"
" (" "Unknown ParseNodeKind for OptionalChain" ")", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 9155); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isMemberExpression || isCallExpression"
") (" "Unknown ParseNodeKind for OptionalChain" ")"); do { MOZ_CrashSequence
(__null, 9155); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
9156#endif
9157 return emitTree(pn);
9158 }
9159 return true;
9160}
9161
9162// Handle the case of a call made on a OptionalChainParseNode.
9163// For example `(a?.b)()` and `(a?.b)?.()`.
9164bool BytecodeEmitter::emitCalleeAndThisForOptionalChain(
9165 UnaryNode* optionalChain, CallNode* callNode, CallOrNewEmitter& cone) {
9166 ParseNode* calleeNode = optionalChain->kid();
9167
9168 // Create a new OptionalEmitter, in order to emit the right bytecode
9169 // in isolation.
9170 OptionalEmitter oe(this, bytecodeSection().stackDepth());
9171
9172 if (!emitOptionalCalleeAndThis(calleeNode, callNode, cone, oe)) {
9173 // [stack] CALLEE THIS
9174 return false;
9175 }
9176
9177 // complete the jump if necessary. This will set both the "this" value
9178 // and the "callee" value to undefined, if the callee is undefined. It
9179 // does not matter much what the this value is, the function call will
9180 // fail if it is not optional, and be set to undefined otherwise.
9181 if (!oe.emitOptionalJumpTarget(JSOp::Undefined,
9182 OptionalEmitter::Kind::Reference)) {
9183 // [stack] # If shortcircuit
9184 // [stack] UNDEFINED UNDEFINED
9185 // [stack] # otherwise
9186 // [stack] CALLEE THIS
9187 return false;
9188 }
9189 return true;
9190}
9191
9192bool BytecodeEmitter::emitOptionalChain(UnaryNode* optionalChain,
9193 ValueUsage valueUsage) {
9194 ParseNode* expr = optionalChain->kid();
9195
9196 OptionalEmitter oe(this, bytecodeSection().stackDepth());
9197
9198 if (!emitOptionalTree(expr, oe, valueUsage)) {
9199 // [stack] VAL
9200 return false;
9201 }
9202
9203 if (!oe.emitOptionalJumpTarget(JSOp::Undefined)) {
9204 // [stack] # If shortcircuit
9205 // [stack] UNDEFINED
9206 // [stack] # otherwise
9207 // [stack] VAL
9208 return false;
9209 }
9210
9211 return true;
9212}
9213
9214bool BytecodeEmitter::emitOptionalDotExpression(PropertyAccessBase* prop,
9215 PropOpEmitter& poe,
9216 bool isSuper,
9217 OptionalEmitter& oe) {
9218 if (!poe.prepareForObj()) {
9219 // [stack]
9220 return false;
9221 }
9222
9223 if (isSuper) {
9224 UnaryNode* base = &prop->expression().as<UnaryNode>();
9225 if (!emitGetThisForSuperBase(base)) {
9226 // [stack] OBJ
9227 return false;
9228 }
9229 } else {
9230 if (!emitOptionalTree(&prop->expression(), oe)) {
9231 // [stack] OBJ
9232 return false;
9233 }
9234 }
9235
9236 if (prop->isKind(ParseNodeKind::OptionalDotExpr)) {
9237 MOZ_ASSERT(!isSuper)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!isSuper)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!isSuper))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!isSuper", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 9237); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!isSuper" ")"
); do { MOZ_CrashSequence(__null, 9237); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9238 if (!oe.emitJumpShortCircuit()) {
9239 // [stack] # if Jump
9240 // [stack] UNDEFINED-OR-NULL
9241 // [stack] # otherwise
9242 // [stack] OBJ
9243 return false;
9244 }
9245 }
9246
9247 if (!poe.emitGet(prop->key().atom())) {
9248 // [stack] PROP
9249 return false;
9250 }
9251
9252 return true;
9253}
9254
9255bool BytecodeEmitter::emitOptionalElemExpression(PropertyByValueBase* elem,
9256 ElemOpEmitter& eoe,
9257 bool isSuper,
9258 OptionalEmitter& oe) {
9259 if (!eoe.prepareForObj()) {
9260 // [stack]
9261 return false;
9262 }
9263
9264 if (isSuper) {
9265 UnaryNode* base = &elem->expression().as<UnaryNode>();
9266 if (!emitGetThisForSuperBase(base)) {
9267 // [stack] OBJ
9268 return false;
9269 }
9270 } else {
9271 if (!emitOptionalTree(&elem->expression(), oe)) {
9272 // [stack] OBJ
9273 return false;
9274 }
9275 }
9276
9277 if (elem->isKind(ParseNodeKind::OptionalElemExpr)) {
9278 MOZ_ASSERT(!isSuper)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!isSuper)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!isSuper))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!isSuper", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 9278); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!isSuper" ")"
); do { MOZ_CrashSequence(__null, 9278); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9279 if (!oe.emitJumpShortCircuit()) {
9280 // [stack] # if Jump
9281 // [stack] UNDEFINED-OR-NULL
9282 // [stack] # otherwise
9283 // [stack] OBJ
9284 return false;
9285 }
9286 }
9287
9288 if (!eoe.prepareForKey()) {
9289 // [stack] OBJ? OBJ
9290 return false;
9291 }
9292
9293 if (!emitTree(&elem->key())) {
9294 // [stack] OBJ? OBJ KEY
9295 return false;
9296 }
9297
9298 if (!eoe.emitGet()) {
9299 // [stack] ELEM
9300 return false;
9301 }
9302
9303 return true;
9304}
9305
9306bool BytecodeEmitter::emitOptionalPrivateExpression(
9307 PrivateMemberAccessBase* privateExpr, PrivateOpEmitter& xoe,
9308 OptionalEmitter& oe) {
9309 if (!emitOptionalTree(&privateExpr->expression(), oe)) {
9310 // [stack] OBJ
9311 return false;
9312 }
9313
9314 if (privateExpr->isKind(ParseNodeKind::OptionalPrivateMemberExpr)) {
9315 if (!oe.emitJumpShortCircuit()) {
9316 // [stack] # if Jump
9317 // [stack] UNDEFINED-OR-NULL
9318 // [stack] # otherwise
9319 // [stack] OBJ
9320 return false;
9321 }
9322 }
9323
9324 if (!xoe.emitReference()) {
9325 // [stack] OBJ NAME
9326 return false;
9327 }
9328 if (!xoe.emitGet()) {
9329 // [stack] CALLEE THIS # if call
9330 // [stack] VALUE # otherwise
9331 return false;
9332 }
9333
9334 return true;
9335}
9336
9337bool BytecodeEmitter::emitShortCircuit(ListNode* node, ValueUsage valueUsage) {
9338 MOZ_ASSERT(node->isKind(ParseNodeKind::OrExpr) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(node->isKind(ParseNodeKind::OrExpr) || node->isKind
(ParseNodeKind::CoalesceExpr) || node->isKind(ParseNodeKind
::AndExpr))>::isValid, "invalid assertion condition"); if (
(__builtin_expect(!!(!(!!(node->isKind(ParseNodeKind::OrExpr
) || node->isKind(ParseNodeKind::CoalesceExpr) || node->
isKind(ParseNodeKind::AndExpr)))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("node->isKind(ParseNodeKind::OrExpr) || node->isKind(ParseNodeKind::CoalesceExpr) || node->isKind(ParseNodeKind::AndExpr)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 9340);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::OrExpr) || node->isKind(ParseNodeKind::CoalesceExpr) || node->isKind(ParseNodeKind::AndExpr)"
")"); do { MOZ_CrashSequence(__null, 9340); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9339 node->isKind(ParseNodeKind::CoalesceExpr) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(node->isKind(ParseNodeKind::OrExpr) || node->isKind
(ParseNodeKind::CoalesceExpr) || node->isKind(ParseNodeKind
::AndExpr))>::isValid, "invalid assertion condition"); if (
(__builtin_expect(!!(!(!!(node->isKind(ParseNodeKind::OrExpr
) || node->isKind(ParseNodeKind::CoalesceExpr) || node->
isKind(ParseNodeKind::AndExpr)))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("node->isKind(ParseNodeKind::OrExpr) || node->isKind(ParseNodeKind::CoalesceExpr) || node->isKind(ParseNodeKind::AndExpr)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 9340);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::OrExpr) || node->isKind(ParseNodeKind::CoalesceExpr) || node->isKind(ParseNodeKind::AndExpr)"
")"); do { MOZ_CrashSequence(__null, 9340); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9340 node->isKind(ParseNodeKind::AndExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(node->isKind(ParseNodeKind::OrExpr) || node->isKind
(ParseNodeKind::CoalesceExpr) || node->isKind(ParseNodeKind
::AndExpr))>::isValid, "invalid assertion condition"); if (
(__builtin_expect(!!(!(!!(node->isKind(ParseNodeKind::OrExpr
) || node->isKind(ParseNodeKind::CoalesceExpr) || node->
isKind(ParseNodeKind::AndExpr)))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("node->isKind(ParseNodeKind::OrExpr) || node->isKind(ParseNodeKind::CoalesceExpr) || node->isKind(ParseNodeKind::AndExpr)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 9340);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::OrExpr) || node->isKind(ParseNodeKind::CoalesceExpr) || node->isKind(ParseNodeKind::AndExpr)"
")"); do { MOZ_CrashSequence(__null, 9340); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9341
9342 /*
9343 * JSOp::Or converts the operand on the stack to boolean, leaves the original
9344 * value on the stack and jumps if true; otherwise it falls into the next
9345 * bytecode, which pops the left operand and then evaluates the right operand.
9346 * The jump goes around the right operand evaluation.
9347 *
9348 * JSOp::And converts the operand on the stack to boolean and jumps if false;
9349 * otherwise it falls into the right operand's bytecode.
9350 */
9351
9352 TDZCheckCache tdzCache(this);
9353
9354 JSOp op;
9355 switch (node->getKind()) {
9356 case ParseNodeKind::OrExpr:
9357 op = JSOp::Or;
9358 break;
9359 case ParseNodeKind::CoalesceExpr:
9360 op = JSOp::Coalesce;
9361 break;
9362 case ParseNodeKind::AndExpr:
9363 op = JSOp::And;
9364 break;
9365 default:
9366 MOZ_CRASH("Unexpected ParseNodeKind")do { do { } while (false); MOZ_ReportCrash("" "Unexpected ParseNodeKind"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 9366);
AnnotateMozCrashReason("MOZ_CRASH(" "Unexpected ParseNodeKind"
")"); do { MOZ_CrashSequence(__null, 9366); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
9367 }
9368
9369 JumpList jump;
9370
9371 // Left-associative operator chain: avoid too much recursion.
9372 //
9373 // Emit all nodes but the last.
9374 for (ParseNode* expr : node->contentsTo(node->last())) {
9375 if (!emitTree(expr)) {
9376 return false;
9377 }
9378 if (!emitJump(op, &jump)) {
9379 return false;
9380 }
9381 if (!emit1(JSOp::Pop)) {
9382 return false;
9383 }
9384 }
9385
9386 // Emit the last node
9387 if (!emitTree(node->last(), valueUsage)) {
9388 return false;
9389 }
9390
9391 if (!emitJumpTargetAndPatch(jump)) {
9392 return false;
9393 }
9394 return true;
9395}
9396
9397bool BytecodeEmitter::emitSequenceExpr(ListNode* node, ValueUsage valueUsage) {
9398 for (ParseNode* child : node->contentsTo(node->last())) {
9399 if (!updateSourceCoordNotes(child->pn_pos.begin)) {
9400 return false;
9401 }
9402 if (!emitTree(child, ValueUsage::IgnoreValue)) {
9403 return false;
9404 }
9405 if (!emit1(JSOp::Pop)) {
9406 return false;
9407 }
9408 }
9409
9410 ParseNode* child = node->last();
9411 if (!updateSourceCoordNotes(child->pn_pos.begin)) {
9412 return false;
9413 }
9414 if (!emitTree(child, valueUsage)) {
9415 return false;
9416 }
9417 return true;
9418}
9419
9420// Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See
9421// the comment on emitSwitch.
9422MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitIncOrDec(UnaryNode* incDec,
9423 ValueUsage valueUsage) {
9424 switch (incDec->kid()->getKind()) {
9425 case ParseNodeKind::ArgumentsLength:
9426 case ParseNodeKind::DotExpr:
9427 return emitPropIncDec(incDec, valueUsage);
9428 case ParseNodeKind::ElemExpr:
9429 return emitElemIncDec(incDec, valueUsage);
9430 case ParseNodeKind::PrivateMemberExpr:
9431 return emitPrivateIncDec(incDec, valueUsage);
9432 case ParseNodeKind::CallExpr:
9433 return emitCallIncDec(incDec);
9434 default:
9435 return emitNameIncDec(incDec, valueUsage);
9436 }
9437}
9438
9439// Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See
9440// the comment on emitSwitch.
9441MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitLabeledStatement(
9442 const LabeledStatement* labeledStmt) {
9443 auto name = labeledStmt->label();
9444 LabelEmitter label(this);
9445
9446 label.emitLabel(name);
9447
9448 if (!emitTree(labeledStmt->statement())) {
9449 return false;
9450 }
9451 if (!label.emitEnd()) {
9452 return false;
9453 }
9454
9455 return true;
9456}
9457
9458bool BytecodeEmitter::emitConditionalExpression(
9459 ConditionalExpression& conditional, ValueUsage valueUsage) {
9460 CondEmitter cond(this);
9461 if (!cond.emitCond()) {
9462 return false;
9463 }
9464
9465 ParseNode* conditionNode = &conditional.condition();
9466 auto conditionKind = IfEmitter::ConditionKind::Positive;
9467 if (conditionNode->isKind(ParseNodeKind::NotExpr)) {
9468 conditionNode = conditionNode->as<UnaryNode>().kid();
9469 conditionKind = IfEmitter::ConditionKind::Negative;
9470 }
9471
9472 // NOTE: NotExpr of conditionNode may be unwrapped, and in that case the
9473 // negation is handled by conditionKind.
9474 if (!emitTree(conditionNode)) {
9475 return false;
9476 }
9477
9478 if (!cond.emitThenElse(conditionKind)) {
9479 return false;
9480 }
9481
9482 if (!emitTree(&conditional.thenExpression(), valueUsage)) {
9483 return false;
9484 }
9485
9486 if (!cond.emitElse()) {
9487 return false;
9488 }
9489
9490 if (!emitTree(&conditional.elseExpression(), valueUsage)) {
9491 return false;
9492 }
9493
9494 if (!cond.emitEnd()) {
9495 return false;
9496 }
9497 MOZ_ASSERT(cond.pushed() == 1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(cond.pushed() == 1)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(cond.pushed() == 1))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("cond.pushed() == 1"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 9497);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "cond.pushed() == 1"
")"); do { MOZ_CrashSequence(__null, 9497); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9498
9499 return true;
9500}
9501
9502// Check for an object-literal property list that can be handled by the
9503// ObjLiteral writer. We ensure that for each `prop: value` pair, the key is a
9504// constant name or numeric index, there is no accessor specified, and the value
9505// can be encoded by an ObjLiteral instruction (constant number, string,
9506// boolean, null/undefined).
9507void BytecodeEmitter::isPropertyListObjLiteralCompatible(
9508 ListNode* obj, bool* withValues, bool* withoutValues) const {
9509 bool keysOK = true;
9510 bool valuesOK = true;
9511 uint32_t propCount = 0;
9512
9513 for (ParseNode* propdef : obj->contents()) {
9514 if (!propdef->is<BinaryNode>()) {
9515 keysOK = false;
9516 break;
9517 }
9518 propCount++;
9519
9520 BinaryNode* prop = &propdef->as<BinaryNode>();
9521 ParseNode* key = prop->left();
9522 ParseNode* value = prop->right();
9523
9524 // Computed keys not OK (ObjLiteral data stores constant keys).
9525 if (key->isKind(ParseNodeKind::ComputedName)) {
9526 keysOK = false;
9527 break;
9528 }
9529
9530 // BigIntExprs should have been lowered to computed names at parse
9531 // time, and so should be excluded above.
9532 MOZ_ASSERT(!key->isKind(ParseNodeKind::BigIntExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!key->isKind(ParseNodeKind::BigIntExpr))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!key->isKind(ParseNodeKind::BigIntExpr)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!key->isKind(ParseNodeKind::BigIntExpr)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 9532);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!key->isKind(ParseNodeKind::BigIntExpr)"
")"); do { MOZ_CrashSequence(__null, 9532); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9533
9534 // Numeric keys OK as long as they are integers and in range.
9535 if (key->isKind(ParseNodeKind::NumberExpr)) {
9536 double numValue = key->as<NumericLiteral>().value();
9537 int32_t i = 0;
9538 if (!NumberIsInt32(numValue, &i)) {
9539 keysOK = false;
9540 break;
9541 }
9542 if (!ObjLiteralWriter::arrayIndexInRange(i)) {
9543 keysOK = false;
9544 break;
9545 }
9546 }
9547
9548 MOZ_ASSERT(key->isKind(ParseNodeKind::ObjectPropertyName) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(key->isKind(ParseNodeKind::ObjectPropertyName) ||
key->isKind(ParseNodeKind::StringExpr) || key->isKind(
ParseNodeKind::NumberExpr))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(key->isKind(ParseNodeKind
::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr
) || key->isKind(ParseNodeKind::NumberExpr)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("key->isKind(ParseNodeKind::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 9550);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr)"
")"); do { MOZ_CrashSequence(__null, 9550); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9549 key->isKind(ParseNodeKind::StringExpr) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(key->isKind(ParseNodeKind::ObjectPropertyName) ||
key->isKind(ParseNodeKind::StringExpr) || key->isKind(
ParseNodeKind::NumberExpr))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(key->isKind(ParseNodeKind
::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr
) || key->isKind(ParseNodeKind::NumberExpr)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("key->isKind(ParseNodeKind::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 9550);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr)"
")"); do { MOZ_CrashSequence(__null, 9550); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9550 key->isKind(ParseNodeKind::NumberExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(key->isKind(ParseNodeKind::ObjectPropertyName) ||
key->isKind(ParseNodeKind::StringExpr) || key->isKind(
ParseNodeKind::NumberExpr))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(key->isKind(ParseNodeKind
::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr
) || key->isKind(ParseNodeKind::NumberExpr)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("key->isKind(ParseNodeKind::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 9550);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr)"
")"); do { MOZ_CrashSequence(__null, 9550); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9551
9552 AccessorType accessorType =
9553 prop->is<PropertyDefinition>()
9554 ? prop->as<PropertyDefinition>().accessorType()
9555 : AccessorType::None;
9556 if (accessorType != AccessorType::None) {
9557 keysOK = false;
9558 break;
9559 }
9560
9561 if (!isRHSObjLiteralCompatible(value)) {
9562 valuesOK = false;
9563 }
9564 }
9565
9566 if (propCount > SharedPropMap::MaxPropsForNonDictionary) {
9567 // JSOp::NewObject cannot accept dictionary-mode objects.
9568 keysOK = false;
9569 }
9570
9571 *withValues = keysOK && valuesOK;
9572 *withoutValues = keysOK;
9573}
9574
9575bool BytecodeEmitter::isArrayObjLiteralCompatible(ListNode* array) const {
9576 for (ParseNode* elem : array->contents()) {
9577 if (elem->isKind(ParseNodeKind::Spread)) {
9578 return false;
9579 }
9580 if (!isRHSObjLiteralCompatible(elem)) {
9581 return false;
9582 }
9583 }
9584 return true;
9585}
9586
9587bool BytecodeEmitter::emitPropertyList(ListNode* obj, PropertyEmitter& pe,
9588 PropListType type) {
9589 // [stack] CTOR? OBJ
9590
9591 size_t curFieldKeyIndex = 0;
9592 size_t curStaticFieldKeyIndex = 0;
9593 for (ParseNode* propdef : obj->contents()) {
9594 if (propdef->is<ClassField>()) {
9595 MOZ_ASSERT(type == ClassBody)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(type == ClassBody)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(type == ClassBody))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("type == ClassBody"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 9595);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == ClassBody" ")"
); do { MOZ_CrashSequence(__null, 9595); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9596 // Only handle computing field keys here: the .initializers lambda array
9597 // is created elsewhere.
9598 ClassField* field = &propdef->as<ClassField>();
9599 if (field->name().getKind() == ParseNodeKind::ComputedName) {
9600 auto fieldKeys =
9601 field->isStatic()
9602 ? TaggedParserAtomIndex::WellKnown::dot_staticFieldKeys_()
9603 : TaggedParserAtomIndex::WellKnown::dot_fieldKeys_();
9604 if (!emitGetName(fieldKeys)) {
9605 // [stack] CTOR OBJ ARRAY
9606 return false;
9607 }
9608
9609 ParseNode* nameExpr = field->name().as<UnaryNode>().kid();
9610
9611 if (!emitTree(nameExpr, ValueUsage::WantValue)) {
9612 // [stack] CTOR OBJ ARRAY KEY
9613 return false;
9614 }
9615
9616 if (!emit1(JSOp::ToPropertyKey)) {
9617 // [stack] CTOR OBJ ARRAY KEY
9618 return false;
9619 }
9620
9621 size_t fieldKeysIndex;
9622 if (field->isStatic()) {
9623 fieldKeysIndex = curStaticFieldKeyIndex++;
9624 } else {
9625 fieldKeysIndex = curFieldKeyIndex++;
9626 }
9627
9628 if (!emitUint32Operand(JSOp::InitElemArray, fieldKeysIndex)) {
9629 // [stack] CTOR OBJ ARRAY
9630 return false;
9631 }
9632
9633 if (!emit1(JSOp::Pop)) {
9634 // [stack] CTOR OBJ
9635 return false;
9636 }
9637 }
9638 continue;
9639 }
9640
9641 if (propdef->isKind(ParseNodeKind::StaticClassBlock)) {
9642 // Static class blocks are emitted as part of
9643 // emitCreateMemberInitializers.
9644 continue;
9645 }
9646
9647 if (propdef->is<LexicalScopeNode>()) {
9648 // Constructors are sometimes wrapped in LexicalScopeNodes. As we
9649 // already handled emitting the constructor, skip it.
9650 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(propdef->as<LexicalScopeNode>().scopeBody()
->is<ClassMethod>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(propdef->as<LexicalScopeNode
>().scopeBody()->is<ClassMethod>()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("propdef->as<LexicalScopeNode>().scopeBody()->is<ClassMethod>()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 9651);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "propdef->as<LexicalScopeNode>().scopeBody()->is<ClassMethod>()"
")"); do { MOZ_CrashSequence(__null, 9651); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9651 propdef->as<LexicalScopeNode>().scopeBody()->is<ClassMethod>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(propdef->as<LexicalScopeNode>().scopeBody()
->is<ClassMethod>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(propdef->as<LexicalScopeNode
>().scopeBody()->is<ClassMethod>()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("propdef->as<LexicalScopeNode>().scopeBody()->is<ClassMethod>()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 9651);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "propdef->as<LexicalScopeNode>().scopeBody()->is<ClassMethod>()"
")"); do { MOZ_CrashSequence(__null, 9651); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9652 continue;
9653 }
9654
9655 // Handle __proto__: v specially because *only* this form, and no other
9656 // involving "__proto__", performs [[Prototype]] mutation.
9657 if (propdef->isKind(ParseNodeKind::MutateProto)) {
9658 // [stack] OBJ
9659 MOZ_ASSERT(type == ObjectLiteral)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(type == ObjectLiteral)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(type == ObjectLiteral))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("type == ObjectLiteral"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 9659);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == ObjectLiteral"
")"); do { MOZ_CrashSequence(__null, 9659); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9660 if (!pe.prepareForProtoValue(propdef->pn_pos.begin)) {
9661 // [stack] OBJ
9662 return false;
9663 }
9664 if (!emitTree(propdef->as<UnaryNode>().kid())) {
9665 // [stack] OBJ PROTO
9666 return false;
9667 }
9668 if (!pe.emitMutateProto()) {
9669 // [stack] OBJ
9670 return false;
9671 }
9672 continue;
9673 }
9674
9675 if (propdef->isKind(ParseNodeKind::Spread)) {
9676 MOZ_ASSERT(type == ObjectLiteral)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(type == ObjectLiteral)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(type == ObjectLiteral))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("type == ObjectLiteral"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 9676);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == ObjectLiteral"
")"); do { MOZ_CrashSequence(__null, 9676); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9677 // [stack] OBJ
9678 if (!pe.prepareForSpreadOperand(propdef->pn_pos.begin)) {
9679 // [stack] OBJ OBJ
9680 return false;
9681 }
9682 if (!emitTree(propdef->as<UnaryNode>().kid())) {
9683 // [stack] OBJ OBJ VAL
9684 return false;
9685 }
9686 if (!pe.emitSpread()) {
9687 // [stack] OBJ
9688 return false;
9689 }
9690 continue;
9691 }
9692
9693 BinaryNode* prop = &propdef->as<BinaryNode>();
9694
9695 ParseNode* key = prop->left();
9696 AccessorType accessorType;
9697 if (prop->is<ClassMethod>()) {
9698 ClassMethod& method = prop->as<ClassMethod>();
9699 accessorType = method.accessorType();
9700
9701 if (!method.isStatic() && key->isKind(ParseNodeKind::PrivateName) &&
9702 accessorType != AccessorType::None) {
9703 // Private non-static accessors are stamped onto instances from
9704 // initializers; see emitCreateMemberInitializers.
9705 continue;
9706 }
9707 } else if (prop->is<PropertyDefinition>()) {
9708 accessorType = prop->as<PropertyDefinition>().accessorType();
9709 } else {
9710 accessorType = AccessorType::None;
9711 }
9712
9713 auto emitValue = [this, &key, &prop, accessorType, &pe]() {
9714 // [stack] CTOR? OBJ CTOR? KEY?
9715
9716 ParseNode* propVal = prop->right();
9717 if (propVal->isDirectRHSAnonFunction()) {
9718 // The following branches except for the last `else` clause emit the
9719 // cases handled in NameResolver::resolveFun (see NameFunctions.cpp)
9720 if (key->isKind(ParseNodeKind::ObjectPropertyName) ||
9721 key->isKind(ParseNodeKind::PrivateName) ||
9722 key->isKind(ParseNodeKind::StringExpr)) {
9723 auto keyAtom = key->as<NameNode>().atom();
9724 if (!emitAnonymousFunctionWithName(propVal, keyAtom)) {
9725 // [stack] CTOR? OBJ CTOR? VAL
9726 return false;
9727 }
9728 } else if (key->isKind(ParseNodeKind::NumberExpr)) {
9729 MOZ_ASSERT(accessorType == AccessorType::None)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(accessorType == AccessorType::None)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(accessorType == AccessorType
::None))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("accessorType == AccessorType::None", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 9729); AnnotateMozCrashReason("MOZ_ASSERT" "(" "accessorType == AccessorType::None"
")"); do { MOZ_CrashSequence(__null, 9729); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9730
9731 auto keyAtom = key->as<NumericLiteral>().toAtom(fc, parserAtoms());
9732 if (!keyAtom) {
9733 return false;
9734 }
9735 if (!emitAnonymousFunctionWithName(propVal, keyAtom)) {
9736 // [stack] CTOR? OBJ CTOR? KEY VAL
9737 return false;
9738 }
9739 } else if (key->isKind(ParseNodeKind::ComputedName) &&
9740 (key->as<UnaryNode>().kid()->isKind(
9741 ParseNodeKind::NumberExpr) ||
9742 key->as<UnaryNode>().kid()->isKind(
9743 ParseNodeKind::StringExpr)) &&
9744 accessorType == AccessorType::None) {
9745 ParseNode* keyKid = key->as<UnaryNode>().kid();
9746 if (keyKid->isKind(ParseNodeKind::NumberExpr)) {
9747 auto keyAtom =
9748 keyKid->as<NumericLiteral>().toAtom(fc, parserAtoms());
9749 if (!keyAtom) {
9750 return false;
9751 }
9752 if (!emitAnonymousFunctionWithName(propVal, keyAtom)) {
9753 // [stack] CTOR? OBJ CTOR? KEY VAL
9754 return false;
9755 }
9756 } else {
9757 MOZ_ASSERT(keyKid->isKind(ParseNodeKind::StringExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(keyKid->isKind(ParseNodeKind::StringExpr))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(keyKid->isKind(ParseNodeKind::StringExpr)))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("keyKid->isKind(ParseNodeKind::StringExpr)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 9757);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "keyKid->isKind(ParseNodeKind::StringExpr)"
")"); do { MOZ_CrashSequence(__null, 9757); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9758 auto keyAtom = keyKid->as<NameNode>().atom();
9759 if (!emitAnonymousFunctionWithName(propVal, keyAtom)) {
9760 // [stack] CTOR? OBJ CTOR? KEY VAL
9761 return false;
9762 }
9763 }
9764 } else {
9765 // Either a proper computed property name or a synthetic computed
9766 // property name for BigInt keys.
9767 MOZ_ASSERT(key->isKind(ParseNodeKind::ComputedName))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(key->isKind(ParseNodeKind::ComputedName))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(key->isKind(ParseNodeKind::ComputedName)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("key->isKind(ParseNodeKind::ComputedName)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 9767);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::ComputedName)"
")"); do { MOZ_CrashSequence(__null, 9767); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9768
9769 FunctionPrefixKind prefix =
9770 accessorType == AccessorType::None ? FunctionPrefixKind::None
9771 : accessorType == AccessorType::Getter ? FunctionPrefixKind::Get
9772 : FunctionPrefixKind::Set;
9773
9774 if (!emitAnonymousFunctionWithComputedName(propVal, prefix)) {
9775 // [stack] CTOR? OBJ CTOR? KEY VAL
9776 return false;
9777 }
9778 }
9779 } else {
9780 if (!emitTree(propVal)) {
9781 // [stack] CTOR? OBJ CTOR? KEY? VAL
9782 return false;
9783 }
9784 }
9785
9786 if (propVal->is<FunctionNode>() &&
9787 propVal->as<FunctionNode>().funbox()->needsHomeObject()) {
9788 if (!pe.emitInitHomeObject()) {
9789 // [stack] CTOR? OBJ CTOR? KEY? FUN
9790 return false;
9791 }
9792 }
9793
9794#ifdef ENABLE_DECORATORS
9795 if (prop->is<ClassMethod>()) {
9796 ClassMethod& method = prop->as<ClassMethod>();
9797 if (method.decorators() && !method.decorators()->empty()) {
9798 DecoratorEmitter::Kind kind;
9799 switch (method.accessorType()) {
9800 case AccessorType::Getter:
9801 kind = DecoratorEmitter::Getter;
9802 break;
9803 case AccessorType::Setter:
9804 kind = DecoratorEmitter::Setter;
9805 break;
9806 case AccessorType::None:
9807 kind = DecoratorEmitter::Method;
9808 break;
9809 }
9810
9811 if (!method.isStatic()) {
9812 bool hasKeyOnStack = key->isKind(ParseNodeKind::NumberExpr) ||
9813 key->isKind(ParseNodeKind::ComputedName);
9814 if (!emitDupAt(hasKeyOnStack ? 4 : 3)) {
9815 // [stack] ADDINIT OBJ KEY? VAL ADDINIT
9816 return false;
9817 }
9818 } else {
9819 // TODO: See bug 1868220 for support for static methods.
9820 // Note: Key will be present if this has a private name.
9821 if (!emit1(JSOp::Undefined)) {
9822 // [stack] CTOR OBJ CTOR KEY? VAL ADDINIT
9823 return false;
9824 }
9825 }
9826
9827 if (!emit1(JSOp::Swap)) {
9828 // [stack] ADDINIT CTOR? OBJ CTOR? KEY? ADDINIT VAL
9829 return false;
9830 }
9831
9832 // The decorators are applied to the current value on the stack,
9833 // possibly replacing it.
9834 DecoratorEmitter de(this);
9835 if (!de.emitApplyDecoratorsToElementDefinition(
9836 kind, key, method.decorators(), method.isStatic())) {
9837 // [stack] ADDINIT CTOR? OBJ CTOR? KEY? ADDINIT VAL
9838 return false;
9839 }
9840
9841 if (!emit1(JSOp::Swap)) {
9842 // [stack] ADDINIT CTOR? OBJ CTOR? KEY? VAL ADDINIT
9843 return false;
9844 }
9845
9846 if (!emitPopN(1)) {
9847 // [stack] ADDINIT CTOR? OBJ CTOR? KEY? VAL
9848 return false;
9849 }
9850 }
9851 }
9852#endif
9853
9854 return true;
9855 };
9856
9857 PropertyEmitter::Kind kind =
9858 (type == ClassBody && propdef->as<ClassMethod>().isStatic())
9859 ? PropertyEmitter::Kind::Static
9860 : PropertyEmitter::Kind::Prototype;
9861 if (key->isKind(ParseNodeKind::ObjectPropertyName) ||
9862 key->isKind(ParseNodeKind::StringExpr)) {
9863 // [stack] CTOR? OBJ
9864
9865 auto keyAtom = key->as<NameNode>().atom();
9866
9867 // emitClass took care of constructor already.
9868 if (type == ClassBody &&
9869 keyAtom == TaggedParserAtomIndex::WellKnown::constructor() &&
9870 !propdef->as<ClassMethod>().isStatic()) {
9871 continue;
9872 }
9873
9874 if (!pe.prepareForPropValue(propdef->pn_pos.begin, kind)) {
9875 // [stack] CTOR? OBJ CTOR?
9876 return false;
9877 }
9878
9879 if (!emitValue()) {
9880 // [stack] CTOR? OBJ CTOR? VAL
9881 return false;
9882 }
9883
9884 if (!pe.emitInit(accessorType, keyAtom)) {
9885 // [stack] CTOR? OBJ
9886 return false;
9887 }
9888
9889 continue;
9890 }
9891
9892 if (key->isKind(ParseNodeKind::NumberExpr)) {
9893 // [stack] CTOR? OBJ
9894 if (!pe.prepareForIndexPropKey(propdef->pn_pos.begin, kind)) {
9895 // [stack] CTOR? OBJ CTOR?
9896 return false;
9897 }
9898 if (!emitNumberOp(key->as<NumericLiteral>().value())) {
9899 // [stack] CTOR? OBJ CTOR? KEY
9900 return false;
9901 }
9902 if (!pe.prepareForIndexPropValue()) {
9903 // [stack] CTOR? OBJ CTOR? KEY
9904 return false;
9905 }
9906 if (!emitValue()) {
9907 // [stack] CTOR? OBJ CTOR? KEY VAL
9908 return false;
9909 }
9910
9911 if (!pe.emitInitIndexOrComputed(accessorType)) {
9912 // [stack] CTOR? OBJ
9913 return false;
9914 }
9915
9916 continue;
9917 }
9918
9919 if (key->isKind(ParseNodeKind::ComputedName)) {
9920 // Either a proper computed property name or a synthetic computed property
9921 // name for BigInt keys.
9922
9923 // [stack] CTOR? OBJ
9924
9925 if (!pe.prepareForComputedPropKey(propdef->pn_pos.begin, kind)) {
9926 // [stack] CTOR? OBJ CTOR?
9927 return false;
9928 }
9929 if (!emitTree(key->as<UnaryNode>().kid())) {
9930 // [stack] CTOR? OBJ CTOR? KEY
9931 return false;
9932 }
9933 if (!pe.prepareForComputedPropValue()) {
9934 // [stack] CTOR? OBJ CTOR? KEY
9935 return false;
9936 }
9937 if (!emitValue()) {
9938 // [stack] CTOR? OBJ CTOR? KEY VAL
9939 return false;
9940 }
9941
9942 if (!pe.emitInitIndexOrComputed(accessorType)) {
9943 // [stack] CTOR? OBJ
9944 return false;
9945 }
9946
9947 continue;
9948 }
9949
9950 MOZ_ASSERT(key->isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(key->isKind(ParseNodeKind::PrivateName))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(key->isKind(ParseNodeKind::PrivateName)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("key->isKind(ParseNodeKind::PrivateName)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 9950);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::PrivateName)"
")"); do { MOZ_CrashSequence(__null, 9950); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9951 MOZ_ASSERT(type == ClassBody)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(type == ClassBody)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(type == ClassBody))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("type == ClassBody"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 9951);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == ClassBody" ")"
); do { MOZ_CrashSequence(__null, 9951); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9952
9953 auto* privateName = &key->as<NameNode>();
9954
9955 if (kind == PropertyEmitter::Kind::Prototype) {
9956 MOZ_ASSERT(accessorType == AccessorType::None)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(accessorType == AccessorType::None)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(accessorType == AccessorType
::None))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("accessorType == AccessorType::None", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 9956); AnnotateMozCrashReason("MOZ_ASSERT" "(" "accessorType == AccessorType::None"
")"); do { MOZ_CrashSequence(__null, 9956); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9957 if (!pe.prepareForPrivateMethod()) {
9958 // [stack] CTOR OBJ
9959 return false;
9960 }
9961 NameOpEmitter noe(this, privateName->atom(),
9962 NameOpEmitter::Kind::SimpleAssignment);
9963
9964 // Ensure the NameOp emitter doesn't push an environment onto the stack,
9965 // because that would change the stack location of the home object.
9966 MOZ_ASSERT(noe.loc().kind() == NameLocation::Kind::FrameSlot ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(noe.loc().kind() == NameLocation::Kind::FrameSlot ||
noe.loc().kind() == NameLocation::Kind::EnvironmentCoordinate
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(noe.loc().kind() == NameLocation::Kind::FrameSlot ||
noe.loc().kind() == NameLocation::Kind::EnvironmentCoordinate
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"noe.loc().kind() == NameLocation::Kind::FrameSlot || noe.loc().kind() == NameLocation::Kind::EnvironmentCoordinate"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 9967);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "noe.loc().kind() == NameLocation::Kind::FrameSlot || noe.loc().kind() == NameLocation::Kind::EnvironmentCoordinate"
")"); do { MOZ_CrashSequence(__null, 9967); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9967 noe.loc().kind() == NameLocation::Kind::EnvironmentCoordinate)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(noe.loc().kind() == NameLocation::Kind::FrameSlot ||
noe.loc().kind() == NameLocation::Kind::EnvironmentCoordinate
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(noe.loc().kind() == NameLocation::Kind::FrameSlot ||
noe.loc().kind() == NameLocation::Kind::EnvironmentCoordinate
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"noe.loc().kind() == NameLocation::Kind::FrameSlot || noe.loc().kind() == NameLocation::Kind::EnvironmentCoordinate"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 9967);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "noe.loc().kind() == NameLocation::Kind::FrameSlot || noe.loc().kind() == NameLocation::Kind::EnvironmentCoordinate"
")"); do { MOZ_CrashSequence(__null, 9967); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9968
9969 if (!noe.prepareForRhs()) {
9970 // [stack] CTOR OBJ
9971 return false;
9972 }
9973 if (!emitValue()) {
9974 // [stack] CTOR OBJ METHOD
9975 return false;
9976 }
9977 if (!noe.emitAssignment()) {
9978 // [stack] CTOR OBJ METHOD
9979 return false;
9980 }
9981 if (!emit1(JSOp::Pop)) {
9982 // [stack] CTOR OBJ
9983 return false;
9984 }
9985 if (!pe.skipInit()) {
9986 // [stack] CTOR OBJ
9987 return false;
9988 }
9989 continue;
9990 }
9991
9992 MOZ_ASSERT(kind == PropertyEmitter::Kind::Static)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(kind == PropertyEmitter::Kind::Static)>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(kind == PropertyEmitter::Kind::Static))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("kind == PropertyEmitter::Kind::Static"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 9992);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "kind == PropertyEmitter::Kind::Static"
")"); do { MOZ_CrashSequence(__null, 9992); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9993
9994 // [stack] CTOR OBJ
9995
9996 if (!pe.prepareForPrivateStaticMethod(propdef->pn_pos.begin)) {
9997 // [stack] CTOR OBJ CTOR
9998 return false;
9999 }
10000 if (!emitGetPrivateName(privateName)) {
10001 // [stack] CTOR OBJ CTOR KEY
10002 return false;
10003 }
10004 if (!emitValue()) {
10005 // [stack] CTOR OBJ CTOR KEY VAL
10006 return false;
10007 }
10008
10009 if (!pe.emitPrivateStaticMethod(accessorType)) {
10010 // [stack] CTOR OBJ
10011 return false;
10012 }
10013
10014 if (privateName->privateNameKind() == PrivateNameKind::Setter) {
10015 if (!emitDupAt(1)) {
10016 // [stack] CTOR OBJ CTOR
10017 return false;
10018 }
10019 if (!emitGetPrivateName(privateName)) {
10020 // [stack] CTOR OBJ CTOR NAME
10021 return false;
10022 }
10023 if (!emitAtomOp(JSOp::GetIntrinsic,
10024 TaggedParserAtomIndex::WellKnown::NoPrivateGetter())) {
10025 // [stack] CTOR OBJ CTOR NAME FUN
10026 return false;
10027 }
10028 if (!emit1(JSOp::InitHiddenElemGetter)) {
10029 // [stack] CTOR OBJ CTOR
10030 return false;
10031 }
10032 if (!emit1(JSOp::Pop)) {
10033 // [stack] CTOR OBJ
10034 return false;
10035 }
10036 }
10037 }
10038
10039 return true;
10040}
10041
10042bool BytecodeEmitter::emitPropertyListObjLiteral(ListNode* obj, JSOp op,
10043 bool useObjLiteralValues) {
10044 ObjLiteralWriter writer;
10045
10046#ifdef DEBUG1
10047 // In self-hosted JS, we check duplication only on debug build.
10048 mozilla::Maybe<mozilla::HashSet<frontend::TaggedParserAtomIndex,
10049 frontend::TaggedParserAtomIndexHasher>>
10050 selfHostedPropNames;
10051 if (emitterMode == BytecodeEmitter::SelfHosting) {
10052 selfHostedPropNames.emplace();
10053 }
10054#endif
10055
10056 if (op == JSOp::Object) {
10057 writer.beginObject(op);
10058 } else {
10059 MOZ_ASSERT(op == JSOp::NewObject)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(op == JSOp::NewObject)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(op == JSOp::NewObject))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("op == JSOp::NewObject"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 10059)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::NewObject"
")"); do { MOZ_CrashSequence(__null, 10059); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10060 writer.beginShape(op);
10061 }
10062
10063 for (ParseNode* propdef : obj->contents()) {
10064 BinaryNode* prop = &propdef->as<BinaryNode>();
10065 ParseNode* key = prop->left();
10066
10067 if (key->is<NameNode>()) {
10068 if (emitterMode == BytecodeEmitter::SelfHosting) {
10069 auto propName = key->as<NameNode>().atom();
10070#ifdef DEBUG1
10071 // Self-hosted JS shouldn't contain duplicate properties.
10072 auto p = selfHostedPropNames->lookupForAdd(propName);
10073 MOZ_ASSERT(!p)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!p)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(!p))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("!p", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 10073); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!p" ")"); do
{ MOZ_CrashSequence(__null, 10073); __attribute__((nomerge))
::abort(); } while (false); } } while (false)
;
10074 if (!selfHostedPropNames->add(p, propName)) {
10075 js::ReportOutOfMemory(fc);
10076 return false;
10077 }
10078#endif
10079 writer.setPropNameNoDuplicateCheck(parserAtoms(), propName);
10080 } else {
10081 if (!writer.setPropName(parserAtoms(), key->as<NameNode>().atom())) {
10082 return false;
10083 }
10084 }
10085 } else {
10086 double numValue = key->as<NumericLiteral>().value();
10087 int32_t i = 0;
10088 DebugOnly<bool> numIsInt =
10089 NumberIsInt32(numValue, &i); // checked previously.
10090 MOZ_ASSERT(numIsInt)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(numIsInt)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(numIsInt))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("numIsInt", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 10090); AnnotateMozCrashReason("MOZ_ASSERT" "(" "numIsInt" ")"
); do { MOZ_CrashSequence(__null, 10090); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10091 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(ObjLiteralWriter::arrayIndexInRange(i))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(ObjLiteralWriter::arrayIndexInRange(i)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("ObjLiteralWriter::arrayIndexInRange(i)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 10092)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "ObjLiteralWriter::arrayIndexInRange(i)"
")"); do { MOZ_CrashSequence(__null, 10092); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10092 ObjLiteralWriter::arrayIndexInRange(i))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(ObjLiteralWriter::arrayIndexInRange(i))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(ObjLiteralWriter::arrayIndexInRange(i)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("ObjLiteralWriter::arrayIndexInRange(i)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 10092)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "ObjLiteralWriter::arrayIndexInRange(i)"
")"); do { MOZ_CrashSequence(__null, 10092); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
; // checked previously.
10093
10094 // Ignore indexed properties if we're not storing property values, and
10095 // rely on InitElem ops to define those. These properties will be either
10096 // dense elements (not possible to represent in the literal's shape) or
10097 // sparse elements (enumerated separately, so this doesn't affect property
10098 // iteration order).
10099 if (!useObjLiteralValues) {
10100 continue;
10101 }
10102
10103 writer.setPropIndex(i);
10104 }
10105
10106 if (useObjLiteralValues) {
10107 MOZ_ASSERT(op == JSOp::Object)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(op == JSOp::Object)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(op == JSOp::Object))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("op == JSOp::Object"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 10107)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::Object"
")"); do { MOZ_CrashSequence(__null, 10107); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10108 ParseNode* value = prop->right();
10109 if (!emitObjLiteralValue(writer, value)) {
10110 return false;
10111 }
10112 } else {
10113 if (!writer.propWithUndefinedValue(fc)) {
10114 return false;
10115 }
10116 }
10117 }
10118
10119 GCThingIndex index;
10120 if (!addObjLiteralData(writer, &index)) {
10121 return false;
10122 }
10123
10124 // JSOp::Object may only be used by (top-level) run-once scripts.
10125 MOZ_ASSERT_IF(op == JSOp::Object,do { if (op == JSOp::Object) { do { static_assert( mozilla::detail
::AssertionConditionType<decltype(sc->isTopLevelContext
() && sc->treatAsRunOnce())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sc->isTopLevelContext() &&
sc->treatAsRunOnce()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("sc->isTopLevelContext() && sc->treatAsRunOnce()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 10126)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isTopLevelContext() && sc->treatAsRunOnce()"
")"); do { MOZ_CrashSequence(__null, 10126); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
10126 sc->isTopLevelContext() && sc->treatAsRunOnce())do { if (op == JSOp::Object) { do { static_assert( mozilla::detail
::AssertionConditionType<decltype(sc->isTopLevelContext
() && sc->treatAsRunOnce())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sc->isTopLevelContext() &&
sc->treatAsRunOnce()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("sc->isTopLevelContext() && sc->treatAsRunOnce()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 10126)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isTopLevelContext() && sc->treatAsRunOnce()"
")"); do { MOZ_CrashSequence(__null, 10126); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
10127
10128 if (!emitGCIndexOp(op, index)) {
10129 // [stack] OBJ
10130 return false;
10131 }
10132
10133 return true;
10134}
10135
10136bool BytecodeEmitter::emitDestructuringRestExclusionSetObjLiteral(
10137 ListNode* pattern) {
10138 // Note: if we want to squeeze out a little more performance, we could switch
10139 // to the `JSOp::Object` opcode, because the exclusion set object is never
10140 // exposed to the user, so it's safe to bake the object into the bytecode.
10141 constexpr JSOp op = JSOp::NewObject;
10142
10143 ObjLiteralWriter writer;
10144 writer.beginShape(op);
10145
10146 for (ParseNode* member : pattern->contents()) {
10147 if (member->isKind(ParseNodeKind::Spread)) {
10148 MOZ_ASSERT(!member->pn_next, "unexpected trailing element after spread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!member->pn_next)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!member->pn_next))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("!member->pn_next"
" (" "unexpected trailing element after spread" ")", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 10148); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!member->pn_next"
") (" "unexpected trailing element after spread" ")"); do { MOZ_CrashSequence
(__null, 10148); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10149 break;
10150 }
10151
10152 TaggedParserAtomIndex atom;
10153 if (member->isKind(ParseNodeKind::MutateProto)) {
10154 atom = TaggedParserAtomIndex::WellKnown::proto_();
10155 } else {
10156 ParseNode* key = member->as<BinaryNode>().left();
10157 atom = key->as<NameNode>().atom();
10158 }
10159
10160 if (!writer.setPropName(parserAtoms(), atom)) {
10161 return false;
10162 }
10163
10164 if (!writer.propWithUndefinedValue(fc)) {
10165 return false;
10166 }
10167 }
10168
10169 GCThingIndex index;
10170 if (!addObjLiteralData(writer, &index)) {
10171 return false;
10172 }
10173
10174 if (!emitGCIndexOp(op, index)) {
10175 // [stack] OBJ
10176 return false;
10177 }
10178
10179 return true;
10180}
10181
10182bool BytecodeEmitter::emitObjLiteralArray(ListNode* array) {
10183 MOZ_ASSERT(checkSingletonContext())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(checkSingletonContext())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(checkSingletonContext()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("checkSingletonContext()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 10183)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "checkSingletonContext()"
")"); do { MOZ_CrashSequence(__null, 10183); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10184
10185 constexpr JSOp op = JSOp::Object;
10186
10187 ObjLiteralWriter writer;
10188 writer.beginArray(op);
10189
10190 writer.beginDenseArrayElements();
10191 for (ParseNode* elem : array->contents()) {
10192 if (!emitObjLiteralValue(writer, elem)) {
10193 return false;
10194 }
10195 }
10196
10197 GCThingIndex index;
10198 if (!addObjLiteralData(writer, &index)) {
10199 return false;
10200 }
10201
10202 if (!emitGCIndexOp(op, index)) {
10203 // [stack] OBJ
10204 return false;
10205 }
10206
10207 return true;
10208}
10209
10210bool BytecodeEmitter::isRHSObjLiteralCompatible(ParseNode* value) const {
10211 return value->isKind(ParseNodeKind::NumberExpr) ||
10212 value->isKind(ParseNodeKind::TrueExpr) ||
10213 value->isKind(ParseNodeKind::FalseExpr) ||
10214 value->isKind(ParseNodeKind::NullExpr) ||
10215 value->isKind(ParseNodeKind::RawUndefinedExpr) ||
10216 value->isKind(ParseNodeKind::StringExpr) ||
10217 value->isKind(ParseNodeKind::TemplateStringExpr);
10218}
10219
10220bool BytecodeEmitter::emitObjLiteralValue(ObjLiteralWriter& writer,
10221 ParseNode* value) {
10222 MOZ_ASSERT(isRHSObjLiteralCompatible(value))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(isRHSObjLiteralCompatible(value))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(isRHSObjLiteralCompatible(value
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("isRHSObjLiteralCompatible(value)", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 10222); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isRHSObjLiteralCompatible(value)"
")"); do { MOZ_CrashSequence(__null, 10222); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10223 if (value->isKind(ParseNodeKind::NumberExpr)) {
10224 double numValue = value->as<NumericLiteral>().value();
10225 int32_t i = 0;
10226 js::Value v;
10227 if (NumberIsInt32(numValue, &i)) {
10228 v.setInt32(i);
10229 } else {
10230 v.setDouble(numValue);
10231 }
10232 if (!writer.propWithConstNumericValue(fc, v)) {
10233 return false;
10234 }
10235 } else if (value->isKind(ParseNodeKind::TrueExpr)) {
10236 if (!writer.propWithTrueValue(fc)) {
10237 return false;
10238 }
10239 } else if (value->isKind(ParseNodeKind::FalseExpr)) {
10240 if (!writer.propWithFalseValue(fc)) {
10241 return false;
10242 }
10243 } else if (value->isKind(ParseNodeKind::NullExpr)) {
10244 if (!writer.propWithNullValue(fc)) {
10245 return false;
10246 }
10247 } else if (value->isKind(ParseNodeKind::RawUndefinedExpr)) {
10248 if (!writer.propWithUndefinedValue(fc)) {
10249 return false;
10250 }
10251 } else if (value->isKind(ParseNodeKind::StringExpr) ||
10252 value->isKind(ParseNodeKind::TemplateStringExpr)) {
10253 if (!writer.propWithAtomValue(fc, parserAtoms(),
10254 value->as<NameNode>().atom())) {
10255 return false;
10256 }
10257 } else {
10258 MOZ_CRASH("Unexpected parse node")do { do { } while (false); MOZ_ReportCrash("" "Unexpected parse node"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 10258)
; AnnotateMozCrashReason("MOZ_CRASH(" "Unexpected parse node"
")"); do { MOZ_CrashSequence(__null, 10258); __attribute__((
nomerge)) ::abort(); } while (false); } while (false)
;
10259 }
10260 return true;
10261}
10262
10263static bool NeedsPrivateBrand(ParseNode* member) {
10264 return member->is<ClassMethod>() &&
10265 member->as<ClassMethod>().name().isKind(ParseNodeKind::PrivateName) &&
10266 !member->as<ClassMethod>().isStatic();
10267}
10268
10269#ifdef ENABLE_DECORATORS
10270static bool HasDecorators(ParseNode* member) {
10271 return member->is<ClassMethod>() && member->as<ClassMethod>().decorators();
10272}
10273#endif
10274
10275mozilla::Maybe<MemberInitializers> BytecodeEmitter::setupMemberInitializers(
10276 ListNode* classMembers, FieldPlacement placement) const {
10277 bool isStatic = placement == FieldPlacement::Static;
10278
10279 size_t numFields = 0;
10280 size_t numPrivateInitializers = 0;
10281 bool hasPrivateBrand = false;
10282#ifdef ENABLE_DECORATORS
10283 bool hasDecorators = false;
10284#endif
10285 for (ParseNode* member : classMembers->contents()) {
10286 if (NeedsFieldInitializer(member, isStatic)) {
10287 numFields++;
10288 } else if (NeedsAccessorInitializer(member, isStatic)) {
10289 numPrivateInitializers++;
10290 hasPrivateBrand = true;
10291 } else if (NeedsPrivateBrand(member)) {
10292 hasPrivateBrand = true;
10293 }
10294#ifdef ENABLE_DECORATORS
10295 if (!hasDecorators && HasDecorators(member)) {
10296 hasDecorators = true;
10297 }
10298#endif
10299 }
10300
10301 // If there are more initializers than can be represented, return invalid.
10302 if (numFields + numPrivateInitializers >
10303 MemberInitializers::MaxInitializers) {
10304 return Nothing();
10305 }
10306 return Some(MemberInitializers(hasPrivateBrand,
10307#ifdef ENABLE_DECORATORS
10308 hasDecorators,
10309#endif
10310 numFields + numPrivateInitializers));
10311}
10312
10313// Purpose of .fieldKeys:
10314// Computed field names (`["x"] = 2;`) must be ran at class-evaluation time,
10315// not object construction time. The transformation to do so is roughly as
10316// follows:
10317//
10318// class C {
10319// [keyExpr] = valueExpr;
10320// }
10321// -->
10322// let .fieldKeys = [keyExpr];
10323// let .initializers = [
10324// () => {
10325// this[.fieldKeys[0]] = valueExpr;
10326// }
10327// ];
10328// class C {
10329// constructor() {
10330// .initializers[0]();
10331// }
10332// }
10333//
10334// BytecodeEmitter::emitCreateFieldKeys does `let .fieldKeys = [...];`
10335// BytecodeEmitter::emitPropertyList fills in the elements of the array.
10336// See GeneralParser::fieldInitializer for the `this[.fieldKeys[0]]` part.
10337bool BytecodeEmitter::emitCreateFieldKeys(ListNode* obj,
10338 FieldPlacement placement) {
10339 bool isStatic = placement == FieldPlacement::Static;
10340 auto isFieldWithComputedName = [isStatic](ParseNode* propdef) {
10341 return propdef->is<ClassField>() &&
10342 propdef->as<ClassField>().isStatic() == isStatic &&
10343 propdef->as<ClassField>().name().getKind() ==
10344 ParseNodeKind::ComputedName;
10345 };
10346
10347 size_t numFieldKeys = std::count_if(
10348 obj->contents().begin(), obj->contents().end(), isFieldWithComputedName);
10349 if (numFieldKeys == 0) {
10350 return true;
10351 }
10352
10353 auto fieldKeys =
10354 isStatic ? TaggedParserAtomIndex::WellKnown::dot_staticFieldKeys_()
10355 : TaggedParserAtomIndex::WellKnown::dot_fieldKeys_();
10356 NameOpEmitter noe(this, fieldKeys, NameOpEmitter::Kind::Initialize);
10357 if (!noe.prepareForRhs()) {
10358 return false;
10359 }
10360
10361 if (!emitUint32Operand(JSOp::NewArray, numFieldKeys)) {
10362 // [stack] ARRAY
10363 return false;
10364 }
10365
10366 if (!noe.emitAssignment()) {
10367 // [stack] ARRAY
10368 return false;
10369 }
10370
10371 if (!emit1(JSOp::Pop)) {
10372 // [stack]
10373 return false;
10374 }
10375
10376 return true;
10377}
10378
10379static bool HasInitializer(ParseNode* node, bool isStaticContext) {
10380 return (node->is<ClassField>() &&
10381 node->as<ClassField>().isStatic() == isStaticContext) ||
10382 (isStaticContext && node->is<StaticClassBlock>());
10383}
10384
10385static FunctionNode* GetInitializer(ParseNode* node, bool isStaticContext) {
10386 MOZ_ASSERT(HasInitializer(node, isStaticContext))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(HasInitializer(node, isStaticContext))>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(HasInitializer(node, isStaticContext)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("HasInitializer(node, isStaticContext)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 10386)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "HasInitializer(node, isStaticContext)"
")"); do { MOZ_CrashSequence(__null, 10386); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10387 MOZ_ASSERT_IF(!node->is<ClassField>(), isStaticContext)do { if (!node->is<ClassField>()) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(isStaticContext
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(isStaticContext))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("isStaticContext", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 10387); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isStaticContext"
")"); do { MOZ_CrashSequence(__null, 10387); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
10388 return node->is<ClassField>() ? node->as<ClassField>().initializer()
10389 : node->as<StaticClassBlock>().function();
10390}
10391
10392static bool IsPrivateInstanceAccessor(const ClassMethod* classMethod) {
10393 return !classMethod->isStatic() &&
10394 classMethod->name().isKind(ParseNodeKind::PrivateName) &&
10395 classMethod->accessorType() != AccessorType::None;
10396}
10397
10398bool BytecodeEmitter::emitCreateMemberInitializers(ClassEmitter& ce,
10399 ListNode* obj,
10400 FieldPlacement placement
10401#ifdef ENABLE_DECORATORS
10402 ,
10403 bool hasHeritage
10404#endif
10405) {
10406 // FieldPlacement::Instance, hasHeritage == false
10407 // [stack] HOME
10408 //
10409 // FieldPlacement::Instance, hasHeritage == true
10410 // [stack] HOME HERIT
10411 //
10412 // FieldPlacement::Static
10413 // [stack] CTOR HOME
10414#ifdef ENABLE_DECORATORS
10415 MOZ_ASSERT_IF(placement == FieldPlacement::Static, !hasHeritage)do { if (placement == FieldPlacement::Static) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(!hasHeritage
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!hasHeritage))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!hasHeritage", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 10415); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!hasHeritage"
")"); do { MOZ_CrashSequence(__null, 10415); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
10416#endif
10417 mozilla::Maybe<MemberInitializers> memberInitializers =
10418 setupMemberInitializers(obj, placement);
10419 if (!memberInitializers) {
10420 ReportAllocationOverflow(fc);
10421 return false;
10422 }
10423
10424 size_t numInitializers = memberInitializers->numMemberInitializers;
10425 if (numInitializers == 0) {
10426 return true;
10427 }
10428
10429 bool isStatic = placement == FieldPlacement::Static;
10430 if (!ce.prepareForMemberInitializers(numInitializers, isStatic)) {
10431 // [stack] HOME HERIT? ARR
10432 // or:
10433 // [stack] CTOR HOME ARR
10434 return false;
10435 }
10436
10437 // Private accessors could be used in the field initializers, so make sure
10438 // accessor initializers appear earlier in the .initializers array so they
10439 // run first. Static private methods are not initialized using initializers
10440 // (emitPropertyList emits bytecode to stamp them onto the constructor), so
10441 // skip this step if isStatic.
10442 if (!isStatic) {
10443 if (!emitPrivateMethodInitializers(ce, obj)) {
10444 return false;
10445 }
10446 }
10447
10448 for (ParseNode* propdef : obj->contents()) {
10449 if (!HasInitializer(propdef, isStatic)) {
10450 continue;
10451 }
10452
10453 FunctionNode* initializer = GetInitializer(propdef, isStatic);
10454
10455 if (!ce.prepareForMemberInitializer()) {
10456 return false;
10457 }
10458 if (!emitTree(initializer)) {
10459 // [stack] HOME HERIT? ARR LAMBDA
10460 // or:
10461 // [stack] CTOR HOME ARR LAMBDA
10462 return false;
10463 }
10464 if (initializer->funbox()->needsHomeObject()) {
10465 MOZ_ASSERT(initializer->funbox()->allowSuperProperty())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(initializer->funbox()->allowSuperProperty())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(initializer->funbox()->allowSuperProperty())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("initializer->funbox()->allowSuperProperty()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 10465)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "initializer->funbox()->allowSuperProperty()"
")"); do { MOZ_CrashSequence(__null, 10465); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10466 if (!ce.emitMemberInitializerHomeObject(isStatic)) {
10467 // [stack] HOME HERIT? ARR LAMBDA
10468 // or:
10469 // [stack] CTOR HOME ARR LAMBDA
10470 return false;
10471 }
10472 }
10473 if (!ce.emitStoreMemberInitializer()) {
10474 // [stack] HOME HERIT? ARR
10475 // or:
10476 // [stack] CTOR HOME ARR
10477 return false;
10478 }
10479 }
10480
10481#ifdef ENABLE_DECORATORS
10482 // Index to use to append new initializers returned by decorators to the array
10483 if (!emitNumberOp(numInitializers)) {
10484 // [stack] HOME HERIT? ARR I
10485 // or:
10486 // [stack] CTOR HOME ARR I
10487 return false;
10488 }
10489
10490 for (ParseNode* propdef : obj->contents()) {
10491 if (!propdef->is<ClassField>()) {
10492 continue;
10493 }
10494 ClassField* field = &propdef->as<ClassField>();
10495 if (field->isStatic() != isStatic) {
10496 continue;
10497 }
10498 if (field->decorators() && !field->decorators()->empty()) {
10499 DecoratorEmitter de(this);
10500 if (!field->hasAccessor()) {
10501 if (!emitDupAt((hasHeritage || isStatic) ? 4 : 3)) {
10502 // [stack] ADDINIT HOME HERIT? ARR I ADDINIT
10503 // or:
10504 // [stack] ADDINIT CTOR HOME ARR I ADDINIT
10505 return false;
10506 }
10507 if (!de.emitApplyDecoratorsToFieldDefinition(
10508 &field->name(), field->decorators(), field->isStatic())) {
10509 // [stack] HOME HERIT? ARR I ADDINIT INITS
10510 // or:
10511 // [stack] CTOR HOME ARR I ADDINIT INITS
10512 return false;
10513 }
10514 if (!emit1(JSOp::Swap)) {
10515 // [stack] HOME HERIT? ARR I INITS ADDINIT
10516 // or:
10517 // [stack] CTOR HOME ARR I INITS ADDINIT
10518 return false;
10519 }
10520 if (!emitPopN(1)) {
10521 // [stack] ADDINIT HOME HERIT? ARR I INITS
10522 // or:
10523 // [stack] ADDINIT CTOR HOME ARR I INITS
10524 return false;
10525 }
10526 } else {
10527 ClassMethod* accessorGetterNode = field->accessorGetterNode();
10528 auto accessorGetterKeyAtom =
10529 accessorGetterNode->left()->as<NameNode>().atom();
10530 ClassMethod* accessorSetterNode = field->accessorSetterNode();
10531 auto accessorSetterKeyAtom =
10532 accessorSetterNode->left()->as<NameNode>().atom();
10533 if (!IsPrivateInstanceAccessor(accessorGetterNode)) {
10534 if (!emitTree(&accessorGetterNode->method())) {
10535 // [stack] ADDINIT HOME HERIT? ARR I GET
10536 // or:
10537 // [stack] ADDINIT CTOR HOME ARR I GET
10538 return false;
10539 }
10540 if (!emitTree(&accessorSetterNode->method())) {
10541 // [stack] ADDINIT HOME HERIT? ARR I GET
10542 // SET
10543 // or:
10544 // [stack] ADDINIT CTOR HOME ARR I GET SET
10545 return false;
10546 }
10547 } else {
10548 MOZ_ASSERT(IsPrivateInstanceAccessor(accessorSetterNode))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsPrivateInstanceAccessor(accessorSetterNode))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(IsPrivateInstanceAccessor(accessorSetterNode)))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("IsPrivateInstanceAccessor(accessorSetterNode)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 10548)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsPrivateInstanceAccessor(accessorSetterNode)"
")"); do { MOZ_CrashSequence(__null, 10548); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10549 auto getAccessor = [this](
10550 ClassMethod* classMethod,
10551 TaggedParserAtomIndex& updatedAtom) -> bool {
10552 // [stack]
10553
10554 // Synthesize a name for the lexical variable that will store the
10555 // private method body.
10556 TaggedParserAtomIndex name =
10557 classMethod->name().as<NameNode>().atom();
10558 AccessorType accessorType = classMethod->accessorType();
10559 StringBuilder storedMethodName(fc);
10560 if (!storedMethodName.append(parserAtoms(), name)) {
10561 return false;
10562 }
10563 if (!storedMethodName.append(accessorType == AccessorType::Getter
10564 ? ".getter"
10565 : ".setter")) {
10566 return false;
10567 }
10568 updatedAtom = storedMethodName.finishParserAtom(parserAtoms(), fc);
10569 if (!updatedAtom) {
10570 return false;
10571 }
10572
10573 return emitGetName(updatedAtom);
10574 // [stack] ACCESSOR
10575 };
10576
10577 if (!getAccessor(accessorGetterNode, accessorGetterKeyAtom)) {
10578 // [stack] ADDINIT HOME HERIT? ARR I GET
10579 // or:
10580 // [stack] ADDINIT CTOR HOME ARR I GET
10581 return false;
10582 };
10583
10584 if (!getAccessor(accessorSetterNode, accessorSetterKeyAtom)) {
10585 // [stack] ADDINIT HOME HERIT? ARR I GET SET
10586 // or:
10587 // [stack] ADDINIT CTOR HOME ARR I GET SET
10588 return false;
10589 };
10590 }
10591
10592 if (!emitDupAt((hasHeritage || isStatic) ? 6 : 5)) {
10593 // [stack] ADDINIT HOME HERIT? ARR I GET SET ADDINIT
10594 // or:
10595 // [stack] ADDINIT CTOR HOME ARR I GET SET ADDINIT
10596 return false;
10597 }
10598
10599 if (!emitUnpickN(2)) {
10600 // [stack] ADDINIT HOME HERIT? ARR I ADDINIT GET SET
10601 // or:
10602 // [stack] ADDINIT CTOR HOME ARR I ADDINIT GET SET
10603 return false;
10604 }
10605
10606 if (!de.emitApplyDecoratorsToAccessorDefinition(
10607 &field->name(), field->decorators(), field->isStatic())) {
10608 // [stack] ADDINIT HOME HERIT? ARR I ADDINIT GET SET INITS
10609 // or:
10610 // [stack] ADDINIT CTOR HOME ARR I ADDINIT GET SET INITS
10611 return false;
10612 }
10613
10614 if (!emitPickN(3)) {
10615 // [stack] HOME HERIT? ARR I GET SET INITS ADDINIT
10616 // or:
10617 // [stack] CTOR HOME ARR I GET SET INITS ADDINIT
10618 return false;
10619 }
10620
10621 if (!emitPopN(1)) {
10622 // [stack] ADDINIT HOME HERIT? ARR I GET SET INITS
10623 // or:
10624 // [stack] ADDINIT CTOR HOME ARR I GET SET INITS
10625 return false;
10626 }
10627
10628 if (!emitUnpickN(2)) {
10629 // [stack] ADDINIT HOME HERIT? ARR I INITS GET SET
10630 // or:
10631 // [stack] ADDINIT CTOR HOME ARR I INITS GET SET
10632 return false;
10633 }
10634
10635 if (!IsPrivateInstanceAccessor(accessorGetterNode)) {
10636 if (!isStatic) {
10637 if (!emitDupAt(hasHeritage ? 6 : 5)) {
10638 // [stack] ADDINIT HOME HERIT? ARR I INITS GET SET HOME
10639 return false;
10640 }
10641 } else {
10642 if (!emitDupAt(6)) {
10643 // [stack] ADDINIT CTOR HOME ARR I INITS GET SET CTOR
10644 return false;
10645 }
10646 if (!emitDupAt(6)) {
10647 // [stack] ADDINIT CTOR HOME ARR I INITS GET SET CTOR HOME
10648 return false;
10649 }
10650 }
10651
10652 PropertyEmitter::Kind kind = field->isStatic()
10653 ? PropertyEmitter::Kind::Static
10654 : PropertyEmitter::Kind::Prototype;
10655 if (!accessorGetterNode->name().isKind(ParseNodeKind::PrivateName)) {
10656 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!accessorSetterNode->name().isKind(ParseNodeKind::
PrivateName))>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(!accessorSetterNode->name().isKind
(ParseNodeKind::PrivateName)))), 0))) { do { } while (false);
MOZ_ReportAssertionFailure("!accessorSetterNode->name().isKind(ParseNodeKind::PrivateName)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 10657)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "!accessorSetterNode->name().isKind(ParseNodeKind::PrivateName)"
")"); do { MOZ_CrashSequence(__null, 10657); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10657 !accessorSetterNode->name().isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!accessorSetterNode->name().isKind(ParseNodeKind::
PrivateName))>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(!accessorSetterNode->name().isKind
(ParseNodeKind::PrivateName)))), 0))) { do { } while (false);
MOZ_ReportAssertionFailure("!accessorSetterNode->name().isKind(ParseNodeKind::PrivateName)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 10657)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "!accessorSetterNode->name().isKind(ParseNodeKind::PrivateName)"
")"); do { MOZ_CrashSequence(__null, 10657); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10658
10659 if (!ce.prepareForPropValue(propdef->pn_pos.begin, kind)) {
10660 // [stack] ADDINIT HOME HERIT? ARR I INITS GET SET HOME
10661 // or:
10662 // [stack] ADDINIT CTOR HOME ARR I INITS GET SET CTOR HOME CTOR
10663 return false;
10664 }
10665 if (!emitPickN(isStatic ? 3 : 1)) {
10666 // [stack] ADDINIT HOME HERIT? ARR I INITS GET HOME SET
10667 // or:
10668 // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME CTOR SET
10669 return false;
10670 }
10671 if (!ce.emitInit(AccessorType::Setter, accessorSetterKeyAtom)) {
10672 // [stack] ADDINIT HOME HERIT? ARR I INITS GET HOME
10673 // or:
10674 // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME
10675 return false;
10676 }
10677
10678 if (!ce.prepareForPropValue(propdef->pn_pos.begin, kind)) {
10679 // [stack] ADDINIT HOME HERIT? ARR I INITS GET HOME
10680 // or:
10681 // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME CTOR
10682 return false;
10683 }
10684 if (!emitPickN(isStatic ? 3 : 1)) {
10685 // [stack] ADDINIT HOME HERIT? ARR I INITS HOME GET
10686 // or:
10687 // [stack] ADDINIT CTOR HOME ARR I INITS CTOR HOME CTOR GET
10688 return false;
10689 }
10690 if (!ce.emitInit(AccessorType::Getter, accessorGetterKeyAtom)) {
10691 // [stack] ADDINIT HOME HERIT? ARR I INITS HOME
10692 // or:
10693 // [stack] ADDINIT CTOR HOME ARR I INITS CTOR HOME
10694 return false;
10695 }
10696 } else {
10697 MOZ_ASSERT(isStatic)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(isStatic)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(isStatic))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("isStatic", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 10697); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isStatic" ")"
); do { MOZ_CrashSequence(__null, 10697); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10698 // The getter and setter share the same name.
10699 if (!emitNewPrivateName(accessorSetterKeyAtom,
10700 accessorSetterKeyAtom)) {
10701 return false;
10702 }
10703 if (!ce.prepareForPrivateStaticMethod(propdef->pn_pos.begin)) {
10704 // [stack] ADDINIT CTOR HOME ARR I INITS GET SET CTOR HOME CTOR
10705 return false;
10706 }
10707 if (!emitGetPrivateName(
10708 &accessorSetterNode->name().as<NameNode>())) {
10709 // [stack] ADDINIT CTOR HOME ARR I INITS GET SET CTOR HOME CTOR
10710 // KEY
10711 return false;
10712 }
10713 if (!emitPickN(4)) {
10714 // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME CTOR KEY
10715 // SET
10716 return false;
10717 }
10718 if (!ce.emitPrivateStaticMethod(AccessorType::Setter)) {
10719 // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME
10720 return false;
10721 }
10722
10723 if (!ce.prepareForPrivateStaticMethod(propdef->pn_pos.begin)) {
10724 // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME CTOR
10725 return false;
10726 }
10727 if (!emitGetPrivateName(
10728 &accessorGetterNode->name().as<NameNode>())) {
10729 // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME CTOR KEY
10730 return false;
10731 }
10732 if (!emitPickN(4)) {
10733 // [stack] ADDINIT CTOR HOME ARR I INITS CTOR HOME CTOR KEY GET
10734 return false;
10735 }
10736 if (!ce.emitPrivateStaticMethod(AccessorType::Getter)) {
10737 // [stack] ADDINIT CTOR HOME ARR I INITS CTOR HOME
10738 return false;
10739 }
10740 }
10741
10742 if (!isStatic) {
10743 if (!emitPopN(1)) {
10744 // [stack] ADDINIT HOME HERIT? ARR I INITS
10745 return false;
10746 }
10747 } else {
10748 if (!emitPopN(2)) {
10749 // [stack] ADDINIT CTOR HOME ARR I INITS
10750 return false;
10751 }
10752 }
10753 } else {
10754 MOZ_ASSERT(IsPrivateInstanceAccessor(accessorSetterNode))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsPrivateInstanceAccessor(accessorSetterNode))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(IsPrivateInstanceAccessor(accessorSetterNode)))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("IsPrivateInstanceAccessor(accessorSetterNode)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 10754)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsPrivateInstanceAccessor(accessorSetterNode)"
")"); do { MOZ_CrashSequence(__null, 10754); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10755
10756 if (!emitLexicalInitialization(accessorSetterKeyAtom)) {
10757 // [stack] ADDINIT HOME HERIT? ARR I INITS GET SET
10758 // or:
10759 // [stack] ADDINIT CTOR HOME ARR I INITS GET SET
10760 return false;
10761 }
10762
10763 if (!emitPopN(1)) {
10764 // [stack] ADDINIT HOME HERIT? ARR I INITS GET
10765 // or:
10766 // [stack] ADDINIT CTOR HOME ARR I INITS GET
10767 return false;
10768 }
10769
10770 if (!emitLexicalInitialization(accessorGetterKeyAtom)) {
10771 // [stack] ADDINIT HOME HERIT? ARR I INITS GET
10772 // or:
10773 // [stack] ADDINIT CTOR HOME ARR I INITS GET
10774 return false;
10775 }
10776
10777 if (!emitPopN(1)) {
10778 // [stack] ADDINIT HOME HERIT? ARR I INITS
10779 // or:
10780 // [stack] ADDINIT CTOR HOME ARR I INITS
10781 return false;
10782 }
10783 }
10784 }
10785 if (!emit1(JSOp::InitElemInc)) {
10786 // [stack] ADDINIT HOME HERIT? ARR I
10787 // or:
10788 // [stack] ADDINIT CTOR HOME ARR I
10789 return false;
10790 }
10791 }
10792 }
10793
10794 // Pop I
10795 if (!emitPopN(1)) {
10796 // [stack] ADDINIT HOME HERIT? ARR
10797 // or:
10798 // [stack] ADDINIT CTOR HOME ARR
10799 return false;
10800 }
10801#endif
10802
10803 if (!ce.emitMemberInitializersEnd()) {
10804 // [stack] ADDINIT HOME HERIT?
10805 // or:
10806 // [stack] ADDINIT CTOR HOME
10807 return false;
10808 }
10809
10810 return true;
10811}
10812
10813bool BytecodeEmitter::emitPrivateMethodInitializers(ClassEmitter& ce,
10814 ListNode* obj) {
10815 for (ParseNode* propdef : obj->contents()) {
10816 if (!propdef->is<ClassMethod>()) {
10817 continue;
10818 }
10819 auto* classMethod = &propdef->as<ClassMethod>();
10820
10821 // Skip over anything which isn't a private instance accessor.
10822 if (!IsPrivateInstanceAccessor(classMethod)) {
10823 continue;
10824 }
10825
10826 if (!ce.prepareForMemberInitializer()) {
10827 // [stack] HOMEOBJ HERITAGE? ARRAY
10828 // or:
10829 // [stack] CTOR HOMEOBJ ARRAY
10830 return false;
10831 }
10832
10833 // Synthesize a name for the lexical variable that will store the
10834 // private method body.
10835 TaggedParserAtomIndex name = classMethod->name().as<NameNode>().atom();
10836 AccessorType accessorType = classMethod->accessorType();
10837 StringBuilder storedMethodName(fc);
10838 if (!storedMethodName.append(parserAtoms(), name)) {
10839 return false;
10840 }
10841 if (!storedMethodName.append(
10842 accessorType == AccessorType::Getter ? ".getter" : ".setter")) {
10843 return false;
10844 }
10845 auto storedMethodAtom =
10846 storedMethodName.finishParserAtom(parserAtoms(), fc);
10847
10848 // Emit the private method body and store it as a lexical var.
10849 if (!emitFunction(&classMethod->method())) {
10850 // [stack] HOMEOBJ HERITAGE? ARRAY METHOD
10851 // or:
10852 // [stack] CTOR HOMEOBJ ARRAY METHOD
10853 return false;
10854 }
10855 // The private method body needs to access the home object,
10856 // and the CE knows where that is on the stack.
10857 if (classMethod->method().funbox()->needsHomeObject()) {
10858 if (!ce.emitMemberInitializerHomeObject(false)) {
10859 // [stack] HOMEOBJ HERITAGE? ARRAY METHOD
10860 // or:
10861 // [stack] CTOR HOMEOBJ ARRAY METHOD
10862 return false;
10863 }
10864 }
10865 if (!emitLexicalInitialization(storedMethodAtom)) {
10866 // [stack] HOMEOBJ HERITAGE? ARRAY METHOD
10867 // or:
10868 // [stack] CTOR HOMEOBJ ARRAY METHOD
10869 return false;
10870 }
10871 if (!emit1(JSOp::Pop)) {
10872 // [stack] HOMEOBJ HERITAGE? ARRAY
10873 // or:
10874 // [stack] CTOR HOMEOBJ ARRAY
10875 return false;
10876 }
10877
10878 if (!emitPrivateMethodInitializer(classMethod, storedMethodAtom)) {
10879 // [stack] HOMEOBJ HERITAGE? ARRAY
10880 // or:
10881 // [stack] CTOR HOMEOBJ ARRAY
10882 return false;
10883 }
10884
10885 // Store the emitted initializer function into the .initializers array.
10886 if (!ce.emitStoreMemberInitializer()) {
10887 // [stack] HOMEOBJ HERITAGE? ARRAY
10888 // or:
10889 // [stack] CTOR HOMEOBJ ARRAY
10890 return false;
10891 }
10892 }
10893
10894 return true;
10895}
10896
10897bool BytecodeEmitter::emitPrivateMethodInitializer(
10898 ClassMethod* classMethod, TaggedParserAtomIndex storedMethodAtom) {
10899 MOZ_ASSERT(IsPrivateInstanceAccessor(classMethod))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsPrivateInstanceAccessor(classMethod))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(IsPrivateInstanceAccessor(classMethod)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("IsPrivateInstanceAccessor(classMethod)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 10899)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsPrivateInstanceAccessor(classMethod)"
")"); do { MOZ_CrashSequence(__null, 10899); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10900
10901 auto* name = &classMethod->name().as<NameNode>();
10902
10903 // Emit the synthesized initializer function.
10904 FunctionNode* funNode = classMethod->initializerIfPrivate();
10905 MOZ_ASSERT(funNode)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(funNode)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(funNode))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("funNode", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 10905); AnnotateMozCrashReason("MOZ_ASSERT" "(" "funNode" ")"
); do { MOZ_CrashSequence(__null, 10905); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10906 FunctionBox* funbox = funNode->funbox();
10907 FunctionEmitter fe(this, funbox, funNode->syntaxKind(),
10908 FunctionEmitter::IsHoisted::No);
10909 if (!fe.prepareForNonLazy()) {
10910 // [stack]
10911 return false;
10912 }
10913
10914 BytecodeEmitter bce2(this, funbox);
10915 if (!bce2.init(funNode->pn_pos)) {
10916 return false;
10917 }
10918 ParamsBodyNode* paramsBody = funNode->body();
10919 FunctionScriptEmitter fse(&bce2, funbox, Nothing(), Nothing());
10920 if (!fse.prepareForParameters()) {
10921 // [stack]
10922 return false;
10923 }
10924 if (!bce2.emitFunctionFormalParameters(paramsBody)) {
10925 // [stack]
10926 return false;
10927 }
10928 if (!fse.prepareForBody()) {
10929 // [stack]
10930 return false;
10931 }
10932
10933 if (!bce2.emit1(JSOp::FunctionThis)) {
10934 // [stack] THIS
10935 return false;
10936 }
10937 if (!bce2.emitGetPrivateName(name)) {
10938 // [stack] THIS NAME
10939 return false;
10940 }
10941 if (!bce2.emitGetName(storedMethodAtom)) {
10942 // [stack] THIS NAME METHOD
10943 return false;
10944 }
10945
10946 switch (name->privateNameKind()) {
10947 case PrivateNameKind::Setter:
10948 if (!bce2.emit1(JSOp::InitHiddenElemSetter)) {
10949 // [stack] THIS
10950 return false;
10951 }
10952 if (!bce2.emitGetPrivateName(name)) {
10953 // [stack] THIS NAME
10954 return false;
10955 }
10956 if (!bce2.emitAtomOp(
10957 JSOp::GetIntrinsic,
10958 TaggedParserAtomIndex::WellKnown::NoPrivateGetter())) {
10959 // [stack] THIS NAME FUN
10960 return false;
10961 }
10962 if (!bce2.emit1(JSOp::InitHiddenElemGetter)) {
10963 // [stack] THIS
10964 return false;
10965 }
10966 break;
10967 case PrivateNameKind::Getter:
10968 case PrivateNameKind::GetterSetter:
10969 if (classMethod->accessorType() == AccessorType::Getter) {
10970 if (!bce2.emit1(JSOp::InitHiddenElemGetter)) {
10971 // [stack] THIS
10972 return false;
10973 }
10974 } else {
10975 if (!bce2.emit1(JSOp::InitHiddenElemSetter)) {
10976 // [stack] THIS
10977 return false;
10978 }
10979 }
10980 break;
10981 default:
10982 MOZ_CRASH("Invalid op")do { do { } while (false); MOZ_ReportCrash("" "Invalid op", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 10982); AnnotateMozCrashReason("MOZ_CRASH(" "Invalid op" ")"
); do { MOZ_CrashSequence(__null, 10982); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
10983 }
10984
10985 // Pop remaining THIS.
10986 if (!bce2.emit1(JSOp::Pop)) {
10987 // [stack]
10988 return false;
10989 }
10990
10991 if (!fse.emitEndBody()) {
10992 // [stack]
10993 return false;
10994 }
10995 if (!fse.intoStencil()) {
10996 return false;
10997 }
10998
10999 if (!fe.emitNonLazyEnd()) {
11000 // [stack] HOMEOBJ HERITAGE? ARRAY FUN
11001 // or:
11002 // [stack] CTOR HOMEOBJ ARRAY FUN
11003 return false;
11004 }
11005
11006 return true;
11007}
11008
11009const MemberInitializers& BytecodeEmitter::findMemberInitializersForCall()
11010 const {
11011 for (const auto* current = this; current; current = current->parent) {
11012 if (current->sc->isFunctionBox()) {
11013 FunctionBox* funbox = current->sc->asFunctionBox();
11014
11015 if (funbox->isArrow()) {
11016 continue;
11017 }
11018
11019 // If we found a non-arrow / non-constructor we were never allowed to
11020 // expect fields in the first place.
11021 MOZ_RELEASE_ASSERT(funbox->isClassConstructor())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(funbox->isClassConstructor())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(funbox->isClassConstructor
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("funbox->isClassConstructor()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 11021); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "funbox->isClassConstructor()"
")"); do { MOZ_CrashSequence(__null, 11021); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11022
11023 return funbox->useMemberInitializers() ? funbox->memberInitializers()
11024 : MemberInitializers::Empty();
11025 }
11026 }
11027
11028 MOZ_RELEASE_ASSERT(compilationState.scopeContext.memberInitializers)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(compilationState.scopeContext.memberInitializers)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(compilationState.scopeContext.memberInitializers))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("compilationState.scopeContext.memberInitializers"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 11028)
; AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "compilationState.scopeContext.memberInitializers"
")"); do { MOZ_CrashSequence(__null, 11028); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11029 return *compilationState.scopeContext.memberInitializers;
11030}
11031
11032bool BytecodeEmitter::emitInitializeInstanceMembers(
11033 bool isDerivedClassConstructor) {
11034 const MemberInitializers& memberInitializers =
11035 findMemberInitializersForCall();
11036 MOZ_ASSERT(memberInitializers.valid)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(memberInitializers.valid)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(memberInitializers.valid))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("memberInitializers.valid"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 11036)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "memberInitializers.valid"
")"); do { MOZ_CrashSequence(__null, 11036); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11037
11038 if (memberInitializers.hasPrivateBrand) {
11039 // This is guaranteed to run after super(), so we don't need TDZ checks.
11040 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_this_())) {
11041 // [stack] THIS
11042 return false;
11043 }
11044 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_privateBrand_())) {
11045 // [stack] THIS BRAND
11046 return false;
11047 }
11048 if (isDerivedClassConstructor) {
11049 if (!emitCheckPrivateField(ThrowCondition::ThrowHas,
11050 ThrowMsgKind::PrivateBrandDoubleInit)) {
11051 // [stack] THIS BRAND BOOL
11052 return false;
11053 }
11054 if (!emit1(JSOp::Pop)) {
11055 // [stack] THIS BRAND
11056 return false;
11057 }
11058 }
11059 if (!emit1(JSOp::Null)) {
11060 // [stack] THIS BRAND NULL
11061 return false;
11062 }
11063 if (!emit1(JSOp::InitHiddenElem)) {
11064 // [stack] THIS
11065 return false;
11066 }
11067 if (!emit1(JSOp::Pop)) {
11068 // [stack]
11069 return false;
11070 }
11071 }
11072
11073 size_t numInitializers = memberInitializers.numMemberInitializers;
11074 if (numInitializers > 0) {
11075 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_initializers_())) {
11076 // [stack] ARRAY
11077 return false;
11078 }
11079
11080 for (size_t index = 0; index < numInitializers; index++) {
11081 if (index < numInitializers - 1) {
11082 // We Dup to keep the array around (it is consumed in the bytecode
11083 // below) for next iterations of this loop, except for the last
11084 // iteration, which avoids an extra Pop at the end of the loop.
11085 if (!emit1(JSOp::Dup)) {
11086 // [stack] ARRAY ARRAY
11087 return false;
11088 }
11089 }
11090
11091 if (!emitNumberOp(index)) {
11092 // [stack] ARRAY? ARRAY INDEX
11093 return false;
11094 }
11095
11096 if (!emit1(JSOp::GetElem)) {
11097 // [stack] ARRAY? FUNC
11098 return false;
11099 }
11100
11101 // This is guaranteed to run after super(), so we don't need TDZ checks.
11102 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_this_())) {
11103 // [stack] ARRAY? FUNC THIS
11104 return false;
11105 }
11106
11107 // Callee is always internal function.
11108 if (!emitCall(JSOp::CallIgnoresRv, 0)) {
11109 // [stack] ARRAY? RVAL
11110 return false;
11111 }
11112
11113 if (!emit1(JSOp::Pop)) {
11114 // [stack] ARRAY?
11115 return false;
11116 }
11117 }
11118#ifdef ENABLE_DECORATORS
11119 if (memberInitializers.hasDecorators) {
11120 // Decorators Proposal
11121 // https://arai-a.github.io/ecma262-compare/?pr=2417&id=sec-initializeinstanceelements
11122 // 4. For each element e of elements, do
11123 // 4.a. If elementRecord.[[Kind]] is field or accessor, then
11124 // 4.a.i. Perform ? InitializeFieldOrAccessor(O, elementRecord).
11125 //
11126
11127 // TODO: (See Bug 1817993) At the moment, we're applying the
11128 // initialization logic in two steps. The pre-decorator initialization
11129 // code runs, stores the initial value, and then we retrieve it here and
11130 // apply the initializers added by decorators. We should unify these two
11131 // steps.
11132 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_initializers_())) {
11133 // [stack] ARRAY
11134 return false;
11135 }
11136
11137 if (!emit1(JSOp::Dup)) {
11138 // [stack] ARRAY ARRAY
11139 return false;
11140 }
11141
11142 if (!emitAtomOp(JSOp::GetProp,
11143 TaggedParserAtomIndex::WellKnown::length())) {
11144 // [stack] ARRAY LENGTH
11145 return false;
11146 }
11147
11148 if (!emitNumberOp(static_cast<double>(numInitializers))) {
11149 // [stack] ARRAY LENGTH INDEX
11150 return false;
11151 }
11152
11153 InternalWhileEmitter wh(this);
11154 // At this point, we have no context to determine offsets in the
11155 // code for this while statement. Ideally, it would correspond to
11156 // the field we're initializing.
11157 if (!wh.emitCond()) {
11158 // [stack] ARRAY LENGTH INDEX
11159 return false;
11160 }
11161
11162 if (!emit1(JSOp::Dup)) {
11163 // [stack] ARRAY LENGTH INDEX INDEX
11164 return false;
11165 }
11166
11167 if (!emitDupAt(2)) {
11168 // [stack] ARRAY LENGTH INDEX INDEX LENGTH
11169 return false;
11170 }
11171
11172 if (!emit1(JSOp::Lt)) {
11173 // [stack] ARRAY LENGTH INDEX BOOL
11174 return false;
11175 }
11176
11177 if (!wh.emitBody()) {
11178 // [stack] ARRAY LENGTH INDEX
11179 return false;
11180 }
11181
11182 if (!emitDupAt(2)) {
11183 // [stack] ARRAY LENGTH INDEX ARRAY
11184 return false;
11185 }
11186
11187 if (!emitDupAt(1)) {
11188 // [stack] ARRAY LENGTH INDEX ARRAY INDEX
11189 return false;
11190 }
11191
11192 // Retrieve initializers for this field
11193 if (!emit1(JSOp::GetElem)) {
11194 // [stack] ARRAY LENGTH INDEX INITIALIZERS
11195 return false;
11196 }
11197
11198 // This is guaranteed to run after super(), so we don't need TDZ checks.
11199 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_this_())) {
11200 // [stack] ARRAY LENGTH INDEX INITIALIZERS THIS
11201 return false;
11202 }
11203
11204 if (!emit1(JSOp::Swap)) {
11205 // [stack] ARRAY LENGTH INDEX THIS INITIALIZERS
11206 return false;
11207 }
11208
11209 DecoratorEmitter de(this);
11210 if (!de.emitInitializeFieldOrAccessor()) {
11211 // [stack] ARRAY LENGTH INDEX
11212 return false;
11213 }
11214
11215 if (!emit1(JSOp::Inc)) {
11216 // [stack] ARRAY LENGTH INDEX
11217 return false;
11218 }
11219
11220 if (!wh.emitEnd()) {
11221 // [stack] ARRAY LENGTH INDEX
11222 return false;
11223 }
11224
11225 if (!emitPopN(3)) {
11226 // [stack]
11227 return false;
11228 }
11229 // 5. Return unused.
11230
11231 if (!de.emitCallExtraInitializers(TaggedParserAtomIndex::WellKnown::
11232 dot_instanceExtraInitializers_())) {
11233 return false;
11234 }
11235 }
11236#endif
11237 }
11238 return true;
11239}
11240
11241bool BytecodeEmitter::emitInitializeStaticFields(ListNode* classMembers) {
11242 auto isStaticField = [](ParseNode* propdef) {
11243 return HasInitializer(propdef, true);
11244 };
11245 size_t numFields =
11246 std::count_if(classMembers->contents().begin(),
11247 classMembers->contents().end(), isStaticField);
11248
11249 if (numFields == 0) {
11250 return true;
11251 }
11252
11253 if (!emitGetName(
11254 TaggedParserAtomIndex::WellKnown::dot_staticInitializers_())) {
11255 // [stack] CTOR ARRAY
11256 return false;
11257 }
11258
11259 for (size_t fieldIndex = 0; fieldIndex < numFields; fieldIndex++) {
11260 bool hasNext = fieldIndex < numFields - 1;
11261 if (hasNext) {
11262 // We Dup to keep the array around (it is consumed in the bytecode below)
11263 // for next iterations of this loop, except for the last iteration, which
11264 // avoids an extra Pop at the end of the loop.
11265 if (!emit1(JSOp::Dup)) {
11266 // [stack] CTOR ARRAY ARRAY
11267 return false;
11268 }
11269 }
11270
11271 if (!emitNumberOp(fieldIndex)) {
11272 // [stack] CTOR ARRAY? ARRAY INDEX
11273 return false;
11274 }
11275
11276 if (!emit1(JSOp::GetElem)) {
11277 // [stack] CTOR ARRAY? FUNC
11278 return false;
11279 }
11280
11281 if (!emitDupAt(1 + hasNext)) {
11282 // [stack] CTOR ARRAY? FUNC CTOR
11283 return false;
11284 }
11285
11286 // Callee is always internal function.
11287 if (!emitCall(JSOp::CallIgnoresRv, 0)) {
11288 // [stack] CTOR ARRAY? RVAL
11289 return false;
11290 }
11291
11292 if (!emit1(JSOp::Pop)) {
11293 // [stack] CTOR ARRAY?
11294 return false;
11295 }
11296 }
11297
11298#ifdef ENABLE_DECORATORS
11299 // Decorators Proposal
11300 // https://arai-a.github.io/ecma262-compare/?pr=2417&id=sec-initializeinstanceelements
11301 // 4. For each element e of elements, do
11302 // 4.a. If elementRecord.[[Kind]] is field or accessor, then
11303 // 4.a.i. Perform ? InitializeFieldOrAccessor(O, elementRecord).
11304 //
11305
11306 // TODO: (See Bug 1817993) At the moment, we're applying the initialization
11307 // logic in two steps. The pre-decorator initialization code runs, stores
11308 // the initial value, and then we retrieve it here and apply the
11309 // initializers added by decorators. We should unify these two steps.
11310 if (!emitGetName(
11311 TaggedParserAtomIndex::WellKnown::dot_staticInitializers_())) {
11312 // [stack] CTOR ARRAY
11313 return false;
11314 }
11315
11316 if (!emit1(JSOp::Dup)) {
11317 // [stack] CTOR ARRAY ARRAY
11318 return false;
11319 }
11320
11321 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::length())) {
11322 // [stack] CTOR ARRAY LENGTH
11323 return false;
11324 }
11325
11326 if (!emitNumberOp(static_cast<double>(numFields))) {
11327 // [stack] CTOR ARRAY LENGTH INDEX
11328 return false;
11329 }
11330
11331 InternalWhileEmitter wh(this);
11332 // At this point, we have no context to determine offsets in the
11333 // code for this while statement. Ideally, it would correspond to
11334 // the field we're initializing.
11335 if (!wh.emitCond()) {
11336 // [stack] CTOR ARRAY LENGTH INDEX
11337 return false;
11338 }
11339
11340 if (!emit1(JSOp::Dup)) {
11341 // [stack] CTOR ARRAY LENGTH INDEX INDEX
11342 return false;
11343 }
11344
11345 if (!emitDupAt(2)) {
11346 // [stack] CTOR ARRAY LENGTH INDEX INDEX LENGTH
11347 return false;
11348 }
11349
11350 if (!emit1(JSOp::Lt)) {
11351 // [stack] CTOR ARRAY LENGTH INDEX BOOL
11352 return false;
11353 }
11354
11355 if (!wh.emitBody()) {
11356 // [stack] CTOR ARRAY LENGTH INDEX
11357 return false;
11358 }
11359
11360 if (!emitDupAt(2)) {
11361 // [stack] CTOR ARRAY LENGTH INDEX ARRAY
11362 return false;
11363 }
11364
11365 if (!emitDupAt(1)) {
11366 // [stack] CTOR ARRAY LENGTH INDEX ARRAY INDEX
11367 return false;
11368 }
11369
11370 // Retrieve initializers for this field
11371 if (!emit1(JSOp::GetElem)) {
11372 // [stack] CTOR ARRAY LENGTH INDEX INITIALIZERS
11373 return false;
11374 }
11375
11376 if (!emitDupAt(4)) {
11377 // [stack] CTOR ARRAY LENGTH INDEX INITIALIZERS CTOR
11378 return false;
11379 }
11380
11381 if (!emit1(JSOp::Swap)) {
11382 // [stack] CTOR ARRAY LENGTH INDEX CTOR INITIALIZERS
11383 return false;
11384 }
11385
11386 DecoratorEmitter de(this);
11387 if (!de.emitInitializeFieldOrAccessor()) {
11388 // [stack] CTOR ARRAY LENGTH INDEX
11389 return false;
11390 }
11391
11392 if (!emit1(JSOp::Inc)) {
11393 // [stack] CTOR ARRAY LENGTH INDEX
11394 return false;
11395 }
11396
11397 if (!wh.emitEnd()) {
11398 // [stack] CTOR ARRAY LENGTH INDEX
11399 return false;
11400 }
11401
11402 if (!emitPopN(3)) {
11403 // [stack] CTOR
11404 return false;
11405 }
11406 // 5. Return unused.
11407#endif
11408
11409 // Overwrite |.staticInitializers| and |.staticFieldKeys| with undefined to
11410 // avoid keeping the arrays alive indefinitely.
11411 auto clearStaticFieldSlot = [&](TaggedParserAtomIndex name) {
11412 NameOpEmitter noe(this, name, NameOpEmitter::Kind::SimpleAssignment);
11413 if (!noe.prepareForRhs()) {
11414 // [stack] ENV? VAL?
11415 return false;
11416 }
11417
11418 if (!emit1(JSOp::Undefined)) {
11419 // [stack] ENV? VAL? UNDEFINED
11420 return false;
11421 }
11422
11423 if (!noe.emitAssignment()) {
11424 // [stack] VAL
11425 return false;
11426 }
11427
11428 if (!emit1(JSOp::Pop)) {
11429 // [stack]
11430 return false;
11431 }
11432
11433 return true;
11434 };
11435
11436 if (!clearStaticFieldSlot(
11437 TaggedParserAtomIndex::WellKnown::dot_staticInitializers_())) {
11438 return false;
11439 }
11440
11441 auto isStaticFieldWithComputedName = [](ParseNode* propdef) {
11442 return propdef->is<ClassField>() && propdef->as<ClassField>().isStatic() &&
11443 propdef->as<ClassField>().name().getKind() ==
11444 ParseNodeKind::ComputedName;
11445 };
11446
11447 if (std::any_of(classMembers->contents().begin(),
11448 classMembers->contents().end(),
11449 isStaticFieldWithComputedName)) {
11450 if (!clearStaticFieldSlot(
11451 TaggedParserAtomIndex::WellKnown::dot_staticFieldKeys_())) {
11452 return false;
11453 }
11454 }
11455
11456 return true;
11457}
11458
11459// Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See
11460// the comment on emitSwitch.
11461MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitObject(ListNode* objNode) {
11462 // Note: this method uses the ObjLiteralWriter and emits ObjLiteralStencil
11463 // objects into the GCThingList, which will evaluate them into real GC objects
11464 // or shapes during JSScript::fullyInitFromEmitter. Eventually we want
11465 // JSOp::Object to be a real opcode, but for now, performance constraints
11466 // limit us to evaluating object literals at the end of parse, when we're
11467 // allowed to allocate GC things.
11468 //
11469 // There are four cases here, in descending order of preference:
11470 //
11471 // 1. The list of property names is "normal" and constant (no computed
11472 // values, no integer indices), the values are all simple constants
11473 // (numbers, booleans, strings), *and* this occurs in a run-once
11474 // (singleton) context. In this case, we can emit ObjLiteral
11475 // instructions to build an object with values, and the object will be
11476 // attached to a JSOp::Object opcode, whose semantics are for the backend
11477 // to simply steal the object from the script.
11478 //
11479 // 2. The list of property names is "normal" and constant as above, *and* this
11480 // occurs in a run-once (singleton) context, but some values are complex
11481 // (computed expressions, sub-objects, functions, etc.). In this case, we
11482 // can still use JSOp::Object (because singleton context), but the object
11483 // has |undefined| property values and InitProp ops are emitted to set the
11484 // values.
11485 //
11486 // 3. The list of property names is "normal" and constant as above, but this
11487 // occurs in a non-run-once (non-singleton) context. In this case, we can
11488 // use the ObjLiteral functionality to describe an *empty* object (all
11489 // values left undefined) with the right fields, which will become a
11490 // JSOp::NewObject opcode using the object's shape to speed up the creation
11491 // of the object each time it executes. The emitted bytecode still needs
11492 // InitProp ops to set the values in this case.
11493 //
11494 // 4. Any other case. As a fallback, we use NewInit to create a new, empty
11495 // object (i.e., `{}`) and then emit bytecode to initialize its properties
11496 // one-by-one.
11497
11498 bool useObjLiteral = false;
11499 bool useObjLiteralValues = false;
11500 isPropertyListObjLiteralCompatible(objNode, &useObjLiteralValues,
11501 &useObjLiteral);
11502
11503 // [stack]
11504 //
11505 ObjectEmitter oe(this);
11506 if (useObjLiteral) {
11507 bool singleton = checkSingletonContext() &&
11508 !objNode->hasNonConstInitializer() && objNode->head();
11509 JSOp op;
11510 if (singleton) {
11511 // Case 1 or 2.
11512 op = JSOp::Object;
11513 } else {
11514 // Case 3.
11515 useObjLiteralValues = false;
11516 op = JSOp::NewObject;
11517 }
11518
11519 // Use an ObjLiteral op. This will record ObjLiteral insns in the
11520 // objLiteralWriter's buffer and add a fixup to the list of ObjLiteral
11521 // fixups so that at GC-publish time at the end of parse, the full object
11522 // (case 1 or 2) or shape (case 3) can be allocated and the bytecode can be
11523 // patched to refer to it.
11524 if (!emitPropertyListObjLiteral(objNode, op, useObjLiteralValues)) {
11525 // [stack] OBJ
11526 return false;
11527 }
11528 // Put the ObjectEmitter in the right state. This tells it that there will
11529 // already be an object on the stack as a result of the (eventual)
11530 // NewObject or Object op, and prepares it to emit values if needed.
11531 if (!oe.emitObjectWithTemplateOnStack()) {
11532 // [stack] OBJ
11533 return false;
11534 }
11535 if (!useObjLiteralValues) {
11536 // Case 2 or 3 above: we still need to emit bytecode to fill in the
11537 // object's property values.
11538 if (!emitPropertyList(objNode, oe, ObjectLiteral)) {
11539 // [stack] OBJ
11540 return false;
11541 }
11542 }
11543 } else {
11544 // Case 4 above: no ObjLiteral use, just bytecode to build the object from
11545 // scratch.
11546 if (!oe.emitObject(objNode->count())) {
11547 // [stack] OBJ
11548 return false;
11549 }
11550 if (!emitPropertyList(objNode, oe, ObjectLiteral)) {
11551 // [stack] OBJ
11552 return false;
11553 }
11554 }
11555
11556 if (!oe.emitEnd()) {
11557 // [stack] OBJ
11558 return false;
11559 }
11560
11561 return true;
11562}
11563
11564bool BytecodeEmitter::emitArrayLiteral(ListNode* array) {
11565 // Emit JSOp::Object if the array consists entirely of primitive values and we
11566 // are in a singleton context.
11567 if (checkSingletonContext() && !array->hasNonConstInitializer() &&
11568 !array->empty() && isArrayObjLiteralCompatible(array)) {
11569 return emitObjLiteralArray(array);
11570 }
11571
11572 return emitArray(array);
11573}
11574
11575bool BytecodeEmitter::emitArray(ListNode* array) {
11576 /*
11577 * Emit code for [a, b, c] that is equivalent to constructing a new
11578 * array and in source order evaluating each element value and adding
11579 * it to the array, without invoking latent setters. We use the
11580 * JSOp::NewInit and JSOp::InitElemArray bytecodes to ignore setters and
11581 * to avoid dup'ing and popping the array as each element is added, as
11582 * JSOp::SetElem/JSOp::SetProp would do.
11583 */
11584
11585 uint32_t nspread = 0;
11586 for (ParseNode* elem : array->contents()) {
11587 if (elem->isKind(ParseNodeKind::Spread)) {
11588 nspread++;
11589 }
11590 }
11591
11592 // Array literal's length is limited to NELEMENTS_LIMIT in parser.
11593 static_assert(NativeObject::MAX_DENSE_ELEMENTS_COUNT <= INT32_MAX(2147483647),
11594 "array literals' maximum length must not exceed limits "
11595 "required by BaselineCompiler::emit_NewArray, "
11596 "BaselineCompiler::emit_InitElemArray, "
11597 "and DoSetElemFallback's handling of JSOp::InitElemArray");
11598
11599 uint32_t count = array->count();
11600 MOZ_ASSERT(count >= nspread)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(count >= nspread)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(count >= nspread))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("count >= nspread"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 11600)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "count >= nspread"
")"); do { MOZ_CrashSequence(__null, 11600); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11601 MOZ_ASSERT(count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT"
" (" "the parser must throw an error if the array exceeds maximum "
"length" ")", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 11603); AnnotateMozCrashReason("MOZ_ASSERT" "(" "count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT"
") (" "the parser must throw an error if the array exceeds maximum "
"length" ")"); do { MOZ_CrashSequence(__null, 11603); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
11602 "the parser must throw an error if the array exceeds maximum "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT"
" (" "the parser must throw an error if the array exceeds maximum "
"length" ")", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 11603); AnnotateMozCrashReason("MOZ_ASSERT" "(" "count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT"
") (" "the parser must throw an error if the array exceeds maximum "
"length" ")"); do { MOZ_CrashSequence(__null, 11603); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
11603 "length")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT"
" (" "the parser must throw an error if the array exceeds maximum "
"length" ")", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 11603); AnnotateMozCrashReason("MOZ_ASSERT" "(" "count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT"
") (" "the parser must throw an error if the array exceeds maximum "
"length" ")"); do { MOZ_CrashSequence(__null, 11603); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
11604
11605 // For arrays with spread, this is a very pessimistic allocation, the
11606 // minimum possible final size.
11607 if (!emitUint32Operand(JSOp::NewArray, count - nspread)) {
11608 // [stack] ARRAY
11609 return false;
11610 }
11611
11612 uint32_t index = 0;
11613 bool afterSpread = false;
11614 for (ParseNode* elem : array->contents()) {
11615 if (elem->isKind(ParseNodeKind::Spread)) {
11616 if (!afterSpread) {
11617 afterSpread = true;
11618 if (!emitNumberOp(index)) {
11619 // [stack] ARRAY INDEX
11620 return false;
11621 }
11622 }
11623
11624 ParseNode* expr = elem->as<UnaryNode>().kid();
11625 SelfHostedIter selfHostedIter = getSelfHostedIterFor(expr);
11626
11627 if (!updateSourceCoordNotes(elem->pn_pos.begin)) {
11628 return false;
11629 }
11630 if (!emitIterable(expr, selfHostedIter)) {
11631 // [stack] ARRAY INDEX ITERABLE
11632 return false;
11633 }
11634 if (!emitIterator(selfHostedIter)) {
11635 // [stack] ARRAY INDEX NEXT ITER
11636 return false;
11637 }
11638 if (!emit2(JSOp::Pick, 3)) {
11639 // [stack] INDEX NEXT ITER ARRAY
11640 return false;
11641 }
11642 if (!emit2(JSOp::Pick, 3)) {
11643 // [stack] NEXT ITER ARRAY INDEX
11644 return false;
11645 }
11646 if (!emitSpread(selfHostedIter)) {
11647 // [stack] ARRAY INDEX
11648 return false;
11649 }
11650 } else {
11651 if (!updateSourceCoordNotesIfNonLiteral(elem)) {
11652 return false;
11653 }
11654 if (elem->isKind(ParseNodeKind::Elision)) {
11655 if (!emit1(JSOp::Hole)) {
11656 return false;
11657 }
11658 } else {
11659 if (!emitTree(elem, ValueUsage::WantValue)) {
11660 // [stack] ARRAY INDEX? VALUE
11661 return false;
11662 }
11663 }
11664
11665 if (afterSpread) {
11666 if (!emit1(JSOp::InitElemInc)) {
11667 // [stack] ARRAY (INDEX+1)
11668 return false;
11669 }
11670 } else {
11671 if (!emitUint32Operand(JSOp::InitElemArray, index)) {
11672 // [stack] ARRAY
11673 return false;
11674 }
11675 }
11676 }
11677
11678 index++;
11679 }
11680 MOZ_ASSERT(index == count)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(index == count)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(index == count))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("index == count"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 11680)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "index == count" ")"
); do { MOZ_CrashSequence(__null, 11680); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
11681 if (afterSpread) {
11682 if (!emit1(JSOp::Pop)) {
11683 // [stack] ARRAY
11684 return false;
11685 }
11686 }
11687 return true;
11688}
11689
11690bool BytecodeEmitter::emitSpreadIntoArray(UnaryNode* elem) {
11691 MOZ_ASSERT(elem->isKind(ParseNodeKind::Spread))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(elem->isKind(ParseNodeKind::Spread))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(elem->isKind(ParseNodeKind::Spread)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("elem->isKind(ParseNodeKind::Spread)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 11691)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "elem->isKind(ParseNodeKind::Spread)"
")"); do { MOZ_CrashSequence(__null, 11691); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11692
11693 if (!updateSourceCoordNotes(elem->pn_pos.begin)) {
11694 // [stack] VALUE
11695 return false;
11696 }
11697
11698 SelfHostedIter selfHostedIter = getSelfHostedIterFor(elem->kid());
11699 MOZ_ASSERT(selfHostedIter == SelfHostedIter::Deny ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(selfHostedIter == SelfHostedIter::Deny || selfHostedIter
== SelfHostedIter::AllowContent)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(selfHostedIter == SelfHostedIter
::Deny || selfHostedIter == SelfHostedIter::AllowContent))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter == SelfHostedIter::Deny || selfHostedIter == SelfHostedIter::AllowContent"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 11700)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter == SelfHostedIter::Deny || selfHostedIter == SelfHostedIter::AllowContent"
")"); do { MOZ_CrashSequence(__null, 11700); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11700 selfHostedIter == SelfHostedIter::AllowContent)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(selfHostedIter == SelfHostedIter::Deny || selfHostedIter
== SelfHostedIter::AllowContent)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(selfHostedIter == SelfHostedIter
::Deny || selfHostedIter == SelfHostedIter::AllowContent))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter == SelfHostedIter::Deny || selfHostedIter == SelfHostedIter::AllowContent"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 11700)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter == SelfHostedIter::Deny || selfHostedIter == SelfHostedIter::AllowContent"
")"); do { MOZ_CrashSequence(__null, 11700); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11701
11702 if (!emitIterator(selfHostedIter)) {
11703 // [stack] NEXT ITER
11704 return false;
11705 }
11706
11707 if (!emitUint32Operand(JSOp::NewArray, 0)) {
11708 // [stack] NEXT ITER ARRAY
11709 return false;
11710 }
11711
11712 if (!emitNumberOp(0)) {
11713 // [stack] NEXT ITER ARRAY INDEX
11714 return false;
11715 }
11716
11717 if (!emitSpread(selfHostedIter)) {
11718 // [stack] ARRAY INDEX
11719 return false;
11720 }
11721
11722 if (!emit1(JSOp::Pop)) {
11723 // [stack] ARRAY
11724 return false;
11725 }
11726 return true;
11727}
11728
11729static inline JSOp UnaryOpParseNodeKindToJSOp(ParseNodeKind pnk) {
11730 switch (pnk) {
11731 case ParseNodeKind::ThrowStmt:
11732 return JSOp::Throw;
11733 case ParseNodeKind::VoidExpr:
11734 return JSOp::Void;
11735 case ParseNodeKind::NotExpr:
11736 return JSOp::Not;
11737 case ParseNodeKind::BitNotExpr:
11738 return JSOp::BitNot;
11739 case ParseNodeKind::PosExpr:
11740 return JSOp::Pos;
11741 case ParseNodeKind::NegExpr:
11742 return JSOp::Neg;
11743 default:
11744 MOZ_CRASH("unexpected unary op")do { do { } while (false); MOZ_ReportCrash("" "unexpected unary op"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 11744)
; AnnotateMozCrashReason("MOZ_CRASH(" "unexpected unary op" ")"
); do { MOZ_CrashSequence(__null, 11744); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
11745 }
11746}
11747
11748bool BytecodeEmitter::emitUnary(UnaryNode* unaryNode) {
11749 if (!updateSourceCoordNotes(unaryNode->pn_pos.begin)) {
11750 return false;
11751 }
11752
11753 JSOp op = UnaryOpParseNodeKindToJSOp(unaryNode->getKind());
11754 ValueUsage valueUsage =
11755 op == JSOp::Void ? ValueUsage::IgnoreValue : ValueUsage::WantValue;
11756 if (!emitTree(unaryNode->kid(), valueUsage)) {
11757 return false;
11758 }
11759 return emit1(op);
11760}
11761
11762bool BytecodeEmitter::emitTypeof(UnaryNode* typeofNode, JSOp op) {
11763 MOZ_ASSERT(op == JSOp::Typeof || op == JSOp::TypeofExpr)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(op == JSOp::Typeof || op == JSOp::TypeofExpr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(op == JSOp::Typeof || op == JSOp::TypeofExpr))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("op == JSOp::Typeof || op == JSOp::TypeofExpr"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 11763)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::Typeof || op == JSOp::TypeofExpr"
")"); do { MOZ_CrashSequence(__null, 11763); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11764
11765 if (!updateSourceCoordNotes(typeofNode->pn_pos.begin)) {
11766 return false;
11767 }
11768
11769 if (!emitTree(typeofNode->kid())) {
11770 return false;
11771 }
11772
11773 return emit1(op);
11774}
11775
11776bool BytecodeEmitter::tryEmitTypeofEq(ListNode* node, bool* emitted) {
11777 // Emit specialized opcode for the following if possible:
11778 // * typeof val == "type"
11779 // * typeof val != "type"
11780 // * typeof val > "u" # minified `typeof val === "undefined"`
11781 // * typeof val < "u" # minified `typeof val !== "undefined"`
11782 //
11783 // NOTE: Given the comparison is done for string, `==` and `===` have
11784 // no difference. Same for `!=` and `!==`.
11785 MOZ_ASSERT(node->isKind(ParseNodeKind::StrictEqExpr) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(node->isKind(ParseNodeKind::StrictEqExpr) || node
->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind
::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr) || node
->isKind(ParseNodeKind::LtExpr) || node->isKind(ParseNodeKind
::GtExpr))>::isValid, "invalid assertion condition"); if (
(__builtin_expect(!!(!(!!(node->isKind(ParseNodeKind::StrictEqExpr
) || node->isKind(ParseNodeKind::EqExpr) || node->isKind
(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind
::NeExpr) || node->isKind(ParseNodeKind::LtExpr) || node->
isKind(ParseNodeKind::GtExpr)))), 0))) { do { } while (false)
; MOZ_ReportAssertionFailure("node->isKind(ParseNodeKind::StrictEqExpr) || node->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr) || node->isKind(ParseNodeKind::LtExpr) || node->isKind(ParseNodeKind::GtExpr)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 11790)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::StrictEqExpr) || node->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr) || node->isKind(ParseNodeKind::LtExpr) || node->isKind(ParseNodeKind::GtExpr)"
")"); do { MOZ_CrashSequence(__null, 11790); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11786 node->isKind(ParseNodeKind::EqExpr) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(node->isKind(ParseNodeKind::StrictEqExpr) || node
->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind
::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr) || node
->isKind(ParseNodeKind::LtExpr) || node->isKind(ParseNodeKind
::GtExpr))>::isValid, "invalid assertion condition"); if (
(__builtin_expect(!!(!(!!(node->isKind(ParseNodeKind::StrictEqExpr
) || node->isKind(ParseNodeKind::EqExpr) || node->isKind
(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind
::NeExpr) || node->isKind(ParseNodeKind::LtExpr) || node->
isKind(ParseNodeKind::GtExpr)))), 0))) { do { } while (false)
; MOZ_ReportAssertionFailure("node->isKind(ParseNodeKind::StrictEqExpr) || node->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr) || node->isKind(ParseNodeKind::LtExpr) || node->isKind(ParseNodeKind::GtExpr)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 11790)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::StrictEqExpr) || node->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr) || node->isKind(ParseNodeKind::LtExpr) || node->isKind(ParseNodeKind::GtExpr)"
")"); do { MOZ_CrashSequence(__null, 11790); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11787 node->isKind(ParseNodeKind::StrictNeExpr) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(node->isKind(ParseNodeKind::StrictEqExpr) || node
->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind
::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr) || node
->isKind(ParseNodeKind::LtExpr) || node->isKind(ParseNodeKind
::GtExpr))>::isValid, "invalid assertion condition"); if (
(__builtin_expect(!!(!(!!(node->isKind(ParseNodeKind::StrictEqExpr
) || node->isKind(ParseNodeKind::EqExpr) || node->isKind
(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind
::NeExpr) || node->isKind(ParseNodeKind::LtExpr) || node->
isKind(ParseNodeKind::GtExpr)))), 0))) { do { } while (false)
; MOZ_ReportAssertionFailure("node->isKind(ParseNodeKind::StrictEqExpr) || node->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr) || node->isKind(ParseNodeKind::LtExpr) || node->isKind(ParseNodeKind::GtExpr)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 11790)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::StrictEqExpr) || node->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr) || node->isKind(ParseNodeKind::LtExpr) || node->isKind(ParseNodeKind::GtExpr)"
")"); do { MOZ_CrashSequence(__null, 11790); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11788 node->isKind(ParseNodeKind::NeExpr) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(node->isKind(ParseNodeKind::StrictEqExpr) || node
->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind
::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr) || node
->isKind(ParseNodeKind::LtExpr) || node->isKind(ParseNodeKind
::GtExpr))>::isValid, "invalid assertion condition"); if (
(__builtin_expect(!!(!(!!(node->isKind(ParseNodeKind::StrictEqExpr
) || node->isKind(ParseNodeKind::EqExpr) || node->isKind
(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind
::NeExpr) || node->isKind(ParseNodeKind::LtExpr) || node->
isKind(ParseNodeKind::GtExpr)))), 0))) { do { } while (false)
; MOZ_ReportAssertionFailure("node->isKind(ParseNodeKind::StrictEqExpr) || node->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr) || node->isKind(ParseNodeKind::LtExpr) || node->isKind(ParseNodeKind::GtExpr)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 11790)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::StrictEqExpr) || node->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr) || node->isKind(ParseNodeKind::LtExpr) || node->isKind(ParseNodeKind::GtExpr)"
")"); do { MOZ_CrashSequence(__null, 11790); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11789 node->isKind(ParseNodeKind::LtExpr) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(node->isKind(ParseNodeKind::StrictEqExpr) || node
->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind
::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr) || node
->isKind(ParseNodeKind::LtExpr) || node->isKind(ParseNodeKind
::GtExpr))>::isValid, "invalid assertion condition"); if (
(__builtin_expect(!!(!(!!(node->isKind(ParseNodeKind::StrictEqExpr
) || node->isKind(ParseNodeKind::EqExpr) || node->isKind
(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind
::NeExpr) || node->isKind(ParseNodeKind::LtExpr) || node->
isKind(ParseNodeKind::GtExpr)))), 0))) { do { } while (false)
; MOZ_ReportAssertionFailure("node->isKind(ParseNodeKind::StrictEqExpr) || node->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr) || node->isKind(ParseNodeKind::LtExpr) || node->isKind(ParseNodeKind::GtExpr)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 11790)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::StrictEqExpr) || node->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr) || node->isKind(ParseNodeKind::LtExpr) || node->isKind(ParseNodeKind::GtExpr)"
")"); do { MOZ_CrashSequence(__null, 11790); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11790 node->isKind(ParseNodeKind::GtExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(node->isKind(ParseNodeKind::StrictEqExpr) || node
->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind
::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr) || node
->isKind(ParseNodeKind::LtExpr) || node->isKind(ParseNodeKind
::GtExpr))>::isValid, "invalid assertion condition"); if (
(__builtin_expect(!!(!(!!(node->isKind(ParseNodeKind::StrictEqExpr
) || node->isKind(ParseNodeKind::EqExpr) || node->isKind
(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind
::NeExpr) || node->isKind(ParseNodeKind::LtExpr) || node->
isKind(ParseNodeKind::GtExpr)))), 0))) { do { } while (false)
; MOZ_ReportAssertionFailure("node->isKind(ParseNodeKind::StrictEqExpr) || node->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr) || node->isKind(ParseNodeKind::LtExpr) || node->isKind(ParseNodeKind::GtExpr)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 11790)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::StrictEqExpr) || node->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr) || node->isKind(ParseNodeKind::LtExpr) || node->isKind(ParseNodeKind::GtExpr)"
")"); do { MOZ_CrashSequence(__null, 11790); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11791
11792 if (node->count() != 2) {
11793 *emitted = false;
11794 return true;
11795 }
11796
11797 ParseNode* left = node->head();
11798 ParseNode* right = left->pn_next;
11799 MOZ_ASSERT(right)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(right)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(right))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("right", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 11799); AnnotateMozCrashReason("MOZ_ASSERT" "(" "right" ")"
); do { MOZ_CrashSequence(__null, 11799); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
11800
11801 UnaryNode* typeofNode;
11802 NameNode* typenameNode;
11803 JSOp op;
11804 JSType type;
11805
11806 if (node->isKind(ParseNodeKind::LtExpr) ||
11807 node->isKind(ParseNodeKind::GtExpr)) {
11808 if (left->isKind(ParseNodeKind::TypeOfNameExpr) &&
11809 right->isKind(ParseNodeKind::StringExpr)) {
11810 typeofNode = &left->as<UnaryNode>();
11811 typenameNode = &right->as<NameNode>();
11812
11813 if (node->isKind(ParseNodeKind::LtExpr)) {
11814 op = JSOp::Ne;
11815 } else {
11816 op = JSOp::Eq;
11817 }
11818 } else if (left->isKind(ParseNodeKind::StringExpr) &&
11819 right->isKind(ParseNodeKind::TypeOfNameExpr)) {
11820 typeofNode = &right->as<UnaryNode>();
11821 typenameNode = &left->as<NameNode>();
11822
11823 if (node->isKind(ParseNodeKind::LtExpr)) {
11824 op = JSOp::Eq;
11825 } else {
11826 op = JSOp::Ne;
11827 }
11828 } else {
11829 *emitted = false;
11830 return true;
11831 }
11832
11833 TaggedParserAtomIndex typeName = typenameNode->atom();
11834 if (typeName.isLength1StaticParserString() &&
11835 typeName.toLength1StaticParserString() ==
11836 Length1StaticParserString('u')) {
11837 type = JSTYPE_UNDEFINED;
11838 } else {
11839 *emitted = false;
11840 return true;
11841 }
11842 } else {
11843 if (node->isKind(ParseNodeKind::StrictEqExpr) ||
11844 node->isKind(ParseNodeKind::EqExpr)) {
11845 op = JSOp::Eq;
11846 } else {
11847 op = JSOp::Ne;
11848 }
11849
11850 // NOTE: ParseNodeKind::TypeOfExpr cannot use JSOp::TypeofEq.
11851 // See JSOp::GetName document.
11852 if (left->isKind(ParseNodeKind::TypeOfNameExpr) &&
11853 right->isKind(ParseNodeKind::StringExpr)) {
11854 typeofNode = &left->as<UnaryNode>();
11855 typenameNode = &right->as<NameNode>();
11856 } else if (right->isKind(ParseNodeKind::TypeOfNameExpr) &&
11857 left->isKind(ParseNodeKind::StringExpr)) {
11858 typeofNode = &right->as<UnaryNode>();
11859 typenameNode = &left->as<NameNode>();
11860 } else {
11861 *emitted = false;
11862 return true;
11863 }
11864
11865 TaggedParserAtomIndex typeName = typenameNode->atom();
11866 if (typeName == TaggedParserAtomIndex::WellKnown::undefined()) {
11867 type = JSTYPE_UNDEFINED;
11868 } else if (typeName == TaggedParserAtomIndex::WellKnown::object()) {
11869 type = JSTYPE_OBJECT;
11870 } else if (typeName == TaggedParserAtomIndex::WellKnown::function()) {
11871 type = JSTYPE_FUNCTION;
11872 } else if (typeName == TaggedParserAtomIndex::WellKnown::string()) {
11873 type = JSTYPE_STRING;
11874 } else if (typeName == TaggedParserAtomIndex::WellKnown::number()) {
11875 type = JSTYPE_NUMBER;
11876 } else if (typeName == TaggedParserAtomIndex::WellKnown::boolean()) {
11877 type = JSTYPE_BOOLEAN;
11878 } else if (typeName == TaggedParserAtomIndex::WellKnown::symbol()) {
11879 type = JSTYPE_SYMBOL;
11880 } else if (typeName == TaggedParserAtomIndex::WellKnown::bigint()) {
11881 type = JSTYPE_BIGINT;
11882 } else {
11883 *emitted = false;
11884 return true;
11885 }
11886 }
11887
11888 if (!updateSourceCoordNotes(typeofNode->pn_pos.begin)) {
11889 return false;
11890 }
11891
11892 if (!emitTree(typeofNode->kid())) {
11893 // [stack] VAL
11894 return false;
11895 }
11896
11897 if (!emit2(JSOp::TypeofEq, TypeofEqOperand(type, op).rawValue())) {
11898 // [stack] CMP
11899 return false;
11900 }
11901
11902 *emitted = true;
11903 return true;
11904}
11905
11906bool BytecodeEmitter::emitFunctionFormalParameters(ParamsBodyNode* paramsBody) {
11907 FunctionBox* funbox = sc->asFunctionBox();
11908
11909 bool hasRest = funbox->hasRest();
11910
11911 FunctionParamsEmitter fpe(this, funbox);
11912 for (ParseNode* arg : paramsBody->parameters()) {
11913 ParseNode* bindingElement = arg;
11914 ParseNode* initializer = nullptr;
11915 if (arg->isKind(ParseNodeKind::AssignExpr)) {
11916 bindingElement = arg->as<BinaryNode>().left();
11917 initializer = arg->as<BinaryNode>().right();
11918 }
11919 bool hasInitializer = !!initializer;
11920 bool isRest =
11921 hasRest && arg->pn_next == *std::end(paramsBody->parameters());
11922 bool isDestructuring = !bindingElement->isKind(ParseNodeKind::Name);
11923
11924 // Left-hand sides are either simple names or destructuring patterns.
11925 MOZ_ASSERT(bindingElement->isKind(ParseNodeKind::Name) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bindingElement->isKind(ParseNodeKind::Name) || bindingElement
->isKind(ParseNodeKind::ArrayExpr) || bindingElement->isKind
(ParseNodeKind::ObjectExpr))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(bindingElement->isKind(ParseNodeKind
::Name) || bindingElement->isKind(ParseNodeKind::ArrayExpr
) || bindingElement->isKind(ParseNodeKind::ObjectExpr)))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("bindingElement->isKind(ParseNodeKind::Name) || bindingElement->isKind(ParseNodeKind::ArrayExpr) || bindingElement->isKind(ParseNodeKind::ObjectExpr)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 11927)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "bindingElement->isKind(ParseNodeKind::Name) || bindingElement->isKind(ParseNodeKind::ArrayExpr) || bindingElement->isKind(ParseNodeKind::ObjectExpr)"
")"); do { MOZ_CrashSequence(__null, 11927); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11926 bindingElement->isKind(ParseNodeKind::ArrayExpr) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bindingElement->isKind(ParseNodeKind::Name) || bindingElement
->isKind(ParseNodeKind::ArrayExpr) || bindingElement->isKind
(ParseNodeKind::ObjectExpr))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(bindingElement->isKind(ParseNodeKind
::Name) || bindingElement->isKind(ParseNodeKind::ArrayExpr
) || bindingElement->isKind(ParseNodeKind::ObjectExpr)))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("bindingElement->isKind(ParseNodeKind::Name) || bindingElement->isKind(ParseNodeKind::ArrayExpr) || bindingElement->isKind(ParseNodeKind::ObjectExpr)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 11927)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "bindingElement->isKind(ParseNodeKind::Name) || bindingElement->isKind(ParseNodeKind::ArrayExpr) || bindingElement->isKind(ParseNodeKind::ObjectExpr)"
")"); do { MOZ_CrashSequence(__null, 11927); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11927 bindingElement->isKind(ParseNodeKind::ObjectExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bindingElement->isKind(ParseNodeKind::Name) || bindingElement
->isKind(ParseNodeKind::ArrayExpr) || bindingElement->isKind
(ParseNodeKind::ObjectExpr))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(bindingElement->isKind(ParseNodeKind
::Name) || bindingElement->isKind(ParseNodeKind::ArrayExpr
) || bindingElement->isKind(ParseNodeKind::ObjectExpr)))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("bindingElement->isKind(ParseNodeKind::Name) || bindingElement->isKind(ParseNodeKind::ArrayExpr) || bindingElement->isKind(ParseNodeKind::ObjectExpr)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 11927)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "bindingElement->isKind(ParseNodeKind::Name) || bindingElement->isKind(ParseNodeKind::ArrayExpr) || bindingElement->isKind(ParseNodeKind::ObjectExpr)"
")"); do { MOZ_CrashSequence(__null, 11927); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11928
11929 auto emitDefaultInitializer = [this, &initializer, &bindingElement]() {
11930 // [stack]
11931
11932 if (!this->emitInitializer(initializer, bindingElement)) {
11933 // [stack] DEFAULT
11934 return false;
11935 }
11936 return true;
11937 };
11938
11939 auto emitDestructuring = [this, &bindingElement]() {
11940 // [stack] ARG
11941
11942 if (!this->emitDestructuringOps(&bindingElement->as<ListNode>(),
11943 DestructuringFlavor::Declaration,
11944 SelfHostedIter::Deny)) {
11945 // [stack] ARG
11946 return false;
11947 }
11948
11949 return true;
11950 };
11951
11952 if (isRest) {
11953 if (isDestructuring) {
11954 if (!fpe.prepareForDestructuringRest()) {
11955 // [stack]
11956 return false;
11957 }
11958 if (!emitDestructuring()) {
11959 // [stack]
11960 return false;
11961 }
11962 if (!fpe.emitDestructuringRestEnd()) {
11963 // [stack]
11964 return false;
11965 }
11966 } else {
11967 auto paramName = bindingElement->as<NameNode>().name();
11968 if (!fpe.emitRest(paramName)) {
11969 // [stack]
11970 return false;
11971 }
11972 }
11973
11974 continue;
11975 }
11976
11977 if (isDestructuring) {
11978 if (hasInitializer) {
11979 if (!fpe.prepareForDestructuringDefaultInitializer()) {
11980 // [stack]
11981 return false;
11982 }
11983 if (!emitDefaultInitializer()) {
11984 // [stack]
11985 return false;
11986 }
11987 if (!fpe.prepareForDestructuringDefault()) {
11988 // [stack]
11989 return false;
11990 }
11991 if (!emitDestructuring()) {
11992 // [stack]
11993 return false;
11994 }
11995 if (!fpe.emitDestructuringDefaultEnd()) {
11996 // [stack]
11997 return false;
11998 }
11999 } else {
12000 if (!fpe.prepareForDestructuring()) {
12001 // [stack]
12002 return false;
12003 }
12004 if (!emitDestructuring()) {
12005 // [stack]
12006 return false;
12007 }
12008 if (!fpe.emitDestructuringEnd()) {
12009 // [stack]
12010 return false;
12011 }
12012 }
12013
12014 continue;
12015 }
12016
12017 if (hasInitializer) {
12018 if (!fpe.prepareForDefault()) {
12019 // [stack]
12020 return false;
12021 }
12022 if (!emitDefaultInitializer()) {
12023 // [stack]
12024 return false;
12025 }
12026 auto paramName = bindingElement->as<NameNode>().name();
12027 if (!fpe.emitDefaultEnd(paramName)) {
12028 // [stack]
12029 return false;
12030 }
12031
12032 continue;
12033 }
12034
12035 auto paramName = bindingElement->as<NameNode>().name();
12036 if (!fpe.emitSimple(paramName)) {
12037 // [stack]
12038 return false;
12039 }
12040 }
12041
12042 return true;
12043}
12044
12045bool BytecodeEmitter::emitInitializeFunctionSpecialNames() {
12046 FunctionBox* funbox = sc->asFunctionBox();
12047
12048 // [stack]
12049
12050 auto emitInitializeFunctionSpecialName =
12051 [](BytecodeEmitter* bce, TaggedParserAtomIndex name, JSOp op) {
12052 // A special name must be slotful, either on the frame or on the
12053 // call environment.
12054 MOZ_ASSERT(bce->lookupName(name).hasKnownSlot())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bce->lookupName(name).hasKnownSlot())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(bce->lookupName(name).hasKnownSlot()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("bce->lookupName(name).hasKnownSlot()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 12054)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "bce->lookupName(name).hasKnownSlot()"
")"); do { MOZ_CrashSequence(__null, 12054); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12055
12056 NameOpEmitter noe(bce, name, NameOpEmitter::Kind::Initialize);
12057 if (!noe.prepareForRhs()) {
12058 // [stack]
12059 return false;
12060 }
12061 if (!bce->emit1(op)) {
12062 // [stack] THIS/ARGUMENTS/NEW.TARGET
12063 return false;
12064 }
12065 if (!noe.emitAssignment()) {
12066 // [stack] THIS/ARGUMENTS/NEW.TARGET
12067 return false;
12068 }
12069 if (!bce->emit1(JSOp::Pop)) {
12070 // [stack]
12071 return false;
12072 }
12073
12074 return true;
12075 };
12076
12077 // Do nothing if the function doesn't have an arguments binding.
12078 if (funbox->needsArgsObj()) {
12079 // Self-hosted code should use the more efficient ArgumentsLength and
12080 // GetArgument intrinsics instead of `arguments`.
12081 MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(emitterMode != BytecodeEmitter::SelfHosting)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(emitterMode != BytecodeEmitter::SelfHosting))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("emitterMode != BytecodeEmitter::SelfHosting"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 12081)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode != BytecodeEmitter::SelfHosting"
")"); do { MOZ_CrashSequence(__null, 12081); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12082 if (!emitInitializeFunctionSpecialName(
12083 this, TaggedParserAtomIndex::WellKnown::arguments(),
12084 JSOp::Arguments)) {
12085 // [stack]
12086 return false;
12087 }
12088 }
12089
12090 // Do nothing if the function doesn't have a this-binding (this
12091 // happens for instance if it doesn't use this/eval or if it's an
12092 // arrow function).
12093 if (funbox->functionHasThisBinding()) {
12094 if (!emitInitializeFunctionSpecialName(
12095 this, TaggedParserAtomIndex::WellKnown::dot_this_(),
12096 JSOp::FunctionThis)) {
12097 return false;
12098 }
12099 }
12100
12101 // Do nothing if the function doesn't have a new.target-binding (this happens
12102 // for instance if it doesn't use new.target/eval or if it's an arrow
12103 // function).
12104 if (funbox->functionHasNewTargetBinding()) {
12105 if (!emitInitializeFunctionSpecialName(
12106 this, TaggedParserAtomIndex::WellKnown::dot_newTarget_(),
12107 JSOp::NewTarget)) {
12108 return false;
12109 }
12110 }
12111
12112 // Do nothing if the function doesn't implicitly return a promise result.
12113 if (funbox->needsPromiseResult()) {
12114 if (!emitInitializeFunctionSpecialName(
12115 this, TaggedParserAtomIndex::WellKnown::dot_generator_(),
12116 JSOp::Generator)) {
12117 // [stack]
12118 return false;
12119 }
12120 }
12121 return true;
12122}
12123
12124bool BytecodeEmitter::emitLexicalInitialization(NameNode* name) {
12125 return emitLexicalInitialization(name->name());
12126}
12127
12128bool BytecodeEmitter::emitLexicalInitialization(TaggedParserAtomIndex name) {
12129 NameOpEmitter noe(this, name, NameOpEmitter::Kind::Initialize);
12130 if (!noe.prepareForRhs()) {
12131 return false;
12132 }
12133
12134 // The caller has pushed the RHS to the top of the stack. Assert that the
12135 // binding can be initialized without a binding object on the stack, and that
12136 // no JSOp::BindUnqualifiedName or JSOp::BindUnqualifiedGName ops were
12137 // emitted.
12138 MOZ_ASSERT(noe.loc().isLexical() || noe.loc().isSynthetic() ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(noe.loc().isLexical() || noe.loc().isSynthetic() || noe
.loc().isPrivateMethod())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(noe.loc().isLexical() || noe
.loc().isSynthetic() || noe.loc().isPrivateMethod()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("noe.loc().isLexical() || noe.loc().isSynthetic() || noe.loc().isPrivateMethod()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 12139)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "noe.loc().isLexical() || noe.loc().isSynthetic() || noe.loc().isPrivateMethod()"
")"); do { MOZ_CrashSequence(__null, 12139); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12139 noe.loc().isPrivateMethod())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(noe.loc().isLexical() || noe.loc().isSynthetic() || noe
.loc().isPrivateMethod())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(noe.loc().isLexical() || noe
.loc().isSynthetic() || noe.loc().isPrivateMethod()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("noe.loc().isLexical() || noe.loc().isSynthetic() || noe.loc().isPrivateMethod()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 12139)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "noe.loc().isLexical() || noe.loc().isSynthetic() || noe.loc().isPrivateMethod()"
")"); do { MOZ_CrashSequence(__null, 12139); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12140 MOZ_ASSERT(!noe.emittedBindOp())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!noe.emittedBindOp())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!noe.emittedBindOp()))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("!noe.emittedBindOp()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 12140)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "!noe.emittedBindOp()"
")"); do { MOZ_CrashSequence(__null, 12140); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12141
12142 if (!noe.emitAssignment()) {
12143 return false;
12144 }
12145
12146 return true;
12147}
12148
12149static MOZ_ALWAYS_INLINEinline ParseNode* FindConstructor(ListNode* classMethods) {
12150 for (ParseNode* classElement : classMethods->contents()) {
12151 ParseNode* unwrappedElement = classElement;
12152 if (unwrappedElement->is<LexicalScopeNode>()) {
12153 unwrappedElement = unwrappedElement->as<LexicalScopeNode>().scopeBody();
12154 }
12155 if (unwrappedElement->is<ClassMethod>()) {
12156 ClassMethod& method = unwrappedElement->as<ClassMethod>();
12157 ParseNode& methodName = method.name();
12158 if (!method.isStatic() &&
12159 (methodName.isKind(ParseNodeKind::ObjectPropertyName) ||
12160 methodName.isKind(ParseNodeKind::StringExpr)) &&
12161 methodName.as<NameNode>().atom() ==
12162 TaggedParserAtomIndex::WellKnown::constructor()) {
12163 return classElement;
12164 }
12165 }
12166 }
12167 return nullptr;
12168}
12169
12170bool BytecodeEmitter::emitNewPrivateName(TaggedParserAtomIndex bindingName,
12171 TaggedParserAtomIndex symbolName) {
12172 if (!emitAtomOp(JSOp::NewPrivateName, symbolName)) {
12173 // [stack] HERITAGE PRIVATENAME
12174 return false;
12175 }
12176
12177 // Add a binding for #name => privatename
12178 if (!emitLexicalInitialization(bindingName)) {
12179 // [stack] HERITAGE PRIVATENAME
12180 return false;
12181 }
12182
12183 // Pop Private name off the stack.
12184 if (!emit1(JSOp::Pop)) {
12185 // [stack] HERITAGE
12186 return false;
12187 }
12188
12189 return true;
12190}
12191
12192bool BytecodeEmitter::emitNewPrivateNames(
12193 TaggedParserAtomIndex privateBrandName, ListNode* classMembers) {
12194 bool hasPrivateBrand = false;
12195
12196 for (ParseNode* classElement : classMembers->contents()) {
12197 ParseNode* elementName;
12198 if (classElement->is<ClassMethod>()) {
12199 elementName = &classElement->as<ClassMethod>().name();
12200 } else if (classElement->is<ClassField>()) {
12201 elementName = &classElement->as<ClassField>().name();
12202 } else {
12203 continue;
12204 }
12205
12206 if (!elementName->isKind(ParseNodeKind::PrivateName)) {
12207 continue;
12208 }
12209
12210 // Non-static private methods' private names are optimized away.
12211 bool isOptimized = false;
12212 if (classElement->is<ClassMethod>() &&
12213 !classElement->as<ClassMethod>().isStatic()) {
12214 hasPrivateBrand = true;
12215 if (classElement->as<ClassMethod>().accessorType() ==
12216 AccessorType::None) {
12217 isOptimized = true;
12218 }
12219 }
12220
12221 if (!isOptimized) {
12222 auto privateName = elementName->as<NameNode>().name();
12223 if (!emitNewPrivateName(privateName, privateName)) {
12224 return false;
12225 }
12226 }
12227 }
12228
12229 if (hasPrivateBrand) {
12230 // We don't make a private name for every optimized method, but we need one
12231 // private name per class, the `.privateBrand`.
12232 if (!emitNewPrivateName(
12233 TaggedParserAtomIndex::WellKnown::dot_privateBrand_(),
12234 privateBrandName)) {
12235 return false;
12236 }
12237 }
12238 return true;
12239}
12240
12241// This follows ES6 14.5.14 (ClassDefinitionEvaluation) and ES6 14.5.15
12242// (BindingClassDeclarationEvaluation).
12243bool BytecodeEmitter::emitClass(
12244 ClassNode* classNode,
12245 ClassNameKind nameKind /* = ClassNameKind::BindingName */,
12246 TaggedParserAtomIndex
12247 nameForAnonymousClass /* = TaggedParserAtomIndex::null() */) {
12248 MOZ_ASSERT((nameKind == ClassNameKind::InferredName) ==do { static_assert( mozilla::detail::AssertionConditionType<
decltype((nameKind == ClassNameKind::InferredName) == bool(nameForAnonymousClass
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!((nameKind == ClassNameKind::InferredName) == bool(nameForAnonymousClass
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("(nameKind == ClassNameKind::InferredName) == bool(nameForAnonymousClass)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 12249)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "(nameKind == ClassNameKind::InferredName) == bool(nameForAnonymousClass)"
")"); do { MOZ_CrashSequence(__null, 12249); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12249 bool(nameForAnonymousClass))do { static_assert( mozilla::detail::AssertionConditionType<
decltype((nameKind == ClassNameKind::InferredName) == bool(nameForAnonymousClass
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!((nameKind == ClassNameKind::InferredName) == bool(nameForAnonymousClass
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("(nameKind == ClassNameKind::InferredName) == bool(nameForAnonymousClass)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 12249)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "(nameKind == ClassNameKind::InferredName) == bool(nameForAnonymousClass)"
")"); do { MOZ_CrashSequence(__null, 12249); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12250
12251 ParseNode* heritageExpression = classNode->heritage();
12252 ListNode* classMembers = classNode->memberList();
12253 ParseNode* constructor = FindConstructor(classMembers);
12254
12255 // If |nameKind != ClassNameKind::ComputedName|
12256 // [stack]
12257 // Else
12258 // [stack] NAME
12259
12260 ClassEmitter ce(this);
12261 TaggedParserAtomIndex innerName;
12262 ClassEmitter::Kind kind = ClassEmitter::Kind::Expression;
12263 if (ClassNames* names = classNode->names()) {
12264 MOZ_ASSERT(nameKind == ClassNameKind::BindingName)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(nameKind == ClassNameKind::BindingName)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(nameKind == ClassNameKind::BindingName))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("nameKind == ClassNameKind::BindingName"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 12264)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "nameKind == ClassNameKind::BindingName"
")"); do { MOZ_CrashSequence(__null, 12264); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12265 innerName = names->innerBinding()->name();
12266 MOZ_ASSERT(innerName)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(innerName)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(innerName))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("innerName", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 12266); AnnotateMozCrashReason("MOZ_ASSERT" "(" "innerName"
")"); do { MOZ_CrashSequence(__null, 12266); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12267
12268 if (names->outerBinding()) {
12269 MOZ_ASSERT(names->outerBinding()->name())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(names->outerBinding()->name())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(names->outerBinding()->
name()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("names->outerBinding()->name()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 12269); AnnotateMozCrashReason("MOZ_ASSERT" "(" "names->outerBinding()->name()"
")"); do { MOZ_CrashSequence(__null, 12269); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12270 MOZ_ASSERT(names->outerBinding()->name() == innerName)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(names->outerBinding()->name() == innerName)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(names->outerBinding()->name() == innerName))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("names->outerBinding()->name() == innerName"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 12270)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "names->outerBinding()->name() == innerName"
")"); do { MOZ_CrashSequence(__null, 12270); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12271 kind = ClassEmitter::Kind::Declaration;
12272 }
12273 }
12274
12275 if (LexicalScopeNode* scopeBindings = classNode->scopeBindings()) {
12276 if (!ce.emitScope(scopeBindings->scopeBindings())) {
12277 // [stack]
12278 return false;
12279 }
12280 }
12281
12282 bool isDerived = !!heritageExpression;
12283 if (isDerived) {
12284 if (!updateSourceCoordNotes(classNode->pn_pos.begin)) {
12285 return false;
12286 }
12287 if (!markStepBreakpoint()) {
12288 return false;
12289 }
12290 if (!emitTree(heritageExpression)) {
12291 // [stack] HERITAGE
12292 return false;
12293 }
12294 }
12295
12296 // The class body scope holds any private names. Those mustn't be visible in
12297 // the heritage expression and hence the scope must be emitted after the
12298 // heritage expression.
12299 if (ClassBodyScopeNode* bodyScopeBindings = classNode->bodyScopeBindings()) {
12300 if (!ce.emitBodyScope(bodyScopeBindings->scopeBindings())) {
12301 // [stack] HERITAGE
12302 return false;
12303 }
12304
12305 // The spec does not say anything about private brands being symbols. It's
12306 // an implementation detail. So we can give the special private brand
12307 // symbol any description we want and users won't normally see it. For
12308 // debugging, use the class name.
12309 auto privateBrandName = innerName;
12310 if (!innerName) {
12311 privateBrandName = nameForAnonymousClass
12312 ? nameForAnonymousClass
12313 : TaggedParserAtomIndex::WellKnown::anonymous();
12314 }
12315 if (!emitNewPrivateNames(privateBrandName, classMembers)) {
12316 return false;
12317 }
12318 }
12319
12320 bool hasNameOnStack = nameKind == ClassNameKind::ComputedName;
12321 if (isDerived) {
12322 if (!ce.emitDerivedClass(innerName, nameForAnonymousClass,
12323 hasNameOnStack)) {
12324 // [stack] HOMEOBJ HERITAGE
12325 return false;
12326 }
12327 } else {
12328 int membersCount = 0;
12329 for (ParseNode* node : classMembers->contents()) {
12330 if (node->getKind() == ParseNodeKind::ClassField) {
12331 membersCount++;
12332 }
12333 }
12334 membersCount = (membersCount > 255) ? 255 : membersCount;
12335 if (!ce.emitClass(innerName, nameForAnonymousClass, hasNameOnStack,
12336 uint8_t(membersCount))) {
12337 // [stack] HOMEOBJ
12338 return false;
12339 }
12340 }
12341
12342 // Stack currently has HOMEOBJ followed by optional HERITAGE. When HERITAGE
12343 // is not used, an implicit value of %FunctionPrototype% is implied.
12344
12345 // See |Parser::classMember(...)| for the reason why |.initializers| is
12346 // created within its own scope.
12347 Maybe<LexicalScopeEmitter> lse;
12348 FunctionNode* ctor;
12349#ifdef ENABLE_DECORATORS
12350 bool extraInitializersPresent = false;
12351#endif
12352 if (constructor->is<LexicalScopeNode>()) {
12353 LexicalScopeNode* constructorScope = &constructor->as<LexicalScopeNode>();
12354
12355 MOZ_ASSERT(!constructorScope->isEmptyScope())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!constructorScope->isEmptyScope())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!constructorScope->isEmptyScope
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!constructorScope->isEmptyScope()", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 12355); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!constructorScope->isEmptyScope()"
")"); do { MOZ_CrashSequence(__null, 12355); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12356#ifdef ENABLE_DECORATORS
12357 // With decorators enabled we expect to see |.initializers|,
12358 // and |.instanceExtraInitializers| in this scope.
12359 MOZ_ASSERT(constructorScope->scopeBindings()->length == 2)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(constructorScope->scopeBindings()->length == 2
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(constructorScope->scopeBindings()->length == 2
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"constructorScope->scopeBindings()->length == 2", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 12359); AnnotateMozCrashReason("MOZ_ASSERT" "(" "constructorScope->scopeBindings()->length == 2"
")"); do { MOZ_CrashSequence(__null, 12359); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12360 MOZ_ASSERT(GetScopeDataTrailingNames(constructorScope->scopeBindings())[0]do { static_assert( mozilla::detail::AssertionConditionType<
decltype(GetScopeDataTrailingNames(constructorScope->scopeBindings
())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(GetScopeDataTrailingNames(constructorScope->scopeBindings
())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 12362)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()"
")"); do { MOZ_CrashSequence(__null, 12362); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12361 .name() ==do { static_assert( mozilla::detail::AssertionConditionType<
decltype(GetScopeDataTrailingNames(constructorScope->scopeBindings
())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(GetScopeDataTrailingNames(constructorScope->scopeBindings
())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 12362)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()"
")"); do { MOZ_CrashSequence(__null, 12362); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12362 TaggedParserAtomIndex::WellKnown::dot_initializers_())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(GetScopeDataTrailingNames(constructorScope->scopeBindings
())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(GetScopeDataTrailingNames(constructorScope->scopeBindings
())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 12362)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()"
")"); do { MOZ_CrashSequence(__null, 12362); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12363 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(GetScopeDataTrailingNames(constructorScope->scopeBindings
())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(GetScopeDataTrailingNames(constructorScope->scopeBindings
())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("GetScopeDataTrailingNames(constructorScope->scopeBindings())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 12366)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_()"
")"); do { MOZ_CrashSequence(__null, 12366); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12364 GetScopeDataTrailingNames(constructorScope->scopeBindings())[1]do { static_assert( mozilla::detail::AssertionConditionType<
decltype(GetScopeDataTrailingNames(constructorScope->scopeBindings
())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(GetScopeDataTrailingNames(constructorScope->scopeBindings
())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("GetScopeDataTrailingNames(constructorScope->scopeBindings())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 12366)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_()"
")"); do { MOZ_CrashSequence(__null, 12366); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12365 .name() ==do { static_assert( mozilla::detail::AssertionConditionType<
decltype(GetScopeDataTrailingNames(constructorScope->scopeBindings
())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(GetScopeDataTrailingNames(constructorScope->scopeBindings
())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("GetScopeDataTrailingNames(constructorScope->scopeBindings())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 12366)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_()"
")"); do { MOZ_CrashSequence(__null, 12366); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12366 TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(GetScopeDataTrailingNames(constructorScope->scopeBindings
())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(GetScopeDataTrailingNames(constructorScope->scopeBindings
())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("GetScopeDataTrailingNames(constructorScope->scopeBindings())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 12366)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_()"
")"); do { MOZ_CrashSequence(__null, 12366); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12367
12368 // We should only call this code if we know decorators are present, see bug
12369 // 1871147.
12370 lse.emplace(this);
12371 if (!lse->emitScope(ScopeKind::Lexical,
12372 constructorScope->scopeBindings())) {
12373 return false;
12374 }
12375
12376 // TODO: See bug 1868220 for support for static extra initializers.
12377 if (!ce.prepareForExtraInitializers(TaggedParserAtomIndex::WellKnown::
12378 dot_instanceExtraInitializers_())) {
12379 return false;
12380 }
12381
12382 if (classNode->addInitializerFunction()) {
12383 DecoratorEmitter de(this);
12384 if (!de.emitCreateAddInitializerFunction(
12385 classNode->addInitializerFunction(),
12386 TaggedParserAtomIndex::WellKnown::
12387 dot_instanceExtraInitializers_())) {
12388 // [stack] HOMEOBJ HERITAGE? ADDINIT
12389 return false;
12390 }
12391
12392 if (!emitUnpickN(isDerived ? 2 : 1)) {
12393 // [stack] ADDINIT HOMEOBJ HERITAGE?
12394 return false;
12395 }
12396
12397 extraInitializersPresent = true;
12398 }
12399#else
12400 // The constructor scope should only contain the |.initializers| binding.
12401 MOZ_ASSERT(constructorScope->scopeBindings()->length == 1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(constructorScope->scopeBindings()->length == 1
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(constructorScope->scopeBindings()->length == 1
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"constructorScope->scopeBindings()->length == 1", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 12401); AnnotateMozCrashReason("MOZ_ASSERT" "(" "constructorScope->scopeBindings()->length == 1"
")"); do { MOZ_CrashSequence(__null, 12401); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12402 MOZ_ASSERT(GetScopeDataTrailingNames(constructorScope->scopeBindings())[0]do { static_assert( mozilla::detail::AssertionConditionType<
decltype(GetScopeDataTrailingNames(constructorScope->scopeBindings
())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(GetScopeDataTrailingNames(constructorScope->scopeBindings
())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 12404)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()"
")"); do { MOZ_CrashSequence(__null, 12404); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12403 .name() ==do { static_assert( mozilla::detail::AssertionConditionType<
decltype(GetScopeDataTrailingNames(constructorScope->scopeBindings
())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(GetScopeDataTrailingNames(constructorScope->scopeBindings
())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 12404)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()"
")"); do { MOZ_CrashSequence(__null, 12404); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12404 TaggedParserAtomIndex::WellKnown::dot_initializers_())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(GetScopeDataTrailingNames(constructorScope->scopeBindings
())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(GetScopeDataTrailingNames(constructorScope->scopeBindings
())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 12404)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()"
")"); do { MOZ_CrashSequence(__null, 12404); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12405#endif
12406
12407 auto needsInitializer = [](ParseNode* propdef) {
12408 return NeedsFieldInitializer(propdef, false) ||
12409 NeedsAccessorInitializer(propdef, false);
12410 };
12411
12412 // As an optimization omit the |.initializers| binding when no instance
12413 // fields or private methods are present.
12414 bool needsInitializers =
12415 std::any_of(classMembers->contents().begin(),
12416 classMembers->contents().end(), needsInitializer);
12417 if (needsInitializers) {
12418#ifndef ENABLE_DECORATORS
12419 lse.emplace(this);
12420 if (!lse->emitScope(ScopeKind::Lexical,
12421 constructorScope->scopeBindings())) {
12422 return false;
12423 }
12424#endif
12425 // Any class with field initializers will have a constructor
12426 if (!emitCreateMemberInitializers(ce, classMembers,
12427 FieldPlacement::Instance
12428#ifdef ENABLE_DECORATORS
12429 ,
12430 isDerived
12431#endif
12432 )) {
12433 return false;
12434 }
12435 }
12436
12437 ctor = &constructorScope->scopeBody()->as<ClassMethod>().method();
12438 } else {
12439 // The |.initializers| binding is never emitted when in self-hosting mode.
12440 MOZ_ASSERT(emitterMode == BytecodeEmitter::SelfHosting)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(emitterMode == BytecodeEmitter::SelfHosting)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(emitterMode == BytecodeEmitter::SelfHosting))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("emitterMode == BytecodeEmitter::SelfHosting"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 12440)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode == BytecodeEmitter::SelfHosting"
")"); do { MOZ_CrashSequence(__null, 12440); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12441 ctor = &constructor->as<ClassMethod>().method();
12442 }
12443
12444 bool needsHomeObject = ctor->funbox()->needsHomeObject();
12445 // HERITAGE is consumed inside emitFunction.
12446 if (nameKind == ClassNameKind::InferredName) {
12447 setFunName(ctor->funbox(), nameForAnonymousClass);
12448 }
12449 if (!emitFunction(ctor, isDerived)) {
12450 // [stack] HOMEOBJ CTOR
12451 return false;
12452 }
12453 if (lse.isSome()) {
12454 if (!lse->emitEnd()) {
12455 return false;
12456 }
12457 lse.reset();
12458 }
12459 if (!ce.emitInitConstructor(needsHomeObject)) {
12460 // [stack] CTOR HOMEOBJ
12461 return false;
12462 }
12463
12464 if (!emitCreateFieldKeys(classMembers, FieldPlacement::Instance)) {
12465 return false;
12466 }
12467
12468#ifdef ENABLE_DECORATORS
12469 // TODO: See Bug 1868220 for support for static extra initializers.
12470 if (!emit1(JSOp::Undefined)) {
12471 // [stack] ADDINIT? CTOR HOMEOBJ UNDEFINED
12472 return false;
12473 }
12474 if (!emitUnpickN(2)) {
12475 // [stack] ADDINIT? UNDEFINED CTOR HOMEOBJ
12476 return false;
12477 }
12478#endif
12479
12480 if (!emitCreateMemberInitializers(ce, classMembers, FieldPlacement::Static
12481#ifdef ENABLE_DECORATORS
12482 ,
12483 false
12484#endif
12485 )) {
12486 return false;
12487 }
12488
12489#ifdef ENABLE_DECORATORS
12490 if (!emitPickN(2)) {
12491 // [stack] ADDINIT? CTOR HOMEOBJ UNDEFINED
12492 return false;
12493 }
12494 if (!emitPopN(1)) {
12495 // [stack] ADDINIT? CTOR HOMEOBJ
12496 return false;
12497 }
12498#endif
12499
12500 if (!emitCreateFieldKeys(classMembers, FieldPlacement::Static)) {
12501 return false;
12502 }
12503
12504 if (!emitPropertyList(classMembers, ce, ClassBody)) {
12505 // [stack] CTOR HOMEOBJ
12506 return false;
12507 }
12508
12509#ifdef ENABLE_DECORATORS
12510 if (extraInitializersPresent) {
12511 if (!emitPickN(2)) {
12512 // [stack] CTOR HOMEOBJ ADDINIT
12513 return false;
12514 }
12515 if (!emitPopN(1)) {
12516 // [stack] CTOR HOMEOBJ
12517 return false;
12518 }
12519 }
12520#endif
12521
12522 if (!ce.emitBinding()) {
12523 // [stack] CTOR
12524 return false;
12525 }
12526
12527 if (!emitInitializeStaticFields(classMembers)) {
12528 // [stack] CTOR
12529 return false;
12530 }
12531
12532#if ENABLE_DECORATORS
12533 if (!ce.prepareForDecorators()) {
12534 // [stack] CTOR
12535 return false;
12536 }
12537 if (classNode->decorators() != nullptr) {
12538 DecoratorEmitter de(this);
12539 NameNode* className =
12540 classNode->names() ? classNode->names()->innerBinding() : nullptr;
12541 if (!de.emitApplyDecoratorsToClassDefinition(className,
12542 classNode->decorators())) {
12543 // [stack] CTOR
12544 return false;
12545 }
12546 }
12547#endif
12548
12549 if (!ce.emitEnd(kind)) {
12550 // [stack] # class declaration
12551 // [stack]
12552 // [stack] # class expression
12553 // [stack] CTOR
12554 return false;
12555 }
12556
12557 return true;
12558}
12559
12560bool BytecodeEmitter::emitExportDefault(BinaryNode* exportNode) {
12561 MOZ_ASSERT(exportNode->isKind(ParseNodeKind::ExportDefaultStmt))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(exportNode->isKind(ParseNodeKind::ExportDefaultStmt
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(exportNode->isKind(ParseNodeKind::ExportDefaultStmt
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("exportNode->isKind(ParseNodeKind::ExportDefaultStmt)", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 12561); AnnotateMozCrashReason("MOZ_ASSERT" "(" "exportNode->isKind(ParseNodeKind::ExportDefaultStmt)"
")"); do { MOZ_CrashSequence(__null, 12561); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12562
12563 ParseNode* valueNode = exportNode->left();
12564 if (valueNode->isDirectRHSAnonFunction()) {
12565 MOZ_ASSERT(exportNode->right())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(exportNode->right())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(exportNode->right()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("exportNode->right()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 12565)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "exportNode->right()"
")"); do { MOZ_CrashSequence(__null, 12565); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12566
12567 if (!emitAnonymousFunctionWithName(
12568 valueNode, TaggedParserAtomIndex::WellKnown::default_())) {
12569 return false;
12570 }
12571 } else {
12572 if (!emitTree(valueNode)) {
12573 return false;
12574 }
12575 }
12576
12577 if (ParseNode* binding = exportNode->right()) {
12578 if (!emitLexicalInitialization(&binding->as<NameNode>())) {
12579 return false;
12580 }
12581
12582 if (!emit1(JSOp::Pop)) {
12583 return false;
12584 }
12585 }
12586
12587 return true;
12588}
12589
12590bool BytecodeEmitter::emitTree(
12591 ParseNode* pn, ValueUsage valueUsage /* = ValueUsage::WantValue */,
12592 EmitLineNumberNote emitLineNote /* = EMIT_LINENOTE */) {
12593 AutoCheckRecursionLimit recursion(fc);
12594 if (!recursion.check(fc)) {
12595 return false;
12596 }
12597
12598 /* Emit notes to tell the current bytecode's source line number.
12599 However, a couple trees require special treatment; see the
12600 relevant emitter functions for details. */
12601 if (emitLineNote == EMIT_LINENOTE &&
12602 !ParseNodeRequiresSpecialLineNumberNotes(pn)) {
12603 if (!updateLineNumberNotes(pn->pn_pos.begin)) {
12604 return false;
12605 }
12606 }
12607
12608 switch (pn->getKind()) {
12609 case ParseNodeKind::Function:
12610 if (!emitFunction(&pn->as<FunctionNode>())) {
12611 return false;
12612 }
12613 break;
12614
12615 case ParseNodeKind::ParamsBody:
12616 MOZ_ASSERT_UNREACHABLE(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"ParamsBody should be handled in emitFunctionScript." ")", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 12617); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "ParamsBody should be handled in emitFunctionScript."
")"); do { MOZ_CrashSequence(__null, 12617); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12617 "ParamsBody should be handled in emitFunctionScript.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"ParamsBody should be handled in emitFunctionScript." ")", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 12617); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "ParamsBody should be handled in emitFunctionScript."
")"); do { MOZ_CrashSequence(__null, 12617); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12618 break;
12619
12620 case ParseNodeKind::IfStmt:
12621 if (!emitIf(&pn->as<TernaryNode>())) {
12622 return false;
12623 }
12624 break;
12625
12626 case ParseNodeKind::SwitchStmt:
12627 if (!emitSwitch(&pn->as<SwitchStatement>())) {
12628 return false;
12629 }
12630 break;
12631
12632 case ParseNodeKind::WhileStmt:
12633 if (!emitWhile(&pn->as<BinaryNode>())) {
12634 return false;
12635 }
12636 break;
12637
12638 case ParseNodeKind::DoWhileStmt:
12639 if (!emitDo(&pn->as<BinaryNode>())) {
12640 return false;
12641 }
12642 break;
12643
12644 case ParseNodeKind::ForStmt:
12645 if (!emitFor(&pn->as<ForNode>())) {
12646 return false;
12647 }
12648 break;
12649
12650 case ParseNodeKind::BreakStmt:
12651 // Ensure that the column of the 'break' is set properly.
12652 if (!updateSourceCoordNotes(pn->pn_pos.begin)) {
12653 return false;
12654 }
12655 if (!markStepBreakpoint()) {
12656 return false;
12657 }
12658
12659 if (!emitBreak(pn->as<BreakStatement>().label())) {
12660 return false;
12661 }
12662 break;
12663
12664 case ParseNodeKind::ContinueStmt:
12665 // Ensure that the column of the 'continue' is set properly.
12666 if (!updateSourceCoordNotes(pn->pn_pos.begin)) {
12667 return false;
12668 }
12669 if (!markStepBreakpoint()) {
12670 return false;
12671 }
12672
12673 if (!emitContinue(pn->as<ContinueStatement>().label())) {
12674 return false;
12675 }
12676 break;
12677
12678 case ParseNodeKind::WithStmt:
12679 if (!emitWith(&pn->as<BinaryNode>())) {
12680 return false;
12681 }
12682 break;
12683
12684 case ParseNodeKind::TryStmt:
12685 if (!emitTry(&pn->as<TryNode>())) {
12686 return false;
12687 }
12688 break;
12689
12690 case ParseNodeKind::Catch:
12691 if (!emitCatch(&pn->as<BinaryNode>())) {
12692 return false;
12693 }
12694 break;
12695
12696 case ParseNodeKind::VarStmt:
12697 if (!emitDeclarationList(&pn->as<ListNode>())) {
12698 return false;
12699 }
12700 break;
12701
12702 case ParseNodeKind::ReturnStmt:
12703 if (!emitReturn(&pn->as<UnaryNode>())) {
12704 return false;
12705 }
12706 break;
12707
12708 case ParseNodeKind::YieldStarExpr:
12709 if (!emitYieldStar(pn->as<UnaryNode>().kid())) {
12710 return false;
12711 }
12712 break;
12713
12714 case ParseNodeKind::Generator:
12715 if (!emit1(JSOp::Generator)) {
12716 return false;
12717 }
12718 break;
12719
12720 case ParseNodeKind::InitialYield:
12721 if (!emitInitialYield(&pn->as<UnaryNode>())) {
12722 return false;
12723 }
12724 break;
12725
12726 case ParseNodeKind::YieldExpr:
12727 if (!emitYield(&pn->as<UnaryNode>())) {
12728 return false;
12729 }
12730 break;
12731
12732 case ParseNodeKind::AwaitExpr:
12733 if (!emitAwaitInInnermostScope(&pn->as<UnaryNode>())) {
12734 return false;
12735 }
12736 break;
12737
12738 case ParseNodeKind::StatementList:
12739 if (!emitStatementList(&pn->as<ListNode>())) {
12740 return false;
12741 }
12742 break;
12743
12744 case ParseNodeKind::EmptyStmt:
12745 break;
12746
12747 case ParseNodeKind::ExpressionStmt:
12748 if (!emitExpressionStatement(&pn->as<UnaryNode>())) {
12749 return false;
12750 }
12751 break;
12752
12753 case ParseNodeKind::LabelStmt:
12754 if (!emitLabeledStatement(&pn->as<LabeledStatement>())) {
12755 return false;
12756 }
12757 break;
12758
12759 case ParseNodeKind::CommaExpr:
12760 if (!emitSequenceExpr(&pn->as<ListNode>(), valueUsage)) {
12761 return false;
12762 }
12763 break;
12764
12765 case ParseNodeKind::InitExpr:
12766 case ParseNodeKind::AssignExpr:
12767 case ParseNodeKind::AddAssignExpr:
12768 case ParseNodeKind::SubAssignExpr:
12769 case ParseNodeKind::BitOrAssignExpr:
12770 case ParseNodeKind::BitXorAssignExpr:
12771 case ParseNodeKind::BitAndAssignExpr:
12772 case ParseNodeKind::LshAssignExpr:
12773 case ParseNodeKind::RshAssignExpr:
12774 case ParseNodeKind::UrshAssignExpr:
12775 case ParseNodeKind::MulAssignExpr:
12776 case ParseNodeKind::DivAssignExpr:
12777 case ParseNodeKind::ModAssignExpr:
12778 case ParseNodeKind::PowAssignExpr: {
12779 BinaryNode* assignNode = &pn->as<BinaryNode>();
12780 if (!emitAssignmentOrInit(assignNode->getKind(), assignNode->left(),
12781 assignNode->right())) {
12782 return false;
12783 }
12784 break;
12785 }
12786
12787 case ParseNodeKind::CoalesceAssignExpr:
12788 case ParseNodeKind::OrAssignExpr:
12789 case ParseNodeKind::AndAssignExpr:
12790 if (!emitShortCircuitAssignment(&pn->as<AssignmentNode>())) {
12791 return false;
12792 }
12793 break;
12794
12795 case ParseNodeKind::ConditionalExpr:
12796 if (!emitConditionalExpression(pn->as<ConditionalExpression>(),
12797 valueUsage)) {
12798 return false;
12799 }
12800 break;
12801
12802 case ParseNodeKind::OrExpr:
12803 case ParseNodeKind::CoalesceExpr:
12804 case ParseNodeKind::AndExpr:
12805 if (!emitShortCircuit(&pn->as<ListNode>(), valueUsage)) {
12806 return false;
12807 }
12808 break;
12809
12810 case ParseNodeKind::StrictEqExpr:
12811 case ParseNodeKind::EqExpr:
12812 case ParseNodeKind::StrictNeExpr:
12813 case ParseNodeKind::NeExpr:
12814 case ParseNodeKind::LtExpr:
12815 case ParseNodeKind::GtExpr: {
12816 bool emitted;
12817 if (!tryEmitTypeofEq(&pn->as<ListNode>(), &emitted)) {
12818 return false;
12819 }
12820 if (emitted) {
12821 return true;
12822 }
12823 }
12824 [[fallthrough]];
12825
12826 case ParseNodeKind::AddExpr:
12827 case ParseNodeKind::SubExpr:
12828 case ParseNodeKind::BitOrExpr:
12829 case ParseNodeKind::BitXorExpr:
12830 case ParseNodeKind::BitAndExpr:
12831 case ParseNodeKind::LeExpr:
12832 case ParseNodeKind::GeExpr:
12833 case ParseNodeKind::InExpr:
12834 case ParseNodeKind::InstanceOfExpr:
12835 case ParseNodeKind::LshExpr:
12836 case ParseNodeKind::RshExpr:
12837 case ParseNodeKind::UrshExpr:
12838 case ParseNodeKind::MulExpr:
12839 case ParseNodeKind::DivExpr:
12840 case ParseNodeKind::ModExpr:
12841 if (!emitLeftAssociative(&pn->as<ListNode>())) {
12842 return false;
12843 }
12844 break;
12845
12846 case ParseNodeKind::PrivateInExpr:
12847 if (!emitPrivateInExpr(&pn->as<ListNode>())) {
12848 return false;
12849 }
12850 break;
12851
12852 case ParseNodeKind::PowExpr:
12853 if (!emitRightAssociative(&pn->as<ListNode>())) {
12854 return false;
12855 }
12856 break;
12857
12858 case ParseNodeKind::TypeOfNameExpr:
12859 if (!emitTypeof(&pn->as<UnaryNode>(), JSOp::Typeof)) {
12860 return false;
12861 }
12862 break;
12863
12864 case ParseNodeKind::TypeOfExpr:
12865 if (!emitTypeof(&pn->as<UnaryNode>(), JSOp::TypeofExpr)) {
12866 return false;
12867 }
12868 break;
12869
12870 case ParseNodeKind::ThrowStmt:
12871 if (!updateSourceCoordNotes(pn->pn_pos.begin)) {
12872 return false;
12873 }
12874 if (!markStepBreakpoint()) {
12875 return false;
12876 }
12877 [[fallthrough]];
12878 case ParseNodeKind::VoidExpr:
12879 case ParseNodeKind::NotExpr:
12880 case ParseNodeKind::BitNotExpr:
12881 case ParseNodeKind::PosExpr:
12882 case ParseNodeKind::NegExpr:
12883 if (!emitUnary(&pn->as<UnaryNode>())) {
12884 return false;
12885 }
12886 break;
12887
12888 case ParseNodeKind::PreIncrementExpr:
12889 case ParseNodeKind::PreDecrementExpr:
12890 case ParseNodeKind::PostIncrementExpr:
12891 case ParseNodeKind::PostDecrementExpr:
12892 if (!emitIncOrDec(&pn->as<UnaryNode>(), valueUsage)) {
12893 return false;
12894 }
12895 break;
12896
12897 case ParseNodeKind::DeleteNameExpr:
12898 if (!emitDeleteName(&pn->as<UnaryNode>())) {
12899 return false;
12900 }
12901 break;
12902
12903 case ParseNodeKind::DeletePropExpr:
12904 if (!emitDeleteProperty(&pn->as<UnaryNode>())) {
12905 return false;
12906 }
12907 break;
12908
12909 case ParseNodeKind::DeleteElemExpr:
12910 if (!emitDeleteElement(&pn->as<UnaryNode>())) {
12911 return false;
12912 }
12913 break;
12914
12915 case ParseNodeKind::DeleteExpr:
12916 if (!emitDeleteExpression(&pn->as<UnaryNode>())) {
12917 return false;
12918 }
12919 break;
12920
12921 case ParseNodeKind::DeleteOptionalChainExpr:
12922 if (!emitDeleteOptionalChain(&pn->as<UnaryNode>())) {
12923 return false;
12924 }
12925 break;
12926
12927 case ParseNodeKind::OptionalChain:
12928 if (!emitOptionalChain(&pn->as<UnaryNode>(), valueUsage)) {
12929 return false;
12930 }
12931 break;
12932
12933 case ParseNodeKind::DotExpr: {
12934 PropertyAccess* prop = &pn->as<PropertyAccess>();
12935 bool isSuper = prop->isSuper();
12936 PropOpEmitter poe(this, PropOpEmitter::Kind::Get,
12937 isSuper ? PropOpEmitter::ObjKind::Super
12938 : PropOpEmitter::ObjKind::Other);
12939 if (!poe.prepareForObj()) {
12940 return false;
12941 }
12942 if (isSuper) {
12943 UnaryNode* base = &prop->expression().as<UnaryNode>();
12944 if (!emitGetThisForSuperBase(base)) {
12945 // [stack] THIS
12946 return false;
12947 }
12948 } else {
12949 if (!emitPropLHS(prop)) {
12950 // [stack] OBJ
12951 return false;
12952 }
12953 }
12954 if (!poe.emitGet(prop->key().atom())) {
12955 // [stack] PROP
12956 return false;
12957 }
12958 break;
12959 }
12960
12961 case ParseNodeKind::ArgumentsLength: {
12962 if (!emitArgumentsLength()) {
12963 return false;
12964 }
12965 break;
12966 }
12967
12968 case ParseNodeKind::ElemExpr: {
12969 PropertyByValue* elem = &pn->as<PropertyByValue>();
12970 bool isSuper = elem->isSuper();
12971 MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!elem->key().isKind(ParseNodeKind::PrivateName))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!elem->key().isKind(ParseNodeKind::PrivateName)))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!elem->key().isKind(ParseNodeKind::PrivateName)"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 12971)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)"
")"); do { MOZ_CrashSequence(__null, 12971); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12972 ElemOpEmitter eoe(this, ElemOpEmitter::Kind::Get,
12973 isSuper ? ElemOpEmitter::ObjKind::Super
12974 : ElemOpEmitter::ObjKind::Other);
12975 if (!emitElemObjAndKey(elem, eoe)) {
12976 // [stack] # if Super
12977 // [stack] THIS KEY
12978 // [stack] # otherwise
12979 // [stack] OBJ KEY
12980 return false;
12981 }
12982 if (!eoe.emitGet()) {
12983 // [stack] ELEM
12984 return false;
12985 }
12986
12987 break;
12988 }
12989
12990 case ParseNodeKind::PrivateMemberExpr: {
12991 PrivateMemberAccess* privateExpr = &pn->as<PrivateMemberAccess>();
12992 PrivateOpEmitter xoe(this, PrivateOpEmitter::Kind::Get,
12993 privateExpr->privateName().name());
12994 if (!emitTree(&privateExpr->expression())) {
12995 // [stack] OBJ
12996 return false;
12997 }
12998 if (!xoe.emitReference()) {
12999 // [stack] OBJ NAME
13000 return false;
13001 }
13002 if (!xoe.emitGet()) {
13003 // [stack] VALUE
13004 return false;
13005 }
13006
13007 break;
13008 }
13009
13010 case ParseNodeKind::NewExpr:
13011 case ParseNodeKind::TaggedTemplateExpr:
13012 case ParseNodeKind::CallExpr:
13013 case ParseNodeKind::SuperCallExpr:
13014 if (!emitCallOrNew(&pn->as<CallNode>(), valueUsage)) {
13015 return false;
13016 }
13017 break;
13018
13019 case ParseNodeKind::LexicalScope:
13020 if (!emitLexicalScope(&pn->as<LexicalScopeNode>())) {
13021 return false;
13022 }
13023 break;
13024
13025 case ParseNodeKind::ConstDecl:
13026 case ParseNodeKind::LetDecl:
13027 if (!emitDeclarationList(&pn->as<ListNode>())) {
13028 return false;
13029 }
13030 break;
13031 case ParseNodeKind::AwaitUsingDecl:
13032 case ParseNodeKind::UsingDecl:
13033 if (!emitDeclarationList(&pn->as<ListNode>())) {
13034 return false;
13035 }
13036 break;
13037
13038 case ParseNodeKind::ImportDecl:
13039 MOZ_ASSERT(sc->isModuleContext())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sc->isModuleContext())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sc->isModuleContext()))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("sc->isModuleContext()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 13039)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isModuleContext()"
")"); do { MOZ_CrashSequence(__null, 13039); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13040 break;
13041
13042 case ParseNodeKind::ExportStmt: {
13043 MOZ_ASSERT(sc->isModuleContext())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sc->isModuleContext())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sc->isModuleContext()))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("sc->isModuleContext()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 13043)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isModuleContext()"
")"); do { MOZ_CrashSequence(__null, 13043); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13044 UnaryNode* node = &pn->as<UnaryNode>();
13045 ParseNode* decl = node->kid();
13046 if (decl->getKind() != ParseNodeKind::ExportSpecList) {
13047 if (!emitTree(decl)) {
13048 return false;
13049 }
13050 }
13051 break;
13052 }
13053
13054 case ParseNodeKind::ExportDefaultStmt:
13055 MOZ_ASSERT(sc->isModuleContext())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sc->isModuleContext())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sc->isModuleContext()))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("sc->isModuleContext()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 13055)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isModuleContext()"
")"); do { MOZ_CrashSequence(__null, 13055); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13056 if (!emitExportDefault(&pn->as<BinaryNode>())) {
13057 return false;
13058 }
13059 break;
13060
13061 case ParseNodeKind::ExportFromStmt:
13062 MOZ_ASSERT(sc->isModuleContext())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sc->isModuleContext())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sc->isModuleContext()))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("sc->isModuleContext()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 13062)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isModuleContext()"
")"); do { MOZ_CrashSequence(__null, 13062); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13063 break;
13064
13065 case ParseNodeKind::CallSiteObj:
13066 if (!emitCallSiteObject(&pn->as<CallSiteNode>())) {
13067 return false;
13068 }
13069 break;
13070
13071 case ParseNodeKind::ArrayExpr:
13072 if (!emitArrayLiteral(&pn->as<ListNode>())) {
13073 return false;
13074 }
13075 break;
13076
13077 case ParseNodeKind::ObjectExpr:
13078 if (!emitObject(&pn->as<ListNode>())) {
13079 return false;
13080 }
13081 break;
13082
13083 case ParseNodeKind::Name:
13084 if (!emitGetName(&pn->as<NameNode>())) {
13085 return false;
13086 }
13087 break;
13088
13089 case ParseNodeKind::PrivateName:
13090 if (!emitGetPrivateName(&pn->as<NameNode>())) {
13091 return false;
13092 }
13093 break;
13094
13095 case ParseNodeKind::TemplateStringListExpr:
13096 if (!emitTemplateString(&pn->as<ListNode>())) {
13097 return false;
13098 }
13099 break;
13100
13101 case ParseNodeKind::TemplateStringExpr:
13102 case ParseNodeKind::StringExpr:
13103 if (!emitStringOp(JSOp::String, pn->as<NameNode>().atom())) {
13104 return false;
13105 }
13106 break;
13107
13108 case ParseNodeKind::NumberExpr:
13109 if (!emitNumberOp(pn->as<NumericLiteral>().value())) {
13110 return false;
13111 }
13112 break;
13113
13114 case ParseNodeKind::BigIntExpr:
13115 if (!emitBigIntOp(&pn->as<BigIntLiteral>())) {
13116 return false;
13117 }
13118 break;
13119
13120 case ParseNodeKind::RegExpExpr: {
13121 GCThingIndex index;
13122 if (!perScriptData().gcThingList().append(&pn->as<RegExpLiteral>(),
13123 &index)) {
13124 return false;
13125 }
13126 if (!emitRegExp(index)) {
13127 return false;
13128 }
13129 break;
13130 }
13131
13132 case ParseNodeKind::TrueExpr:
13133 if (!emit1(JSOp::True)) {
13134 return false;
13135 }
13136 break;
13137 case ParseNodeKind::FalseExpr:
13138 if (!emit1(JSOp::False)) {
13139 return false;
13140 }
13141 break;
13142 case ParseNodeKind::NullExpr:
13143 if (!emit1(JSOp::Null)) {
13144 return false;
13145 }
13146 break;
13147 case ParseNodeKind::RawUndefinedExpr:
13148 if (!emit1(JSOp::Undefined)) {
13149 return false;
13150 }
13151 break;
13152
13153 case ParseNodeKind::ThisExpr:
13154 if (!emitThisLiteral(&pn->as<ThisLiteral>())) {
13155 return false;
13156 }
13157 break;
13158
13159 case ParseNodeKind::DebuggerStmt:
13160 if (!updateSourceCoordNotes(pn->pn_pos.begin)) {
13161 return false;
13162 }
13163 if (!markStepBreakpoint()) {
13164 return false;
13165 }
13166 if (!emit1(JSOp::Debugger)) {
13167 return false;
13168 }
13169 break;
13170
13171 case ParseNodeKind::ClassDecl:
13172 if (!emitClass(&pn->as<ClassNode>())) {
13173 return false;
13174 }
13175 break;
13176
13177 case ParseNodeKind::NewTargetExpr:
13178 if (!emitNewTarget(&pn->as<NewTargetNode>())) {
13179 return false;
13180 }
13181 break;
13182
13183 case ParseNodeKind::ImportMetaExpr:
13184 if (!emit1(JSOp::ImportMeta)) {
13185 return false;
13186 }
13187 break;
13188
13189 case ParseNodeKind::CallImportExpr: {
13190 CallImportNode* callImport = &pn->as<CallImportNode>();
13191 BinaryNode* spec = &callImport->right()->as<BinaryNode>();
13192
13193 if (!emitTree(spec->left())) {
13194 // [stack] specifier
13195 return false;
13196 }
13197
13198 // import.source does not have an options parameter, so its spec always
13199 // carries a PosHolder in place of the options argument.
13200 if (!spec->right()->isKind(ParseNodeKind::PosHolder)) {
13201 // [stack] specifier options
13202 if (!emitTree(spec->right())) {
13203 return false;
13204 }
13205 } else {
13206 // [stack] specifier undefined
13207 if (!emit1(JSOp::Undefined)) {
13208 return false;
13209 }
13210 }
13211
13212 if (!emit2(JSOp::DynamicImport, uint8_t(callImport->phase()))) {
13213 return false;
13214 }
13215
13216 break;
13217 }
13218
13219 case ParseNodeKind::SetThis:
13220 if (!emitSetThis(&pn->as<BinaryNode>())) {
13221 return false;
13222 }
13223 break;
13224
13225 case ParseNodeKind::PropertyNameExpr:
13226 case ParseNodeKind::PosHolder:
13227 MOZ_FALLTHROUGH_ASSERT(do { do { } while (false); MOZ_ReportCrash("" "MOZ_FALLTHROUGH_ASSERT: "
"Should never try to emit ParseNodeKind::PosHolder or ::Property"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 13228)
; AnnotateMozCrashReason("MOZ_CRASH(" "MOZ_FALLTHROUGH_ASSERT: "
"Should never try to emit ParseNodeKind::PosHolder or ::Property"
")"); do { MOZ_CrashSequence(__null, 13228); __attribute__((
nomerge)) ::abort(); } while (false); } while (false)
13228 "Should never try to emit ParseNodeKind::PosHolder or ::Property")do { do { } while (false); MOZ_ReportCrash("" "MOZ_FALLTHROUGH_ASSERT: "
"Should never try to emit ParseNodeKind::PosHolder or ::Property"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 13228)
; AnnotateMozCrashReason("MOZ_CRASH(" "MOZ_FALLTHROUGH_ASSERT: "
"Should never try to emit ParseNodeKind::PosHolder or ::Property"
")"); do { MOZ_CrashSequence(__null, 13228); __attribute__((
nomerge)) ::abort(); } while (false); } while (false)
;
13229
13230 default:
13231 MOZ_ASSERT(0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(0)>::isValid, "invalid assertion condition"); if (
(__builtin_expect(!!(!(!!(0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("0", "./../../../../js/src/frontend/BytecodeEmitter.cpp", 13231
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0" ")"); do { MOZ_CrashSequence
(__null, 13231); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
13232 }
13233
13234 return true;
13235}
13236
13237static bool AllocSrcNote(FrontendContext* fc, SrcNotesVector& notes,
13238 unsigned size, unsigned* index) {
13239 size_t oldLength = notes.length();
13240
13241 if (MOZ_UNLIKELY(oldLength + size > MaxSrcNotesLength)(__builtin_expect(!!(oldLength + size > MaxSrcNotesLength)
, 0))
) {
13242 ReportAllocationOverflow(fc);
13243 return false;
13244 }
13245
13246 if (!notes.growByUninitialized(size)) {
13247 return false;
13248 }
13249
13250 *index = oldLength;
13251 return true;
13252}
13253
13254bool BytecodeEmitter::addTryNote(TryNoteKind kind, uint32_t stackDepth,
13255 BytecodeOffset start, BytecodeOffset end) {
13256 MOZ_ASSERT(!inPrologue())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!inPrologue())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!inPrologue()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!inPrologue()",
"./../../../../js/src/frontend/BytecodeEmitter.cpp", 13256);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inPrologue()" ")")
; do { MOZ_CrashSequence(__null, 13256); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
13257 return bytecodeSection().tryNoteList().append(kind, stackDepth, start, end);
13258}
13259
13260bool BytecodeEmitter::newSrcNote(SrcNoteType type, unsigned* indexp) {
13261 SrcNotesVector& notes = bytecodeSection().notes();
13262 unsigned index;
13263
13264 /*
13265 * Compute delta from the last annotated bytecode's offset. If it's too
13266 * big to fit in sn, allocate one or more xdelta notes and reset sn.
13267 */
13268 BytecodeOffset offset = bytecodeSection().offset();
13269 ptrdiff_t delta = (offset - bytecodeSection().lastNoteOffset()).value();
13270 bytecodeSection().setLastNoteOffset(offset);
13271
13272 auto allocator = [&](unsigned size) -> SrcNote* {
13273 if (!AllocSrcNote(fc, notes, size, &index)) {
13274 return nullptr;
13275 }
13276 return &notes[index];
13277 };
13278
13279 if (!SrcNoteWriter::writeNote(type, delta, allocator)) {
13280 return false;
13281 }
13282
13283 if (indexp) {
13284 *indexp = index;
13285 }
13286
13287 if (type == SrcNoteType::NewLine || type == SrcNoteType::SetLine) {
13288 lastLineOnlySrcNoteIndex = index;
13289 } else {
13290 lastLineOnlySrcNoteIndex = LastSrcNoteIsNotLineOnly;
13291 }
13292
13293 return true;
13294}
13295
13296bool BytecodeEmitter::newSrcNote2(SrcNoteType type, ptrdiff_t offset,
13297 unsigned* indexp) {
13298 unsigned index;
13299 if (!newSrcNote(type, &index)) {
13300 return false;
13301 }
13302 if (!newSrcNoteOperand(offset)) {
13303 return false;
13304 }
13305 if (indexp) {
13306 *indexp = index;
13307 }
13308 return true;
13309}
13310
13311bool BytecodeEmitter::convertLastNewLineToNewLineColumn(
13312 JS::LimitedColumnNumberOneOrigin column) {
13313 SrcNotesVector& notes = bytecodeSection().notes();
13314 MOZ_ASSERT(lastLineOnlySrcNoteIndex == notes.length() - 1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(lastLineOnlySrcNoteIndex == notes.length() - 1)>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(lastLineOnlySrcNoteIndex == notes.length() - 1))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("lastLineOnlySrcNoteIndex == notes.length() - 1"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 13314)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "lastLineOnlySrcNoteIndex == notes.length() - 1"
")"); do { MOZ_CrashSequence(__null, 13314); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13315 SrcNote* sn = &notes[lastLineOnlySrcNoteIndex];
13316 MOZ_ASSERT(sn->type() == SrcNoteType::NewLine)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sn->type() == SrcNoteType::NewLine)>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(sn->type() == SrcNoteType::NewLine))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("sn->type() == SrcNoteType::NewLine"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 13316)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "sn->type() == SrcNoteType::NewLine"
")"); do { MOZ_CrashSequence(__null, 13316); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13317
13318 SrcNoteWriter::convertNote(sn, SrcNoteType::NewLineColumn);
13319 if (!newSrcNoteOperand(SrcNote::NewLineColumn::toOperand(column))) {
13320 return false;
13321 }
13322
13323 lastLineOnlySrcNoteIndex = LastSrcNoteIsNotLineOnly;
13324 return true;
13325}
13326
13327bool BytecodeEmitter::convertLastSetLineToSetLineColumn(
13328 JS::LimitedColumnNumberOneOrigin column) {
13329 SrcNotesVector& notes = bytecodeSection().notes();
13330 // The Line operand is either 1 byte or 4 bytes.
13331 MOZ_ASSERT(lastLineOnlySrcNoteIndex == notes.length() - 1 - 1 ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(lastLineOnlySrcNoteIndex == notes.length() - 1 - 1 ||
lastLineOnlySrcNoteIndex == notes.length() - 1 - 4)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(lastLineOnlySrcNoteIndex == notes.length() - 1 - 1 || lastLineOnlySrcNoteIndex
== notes.length() - 1 - 4))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("lastLineOnlySrcNoteIndex == notes.length() - 1 - 1 || lastLineOnlySrcNoteIndex == notes.length() - 1 - 4"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 13332)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "lastLineOnlySrcNoteIndex == notes.length() - 1 - 1 || lastLineOnlySrcNoteIndex == notes.length() - 1 - 4"
")"); do { MOZ_CrashSequence(__null, 13332); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
13332 lastLineOnlySrcNoteIndex == notes.length() - 1 - 4)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(lastLineOnlySrcNoteIndex == notes.length() - 1 - 1 ||
lastLineOnlySrcNoteIndex == notes.length() - 1 - 4)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(lastLineOnlySrcNoteIndex == notes.length() - 1 - 1 || lastLineOnlySrcNoteIndex
== notes.length() - 1 - 4))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("lastLineOnlySrcNoteIndex == notes.length() - 1 - 1 || lastLineOnlySrcNoteIndex == notes.length() - 1 - 4"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 13332)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "lastLineOnlySrcNoteIndex == notes.length() - 1 - 1 || lastLineOnlySrcNoteIndex == notes.length() - 1 - 4"
")"); do { MOZ_CrashSequence(__null, 13332); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13333 SrcNote* sn = &notes[lastLineOnlySrcNoteIndex];
13334 MOZ_ASSERT(sn->type() == SrcNoteType::SetLine)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sn->type() == SrcNoteType::SetLine)>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(sn->type() == SrcNoteType::SetLine))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("sn->type() == SrcNoteType::SetLine"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 13334)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "sn->type() == SrcNoteType::SetLine"
")"); do { MOZ_CrashSequence(__null, 13334); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13335
13336 SrcNoteWriter::convertNote(sn, SrcNoteType::SetLineColumn);
13337 if (!newSrcNoteOperand(SrcNote::SetLineColumn::columnToOperand(column))) {
13338 return false;
13339 }
13340
13341 lastLineOnlySrcNoteIndex = LastSrcNoteIsNotLineOnly;
13342 return true;
13343}
13344
13345bool BytecodeEmitter::newSrcNoteOperand(ptrdiff_t operand) {
13346 if (!SrcNote::isRepresentableOperand(operand)) {
13347 reportError(nullptr, JSMSG_NEED_DIET, "script");
13348 return false;
13349 }
13350
13351 SrcNotesVector& notes = bytecodeSection().notes();
13352
13353 auto allocator = [&](unsigned size) -> SrcNote* {
13354 unsigned index;
13355 if (!AllocSrcNote(fc, notes, size, &index)) {
13356 return nullptr;
13357 }
13358 return &notes[index];
13359 };
13360
13361 return SrcNoteWriter::writeOperand(operand, allocator);
13362}
13363
13364bool BytecodeEmitter::intoScriptStencil(ScriptIndex scriptIndex) {
13365 js::UniquePtr<ImmutableScriptData> immutableScriptData =
13366 createImmutableScriptData();
13367 if (!immutableScriptData) {
13368 return false;
13369 }
13370
13371 MOZ_ASSERT(outermostScope().hasNonSyntacticScopeOnChain() ==do { static_assert( mozilla::detail::AssertionConditionType<
decltype(outermostScope().hasNonSyntacticScopeOnChain() == sc
->hasNonSyntacticScope())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(outermostScope().hasNonSyntacticScopeOnChain
() == sc->hasNonSyntacticScope()))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("outermostScope().hasNonSyntacticScopeOnChain() == sc->hasNonSyntacticScope()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 13372)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "outermostScope().hasNonSyntacticScopeOnChain() == sc->hasNonSyntacticScope()"
")"); do { MOZ_CrashSequence(__null, 13372); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
13372 sc->hasNonSyntacticScope())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(outermostScope().hasNonSyntacticScopeOnChain() == sc
->hasNonSyntacticScope())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(outermostScope().hasNonSyntacticScopeOnChain
() == sc->hasNonSyntacticScope()))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("outermostScope().hasNonSyntacticScopeOnChain() == sc->hasNonSyntacticScope()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 13372)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "outermostScope().hasNonSyntacticScopeOnChain() == sc->hasNonSyntacticScope()"
")"); do { MOZ_CrashSequence(__null, 13372); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13373
13374 auto& things = perScriptData().gcThingList().objects();
13375 if (!compilationState.appendGCThings(fc, scriptIndex, things)) {
13376 return false;
13377 }
13378
13379 // Hand over the ImmutableScriptData instance generated by BCE.
13380 auto* sharedData =
13381 SharedImmutableScriptData::createWith(fc, std::move(immutableScriptData));
13382 if (!sharedData) {
13383 return false;
13384 }
13385
13386 // De-duplicate the bytecode within the runtime.
13387 if (!compilationState.sharedData.addAndShare(fc, scriptIndex, sharedData)) {
13388 return false;
13389 }
13390
13391 ScriptStencil& script = compilationState.scriptData[scriptIndex];
13392 script.setHasSharedData();
13393
13394 // Update flags specific to functions.
13395 if (sc->isFunctionBox()) {
13396 FunctionBox* funbox = sc->asFunctionBox();
13397 MOZ_ASSERT(&script == &funbox->functionStencil())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(&script == &funbox->functionStencil())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(&script == &funbox->functionStencil()))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("&script == &funbox->functionStencil()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 13397)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "&script == &funbox->functionStencil()"
")"); do { MOZ_CrashSequence(__null, 13397); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13398 funbox->copyUpdatedImmutableFlags();
13399 MOZ_ASSERT(script.isFunction())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(script.isFunction())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(script.isFunction()))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("script.isFunction()"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 13399)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "script.isFunction()"
")"); do { MOZ_CrashSequence(__null, 13399); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13400 } else {
13401 ScriptStencilExtra& scriptExtra = compilationState.scriptExtra[scriptIndex];
13402 sc->copyScriptExtraFields(scriptExtra);
13403 }
13404
13405 return true;
13406}
13407
13408SelfHostedIter BytecodeEmitter::getSelfHostedIterFor(
13409 ParseNode* parseNode) const {
13410 if (emitterMode == BytecodeEmitter::SelfHosting &&
13411 parseNode->isKind(ParseNodeKind::CallExpr)) {
13412 auto* callee = parseNode->as<CallNode>().callee();
13413 if (callee->isName(TaggedParserAtomIndex::WellKnown::allowContentIter())) {
13414 return SelfHostedIter::AllowContent;
13415 }
13416 if (callee->isName(
13417 TaggedParserAtomIndex::WellKnown::allowContentIterWith())) {
13418 return SelfHostedIter::AllowContentWith;
13419 }
13420 if (callee->isName(
13421 TaggedParserAtomIndex::WellKnown::allowContentIterWithNext())) {
13422 return SelfHostedIter::AllowContentWithNext;
13423 }
13424 }
13425
13426 return SelfHostedIter::Deny;
13427}
13428
13429#if defined(DEBUG1) || defined(JS_JITSPEW1)
13430void BytecodeEmitter::dumpAtom(TaggedParserAtomIndex index) const {
13431 parserAtoms().dump(index);
13432}
13433#endif