Bug Summary

File:root/firefox-clang/obj-x86_64-pc-linux-gnu/js/src/frontend/./../../../../js/src/frontend/BytecodeEmitter.cpp
Warning:line 831, 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-10-17-231001-351276-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/FrontendContext.h" // FrontendContext
38#include "frontend/FunctionEmitter.h" // FunctionEmitter, FunctionScriptEmitter, FunctionParamsEmitter
39#include "frontend/IfEmitter.h" // IfEmitter, InternalIfEmitter, CondEmitter
40#include "frontend/LabelEmitter.h" // LabelEmitter
41#include "frontend/LexicalScopeEmitter.h" // LexicalScopeEmitter
42#include "frontend/ModuleSharedContext.h" // ModuleSharedContext
43#include "frontend/NameAnalysisTypes.h" // PrivateNameKind
44#include "frontend/NameFunctions.h" // NameFunctions
45#include "frontend/NameOpEmitter.h" // NameOpEmitter
46#include "frontend/ObjectEmitter.h" // PropertyEmitter, ObjectEmitter, ClassEmitter
47#include "frontend/OptionalEmitter.h" // OptionalEmitter
48#include "frontend/ParseContext.h" // ParseContext::Scope
49#include "frontend/ParseNode.h" // ParseNodeKind, ParseNode and subclasses
50#include "frontend/Parser.h" // Parser
51#include "frontend/ParserAtom.h" // ParserAtomsTable, ParserAtom
52#include "frontend/PrivateOpEmitter.h" // PrivateOpEmitter
53#include "frontend/PropOpEmitter.h" // PropOpEmitter
54#include "frontend/SourceNotes.h" // SrcNote, SrcNoteType, SrcNoteWriter
55#include "frontend/SwitchEmitter.h" // SwitchEmitter
56#include "frontend/TaggedParserAtomIndexHasher.h" // TaggedParserAtomIndexHasher
57#include "frontend/TDZCheckCache.h" // TDZCheckCache
58#include "frontend/TryEmitter.h" // TryEmitter
59#include "frontend/UsingEmitter.h" // UsingEmitter
60#include "frontend/WhileEmitter.h" // WhileEmitter
61#include "js/ColumnNumber.h" // JS::LimitedColumnNumberOneOrigin, JS::ColumnNumberOffset
62#include "js/friend/ErrorMessages.h" // JSMSG_*
63#include "js/friend/StackLimits.h" // AutoCheckRecursionLimit
64#include "util/StringBuilder.h" // StringBuilder
65#include "vm/BytecodeUtil.h" // JOF_*, IsArgOp, IsLocalOp, SET_UINT24, SET_ICINDEX, BytecodeFallsThrough, BytecodeIsJumpTarget
66#include "vm/CompletionKind.h" // CompletionKind
67#include "vm/ConstantCompareOperand.h" // ConstantCompareOperand
68#include "vm/FunctionPrefixKind.h" // FunctionPrefixKind
69#include "vm/GeneratorObject.h" // AbstractGeneratorObject
70#include "vm/Opcodes.h" // JSOp, JSOpLength_*
71#include "vm/PropMap.h" // SharedPropMap::MaxPropsForNonDictionary
72#include "vm/Scope.h" // GetScopeDataTrailingNames
73#include "vm/SharedStencil.h" // ScopeNote
74#include "vm/ThrowMsgKind.h" // ThrowMsgKind
75#include "vm/TypeofEqOperand.h" // TypeofEqOperand
76
77using namespace js;
78using namespace js::frontend;
79
80using mozilla::AssertedCast;
81using mozilla::AsVariant;
82using mozilla::DebugOnly;
83using mozilla::Maybe;
84using mozilla::Nothing;
85using mozilla::NumberEqualsInt32;
86using mozilla::NumberIsInt32;
87using mozilla::Some;
88
89static bool ParseNodeRequiresSpecialLineNumberNotes(ParseNode* pn) {
90 // The few node types listed below are exceptions to the usual
91 // location-source-note-emitting code in BytecodeEmitter::emitTree().
92 // Single-line `while` loops and C-style `for` loops require careful
93 // handling to avoid strange stepping behavior.
94 // Functions usually shouldn't have location information (bug 1431202).
95
96 ParseNodeKind kind = pn->getKind();
97 return kind == ParseNodeKind::WhileStmt || kind == ParseNodeKind::ForStmt ||
98 kind == ParseNodeKind::Function;
99}
100
101static bool NeedsFieldInitializer(ParseNode* member, bool inStaticContext) {
102 // For the purposes of bytecode emission, StaticClassBlocks are treated as if
103 // they were static initializers.
104 return (member->is<StaticClassBlock>() && inStaticContext) ||
105 (member->is<ClassField>() &&
106 member->as<ClassField>().isStatic() == inStaticContext);
107}
108
109static bool NeedsAccessorInitializer(ParseNode* member, bool isStatic) {
110 if (isStatic) {
111 return false;
112 }
113 return member->is<ClassMethod>() &&
114 member->as<ClassMethod>().name().isKind(ParseNodeKind::PrivateName) &&
115 !member->as<ClassMethod>().isStatic() &&
116 member->as<ClassMethod>().accessorType() != AccessorType::None;
117}
118
119static bool ShouldSuppressBreakpointsAndSourceNotes(
120 SharedContext* sc, BytecodeEmitter::EmitterMode emitterMode) {
121 // Suppress for all self-hosting code.
122 if (emitterMode == BytecodeEmitter::EmitterMode::SelfHosting) {
123 return true;
124 }
125
126 // Suppress for synthesized class constructors.
127 if (sc->isFunctionBox()) {
128 FunctionBox* funbox = sc->asFunctionBox();
129 return funbox->isSyntheticFunction() && funbox->isClassConstructor();
130 }
131
132 return false;
133}
134
135BytecodeEmitter::BytecodeEmitter(BytecodeEmitter* parent, FrontendContext* fc,
136 SharedContext* sc,
137 const ErrorReporter& errorReporter,
138 CompilationState& compilationState,
139 EmitterMode emitterMode)
140 : sc(sc),
141 fc(fc),
142 parent(parent),
143 bytecodeSection_(fc, sc->extent().lineno,
144 JS::LimitedColumnNumberOneOrigin(sc->extent().column)),
145 perScriptData_(fc, compilationState),
146 errorReporter_(errorReporter),
147 compilationState(compilationState),
148 suppressBreakpointsAndSourceNotes(
149 ShouldSuppressBreakpointsAndSourceNotes(sc, emitterMode)),
150 emitterMode(emitterMode) {
151 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", 151); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "fc == parent->fc" ")"); do { MOZ_CrashSequence
(__null, 151); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false); } } while (false)
;
152}
153
154BytecodeEmitter::BytecodeEmitter(BytecodeEmitter* parent, SharedContext* sc)
155 : BytecodeEmitter(parent, parent->fc, sc, parent->errorReporter_,
156 parent->compilationState, parent->emitterMode) {}
157
158BytecodeEmitter::BytecodeEmitter(FrontendContext* fc,
159 const EitherParser& parser, SharedContext* sc,
160 CompilationState& compilationState,
161 EmitterMode emitterMode)
162 : BytecodeEmitter(nullptr, fc, sc, parser.errorReporter(), compilationState,
163 emitterMode) {
164 ep_.emplace(parser);
165}
166
167void BytecodeEmitter::initFromBodyPosition(TokenPos bodyPosition) {
168 setScriptStartOffsetIfUnset(bodyPosition.begin);
169 setFunctionBodyEndPos(bodyPosition.end);
170}
171
172bool BytecodeEmitter::init() {
173 if (!parent) {
174 if (!compilationState.prepareSharedDataStorage(fc)) {
175 return false;
176 }
177 }
178 return perScriptData_.init(fc);
179}
180
181bool BytecodeEmitter::init(TokenPos bodyPosition) {
182 initFromBodyPosition(bodyPosition);
183 return init();
184}
185
186template <typename T>
187T* BytecodeEmitter::findInnermostNestableControl() const {
188 return NestableControl::findNearest<T>(innermostNestableControl);
189}
190
191template <typename T, typename Predicate /* (T*) -> bool */>
192T* BytecodeEmitter::findInnermostNestableControl(Predicate predicate) const {
193 return NestableControl::findNearest<T>(innermostNestableControl, predicate);
194}
195
196NameLocation BytecodeEmitter::lookupName(TaggedParserAtomIndex name) {
197 return innermostEmitterScope()->lookup(this, name);
198}
199
200void BytecodeEmitter::lookupPrivate(TaggedParserAtomIndex name,
201 NameLocation& loc,
202 Maybe<NameLocation>& brandLoc) {
203 innermostEmitterScope()->lookupPrivate(this, name, loc, brandLoc);
204}
205
206Maybe<NameLocation> BytecodeEmitter::locationOfNameBoundInScope(
207 TaggedParserAtomIndex name, EmitterScope* target) {
208 return innermostEmitterScope()->locationBoundInScope(name, target);
209}
210
211template <typename T>
212Maybe<NameLocation> BytecodeEmitter::locationOfNameBoundInScopeType(
213 TaggedParserAtomIndex name, EmitterScope* source) {
214 EmitterScope* aScope = source;
215 while (!aScope->scope(this).is<T>()) {
216 aScope = aScope->enclosingInFrame();
217 }
218 return source->locationBoundInScope(name, aScope);
219}
220
221bool BytecodeEmitter::markStepBreakpoint() {
222 if (skipBreakpointSrcNotes()) {
223 return true;
224 }
225
226 if (!newSrcNote(SrcNoteType::BreakpointStepSep)) {
227 return false;
228 }
229
230 // We track the location of the most recent separator for use in
231 // markSimpleBreakpoint. Note that this means that the position must already
232 // be set before markStepBreakpoint is called.
233 bytecodeSection().updateSeparatorPosition();
234
235 return true;
236}
237
238bool BytecodeEmitter::markSimpleBreakpoint() {
239 if (skipBreakpointSrcNotes()) {
240 return true;
241 }
242
243 // If a breakable call ends up being the same location as the most recent
244 // expression start, we need to skip marking it breakable in order to avoid
245 // having two breakpoints with the same line/column position.
246 // Note: This assumes that the position for the call has already been set.
247 if (!bytecodeSection().isDuplicateLocation()) {
248 if (!newSrcNote(SrcNoteType::Breakpoint)) {
249 return false;
250 }
251 }
252
253 return true;
254}
255
256bool BytecodeEmitter::emitCheck(JSOp op, ptrdiff_t delta,
257 BytecodeOffset* offset) {
258 size_t oldLength = bytecodeSection().code().length();
259 *offset = BytecodeOffset(oldLength);
260
261 size_t newLength = oldLength + size_t(delta);
262 if (MOZ_UNLIKELY(newLength > MaxBytecodeLength)(__builtin_expect(!!(newLength > MaxBytecodeLength), 0))) {
263 ReportAllocationOverflow(fc);
264 return false;
265 }
266
267 if (!bytecodeSection().code().growByUninitialized(delta)) {
268 return false;
269 }
270
271 if (BytecodeOpHasIC(op)) {
272 // Even if every bytecode op is a JOF_IC op and the function has ARGC_LIMIT
273 // arguments, numICEntries cannot overflow.
274 static_assert(MaxBytecodeLength + 1 /* this */ + ARGC_LIMIT <= UINT32_MAX(4294967295U),
275 "numICEntries must not overflow");
276 bytecodeSection().incrementNumICEntries();
277 }
278
279 return true;
280}
281
282#ifdef DEBUG1
283bool BytecodeEmitter::checkStrictOrSloppy(JSOp op) const {
284 if (IsCheckStrictOp(op) && !sc->strict()) {
285 return false;
286 }
287 if (IsCheckSloppyOp(op) && sc->strict()) {
288 return false;
289 }
290 return true;
291}
292#endif
293
294bool BytecodeEmitter::emit1(JSOp op) {
295 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", 295); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "checkStrictOrSloppy(op)" ")"); do { MOZ_CrashSequence
(__null, 295); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
296 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", 296); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetOpLength(op) == 1" ")"); do { MOZ_CrashSequence
(__null, 296); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
297
298 BytecodeOffset offset;
299 if (!emitCheck(op, 1, &offset)) {
300 return false;
301 }
302
303 jsbytecode* code = bytecodeSection().code(offset);
304 code[0] = jsbytecode(op);
305 bytecodeSection().updateDepth(op, offset);
306 return true;
307}
308
309bool BytecodeEmitter::emit2(JSOp op, uint8_t op1) {
310 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", 310); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "checkStrictOrSloppy(op)" ")"); do { MOZ_CrashSequence
(__null, 310); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
311 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", 311); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetOpLength(op) == 2" ")"); do { MOZ_CrashSequence
(__null, 311); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
312
313 BytecodeOffset offset;
314 if (!emitCheck(op, 2, &offset)) {
315 return false;
316 }
317
318 jsbytecode* code = bytecodeSection().code(offset);
319 code[0] = jsbytecode(op);
320 code[1] = jsbytecode(op1);
321 bytecodeSection().updateDepth(op, offset);
322 return true;
323}
324
325bool BytecodeEmitter::emit3(JSOp op, jsbytecode op1, jsbytecode op2) {
326 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", 326); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "checkStrictOrSloppy(op)" ")"); do { MOZ_CrashSequence
(__null, 326); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
327 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", 327); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetOpLength(op) == 3" ")"); do { MOZ_CrashSequence
(__null, 327); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
328
329 /* These should filter through emitVarOp. */
330 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"
, 330); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsArgOp(op)"
")"); do { MOZ_CrashSequence(__null, 330); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
331 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", 331); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!IsLocalOp(op)" ")"); do { MOZ_CrashSequence
(__null, 331); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
332
333 BytecodeOffset offset;
334 if (!emitCheck(op, 3, &offset)) {
335 return false;
336 }
337
338 jsbytecode* code = bytecodeSection().code(offset);
339 code[0] = jsbytecode(op);
340 code[1] = op1;
341 code[2] = op2;
342 bytecodeSection().updateDepth(op, offset);
343 return true;
344}
345
346bool BytecodeEmitter::emitN(JSOp op, size_t extra, BytecodeOffset* offset) {
347 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", 347); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "checkStrictOrSloppy(op)" ")"); do { MOZ_CrashSequence
(__null, 347); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
348 ptrdiff_t length = 1 + ptrdiff_t(extra);
349
350 BytecodeOffset off;
351 if (!emitCheck(op, length, &off)) {
352 return false;
353 }
354
355 jsbytecode* code = bytecodeSection().code(off);
356 code[0] = jsbytecode(op);
357 /* The remaining |extra| bytes are set by the caller */
358
359 /*
360 * Don't updateDepth if op's use-count comes from the immediate
361 * operand yet to be stored in the extra bytes after op.
362 */
363 if (CodeSpec(op).nuses >= 0) {
364 bytecodeSection().updateDepth(op, off);
365 }
366
367 if (offset) {
368 *offset = off;
369 }
370 return true;
371}
372
373bool BytecodeEmitter::emitJumpTargetOp(JSOp op, BytecodeOffset* off) {
374 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", 374); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "BytecodeIsJumpTarget(op)" ")"); do { MOZ_CrashSequence
(__null, 374); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
375
376 // Record the current IC-entry index at start of this op.
377 uint32_t numEntries = bytecodeSection().numICEntries();
378
379 size_t n = GetOpLength(op) - 1;
380 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", 380); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetOpLength(op) >= 1 + ICINDEX_LEN" ")"
); do { MOZ_CrashSequence(__null, 380); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
381
382 if (!emitN(op, n, off)) {
383 return false;
384 }
385
386 SET_ICINDEX(bytecodeSection().code(*off), numEntries);
387 return true;
388}
389
390bool BytecodeEmitter::emitJumpTarget(JumpTarget* target) {
391 BytecodeOffset off = bytecodeSection().offset();
392
393 // Alias consecutive jump targets.
394 if (bytecodeSection().lastTargetOffset().valid() &&
395 off == bytecodeSection().lastTargetOffset() +
396 BytecodeOffsetDiff(JSOpLength_JumpTarget)) {
397 target->offset = bytecodeSection().lastTargetOffset();
398 return true;
399 }
400
401 target->offset = off;
402 bytecodeSection().setLastTargetOffset(off);
403
404 BytecodeOffset opOff;
405 return emitJumpTargetOp(JSOp::JumpTarget, &opOff);
406}
407
408bool BytecodeEmitter::emitJumpNoFallthrough(JSOp op, JumpList* jump) {
409 BytecodeOffset offset;
410 if (!emitCheck(op, 5, &offset)) {
411 return false;
412 }
413
414 jsbytecode* code = bytecodeSection().code(offset);
415 code[0] = jsbytecode(op);
416 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", 417); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!jump->offset.valid() || (0 <= jump->offset.value() && jump->offset < offset)"
")"); do { MOZ_CrashSequence(__null, 417); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
417 (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", 417); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!jump->offset.valid() || (0 <= jump->offset.value() && jump->offset < offset)"
")"); do { MOZ_CrashSequence(__null, 417); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
418 jump->push(bytecodeSection().code(BytecodeOffset(0)), offset);
419 bytecodeSection().updateDepth(op, offset);
420 return true;
421}
422
423bool BytecodeEmitter::emitJump(JSOp op, JumpList* jump) {
424 if (!emitJumpNoFallthrough(op, jump)) {
425 return false;
426 }
427 if (BytecodeFallsThrough(op)) {
428 JumpTarget fallthrough;
429 if (!emitJumpTarget(&fallthrough)) {
430 return false;
431 }
432 }
433 return true;
434}
435
436void BytecodeEmitter::patchJumpsToTarget(JumpList jump, JumpTarget target) {
437 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", 439); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset())"
")"); do { MOZ_CrashSequence(__null, 439); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
438 !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", 439); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset())"
")"); do { MOZ_CrashSequence(__null, 439); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
439 (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", 439); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset())"
")"); do { MOZ_CrashSequence(__null, 439); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
440 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", 441); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "0 <= target.offset.value() && target.offset <= bytecodeSection().offset()"
")"); do { MOZ_CrashSequence(__null, 441); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
441 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", 441); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "0 <= target.offset.value() && target.offset <= bytecodeSection().offset()"
")"); do { MOZ_CrashSequence(__null, 441); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
442 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", 445); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))"
")"); do { MOZ_CrashSequence(__null, 445); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
443 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", 445); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))"
")"); do { MOZ_CrashSequence(__null, 445); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
444 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", 445); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))"
")"); do { MOZ_CrashSequence(__null, 445); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
445 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", 445); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))"
")"); do { MOZ_CrashSequence(__null, 445); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
446 jump.patchAll(bytecodeSection().code(BytecodeOffset(0)), target);
447}
448
449bool BytecodeEmitter::emitJumpTargetAndPatch(JumpList jump) {
450 if (!jump.offset.valid()) {
451 return true;
452 }
453 JumpTarget target;
454 if (!emitJumpTarget(&target)) {
455 return false;
456 }
457 patchJumpsToTarget(jump, target);
458 return true;
459}
460
461bool BytecodeEmitter::emitCall(JSOp op, uint16_t argc,
462 const Maybe<uint32_t>& sourceCoordOffset) {
463 if (sourceCoordOffset.isSome()) {
464 if (!updateSourceCoordNotes(*sourceCoordOffset)) {
465 return false;
466 }
467 }
468 return emit3(op, ARGC_LO(argc), ARGC_HI(argc));
469}
470
471bool BytecodeEmitter::emitCall(JSOp op, uint16_t argc, ParseNode* pn) {
472 return emitCall(op, argc, pn ? Some(pn->pn_pos.begin) : Nothing());
473}
474
475bool BytecodeEmitter::emitDupAt(unsigned slotFromTop, unsigned count) {
476 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", 476); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "slotFromTop < unsigned(bytecodeSection().stackDepth())"
")"); do { MOZ_CrashSequence(__null, 476); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
477 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", 477); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "slotFromTop + 1 >= count" ")"); do { MOZ_CrashSequence
(__null, 477); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
478
479 if (slotFromTop == 0 && count == 1) {
480 return emit1(JSOp::Dup);
481 }
482
483 if (slotFromTop == 1 && count == 2) {
484 return emit1(JSOp::Dup2);
485 }
486
487 if (slotFromTop >= Bit(24)) {
488 reportError(nullptr, JSMSG_TOO_MANY_LOCALS);
489 return false;
490 }
491
492 for (unsigned i = 0; i < count; i++) {
493 BytecodeOffset off;
494 if (!emitN(JSOp::DupAt, 3, &off)) {
495 return false;
496 }
497
498 jsbytecode* pc = bytecodeSection().code(off);
499 SET_UINT24(pc, slotFromTop);
500 }
501
502 return true;
503}
504
505bool BytecodeEmitter::emitPopN(unsigned n) {
506 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"
, 506); AnnotateMozCrashReason("MOZ_ASSERT" "(" "n != 0" ")")
; do { MOZ_CrashSequence(__null, 506); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
507
508 if (n == 1) {
509 return emit1(JSOp::Pop);
510 }
511
512 // 2 JSOp::Pop instructions (2 bytes) are shorter than JSOp::PopN (3 bytes).
513 if (n == 2) {
514 return emit1(JSOp::Pop) && emit1(JSOp::Pop);
515 }
516
517 // Emit multiple ops if there are many values to pop.
518 while (n > UINT16_MAX(65535)) {
519 if (!emitUint16Operand(JSOp::PopN, UINT16_MAX(65535))) {
520 return false;
521 }
522 n -= UINT16_MAX(65535);
523 }
524 return emitUint16Operand(JSOp::PopN, n);
525}
526
527bool BytecodeEmitter::emitPickN(uint8_t n) {
528 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"
, 528); AnnotateMozCrashReason("MOZ_ASSERT" "(" "n != 0" ")")
; do { MOZ_CrashSequence(__null, 528); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
529
530 if (n == 1) {
531 return emit1(JSOp::Swap);
532 }
533
534 return emit2(JSOp::Pick, n);
535}
536
537bool BytecodeEmitter::emitUnpickN(uint8_t n) {
538 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"
, 538); AnnotateMozCrashReason("MOZ_ASSERT" "(" "n != 0" ")")
; do { MOZ_CrashSequence(__null, 538); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
539
540 if (n == 1) {
541 return emit1(JSOp::Swap);
542 }
543
544 return emit2(JSOp::Unpick, n);
545}
546
547bool BytecodeEmitter::emitCheckIsObj(CheckIsObjectKind kind) {
548 return emit2(JSOp::CheckIsObj, uint8_t(kind));
549}
550
551bool BytecodeEmitter::emitBuiltinObject(BuiltinObjectKind kind) {
552 return emit2(JSOp::BuiltinObject, uint8_t(kind));
553}
554
555/* Updates line number notes, not column notes. */
556bool BytecodeEmitter::updateLineNumberNotes(uint32_t offset) {
557 if (skipLocationSrcNotes()) {
558 return true;
559 }
560
561 const ErrorReporter& er = errorReporter();
562 std::optional<bool> onThisLineStatus =
563 er.isOnThisLine(offset, bytecodeSection().currentLine());
564 if (!onThisLineStatus.has_value()) {
565 er.errorNoOffset(JSMSG_OUT_OF_MEMORY);
566 return false;
567 }
568
569 bool onThisLine = *onThisLineStatus;
570
571 if (!onThisLine) {
572 unsigned line = er.lineAt(offset);
573 unsigned delta = line - bytecodeSection().currentLine();
574
575 // If we use a `SetLine` note below, we want it to be relative to the
576 // scripts initial line number for better chance of sharing.
577 unsigned initialLine = sc->extent().lineno;
578 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", 578); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "line >= initialLine" ")"); do { MOZ_CrashSequence
(__null, 578); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
579
580 /*
581 * Encode any change in the current source line number by using
582 * either several SrcNoteType::NewLine notes or just one
583 * SrcNoteType::SetLine note, whichever consumes less space.
584 *
585 * NB: We handle backward line number deltas (possible with for
586 * loops where the update part is emitted after the body, but its
587 * line number is <= any line number in the body) here by letting
588 * unsigned delta_ wrap to a very large number, which triggers a
589 * SrcNoteType::SetLine.
590 */
591 bytecodeSection().setCurrentLine(line, offset);
592 if (delta >= SrcNote::SetLine::lengthFor(line, initialLine)) {
593 if (!newSrcNote2(SrcNoteType::SetLine,
594 SrcNote::SetLine::toOperand(line, initialLine))) {
595 return false;
596 }
597 } else {
598 do {
599 if (!newSrcNote(SrcNoteType::NewLine)) {
600 return false;
601 }
602 } while (--delta != 0);
603 }
604
605 bytecodeSection().updateSeparatorPositionIfPresent();
606 }
607 return true;
608}
609
610/* Updates the line number and column number information in the source notes. */
611bool BytecodeEmitter::updateSourceCoordNotes(uint32_t offset) {
612 if (skipLocationSrcNotes()) {
613 return true;
614 }
615
616 if (!updateLineNumberNotes(offset)) {
617 return false;
618 }
619
620 JS::LimitedColumnNumberOneOrigin columnIndex =
621 errorReporter().columnAt(offset);
622
623 // Assert colspan is always representable.
624 static_assert((0 - ptrdiff_t(JS::LimitedColumnNumberOneOrigin::Limit)) >=
625 SrcNote::ColSpan::MinColSpan);
626 static_assert((ptrdiff_t(JS::LimitedColumnNumberOneOrigin::Limit) - 0) <=
627 SrcNote::ColSpan::MaxColSpan);
628
629 JS::ColumnNumberOffset colspan = columnIndex - bytecodeSection().lastColumn();
630
631 if (colspan != JS::ColumnNumberOffset::zero()) {
632 if (lastLineOnlySrcNoteIndex != LastSrcNoteIsNotLineOnly) {
633 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", 634); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "bytecodeSection().lastColumn() == JS::LimitedColumnNumberOneOrigin()"
")"); do { MOZ_CrashSequence(__null, 634); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
634 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", 634); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "bytecodeSection().lastColumn() == JS::LimitedColumnNumberOneOrigin()"
")"); do { MOZ_CrashSequence(__null, 634); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
635
636 const SrcNotesVector& notes = bytecodeSection().notes();
637 SrcNoteType type = notes[lastLineOnlySrcNoteIndex].type();
638 if (type == SrcNoteType::NewLine) {
639 if (!convertLastNewLineToNewLineColumn(columnIndex)) {
640 return false;
641 }
642 } else {
643 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"
, 643); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == SrcNoteType::SetLine"
")"); do { MOZ_CrashSequence(__null, 643); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
644 if (!convertLastSetLineToSetLineColumn(columnIndex)) {
645 return false;
646 }
647 }
648 } else {
649 if (!newSrcNote2(SrcNoteType::ColSpan,
650 SrcNote::ColSpan::toOperand(colspan))) {
651 return false;
652 }
653 }
654 bytecodeSection().setLastColumn(columnIndex, offset);
655 bytecodeSection().updateSeparatorPositionIfPresent();
656 }
657 return true;
658}
659
660bool BytecodeEmitter::updateSourceCoordNotesIfNonLiteral(ParseNode* node) {
661 if (node->isLiteral()) {
662 return true;
663 }
664 return updateSourceCoordNotes(node->pn_pos.begin);
665}
666
667uint32_t BytecodeEmitter::getOffsetForLoop(ParseNode* nextpn) const {
668 // Try to give the JSOp::LoopHead the same line number as the next
669 // instruction. nextpn is often a block, in which case the next instruction
670 // typically comes from the first statement inside.
671 if (nextpn->is<LexicalScopeNode>()) {
672 nextpn = nextpn->as<LexicalScopeNode>().scopeBody();
673 }
674 if (nextpn->isKind(ParseNodeKind::StatementList)) {
675 if (ParseNode* firstStatement = nextpn->as<ListNode>().head()) {
676 nextpn = firstStatement;
677 }
678 }
679
680 return nextpn->pn_pos.begin;
681}
682
683bool BytecodeEmitter::emitUint16Operand(JSOp op, uint32_t operand) {
684 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", 684); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "operand <= (65535)" ")"); do { MOZ_CrashSequence
(__null, 684); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
685 if (!emit3(op, UINT16_LO(operand), UINT16_HI(operand))) {
686 return false;
687 }
688 return true;
689}
690
691bool BytecodeEmitter::emitUint32Operand(JSOp op, uint32_t operand) {
692 BytecodeOffset off;
693 if (!emitN(op, 4, &off)) {
694 return false;
695 }
696 SET_UINT32(bytecodeSection().code(off), operand);
697 return true;
698}
699
700bool BytecodeEmitter::emitGoto(NestableControl* target, GotoKind kind) {
701 NonLocalExitControl nle(this, kind == GotoKind::Continue
702 ? NonLocalExitKind::Continue
703 : NonLocalExitKind::Break);
704 return nle.emitNonLocalJump(target);
705}
706
707AbstractScopePtr BytecodeEmitter::innermostScope() const {
708 return innermostEmitterScope()->scope(this);
709}
710
711ScopeIndex BytecodeEmitter::innermostScopeIndex() const {
712 return *innermostEmitterScope()->scopeIndex(this);
713}
714
715bool BytecodeEmitter::emitGCIndexOp(JSOp op, GCThingIndex index) {
716 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", 716); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "checkStrictOrSloppy(op)" ")"); do { MOZ_CrashSequence
(__null, 716); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
717
718 constexpr size_t OpLength = 1 + GCTHING_INDEX_LEN;
719 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", 719); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetOpLength(op) == OpLength" ")"); do { MOZ_CrashSequence
(__null, 719); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
720
721 BytecodeOffset offset;
722 if (!emitCheck(op, OpLength, &offset)) {
723 return false;
724 }
725
726 jsbytecode* code = bytecodeSection().code(offset);
727 code[0] = jsbytecode(op);
728 SET_GCTHING_INDEX(code, index);
729 bytecodeSection().updateDepth(op, offset);
730 return true;
731}
732
733bool BytecodeEmitter::emitAtomOp(JSOp op, TaggedParserAtomIndex atom) {
734 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"
, 734); AnnotateMozCrashReason("MOZ_ASSERT" "(" "atom" ")"); do
{ MOZ_CrashSequence(__null, 734); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
735
736 // .generator lookups should be emitted as JSOp::GetAliasedVar instead of
737 // JSOp::GetName etc, to bypass |with| objects on the scope chain.
738 // It's safe to emit .this lookups though because |with| objects skip
739 // those.
740 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", 741); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "atom != TaggedParserAtomIndex::WellKnown::dot_generator_()"
")"); do { MOZ_CrashSequence(__null, 741); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
741 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", 741); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "atom != TaggedParserAtomIndex::WellKnown::dot_generator_()"
")"); do { MOZ_CrashSequence(__null, 741); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
742
743 GCThingIndex index;
744 if (!makeAtomIndex(atom, ParserAtom::Atomize::Yes, &index)) {
745 return false;
746 }
747
748 return emitAtomOp(op, index);
749}
750
751bool BytecodeEmitter::emitAtomOp(JSOp op, GCThingIndex atomIndex) {
752 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", 752); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "JOF_OPTYPE(op) == JOF_ATOM" ")"); do { MOZ_CrashSequence
(__null, 752); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
753#ifdef DEBUG1
754 auto atom = perScriptData().gcThingList().getAtom(atomIndex);
755 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", 755); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "compilationState.parserAtoms.isInstantiatedAsJSAtom(atom)"
")"); do { MOZ_CrashSequence(__null, 755); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
756#endif
757 return emitGCIndexOp(op, atomIndex);
758}
759
760bool BytecodeEmitter::emitStringOp(JSOp op, TaggedParserAtomIndex atom) {
761 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"
, 761); AnnotateMozCrashReason("MOZ_ASSERT" "(" "atom" ")"); do
{ MOZ_CrashSequence(__null, 761); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
762 GCThingIndex index;
763 if (!makeAtomIndex(atom, ParserAtom::Atomize::No, &index)) {
764 return false;
765 }
766
767 return emitStringOp(op, index);
768}
769
770bool BytecodeEmitter::emitStringOp(JSOp op, GCThingIndex atomIndex) {
771 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"
, 771); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JOF_OPTYPE(op) == JOF_STRING"
")"); do { MOZ_CrashSequence(__null, 771); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
772 return emitGCIndexOp(op, atomIndex);
773}
774
775bool BytecodeEmitter::emitInternedScopeOp(GCThingIndex index, JSOp op) {
776 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", 776); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "JOF_OPTYPE(op) == JOF_SCOPE" ")"); do { MOZ_CrashSequence
(__null, 776); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
777 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", 777); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "index < perScriptData().gcThingList().length()"
")"); do { MOZ_CrashSequence(__null, 777); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
778 return emitGCIndexOp(op, index);
779}
780
781bool BytecodeEmitter::emitInternedObjectOp(GCThingIndex index, JSOp op) {
782 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"
, 782); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JOF_OPTYPE(op) == JOF_OBJECT"
")"); do { MOZ_CrashSequence(__null, 782); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
783 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", 783); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "index < perScriptData().gcThingList().length()"
")"); do { MOZ_CrashSequence(__null, 783); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
784 return emitGCIndexOp(op, index);
785}
786
787bool BytecodeEmitter::emitRegExp(GCThingIndex index) {
788 return emitGCIndexOp(JSOp::RegExp, index);
789}
790
791bool BytecodeEmitter::emitLocalOp(JSOp op, uint32_t slot) {
792 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"
, 792); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JOF_OPTYPE(op) != JOF_ENVCOORD"
")"); do { MOZ_CrashSequence(__null, 792); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
793 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", 793); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "IsLocalOp(op)" ")"); do { MOZ_CrashSequence
(__null, 793); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
794
795 BytecodeOffset off;
796 if (!emitN(op, LOCALNO_LEN, &off)) {
797 return false;
798 }
799
800 SET_LOCALNO(bytecodeSection().code(off), slot);
801 return true;
802}
803
804bool BytecodeEmitter::emitArgOp(JSOp op, uint16_t slot) {
805 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"
, 805); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsArgOp(op)"
")"); do { MOZ_CrashSequence(__null, 805); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
806 BytecodeOffset off;
807 if (!emitN(op, ARGNO_LEN, &off)) {
808 return false;
809 }
810
811 SET_ARGNO(bytecodeSection().code(off), slot);
812 return true;
813}
814
815bool BytecodeEmitter::emitEnvCoordOp(JSOp op, EnvironmentCoordinate ec) {
816 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", 817); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "JOF_OPTYPE(op) == JOF_ENVCOORD || JOF_OPTYPE(op) == JOF_DEBUGCOORD"
")"); do { MOZ_CrashSequence(__null, 817); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
817 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", 817); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "JOF_OPTYPE(op) == JOF_ENVCOORD || JOF_OPTYPE(op) == JOF_DEBUGCOORD"
")"); do { MOZ_CrashSequence(__null, 817); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
818
819 constexpr size_t N = ENVCOORD_HOPS_LEN + ENVCOORD_SLOT_LEN;
820 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", 820); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetOpLength(op) == 1 + N" ")"); do { MOZ_CrashSequence
(__null, 820); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
821
822 BytecodeOffset off;
823 if (!emitN(op, N, &off)) {
824 return false;
825 }
826
827 jsbytecode* pc = bytecodeSection().code(off);
828 SET_ENVCOORD_HOPS(pc, ec.hops());
829 pc += ENVCOORD_HOPS_LEN;
830 SET_ENVCOORD_SLOT(pc, ec.slot());
831 pc += ENVCOORD_SLOT_LEN;
Value stored to 'pc' is never read
832 return true;
833}
834
835bool BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer) const {
836 AutoCheckRecursionLimit recursion(fc);
837 if (!recursion.check(fc)) {
838 return false;
839 }
840
841restart:
842
843 switch (pn->getKind()) {
844 // Trivial cases with no side effects.
845 case ParseNodeKind::EmptyStmt:
846 case ParseNodeKind::TrueExpr:
847 case ParseNodeKind::FalseExpr:
848 case ParseNodeKind::NullExpr:
849 case ParseNodeKind::RawUndefinedExpr:
850 case ParseNodeKind::Elision:
851 case ParseNodeKind::Generator:
852 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"
, 852); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<NullaryNode>()"
")"); do { MOZ_CrashSequence(__null, 852); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
853 *answer = false;
854 return true;
855
856 case ParseNodeKind::ObjectPropertyName:
857 case ParseNodeKind::PrivateName: // no side effects, unlike
858 // ParseNodeKind::Name
859 case ParseNodeKind::StringExpr:
860 case ParseNodeKind::TemplateStringExpr:
861 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", 861); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "pn->is<NameNode>()" ")"); do { MOZ_CrashSequence
(__null, 861); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
862 *answer = false;
863 return true;
864
865 case ParseNodeKind::RegExpExpr:
866 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"
, 866); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<RegExpLiteral>()"
")"); do { MOZ_CrashSequence(__null, 866); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
867 *answer = false;
868 return true;
869
870 case ParseNodeKind::NumberExpr:
871 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"
, 871); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<NumericLiteral>()"
")"); do { MOZ_CrashSequence(__null, 871); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
872 *answer = false;
873 return true;
874
875 case ParseNodeKind::BigIntExpr:
876 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"
, 876); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BigIntLiteral>()"
")"); do { MOZ_CrashSequence(__null, 876); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
877 *answer = false;
878 return true;
879
880 // |this| can throw in derived class constructors, including nested arrow
881 // functions or eval.
882 case ParseNodeKind::ThisExpr:
883 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"
, 883); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { MOZ_CrashSequence(__null, 883); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
884 *answer = sc->needsThisTDZChecks();
885 return true;
886
887 // |new.target| doesn't have any side-effects.
888 case ParseNodeKind::NewTargetExpr: {
889 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"
, 889); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<NewTargetNode>()"
")"); do { MOZ_CrashSequence(__null, 889); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
890 *answer = false;
891 return true;
892 }
893
894 // Trivial binary nodes with more token pos holders.
895 case ParseNodeKind::ImportMetaExpr: {
896 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", 896); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "pn->as<BinaryNode>().left()->isKind(ParseNodeKind::PosHolder)"
")"); do { MOZ_CrashSequence(__null, 896); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
897 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", 898); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "pn->as<BinaryNode>().right()->isKind(ParseNodeKind::PosHolder)"
")"); do { MOZ_CrashSequence(__null, 898); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
898 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", 898); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "pn->as<BinaryNode>().right()->isKind(ParseNodeKind::PosHolder)"
")"); do { MOZ_CrashSequence(__null, 898); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
899 *answer = false;
900 return true;
901 }
902
903 case ParseNodeKind::BreakStmt:
904 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"
, 904); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BreakStatement>()"
")"); do { MOZ_CrashSequence(__null, 904); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
905 *answer = true;
906 return true;
907
908 case ParseNodeKind::ContinueStmt:
909 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"
, 909); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<ContinueStatement>()"
")"); do { MOZ_CrashSequence(__null, 909); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
910 *answer = true;
911 return true;
912
913 case ParseNodeKind::DebuggerStmt:
914 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"
, 914); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<DebuggerStatement>()"
")"); do { MOZ_CrashSequence(__null, 914); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
915 *answer = true;
916 return true;
917
918 // Watch out for getters!
919 case ParseNodeKind::OptionalDotExpr:
920 case ParseNodeKind::DotExpr:
921 case ParseNodeKind::ArgumentsLength:
922 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"
, 922); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { MOZ_CrashSequence(__null, 922); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
923 *answer = true;
924 return true;
925
926 // Unary cases with side effects only if the child has them.
927 case ParseNodeKind::TypeOfExpr:
928 case ParseNodeKind::VoidExpr:
929 case ParseNodeKind::NotExpr:
930 return checkSideEffects(pn->as<UnaryNode>().kid(), answer);
931
932 // Even if the name expression is effect-free, performing ToPropertyKey on
933 // it might not be effect-free:
934 //
935 // RegExp.prototype.toString = () => { throw 42; };
936 // ({ [/regex/]: 0 }); // ToPropertyKey(/regex/) throws 42
937 //
938 // function Q() {
939 // ({ [new.target]: 0 });
940 // }
941 // Q.toString = () => { throw 17; };
942 // new Q; // new.target will be Q, ToPropertyKey(Q) throws 17
943 case ParseNodeKind::ComputedName:
944 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"
, 944); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { MOZ_CrashSequence(__null, 944); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
945 *answer = true;
946 return true;
947
948 // Looking up or evaluating the associated name could throw.
949 case ParseNodeKind::TypeOfNameExpr:
950 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"
, 950); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { MOZ_CrashSequence(__null, 950); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
951 *answer = true;
952 return true;
953
954 // This unary case has side effects on the enclosing object, sure. But
955 // that's not the question this function answers: it's whether the
956 // operation may have a side effect on something *other* than the result
957 // of the overall operation in which it's embedded. The answer to that
958 // is no, because an object literal having a mutated prototype only
959 // produces a value, without affecting anything else.
960 case ParseNodeKind::MutateProto:
961 return checkSideEffects(pn->as<UnaryNode>().kid(), answer);
962
963 // Unary cases with obvious side effects.
964 case ParseNodeKind::PreIncrementExpr:
965 case ParseNodeKind::PostIncrementExpr:
966 case ParseNodeKind::PreDecrementExpr:
967 case ParseNodeKind::PostDecrementExpr:
968 case ParseNodeKind::ThrowStmt:
969 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"
, 969); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { MOZ_CrashSequence(__null, 969); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
970 *answer = true;
971 return true;
972
973 // These might invoke valueOf/toString, even with a subexpression without
974 // side effects! Consider |+{ valueOf: null, toString: null }|.
975 case ParseNodeKind::BitNotExpr:
976 case ParseNodeKind::PosExpr:
977 case ParseNodeKind::NegExpr:
978 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"
, 978); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { MOZ_CrashSequence(__null, 978); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
979 *answer = true;
980 return true;
981
982 // This invokes the (user-controllable) iterator protocol.
983 case ParseNodeKind::Spread:
984 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"
, 984); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { MOZ_CrashSequence(__null, 984); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
985 *answer = true;
986 return true;
987
988 case ParseNodeKind::InitialYield:
989 case ParseNodeKind::YieldStarExpr:
990 case ParseNodeKind::YieldExpr:
991 case ParseNodeKind::AwaitExpr:
992 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"
, 992); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { MOZ_CrashSequence(__null, 992); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
993 *answer = true;
994 return true;
995
996 // Deletion generally has side effects, even if isolated cases have none.
997 case ParseNodeKind::DeleteNameExpr:
998 case ParseNodeKind::DeletePropExpr:
999 case ParseNodeKind::DeleteElemExpr:
1000 case ParseNodeKind::DeleteOptionalChainExpr:
1001 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"
, 1001); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { MOZ_CrashSequence(__null, 1001); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1002 *answer = true;
1003 return true;
1004
1005 // Deletion of a non-Reference expression has side effects only through
1006 // evaluating the expression.
1007 case ParseNodeKind::DeleteExpr: {
1008 ParseNode* expr = pn->as<UnaryNode>().kid();
1009 return checkSideEffects(expr, answer);
1010 }
1011
1012 case ParseNodeKind::ExpressionStmt:
1013 return checkSideEffects(pn->as<UnaryNode>().kid(), answer);
1014
1015 // Binary cases with obvious side effects.
1016 case ParseNodeKind::InitExpr:
1017 *answer = true;
1018 return true;
1019
1020 case ParseNodeKind::AssignExpr:
1021 case ParseNodeKind::AddAssignExpr:
1022 case ParseNodeKind::SubAssignExpr:
1023 case ParseNodeKind::CoalesceAssignExpr:
1024 case ParseNodeKind::OrAssignExpr:
1025 case ParseNodeKind::AndAssignExpr:
1026 case ParseNodeKind::BitOrAssignExpr:
1027 case ParseNodeKind::BitXorAssignExpr:
1028 case ParseNodeKind::BitAndAssignExpr:
1029 case ParseNodeKind::LshAssignExpr:
1030 case ParseNodeKind::RshAssignExpr:
1031 case ParseNodeKind::UrshAssignExpr:
1032 case ParseNodeKind::MulAssignExpr:
1033 case ParseNodeKind::DivAssignExpr:
1034 case ParseNodeKind::ModAssignExpr:
1035 case ParseNodeKind::PowAssignExpr:
1036 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"
, 1036); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<AssignmentNode>()"
")"); do { MOZ_CrashSequence(__null, 1036); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1037 *answer = true;
1038 return true;
1039
1040 case ParseNodeKind::SetThis:
1041 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"
, 1041); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { MOZ_CrashSequence(__null, 1041); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1042 *answer = true;
1043 return true;
1044
1045 case ParseNodeKind::StatementList:
1046 // Strict equality operations and short circuit operators are well-behaved
1047 // and perform no conversions.
1048 case ParseNodeKind::CoalesceExpr:
1049 case ParseNodeKind::OrExpr:
1050 case ParseNodeKind::AndExpr:
1051 case ParseNodeKind::StrictEqExpr:
1052 case ParseNodeKind::StrictNeExpr:
1053 // Any subexpression of a comma expression could be effectful.
1054 case ParseNodeKind::CommaExpr:
1055 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"
, 1055); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!pn->as<ListNode>().empty()"
")"); do { MOZ_CrashSequence(__null, 1055); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1056 [[fallthrough]];
1057 // Subcomponents of a literal may be effectful.
1058 case ParseNodeKind::ArrayExpr:
1059 case ParseNodeKind::ObjectExpr:
1060 for (ParseNode* item : pn->as<ListNode>().contents()) {
1061 if (!checkSideEffects(item, answer)) {
1062 return false;
1063 }
1064 if (*answer) {
1065 return true;
1066 }
1067 }
1068 return true;
1069
1070#ifdef ENABLE_DECORATORS
1071 case ParseNodeKind::DecoratorList:
1072 MOZ_CRASH("Decorators are not supported yet")do { do { } while (false); MOZ_ReportCrash("" "Decorators are not supported yet"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 1072);
AnnotateMozCrashReason("MOZ_CRASH(" "Decorators are not supported yet"
")"); do { MOZ_CrashSequence(__null, 1072); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
1073#endif
1074
1075 case ParseNodeKind::UsingDecl:
1076 case ParseNodeKind::AwaitUsingDecl:
1077 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", 1077);
AnnotateMozCrashReason("MOZ_CRASH(" "Using declarations are not supported yet"
")"); do { MOZ_CrashSequence(__null, 1077); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
1078
1079 // Most other binary operations (parsed as lists in SpiderMonkey) may
1080 // perform conversions triggering side effects. Math operations perform
1081 // ToNumber and may fail invoking invalid user-defined toString/valueOf:
1082 // |5 < { toString: null }|. |instanceof| throws if provided a
1083 // non-object constructor: |null instanceof null|. |in| throws if given
1084 // a non-object RHS: |5 in null|.
1085 case ParseNodeKind::BitOrExpr:
1086 case ParseNodeKind::BitXorExpr:
1087 case ParseNodeKind::BitAndExpr:
1088 case ParseNodeKind::EqExpr:
1089 case ParseNodeKind::NeExpr:
1090 case ParseNodeKind::LtExpr:
1091 case ParseNodeKind::LeExpr:
1092 case ParseNodeKind::GtExpr:
1093 case ParseNodeKind::GeExpr:
1094 case ParseNodeKind::InstanceOfExpr:
1095 case ParseNodeKind::InExpr:
1096 case ParseNodeKind::PrivateInExpr:
1097 case ParseNodeKind::LshExpr:
1098 case ParseNodeKind::RshExpr:
1099 case ParseNodeKind::UrshExpr:
1100 case ParseNodeKind::AddExpr:
1101 case ParseNodeKind::SubExpr:
1102 case ParseNodeKind::MulExpr:
1103 case ParseNodeKind::DivExpr:
1104 case ParseNodeKind::ModExpr:
1105 case ParseNodeKind::PowExpr:
1106 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", 1106);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->as<ListNode>().count() >= 2"
")"); do { MOZ_CrashSequence(__null, 1106); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1107 *answer = true;
1108 return true;
1109
1110 case ParseNodeKind::PropertyDefinition:
1111 case ParseNodeKind::Case: {
1112 BinaryNode* node = &pn->as<BinaryNode>();
1113 if (!checkSideEffects(node->left(), answer)) {
1114 return false;
1115 }
1116 if (*answer) {
1117 return true;
1118 }
1119 return checkSideEffects(node->right(), answer);
1120 }
1121
1122 // More getters.
1123 case ParseNodeKind::ElemExpr:
1124 case ParseNodeKind::OptionalElemExpr:
1125 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"
, 1125); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { MOZ_CrashSequence(__null, 1125); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1126 *answer = true;
1127 return true;
1128
1129 // Throws if the operand is not of the right class. Can also call a private
1130 // getter.
1131 case ParseNodeKind::PrivateMemberExpr:
1132 case ParseNodeKind::OptionalPrivateMemberExpr:
1133 *answer = true;
1134 return true;
1135
1136 // These affect visible names in this code, or in other code.
1137 case ParseNodeKind::ImportDecl:
1138 case ParseNodeKind::ExportFromStmt:
1139 case ParseNodeKind::ExportDefaultStmt:
1140 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"
, 1140); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { MOZ_CrashSequence(__null, 1140); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1141 *answer = true;
1142 return true;
1143
1144 // Likewise.
1145 case ParseNodeKind::ExportStmt:
1146 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"
, 1146); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { MOZ_CrashSequence(__null, 1146); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1147 *answer = true;
1148 return true;
1149
1150 case ParseNodeKind::CallImportExpr:
1151 case ParseNodeKind::CallImportSpec:
1152 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"
, 1152); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { MOZ_CrashSequence(__null, 1152); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1153 *answer = true;
1154 return true;
1155
1156 // Every part of a loop might be effect-free, but looping infinitely *is*
1157 // an effect. (Language lawyer trivia: C++ says threads can be assumed
1158 // to exit or have side effects, C++14 [intro.multithread]p27, so a C++
1159 // implementation's equivalent of the below could set |*answer = false;|
1160 // if all loop sub-nodes set |*answer = false|!)
1161 case ParseNodeKind::DoWhileStmt:
1162 case ParseNodeKind::WhileStmt:
1163 case ParseNodeKind::ForStmt:
1164 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"
, 1164); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { MOZ_CrashSequence(__null, 1164); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1165 *answer = true;
1166 return true;
1167
1168 // Declarations affect the name set of the relevant scope.
1169 case ParseNodeKind::VarStmt:
1170 case ParseNodeKind::ConstDecl:
1171 case ParseNodeKind::LetDecl:
1172 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", 1172);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<ListNode>()"
")"); do { MOZ_CrashSequence(__null, 1172); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1173 *answer = true;
1174 return true;
1175
1176 case ParseNodeKind::IfStmt:
1177 case ParseNodeKind::ConditionalExpr: {
1178 TernaryNode* node = &pn->as<TernaryNode>();
1179 if (!checkSideEffects(node->kid1(), answer)) {
1180 return false;
1181 }
1182 if (*answer) {
1183 return true;
1184 }
1185 if (!checkSideEffects(node->kid2(), answer)) {
1186 return false;
1187 }
1188 if (*answer) {
1189 return true;
1190 }
1191 if ((pn = node->kid3())) {
1192 goto restart;
1193 }
1194 return true;
1195 }
1196
1197 // Function calls can invoke non-local code.
1198 case ParseNodeKind::NewExpr:
1199 case ParseNodeKind::CallExpr:
1200 case ParseNodeKind::OptionalCallExpr:
1201 case ParseNodeKind::TaggedTemplateExpr:
1202 case ParseNodeKind::SuperCallExpr:
1203 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"
, 1203); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { MOZ_CrashSequence(__null, 1203); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1204 *answer = true;
1205 return true;
1206
1207 // Function arg lists can contain arbitrary expressions. Technically
1208 // this only causes side-effects if one of the arguments does, but since
1209 // the call being made will always trigger side-effects, it isn't needed.
1210 case ParseNodeKind::Arguments:
1211 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", 1211);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<ListNode>()"
")"); do { MOZ_CrashSequence(__null, 1211); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1212 *answer = true;
1213 return true;
1214
1215 case ParseNodeKind::OptionalChain:
1216 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"
, 1216); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { MOZ_CrashSequence(__null, 1216); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1217 *answer = true;
1218 return true;
1219
1220 // Classes typically introduce names. Even if no name is introduced,
1221 // the heritage and/or class body (through computed property names)
1222 // usually have effects.
1223 case ParseNodeKind::ClassDecl:
1224 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"
, 1224); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<ClassNode>()"
")"); do { MOZ_CrashSequence(__null, 1224); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1225 *answer = true;
1226 return true;
1227
1228 // |with| calls |ToObject| on its expression and so throws if that value
1229 // is null/undefined.
1230 case ParseNodeKind::WithStmt:
1231 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"
, 1231); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { MOZ_CrashSequence(__null, 1231); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1232 *answer = true;
1233 return true;
1234
1235 case ParseNodeKind::ReturnStmt:
1236 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"
, 1236); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { MOZ_CrashSequence(__null, 1236); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1237 *answer = true;
1238 return true;
1239
1240 case ParseNodeKind::Name:
1241 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", 1241);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<NameNode>()"
")"); do { MOZ_CrashSequence(__null, 1241); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1242 *answer = true;
1243 return true;
1244
1245 // Shorthands could trigger getters: the |x| in the object literal in
1246 // |with ({ get x() { throw 42; } }) ({ x });|, for example, triggers
1247 // one. (Of course, it isn't necessary to use |with| for a shorthand to
1248 // trigger a getter.)
1249 case ParseNodeKind::Shorthand:
1250 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"
, 1250); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { MOZ_CrashSequence(__null, 1250); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1251 *answer = true;
1252 return true;
1253
1254 case ParseNodeKind::Function:
1255 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"
, 1255); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<FunctionNode>()"
")"); do { MOZ_CrashSequence(__null, 1255); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1256 /*
1257 * A named function, contrary to ES3, is no longer effectful, because
1258 * we bind its name lexically (using JSOp::Callee) instead of creating
1259 * an Object instance and binding a readonly, permanent property in it
1260 * (the object and binding can be detected and hijacked or captured).
1261 * This is a bug fix to ES3; it is fixed in ES3.1 drafts.
1262 */
1263 *answer = false;
1264 return true;
1265
1266 case ParseNodeKind::Module:
1267 *answer = false;
1268 return true;
1269
1270 case ParseNodeKind::TryStmt: {
1271 TryNode* tryNode = &pn->as<TryNode>();
1272 if (!checkSideEffects(tryNode->body(), answer)) {
1273 return false;
1274 }
1275 if (*answer) {
1276 return true;
1277 }
1278 if (LexicalScopeNode* catchScope = tryNode->catchScope()) {
1279 if (!checkSideEffects(catchScope, answer)) {
1280 return false;
1281 }
1282 if (*answer) {
1283 return true;
1284 }
1285 }
1286 if (ParseNode* finallyBlock = tryNode->finallyBlock()) {
1287 if (!checkSideEffects(finallyBlock, answer)) {
1288 return false;
1289 }
1290 }
1291 return true;
1292 }
1293
1294 case ParseNodeKind::Catch: {
1295 BinaryNode* catchClause = &pn->as<BinaryNode>();
1296 if (ParseNode* name = catchClause->left()) {
1297 if (!checkSideEffects(name, answer)) {
1298 return false;
1299 }
1300 if (*answer) {
1301 return true;
1302 }
1303 }
1304 return checkSideEffects(catchClause->right(), answer);
1305 }
1306
1307 case ParseNodeKind::SwitchStmt: {
1308 SwitchStatement* switchStmt = &pn->as<SwitchStatement>();
1309 if (!checkSideEffects(&switchStmt->discriminant(), answer)) {
1310 return false;
1311 }
1312 return *answer ||
1313 checkSideEffects(&switchStmt->lexicalForCaseList(), answer);
1314 }
1315
1316 case ParseNodeKind::LabelStmt:
1317 return checkSideEffects(pn->as<LabeledStatement>().statement(), answer);
1318
1319 case ParseNodeKind::LexicalScope:
1320 return checkSideEffects(pn->as<LexicalScopeNode>().scopeBody(), answer);
1321
1322 // We could methodically check every interpolated expression, but it's
1323 // probably not worth the trouble. Treat template strings as effect-free
1324 // only if they don't contain any substitutions.
1325 case ParseNodeKind::TemplateStringListExpr: {
1326 ListNode* list = &pn->as<ListNode>();
1327 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", 1327);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!list->empty()" ")"
); do { MOZ_CrashSequence(__null, 1327); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1328 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"
, 1330); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(list->count() % 2) == 1"
") (" "template strings must alternate template and substitution "
"parts" ")"); do { MOZ_CrashSequence(__null, 1330); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
1329 "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"
, 1330); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(list->count() % 2) == 1"
") (" "template strings must alternate template and substitution "
"parts" ")"); do { MOZ_CrashSequence(__null, 1330); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
1330 "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"
, 1330); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(list->count() % 2) == 1"
") (" "template strings must alternate template and substitution "
"parts" ")"); do { MOZ_CrashSequence(__null, 1330); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
1331 *answer = list->count() > 1;
1332 return true;
1333 }
1334
1335 // This should be unreachable but is left as-is for now.
1336 case ParseNodeKind::ParamsBody:
1337 *answer = true;
1338 return true;
1339
1340 case ParseNodeKind::ForIn: // by ParseNodeKind::For
1341 case ParseNodeKind::ForOf: // by ParseNodeKind::For
1342 case ParseNodeKind::ForHead: // by ParseNodeKind::For
1343 case ParseNodeKind::DefaultConstructor: // by ParseNodeKind::ClassDecl
1344 case ParseNodeKind::ClassBodyScope: // by ParseNodeKind::ClassDecl
1345 case ParseNodeKind::ClassMethod: // by ParseNodeKind::ClassDecl
1346 case ParseNodeKind::ClassField: // by ParseNodeKind::ClassDecl
1347 case ParseNodeKind::ClassNames: // by ParseNodeKind::ClassDecl
1348 case ParseNodeKind::StaticClassBlock: // by ParseNodeKind::ClassDecl
1349 case ParseNodeKind::ClassMemberList: // by ParseNodeKind::ClassDecl
1350 case ParseNodeKind::ImportSpecList: // by ParseNodeKind::Import
1351 case ParseNodeKind::ImportSpec: // by ParseNodeKind::Import
1352 case ParseNodeKind::ImportNamespaceSpec: // by ParseNodeKind::Import
1353 case ParseNodeKind::ImportAttribute: // by ParseNodeKind::Import
1354 case ParseNodeKind::ImportAttributeList: // by ParseNodeKind::Import
1355 case ParseNodeKind::ImportModuleRequest: // by ParseNodeKind::Import
1356 case ParseNodeKind::ExportBatchSpecStmt: // by ParseNodeKind::Export
1357 case ParseNodeKind::ExportSpecList: // by ParseNodeKind::Export
1358 case ParseNodeKind::ExportSpec: // by ParseNodeKind::Export
1359 case ParseNodeKind::ExportNamespaceSpec: // by ParseNodeKind::Export
1360 case ParseNodeKind::CallSiteObj: // by ParseNodeKind::TaggedTemplate
1361 case ParseNodeKind::PosHolder: // by ParseNodeKind::NewTarget
1362 case ParseNodeKind::SuperBase: // by ParseNodeKind::Elem and others
1363 case ParseNodeKind::PropertyNameExpr: // by ParseNodeKind::Dot
1364 MOZ_CRASH("handled by parent nodes")do { do { } while (false); MOZ_ReportCrash("" "handled by parent nodes"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 1364);
AnnotateMozCrashReason("MOZ_CRASH(" "handled by parent nodes"
")"); do { MOZ_CrashSequence(__null, 1364); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
1365
1366 case ParseNodeKind::LastUnused:
1367 case ParseNodeKind::Limit:
1368 MOZ_CRASH("invalid node kind")do { do { } while (false); MOZ_ReportCrash("" "invalid node kind"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 1368);
AnnotateMozCrashReason("MOZ_CRASH(" "invalid node kind" ")")
; do { MOZ_CrashSequence(__null, 1368); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
1369 }
1370
1371 MOZ_CRASH(do { do { } while (false); MOZ_ReportCrash("" "invalid, unenumerated ParseNodeKind value encountered in "
"BytecodeEmitter::checkSideEffects", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 1373); AnnotateMozCrashReason("MOZ_CRASH(" "invalid, unenumerated ParseNodeKind value encountered in "
"BytecodeEmitter::checkSideEffects" ")"); do { MOZ_CrashSequence
(__null, 1373); __attribute__((nomerge)) ::abort(); } while (
false); } while (false)
1372 "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"
, 1373); AnnotateMozCrashReason("MOZ_CRASH(" "invalid, unenumerated ParseNodeKind value encountered in "
"BytecodeEmitter::checkSideEffects" ")"); do { MOZ_CrashSequence
(__null, 1373); __attribute__((nomerge)) ::abort(); } while (
false); } while (false)
1373 "BytecodeEmitter::checkSideEffects")do { do { } while (false); MOZ_ReportCrash("" "invalid, unenumerated ParseNodeKind value encountered in "
"BytecodeEmitter::checkSideEffects", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 1373); AnnotateMozCrashReason("MOZ_CRASH(" "invalid, unenumerated ParseNodeKind value encountered in "
"BytecodeEmitter::checkSideEffects" ")"); do { MOZ_CrashSequence
(__null, 1373); __attribute__((nomerge)) ::abort(); } while (
false); } while (false)
;
1374}
1375
1376bool BytecodeEmitter::isInLoop() const {
1377 return findInnermostNestableControl<LoopControl>();
1378}
1379
1380bool BytecodeEmitter::checkSingletonContext() const {
1381 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", 1381);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isTopLevelContext()"
")"); do { MOZ_CrashSequence(__null, 1381); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
1382 return sc->treatAsRunOnce() && !isInLoop();
1383}
1384
1385bool BytecodeEmitter::needsImplicitThis() const {
1386 // Short-circuit if there is an enclosing 'with' scope.
1387 if (sc->inWith()) {
1388 return true;
1389 }
1390
1391 // Otherwise see if the current point is under a 'with'.
1392 for (EmitterScope* es = innermostEmitterScope(); es;
1393 es = es->enclosingInFrame()) {
1394 if (es->scope(this).kind() == ScopeKind::With) {
1395 return true;
1396 }
1397 }
1398
1399 return false;
1400}
1401
1402size_t BytecodeEmitter::countThisEnvironmentHops() const {
1403 unsigned numHops = 0;
1404
1405 for (const auto* current = this; current; current = current->parent) {
1406 for (EmitterScope* es = current->innermostEmitterScope(); es;
1407 es = es->enclosingInFrame()) {
1408 if (es->scope(current).is<FunctionScope>()) {
1409 if (!es->scope(current).isArrow()) {
1410 // The Parser is responsible for marking the environment as either
1411 // closed-over or used-by-eval which ensure that is must exist.
1412 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", 1412);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "es->scope(current).hasEnvironment()"
")"); do { MOZ_CrashSequence(__null, 1412); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1413 return numHops;
1414 }
1415 }
1416 if (es->scope(current).hasEnvironment()) {
1417 numHops++;
1418 }
1419 }
1420 }
1421
1422 // The "this" environment exists outside of the compilation, but the
1423 // `ScopeContext` recorded the number of additional hops needed, so add
1424 // those in now.
1425 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", 1425);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->allowSuperProperty()"
")"); do { MOZ_CrashSequence(__null, 1425); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1426 numHops += compilationState.scopeContext.enclosingThisEnvironmentHops;
1427 return numHops;
1428}
1429
1430bool BytecodeEmitter::emitThisEnvironmentCallee() {
1431 // Get the innermost enclosing function that has a |this| binding.
1432
1433 // Directly load callee from the frame if possible.
1434 if (sc->isFunctionBox() && !sc->asFunctionBox()->isArrow()) {
1435 return emit1(JSOp::Callee);
1436 }
1437
1438 // We have to load the callee from the environment chain.
1439 size_t numHops = countThisEnvironmentHops();
1440
1441 static_assert(
1442 ENVCOORD_HOPS_LIMIT - 1 <= UINT16_MAX(65535),
1443 "JSOp::EnvCallee operand size should match ENVCOORD_HOPS_LIMIT");
1444
1445 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"
, 1445); AnnotateMozCrashReason("MOZ_ASSERT" "(" "numHops < ENVCOORD_HOPS_LIMIT - 1"
")"); do { MOZ_CrashSequence(__null, 1445); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1446
1447 return emitUint16Operand(JSOp::EnvCallee, numHops);
1448}
1449
1450bool BytecodeEmitter::emitSuperBase() {
1451 if (!emitThisEnvironmentCallee()) {
1452 return false;
1453 }
1454
1455 return emit1(JSOp::SuperBase);
1456}
1457
1458void BytecodeEmitter::reportError(ParseNode* pn, unsigned errorNumber,
1459 ...) const {
1460 uint32_t offset = pn ? pn->pn_pos.begin : *scriptStartOffset;
1461
1462 va_list args;
1463 va_start(args, errorNumber)__builtin_va_start(args, errorNumber);
1464
1465 errorReporter().errorWithNotesAtVA(nullptr, AsVariant(offset), errorNumber,
1466 &args);
1467
1468 va_end(args)__builtin_va_end(args);
1469}
1470
1471void BytecodeEmitter::reportError(uint32_t offset, unsigned errorNumber,
1472 ...) const {
1473 va_list args;
1474 va_start(args, errorNumber)__builtin_va_start(args, errorNumber);
1475
1476 errorReporter().errorWithNotesAtVA(nullptr, AsVariant(offset), errorNumber,
1477 &args);
1478
1479 va_end(args)__builtin_va_end(args);
1480}
1481
1482bool BytecodeEmitter::addObjLiteralData(ObjLiteralWriter& writer,
1483 GCThingIndex* outIndex) {
1484 if (!writer.checkForDuplicatedNames(fc)) {
1485 return false;
1486 }
1487
1488 size_t len = writer.getCode().size();
1489 auto* code = compilationState.alloc.newArrayUninitialized<uint8_t>(len);
1490 if (!code) {
1491 js::ReportOutOfMemory(fc);
1492 return false;
1493 }
1494 memcpy(code, writer.getCode().data(), len);
1495
1496 ObjLiteralIndex objIndex(compilationState.objLiteralData.length());
1497 if (uint32_t(objIndex) >= TaggedScriptThingIndex::IndexLimit) {
1498 ReportAllocationOverflow(fc);
1499 return false;
1500 }
1501 if (!compilationState.objLiteralData.emplaceBack(code, len, writer.getKind(),
1502 writer.getFlags(),
1503 writer.getPropertyCount())) {
1504 js::ReportOutOfMemory(fc);
1505 return false;
1506 }
1507
1508 return perScriptData().gcThingList().append(objIndex, outIndex);
1509}
1510
1511bool BytecodeEmitter::emitPrepareIteratorResult() {
1512 constexpr JSOp op = JSOp::NewObject;
1513
1514 ObjLiteralWriter writer;
1515 writer.beginShape(op);
1516
1517 writer.setPropNameNoDuplicateCheck(parserAtoms(),
1518 TaggedParserAtomIndex::WellKnown::value());
1519 if (!writer.propWithUndefinedValue(fc)) {
1520 return false;
1521 }
1522 writer.setPropNameNoDuplicateCheck(parserAtoms(),
1523 TaggedParserAtomIndex::WellKnown::done());
1524 if (!writer.propWithUndefinedValue(fc)) {
1525 return false;
1526 }
1527
1528 GCThingIndex shape;
1529 if (!addObjLiteralData(writer, &shape)) {
1530 return false;
1531 }
1532
1533 return emitGCIndexOp(op, shape);
1534}
1535
1536bool BytecodeEmitter::emitFinishIteratorResult(bool done) {
1537 if (!emitAtomOp(JSOp::InitProp, TaggedParserAtomIndex::WellKnown::value())) {
1538 return false;
1539 }
1540 if (!emit1(done ? JSOp::True : JSOp::False)) {
1541 return false;
1542 }
1543 if (!emitAtomOp(JSOp::InitProp, TaggedParserAtomIndex::WellKnown::done())) {
1544 return false;
1545 }
1546 return true;
1547}
1548
1549bool BytecodeEmitter::emitGetNameAtLocation(TaggedParserAtomIndex name,
1550 const NameLocation& loc) {
1551 NameOpEmitter noe(this, name, loc, NameOpEmitter::Kind::Get);
1552 if (!noe.emitGet()) {
1553 return false;
1554 }
1555
1556 return true;
1557}
1558
1559bool BytecodeEmitter::emitGetName(NameNode* name) {
1560 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"
, 1560); AnnotateMozCrashReason("MOZ_ASSERT" "(" "name->isKind(ParseNodeKind::Name)"
")"); do { MOZ_CrashSequence(__null, 1560); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1561
1562 return emitGetName(name->name());
1563}
1564
1565bool BytecodeEmitter::emitGetPrivateName(NameNode* name) {
1566 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", 1566);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "name->isKind(ParseNodeKind::PrivateName)"
")"); do { MOZ_CrashSequence(__null, 1566); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1567 return emitGetPrivateName(name->name());
1568}
1569
1570bool BytecodeEmitter::emitGetPrivateName(TaggedParserAtomIndex nameAtom) {
1571 // The parser ensures the private name is present on the environment chain,
1572 // but its location can be Dynamic or Global when emitting debugger
1573 // eval-in-frame code.
1574 NameLocation location = lookupName(nameAtom);
1575 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", 1578);
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, 1578); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1576 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", 1578);
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, 1578); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1577 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", 1578);
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, 1578); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1578 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", 1578);
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, 1578); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1579
1580 return emitGetNameAtLocation(nameAtom, location);
1581}
1582
1583bool BytecodeEmitter::emitTDZCheckIfNeeded(TaggedParserAtomIndex name,
1584 const NameLocation& loc,
1585 ValueIsOnStack isOnStack) {
1586 // Dynamic accesses have TDZ checks built into their VM code and should
1587 // never emit explicit TDZ checks.
1588 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", 1588);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "loc.hasKnownSlot()"
")"); do { MOZ_CrashSequence(__null, 1588); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1589 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", 1589);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "loc.isLexical() || loc.isPrivateMethod() || loc.isSynthetic()"
")"); do { MOZ_CrashSequence(__null, 1589); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1590
1591 // Private names are implemented as lexical bindings, but it's just an
1592 // implementation detail. Per spec there's no TDZ check when using them.
1593 if (parserAtoms().isPrivateName(name)) {
1594 return true;
1595 }
1596
1597 // `.initializers` is an implementation detail that is always populated
1598 // before a constructor can read it.
1599 if (name == TaggedParserAtomIndex::WellKnown::dot_initializers_()) {
1600 return true;
1601 }
1602
1603 Maybe<MaybeCheckTDZ> check =
1604 innermostTDZCheckCache->needsTDZCheck(this, name);
1605 if (!check) {
1606 return false;
1607 }
1608
1609 // We've already emitted a check in this basic block.
1610 if (*check == DontCheckTDZ) {
1611 return true;
1612 }
1613
1614 // If the value is not on the stack, we have to load it first.
1615 if (isOnStack == ValueIsOnStack::No) {
1616 if (loc.kind() == NameLocation::Kind::FrameSlot) {
1617 if (!emitLocalOp(JSOp::GetLocal, loc.frameSlot())) {
1618 return false;
1619 }
1620 } else {
1621 if (!emitEnvCoordOp(JSOp::GetAliasedVar, loc.environmentCoordinate())) {
1622 return false;
1623 }
1624 }
1625 }
1626
1627 // Emit the lexical check.
1628 if (loc.kind() == NameLocation::Kind::FrameSlot) {
1629 if (!emitLocalOp(JSOp::CheckLexical, loc.frameSlot())) {
1630 return false;
1631 }
1632 } else {
1633 if (!emitEnvCoordOp(JSOp::CheckAliasedLexical,
1634 loc.environmentCoordinate())) {
1635 return false;
1636 }
1637 }
1638
1639 // Pop the value if needed.
1640 if (isOnStack == ValueIsOnStack::No) {
1641 if (!emit1(JSOp::Pop)) {
1642 return false;
1643 }
1644 }
1645
1646 return innermostTDZCheckCache->noteTDZCheck(this, name, DontCheckTDZ);
1647}
1648
1649bool BytecodeEmitter::emitPropLHS(NonOptionalPropertyAccessBase* prop) {
1650 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", 1650);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!prop->isSuper()"
")"); do { MOZ_CrashSequence(__null, 1650); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1651
1652 ParseNode* expr = &prop->expression();
1653
1654 // Not all non-optional property accesses can be flattened (e.g. super.x or
1655 // arguments.length); use emitTree for those instead.
1656 if (!expr->is<PropertyAccess>() || expr->as<PropertyAccess>().isSuper()) {
1657 return emitTree(expr);
1658 }
1659
1660 // If the object operand is also a dotted property reference, reverse the
1661 // list linked via expression() temporarily so we can iterate over it from
1662 // the bottom up (reversing again as we go), to avoid excessive recursion.
1663 PropertyAccess* pndot = &expr->as<PropertyAccess>();
1664 ParseNode* pnup = nullptr;
1665 ParseNode* pndown;
1666 for (;;) {
1667 // Reverse pndot->expression() to point up, not down.
1668 pndown = &pndot->expression();
1669 pndot->setExpression(pnup);
1670 if (!pndown->is<PropertyAccess>() ||
1671 pndown->as<PropertyAccess>().isSuper()) {
1672 break;
1673 }
1674 pnup = pndot;
1675 pndot = &pndown->as<PropertyAccess>();
1676 }
1677
1678 // pndown is a primary expression, not a dotted property reference.
1679 if (!emitTree(pndown)) {
1680 return false;
1681 }
1682
1683 while (true) {
1684 // Walk back up the list, emitting annotated name ops.
1685 if (!emitAtomOp(JSOp::GetProp, pndot->key().atom())) {
1686 return false;
1687 }
1688
1689 // Reverse the pndot->expression() link again.
1690 pnup = pndot->maybeExpression();
1691 pndot->setExpression(pndown);
1692 pndown = pndot;
1693 if (!pnup) {
1694 break;
1695 }
1696 pndot = &pnup->as<PropertyAccess>();
1697 }
1698 return true;
1699}
1700
1701bool BytecodeEmitter::emitArgumentsLength() {
1702 if (sc->isFunctionBox() &&
1703 sc->asFunctionBox()->isEligibleForArgumentsLength() &&
1704 !sc->asFunctionBox()->needsArgsObj()) {
1705 return emit1(JSOp::ArgumentsLength);
1706 }
1707
1708 PropOpEmitter poe(this, PropOpEmitter::Kind::Get,
1709 PropOpEmitter::ObjKind::Other);
1710 if (!poe.prepareForObj()) {
1711 return false;
1712 }
1713
1714 NameOpEmitter noe(this, TaggedParserAtomIndex::WellKnown::arguments(),
1715 NameOpEmitter::Kind::Get);
1716 if (!noe.emitGet()) {
1717 return false;
1718 }
1719 return poe.emitGet(TaggedParserAtomIndex::WellKnown::length());
1720}
1721
1722bool BytecodeEmitter::emitPropIncDec(UnaryNode* incDec, ValueUsage valueUsage) {
1723 NonOptionalPropertyAccessBase* prop =
1724 &incDec->kid()->as<NonOptionalPropertyAccessBase>();
1725 bool isSuper = prop->isSuper();
1726 ParseNodeKind kind = incDec->getKind();
1727 PropOpEmitter poe(
1728 this,
1729 kind == ParseNodeKind::PostIncrementExpr
1730 ? PropOpEmitter::Kind::PostIncrement
1731 : kind == ParseNodeKind::PreIncrementExpr
1732 ? PropOpEmitter::Kind::PreIncrement
1733 : kind == ParseNodeKind::PostDecrementExpr
1734 ? PropOpEmitter::Kind::PostDecrement
1735 : PropOpEmitter::Kind::PreDecrement,
1736 isSuper ? PropOpEmitter::ObjKind::Super : PropOpEmitter::ObjKind::Other);
1737 if (!poe.prepareForObj()) {
1738 return false;
1739 }
1740 if (isSuper) {
1741 UnaryNode* base = &prop->expression().as<UnaryNode>();
1742 if (!emitGetThisForSuperBase(base)) {
1743 // [stack] THIS
1744 return false;
1745 }
1746 } else {
1747 if (!emitPropLHS(prop)) {
1748 // [stack] OBJ
1749 return false;
1750 }
1751 }
1752 if (!poe.emitIncDec(prop->key().atom(), valueUsage)) {
1753 // [stack] RESULT
1754 return false;
1755 }
1756
1757 return true;
1758}
1759
1760bool BytecodeEmitter::emitNameIncDec(UnaryNode* incDec, ValueUsage valueUsage) {
1761 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", 1761);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "incDec->kid()->isKind(ParseNodeKind::Name)"
")"); do { MOZ_CrashSequence(__null, 1761); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1762
1763 ParseNodeKind kind = incDec->getKind();
1764 NameNode* name = &incDec->kid()->as<NameNode>();
1765 NameOpEmitter noe(this, name->atom(),
1766 kind == ParseNodeKind::PostIncrementExpr
1767 ? NameOpEmitter::Kind::PostIncrement
1768 : kind == ParseNodeKind::PreIncrementExpr
1769 ? NameOpEmitter::Kind::PreIncrement
1770 : kind == ParseNodeKind::PostDecrementExpr
1771 ? NameOpEmitter::Kind::PostDecrement
1772 : NameOpEmitter::Kind::PreDecrement);
1773 if (!noe.emitIncDec(valueUsage)) {
1774 return false;
1775 }
1776
1777 return true;
1778}
1779
1780bool BytecodeEmitter::emitElemObjAndKey(PropertyByValue* elem,
1781 ElemOpEmitter& eoe) {
1782 ParseNode* exprOrSuper = &elem->expression();
1783 ParseNode* key = &elem->key();
1784
1785 if (!eoe.prepareForObj()) {
1786 // [stack]
1787 return false;
1788 }
1789
1790 if (elem->isSuper()) {
1791 auto* base = &exprOrSuper->as<UnaryNode>();
1792 if (!emitGetThisForSuperBase(base)) {
1793 // [stack] THIS
1794 return false;
1795 }
1796 } else {
1797 if (!emitTree(exprOrSuper)) {
1798 // [stack] OBJ
1799 return false;
1800 }
1801 }
1802
1803 if (!eoe.prepareForKey()) {
1804 // [stack] # if Super
1805 // [stack] THIS? THIS
1806 // [stack] # otherwise
1807 // [stack] OBJ? OBJ
1808 return false;
1809 }
1810
1811 if (!emitTree(key)) {
1812 // [stack] # if Super
1813 // [stack] THIS? THIS KEY
1814 // [stack] # otherwise
1815 // [stack] OBJ? OBJ KEY
1816 return false;
1817 }
1818
1819 return true;
1820}
1821
1822bool BytecodeEmitter::emitElemOpBase(JSOp op) {
1823 if (!emit1(op)) {
1824 return false;
1825 }
1826
1827 return true;
1828}
1829
1830static ElemOpEmitter::Kind ConvertIncDecKind(ParseNodeKind kind) {
1831 switch (kind) {
1832 case ParseNodeKind::PostIncrementExpr:
1833 return ElemOpEmitter::Kind::PostIncrement;
1834 case ParseNodeKind::PreIncrementExpr:
1835 return ElemOpEmitter::Kind::PreIncrement;
1836 case ParseNodeKind::PostDecrementExpr:
1837 return ElemOpEmitter::Kind::PostDecrement;
1838 case ParseNodeKind::PreDecrementExpr:
1839 return ElemOpEmitter::Kind::PreDecrement;
1840 default:
1841 MOZ_CRASH("unexpected inc/dec node kind")do { do { } while (false); MOZ_ReportCrash("" "unexpected inc/dec node kind"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 1841);
AnnotateMozCrashReason("MOZ_CRASH(" "unexpected inc/dec node kind"
")"); do { MOZ_CrashSequence(__null, 1841); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
1842 }
1843}
1844
1845static PrivateOpEmitter::Kind PrivateConvertIncDecKind(ParseNodeKind kind) {
1846 switch (kind) {
1847 case ParseNodeKind::PostIncrementExpr:
1848 return PrivateOpEmitter::Kind::PostIncrement;
1849 case ParseNodeKind::PreIncrementExpr:
1850 return PrivateOpEmitter::Kind::PreIncrement;
1851 case ParseNodeKind::PostDecrementExpr:
1852 return PrivateOpEmitter::Kind::PostDecrement;
1853 case ParseNodeKind::PreDecrementExpr:
1854 return PrivateOpEmitter::Kind::PreDecrement;
1855 default:
1856 MOZ_CRASH("unexpected inc/dec node kind")do { do { } while (false); MOZ_ReportCrash("" "unexpected inc/dec node kind"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 1856);
AnnotateMozCrashReason("MOZ_CRASH(" "unexpected inc/dec node kind"
")"); do { MOZ_CrashSequence(__null, 1856); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
1857 }
1858}
1859
1860bool BytecodeEmitter::emitElemIncDec(UnaryNode* incDec, ValueUsage valueUsage) {
1861 PropertyByValue* elemExpr = &incDec->kid()->as<PropertyByValue>();
1862 bool isSuper = elemExpr->isSuper();
1863 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"
, 1863); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elemExpr->key().isKind(ParseNodeKind::PrivateName)"
")"); do { MOZ_CrashSequence(__null, 1863); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1864 ParseNodeKind kind = incDec->getKind();
1865 ElemOpEmitter eoe(
1866 this, ConvertIncDecKind(kind),
1867 isSuper ? ElemOpEmitter::ObjKind::Super : ElemOpEmitter::ObjKind::Other);
1868 if (!emitElemObjAndKey(elemExpr, eoe)) {
1869 // [stack] # if Super
1870 // [stack] THIS KEY
1871 // [stack] # otherwise
1872 // [stack] OBJ KEY
1873 return false;
1874 }
1875 if (!eoe.emitIncDec(valueUsage)) {
1876 // [stack] RESULT
1877 return false;
1878 }
1879
1880 return true;
1881}
1882
1883bool BytecodeEmitter::emitCallIncDec(UnaryNode* incDec) {
1884 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", 1887);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind(ParseNodeKind::PostDecrementExpr)"
")"); do { MOZ_CrashSequence(__null, 1887); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1885 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", 1887);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind(ParseNodeKind::PostDecrementExpr)"
")"); do { MOZ_CrashSequence(__null, 1887); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1886 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", 1887);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind(ParseNodeKind::PostDecrementExpr)"
")"); do { MOZ_CrashSequence(__null, 1887); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1887 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", 1887);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind(ParseNodeKind::PostDecrementExpr)"
")"); do { MOZ_CrashSequence(__null, 1887); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1888
1889 ParseNode* call = incDec->kid();
1890 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", 1890);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "call->isKind(ParseNodeKind::CallExpr)"
")"); do { MOZ_CrashSequence(__null, 1890); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1891 if (!emitTree(call)) {
1892 // [stack] CALLRESULT
1893 return false;
1894 }
1895
1896 // The increment/decrement has no side effects, so proceed to throw for
1897 // invalid assignment target.
1898 return emit2(JSOp::ThrowMsg, uint8_t(ThrowMsgKind::AssignToCall));
1899}
1900
1901bool BytecodeEmitter::emitPrivateIncDec(UnaryNode* incDec,
1902 ValueUsage valueUsage) {
1903 PrivateMemberAccess* privateExpr = &incDec->kid()->as<PrivateMemberAccess>();
1904 ParseNodeKind kind = incDec->getKind();
1905 PrivateOpEmitter xoe(this, PrivateConvertIncDecKind(kind),
1906 privateExpr->privateName().name());
1907 if (!emitTree(&privateExpr->expression())) {
1908 // [stack] OBJ
1909 return false;
1910 }
1911 if (!xoe.emitReference()) {
1912 // [stack] OBJ NAME
1913 return false;
1914 }
1915 if (!xoe.emitIncDec(valueUsage)) {
1916 // [stack] RESULT
1917 return false;
1918 }
1919
1920 return true;
1921}
1922
1923bool BytecodeEmitter::emitDouble(double d) {
1924 BytecodeOffset offset;
1925 if (!emitCheck(JSOp::Double, 9, &offset)) {
1926 return false;
1927 }
1928
1929 jsbytecode* code = bytecodeSection().code(offset);
1930 code[0] = jsbytecode(JSOp::Double);
1931 SET_INLINE_VALUE(code, DoubleValue(d));
1932 bytecodeSection().updateDepth(JSOp::Double, offset);
1933 return true;
1934}
1935
1936bool BytecodeEmitter::emitNumberOp(double dval) {
1937 int32_t ival;
1938 if (NumberIsInt32(dval, &ival)) {
1939 if (ival == 0) {
1940 return emit1(JSOp::Zero);
1941 }
1942 if (ival == 1) {
1943 return emit1(JSOp::One);
1944 }
1945 if ((int)(int8_t)ival == ival) {
1946 return emit2(JSOp::Int8, uint8_t(int8_t(ival)));
1947 }
1948
1949 uint32_t u = uint32_t(ival);
1950 if (u < Bit(16)) {
1951 if (!emitUint16Operand(JSOp::Uint16, u)) {
1952 return false;
1953 }
1954 } else if (u < Bit(24)) {
1955 BytecodeOffset off;
1956 if (!emitN(JSOp::Uint24, 3, &off)) {
1957 return false;
1958 }
1959 SET_UINT24(bytecodeSection().code(off), u);
1960 } else {
1961 BytecodeOffset off;
1962 if (!emitN(JSOp::Int32, 4, &off)) {
1963 return false;
1964 }
1965 SET_INT32(bytecodeSection().code(off), ival);
1966 }
1967 return true;
1968 }
1969
1970 return emitDouble(dval);
1971}
1972
1973/*
1974 * Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047.
1975 * LLVM is deciding to inline this function which uses a lot of stack space
1976 * into emitTree which is recursive and uses relatively little stack space.
1977 */
1978MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitSwitch(SwitchStatement* switchStmt) {
1979 LexicalScopeNode& lexical = switchStmt->lexicalForCaseList();
1980 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", 1980);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "lexical.isKind(ParseNodeKind::LexicalScope)"
")"); do { MOZ_CrashSequence(__null, 1980); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1981 ListNode* cases = &lexical.scopeBody()->as<ListNode>();
1982 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", 1982);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "cases->isKind(ParseNodeKind::StatementList)"
")"); do { MOZ_CrashSequence(__null, 1982); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1983
1984 SwitchEmitter se(this);
1985 if (!se.emitDiscriminant(switchStmt->discriminant().pn_pos.begin)) {
1986 return false;
1987 }
1988
1989 if (!markStepBreakpoint()) {
1990 return false;
1991 }
1992 if (!emitTree(&switchStmt->discriminant())) {
1993 return false;
1994 }
1995
1996 // Enter the scope before pushing the switch BreakableControl since all
1997 // breaks are under this scope.
1998
1999 if (!lexical.isEmptyScope()) {
2000 if (!se.emitLexical(lexical.scopeBindings())) {
2001 return false;
2002 }
2003
2004 // A switch statement may contain hoisted functions inside its
2005 // cases. The hasTopLevelFunctionDeclarations flag is propagated from the
2006 // StatementList bodies of the cases to the case list.
2007 if (cases->hasTopLevelFunctionDeclarations()) {
2008 for (ParseNode* item : cases->contents()) {
2009 CaseClause* caseClause = &item->as<CaseClause>();
2010 ListNode* statements = caseClause->statementList();
2011 if (statements->hasTopLevelFunctionDeclarations()) {
2012 if (!emitHoistedFunctionsInList(statements)) {
2013 return false;
2014 }
2015 }
2016 }
2017 }
2018 } else {
2019 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", 2019);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!cases->hasTopLevelFunctionDeclarations()"
")"); do { MOZ_CrashSequence(__null, 2019); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2020 }
2021
2022 SwitchEmitter::TableGenerator tableGen(this);
2023 uint32_t caseCount = cases->count() - (switchStmt->hasDefault() ? 1 : 0);
2024 if (caseCount == 0) {
2025 tableGen.finish(0);
2026 } else {
2027 for (ParseNode* item : cases->contents()) {
2028 CaseClause* caseClause = &item->as<CaseClause>();
2029 if (caseClause->isDefault()) {
2030 continue;
2031 }
2032
2033 ParseNode* caseValue = caseClause->caseExpression();
2034
2035 if (caseValue->getKind() != ParseNodeKind::NumberExpr) {
2036 tableGen.setInvalid();
2037 break;
2038 }
2039
2040 int32_t i;
2041 if (!NumberEqualsInt32(caseValue->as<NumericLiteral>().value(), &i)) {
2042 tableGen.setInvalid();
2043 break;
2044 }
2045
2046 if (!tableGen.addNumber(i)) {
2047 return false;
2048 }
2049 }
2050
2051 tableGen.finish(caseCount);
2052 }
2053
2054 if (!se.validateCaseCount(caseCount)) {
2055 return false;
2056 }
2057
2058 bool isTableSwitch = tableGen.isValid();
2059 if (isTableSwitch) {
2060 if (!se.emitTable(tableGen)) {
2061 return false;
2062 }
2063 } else {
2064 if (!se.emitCond()) {
2065 return false;
2066 }
2067
2068 // Emit code for evaluating cases and jumping to case statements.
2069 for (ParseNode* item : cases->contents()) {
2070 CaseClause* caseClause = &item->as<CaseClause>();
2071 if (caseClause->isDefault()) {
2072 continue;
2073 }
2074
2075 if (!se.prepareForCaseValue()) {
2076 return false;
2077 }
2078
2079 ParseNode* caseValue = caseClause->caseExpression();
2080 // If the expression is a literal, suppress line number emission so
2081 // that debugging works more naturally.
2082 if (!emitTree(
2083 caseValue, ValueUsage::WantValue,
2084 caseValue->isLiteral() ? SUPPRESS_LINENOTE : EMIT_LINENOTE)) {
2085 return false;
2086 }
2087
2088 if (!se.emitCaseJump()) {
2089 return false;
2090 }
2091 }
2092 }
2093
2094 // Emit code for each case's statements.
2095 for (ParseNode* item : cases->contents()) {
2096 CaseClause* caseClause = &item->as<CaseClause>();
2097 if (caseClause->isDefault()) {
2098 if (!se.emitDefaultBody()) {
2099 return false;
2100 }
2101 } else {
2102 if (isTableSwitch) {
2103 ParseNode* caseValue = caseClause->caseExpression();
2104 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", 2104);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "caseValue->isKind(ParseNodeKind::NumberExpr)"
")"); do { MOZ_CrashSequence(__null, 2104); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2105
2106 NumericLiteral* literal = &caseValue->as<NumericLiteral>();
2107#ifdef DEBUG1
2108 // Use NumberEqualsInt32 here because switches compare using
2109 // strict equality, which will equate -0 and +0. In contrast
2110 // NumberIsInt32 would return false for -0.
2111 int32_t v;
2112 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"
, 2112); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mozilla::NumberEqualsInt32(literal->value(), &v)"
")"); do { MOZ_CrashSequence(__null, 2112); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2113#endif
2114 int32_t i = int32_t(literal->value());
2115
2116 if (!se.emitCaseBody(i, tableGen)) {
2117 return false;
2118 }
2119 } else {
2120 if (!se.emitCaseBody()) {
2121 return false;
2122 }
2123 }
2124 }
2125
2126 if (!emitTree(caseClause->statementList())) {
2127 return false;
2128 }
2129 }
2130
2131 if (!se.emitEnd()) {
2132 return false;
2133 }
2134
2135 return true;
2136}
2137
2138static constexpr size_t MaxResumeIndex = BitMask(24);
2139
2140bool BytecodeEmitter::checkResumeIndexLimit() {
2141 static_assert(
2142 MaxResumeIndex < uint32_t(AbstractGeneratorObject::RESUME_INDEX_RUNNING),
2143 "resumeIndex should not include magic AbstractGeneratorObject "
2144 "resumeIndex values");
2145 static_assert(
2146 MaxResumeIndex <= INT32_MAX(2147483647) / sizeof(uintptr_t),
2147 "resumeIndex * sizeof(uintptr_t) must fit in an int32. JIT code relies "
2148 "on this when loading resume entries from BaselineScript");
2149
2150 size_t numIndices =
2151 bytecodeSection().resumeOffsetList().length() +
2152 bytecodeSection().tableSwitchOffsetList().numCaseOffsets();
2153 if (numIndices > MaxResumeIndex) {
2154 reportError(nullptr, JSMSG_TOO_MANY_RESUME_INDEXES);
2155 return false;
2156 }
2157 return true;
2158}
2159
2160bool BytecodeEmitter::allocateResumeIndex(BytecodeOffset offset,
2161 uint32_t* resumeIndex) {
2162 if (!checkResumeIndexLimit()) {
2163 return false;
2164 }
2165 *resumeIndex = bytecodeSection().resumeOffsetList().length();
2166 return bytecodeSection().resumeOffsetList().append(offset.value());
2167}
2168
2169bool BytecodeEmitter::allocateTableSwitchResumeIndexRange(
2170 mozilla::Span<BytecodeOffset> caseOffsets, BytecodeOffset switchOffset,
2171 uint32_t* firstResumeIndex) {
2172 if (caseOffsets.empty()) {
2173 // Empty switches don't need adjustment.
2174 *firstResumeIndex = 0;
2175 return true;
2176 }
2177 auto& list = bytecodeSection().tableSwitchOffsetList();
2178
2179 // The final resume index depends on the number of yield and await ops in the
2180 // script, so store an index relative to the first table switch entry for now.
2181 // finishResumeOffsets adjusts it.
2182 *firstResumeIndex = list.numCaseOffsets();
2183 if (!list.appendTableSwitch(switchOffset)) {
2184 return false;
2185 }
2186
2187 for (BytecodeOffset offset : caseOffsets) {
2188 if (!checkResumeIndexLimit()) {
2189 return false;
2190 }
2191 if (!list.appendCaseOffset(offset)) {
2192 return false;
2193 }
2194 }
2195
2196 return true;
2197}
2198
2199bool BytecodeEmitter::finishResumeOffsets() {
2200 auto& resumeOffsets = bytecodeSection().resumeOffsetList();
2201 auto& tableSwitches = bytecodeSection().tableSwitchOffsetList();
2202
2203 size_t numIndices = resumeOffsets.length() + tableSwitches.numCaseOffsets();
2204 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"
, 2204); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "numIndices <= MaxResumeIndex + 1"
")"); do { MOZ_CrashSequence(__null, 2204); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2205
2206 // Without yield/await entries, the relative indices SwitchEmitter wrote are
2207 // already the final resume indices, so there's nothing to patch.
2208 if (resumeOffsets.length() == 0) {
2209 resumeOffsets.setFrom(std::move(tableSwitches.caseOffsets));
2210 return true;
2211 }
2212
2213 // The table switch entries go after the yield and await entries.
2214 uint32_t firstTableSwitchIndex = resumeOffsets.length();
2215 if (!resumeOffsets.appendAll(tableSwitches.caseOffsets)) {
2216 return false;
2217 }
2218 for (BytecodeOffset switchOffset : tableSwitches.switchOffsets) {
2219 jsbytecode* pc = bytecodeSection().code(switchOffset);
2220 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"
, 2220); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JSOp(*pc) == JSOp::TableSwitch"
")"); do { MOZ_CrashSequence(__null, 2220); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2221 pc += 3 * JUMP_OFFSET_LEN;
2222 SET_RESUMEINDEX(pc, GET_RESUMEINDEX(pc) + firstTableSwitchIndex);
2223 }
2224 return true;
2225}
2226
2227bool BytecodeEmitter::emitYieldOp(JSOp op) {
2228 // ParseContext::Scope::setOwnStackSlotCount should check the fixed slot
2229 // for the following, and it should prevent using fixed slot if there are
2230 // too many bindings:
2231 // * generator or asyn function
2232 // * module code after top-level await
2233 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", 2234);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "innermostEmitterScopeNoCheck()->frameSlotEnd() <= ParseContext::Scope::FixedSlotLimit"
")"); do { MOZ_CrashSequence(__null, 2234); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2234 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", 2234);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "innermostEmitterScopeNoCheck()->frameSlotEnd() <= ParseContext::Scope::FixedSlotLimit"
")"); do { MOZ_CrashSequence(__null, 2234); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2235
2236 if (op == JSOp::FinalYieldRval) {
2237 return emit1(JSOp::FinalYieldRval);
2238 }
2239
2240 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", 2241);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::InitialYield || op == JSOp::Yield || op == JSOp::Await"
")"); do { MOZ_CrashSequence(__null, 2241); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2241 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", 2241);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::InitialYield || op == JSOp::Yield || op == JSOp::Await"
")"); do { MOZ_CrashSequence(__null, 2241); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2242
2243 BytecodeOffset off;
2244 if (!emitN(op, 3, &off)) {
2245 return false;
2246 }
2247
2248 // InitialYield is always the first yield node.
2249 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"
, 2249); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().numYields() == 0"
")"); do { MOZ_CrashSequence(__null, 2249); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
2250
2251 if (op == JSOp::InitialYield || op == JSOp::Yield) {
2252 bytecodeSection().addNumYields();
2253 }
2254
2255 uint32_t resumeIndex;
2256 if (!allocateResumeIndex(bytecodeSection().offset(), &resumeIndex)) {
2257 return false;
2258 }
2259
2260 // InitialYield is the first resumable instruction.
2261 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", 2263);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "resumeIndex == AbstractGeneratorObject::RESUME_INDEX_INITIAL_YIELD"
")"); do { MOZ_CrashSequence(__null, 2263); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
2262 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", 2263);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "resumeIndex == AbstractGeneratorObject::RESUME_INDEX_INITIAL_YIELD"
")"); do { MOZ_CrashSequence(__null, 2263); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
2263 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", 2263);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "resumeIndex == AbstractGeneratorObject::RESUME_INDEX_INITIAL_YIELD"
")"); do { MOZ_CrashSequence(__null, 2263); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
2264
2265 SET_RESUMEINDEX(bytecodeSection().code(off), resumeIndex);
2266
2267 BytecodeOffset unusedOffset;
2268 return emitJumpTargetOp(JSOp::AfterYield, &unusedOffset);
2269}
2270
2271bool BytecodeEmitter::emitPushResumeKind(GeneratorResumeKind kind) {
2272 return emit2(JSOp::ResumeKind, uint8_t(kind));
2273}
2274
2275bool BytecodeEmitter::emitSetThis(BinaryNode* setThisNode) {
2276 // ParseNodeKind::SetThis is used to update |this| after a super() call
2277 // in a derived class constructor.
2278
2279 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", 2279);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "setThisNode->isKind(ParseNodeKind::SetThis)"
")"); do { MOZ_CrashSequence(__null, 2279); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2280 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"
, 2280); AnnotateMozCrashReason("MOZ_ASSERT" "(" "setThisNode->left()->isKind(ParseNodeKind::Name)"
")"); do { MOZ_CrashSequence(__null, 2280); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2281
2282 auto name = setThisNode->left()->as<NameNode>().name();
2283
2284 // The 'this' binding is not lexical, but due to super() semantics this
2285 // initialization needs to be treated as a lexical one.
2286 NameLocation loc = lookupName(name);
2287 NameLocation lexicalLoc;
2288 if (loc.kind() == NameLocation::Kind::FrameSlot) {
2289 lexicalLoc = NameLocation::FrameSlot(BindingKind::Let, loc.frameSlot());
2290 } else if (loc.kind() == NameLocation::Kind::EnvironmentCoordinate) {
2291 EnvironmentCoordinate coord = loc.environmentCoordinate();
2292 uint16_t hops = AssertedCast<uint16_t>(coord.hops());
2293 lexicalLoc = NameLocation::EnvironmentCoordinate(BindingKind::Let, hops,
2294 coord.slot());
2295 } else {
2296 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", 2296);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "loc.kind() == NameLocation::Kind::Dynamic"
")"); do { MOZ_CrashSequence(__null, 2296); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2297 lexicalLoc = loc;
2298 }
2299
2300 NameOpEmitter noe(this, name, lexicalLoc, NameOpEmitter::Kind::Initialize);
2301 if (!noe.prepareForRhs()) {
2302 // [stack]
2303 return false;
2304 }
2305
2306 // Emit the new |this| value.
2307 if (!emitTree(setThisNode->right())) {
2308 // [stack] NEWTHIS
2309 return false;
2310 }
2311
2312 // Get the original |this| and throw if we already initialized
2313 // it. Do *not* use the NameLocation argument, as that's the special
2314 // lexical location below to deal with super() semantics.
2315 if (!emitGetName(name)) {
2316 // [stack] NEWTHIS THIS
2317 return false;
2318 }
2319 if (!emit1(JSOp::CheckThisReinit)) {
2320 // [stack] NEWTHIS THIS
2321 return false;
2322 }
2323 if (!emit1(JSOp::Pop)) {
2324 // [stack] NEWTHIS
2325 return false;
2326 }
2327 if (!noe.emitAssignment()) {
2328 // [stack] NEWTHIS
2329 return false;
2330 }
2331
2332 if (!emitInitializeInstanceMembers(true)) {
2333 return false;
2334 }
2335
2336 return true;
2337}
2338
2339bool BytecodeEmitter::defineHoistedTopLevelFunctions(ParseNode* body) {
2340 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"
, 2340); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inPrologue()"
")"); do { MOZ_CrashSequence(__null, 2340); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2341 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", 2341);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isGlobalContext() || (sc->isEvalContext() && !sc->strict())"
")"); do { MOZ_CrashSequence(__null, 2341); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2342 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", 2342);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "body->is<LexicalScopeNode>() || body->is<ListNode>()"
")"); do { MOZ_CrashSequence(__null, 2342); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2343
2344 if (body->is<LexicalScopeNode>()) {
2345 body = body->as<LexicalScopeNode>().scopeBody();
2346 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"
, 2346); AnnotateMozCrashReason("MOZ_ASSERT" "(" "body->is<ListNode>()"
")"); do { MOZ_CrashSequence(__null, 2346); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2347 }
2348
2349 if (!body->as<ListNode>().hasTopLevelFunctionDeclarations()) {
2350 return true;
2351 }
2352
2353 return emitHoistedFunctionsInList(&body->as<ListNode>());
2354}
2355
2356// For Global and sloppy-Eval scripts, this performs most of the steps of the
2357// spec's [GlobalDeclarationInstantiation] and [EvalDeclarationInstantiation]
2358// operations.
2359//
2360// Note that while strict-Eval is handled in the same part of the spec, it never
2361// fails for global-redeclaration checks so those scripts initialize directly in
2362// their bytecode.
2363bool BytecodeEmitter::emitDeclarationInstantiation(ParseNode* body) {
2364 if (sc->isModuleContext()) {
2365 // ES Modules have dedicated variable and lexial environments and therefore
2366 // do not have to perform redeclaration checks. We initialize their bindings
2367 // elsewhere in bytecode.
2368 return true;
2369 }
2370
2371 if (sc->isEvalContext() && sc->strict()) {
2372 // Strict Eval has a dedicated variables (and lexical) environment and
2373 // therefore does not have to perform redeclaration checks. We initialize
2374 // their bindings elsewhere in the bytecode.
2375 return true;
2376 }
2377
2378 // If we have no variables bindings, then we are done!
2379 if (sc->isGlobalContext()) {
2380 if (!sc->asGlobalContext()->bindings) {
2381 return true;
2382 }
2383 } else {
2384 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", 2384);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isEvalContext()"
")"); do { MOZ_CrashSequence(__null, 2384); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2385
2386 if (!sc->asEvalContext()->bindings) {
2387 return true;
2388 }
2389 }
2390
2391#if DEBUG1
2392 // There should be no emitted functions yet.
2393 for (const auto& thing : perScriptData().gcThingList().objects()) {
2394 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", 2394);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "thing.isEmptyGlobalScope() || thing.isScope()"
")"); do { MOZ_CrashSequence(__null, 2394); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2395 }
2396#endif
2397
2398 // Emit the hoisted functions to gc-things list. There is no bytecode
2399 // generated yet to bind them.
2400 if (!defineHoistedTopLevelFunctions(body)) {
2401 return false;
2402 }
2403
2404 // Save the last GCThingIndex emitted. The hoisted functions are contained in
2405 // the gc-things list up until this point. This set of gc-things also contain
2406 // initial scopes (of which there must be at least one).
2407 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", 2407);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "perScriptData().gcThingList().length() > 0"
")"); do { MOZ_CrashSequence(__null, 2407); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2408 GCThingIndex lastFun =
2409 GCThingIndex(perScriptData().gcThingList().length() - 1);
2410
2411#if DEBUG1
2412 for (const auto& thing : perScriptData().gcThingList().objects()) {
2413 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", 2414);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "thing.isEmptyGlobalScope() || thing.isScope() || thing.isFunction()"
")"); do { MOZ_CrashSequence(__null, 2414); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2414 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", 2414);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "thing.isEmptyGlobalScope() || thing.isScope() || thing.isFunction()"
")"); do { MOZ_CrashSequence(__null, 2414); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2415 }
2416#endif
2417
2418 // Check for declaration conflicts and initialize the bindings.
2419 // NOTE: The self-hosting top-level script should not populate the builtins
2420 // directly on the GlobalObject (and instead uses JSOp::GetIntrinsic for
2421 // lookups).
2422 if (emitterMode == BytecodeEmitter::EmitterMode::Normal) {
2423 if (!emitGCIndexOp(JSOp::GlobalOrEvalDeclInstantiation, lastFun)) {
2424 return false;
2425 }
2426 }
2427
2428 return true;
2429}
2430
2431bool BytecodeEmitter::emitScript(ParseNode* body) {
2432 if (!fc->checkCompilationCancellation()) {
2433 return false;
2434 }
2435
2436 setScriptStartOffsetIfUnset(body->pn_pos.begin);
2437
2438 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"
, 2438); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inPrologue()"
")"); do { MOZ_CrashSequence(__null, 2438); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2439
2440 TDZCheckCache tdzCache(this);
2441 EmitterScope emitterScope(this);
2442 Maybe<AsyncEmitter> topLevelAwait;
2443 if (sc->isGlobalContext()) {
2444 if (!emitterScope.enterGlobal(this, sc->asGlobalContext())) {
2445 return false;
2446 }
2447 } else if (sc->isEvalContext()) {
2448 if (!emitterScope.enterEval(this, sc->asEvalContext())) {
2449 return false;
2450 }
2451 } else {
2452 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", 2452);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isModuleContext()"
")"); do { MOZ_CrashSequence(__null, 2452); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2453 if (!emitterScope.enterModule(this, sc->asModuleContext())) {
2454 return false;
2455 }
2456 if (sc->asModuleContext()->isAsync()) {
2457 topLevelAwait.emplace(this);
2458 }
2459 }
2460
2461 setFunctionBodyEndPos(body->pn_pos.end);
2462
2463 bool isSloppyEval = sc->isEvalContext() && !sc->strict();
2464 if (isSloppyEval && body->is<LexicalScopeNode>() &&
2465 !body->as<LexicalScopeNode>().isEmptyScope()) {
2466 // Sloppy eval scripts may emit hoisted functions bindings with a
2467 // `JSOp::GlobalOrEvalDeclInstantiation` opcode below. If this eval needs a
2468 // top-level lexical environment, we must ensure that environment is created
2469 // before those functions are created and bound.
2470 //
2471 // This differs from the global-script case below because the global-lexical
2472 // environment exists outside the script itself. In the case of strict eval
2473 // scripts, the `emitterScope` above is already sufficient.
2474 EmitterScope lexicalEmitterScope(this);
2475 LexicalScopeNode* scope = &body->as<LexicalScopeNode>();
2476
2477 if (!lexicalEmitterScope.enterLexical(this, ScopeKind::Lexical,
2478 scope->scopeBindings())) {
2479 return false;
2480 }
2481
2482 if (!emitDeclarationInstantiation(scope->scopeBody())) {
2483 return false;
2484 }
2485
2486 switchToMain();
2487
2488 ParseNode* scopeBody = scope->scopeBody();
2489 if (!emitLexicalScopeBody(scopeBody)) {
2490 return false;
2491 }
2492
2493 if (!updateSourceCoordNotes(scopeBody->pn_pos.end)) {
2494 return false;
2495 }
2496
2497 if (!lexicalEmitterScope.leave(this)) {
2498 return false;
2499 }
2500 } else {
2501 if (!emitDeclarationInstantiation(body)) {
2502 return false;
2503 }
2504 if (topLevelAwait) {
2505 if (!topLevelAwait->prepareForModule()) {
2506 return false;
2507 }
2508 }
2509
2510 switchToMain();
2511
2512 if (!emitterScope.prepareForModuleDisposableScopeBody(this)) {
2513 return false;
2514 }
2515
2516 if (topLevelAwait) {
2517 if (!topLevelAwait->prepareForBody()) {
2518 return false;
2519 }
2520 }
2521
2522 if (!emitTree(body)) {
2523 // [stack]
2524 return false;
2525 }
2526
2527 if (!updateSourceCoordNotes(body->pn_pos.end)) {
2528 return false;
2529 }
2530 }
2531
2532 if (!emitterScope.emitModuleDisposableScopeBodyEnd(this)) {
2533 return false;
2534 }
2535
2536 if (topLevelAwait) {
2537 if (!topLevelAwait->emitEndModule()) {
2538 return false;
2539 }
2540 }
2541
2542 if (!markSimpleBreakpoint()) {
2543 return false;
2544 }
2545
2546 if (!emitReturnRval()) {
2547 return false;
2548 }
2549
2550 if (!emitterScope.leave(this)) {
2551 return false;
2552 }
2553
2554 if (!NameFunctions(fc, parserAtoms(), body)) {
2555 return false;
2556 }
2557
2558 // Create a Stencil and convert it into a JSScript.
2559 return intoScriptStencil(CompilationStencil::TopLevelIndex);
2560}
2561
2562js::UniquePtr<ImmutableScriptData>
2563BytecodeEmitter::createImmutableScriptData() {
2564 uint32_t nslots;
2565 if (!getNslots(&nslots)) {
2566 return nullptr;
2567 }
2568
2569 if (!finishResumeOffsets()) {
2570 return nullptr;
2571 }
2572
2573 bool isFunction = sc->isFunctionBox();
2574 uint16_t funLength = isFunction ? sc->asFunctionBox()->length() : 0;
2575
2576 mozilla::SaturateUint8 propertyCountEstimate = propertyAdditionEstimate;
2577
2578 // Add fields to the property count estimate.
2579 if (isFunction && sc->asFunctionBox()->useMemberInitializers()) {
2580 propertyCountEstimate +=
2581 sc->asFunctionBox()->memberInitializers().numMemberInitializers;
2582 }
2583
2584#ifdef DEBUG1
2585 uint32_t codeLength = bytecodeSection().code().length();
2586 bytecodeSection().tryNoteList().checkTryNotes(codeLength);
2587 bytecodeSection().scopeNoteList().checkScopeNotes(codeLength);
2588#endif
2589
2590 return ImmutableScriptData::new_(
2591 fc, mainOffset(), maxFixedSlots, nslots, bodyScopeIndex,
2592 bytecodeSection().numICEntries(), isFunction, funLength,
2593 propertyCountEstimate.value(), bytecodeSection().code(),
2594 bytecodeSection().notes(), bytecodeSection().resumeOffsetList().span(),
2595 bytecodeSection().scopeNoteList().span(),
2596 bytecodeSection().tryNoteList().span());
2597}
2598
2599bool BytecodeEmitter::emitCheckIsCallable() {
2600 // This emits code to check if the value at the top of the stack is
2601 // callable. The value is left on the stack.
2602 // [stack] VAL
2603 if (!emitAtomOp(JSOp::GetIntrinsic,
2604 TaggedParserAtomIndex::WellKnown::IsCallable())) {
2605 // [stack] VAL ISCALLABLE
2606 return false;
2607 }
2608 if (!emit1(JSOp::Undefined)) {
2609 // [stack] VAL ISCALLABLE UNDEFINED
2610 return false;
2611 }
2612 if (!emitDupAt(2)) {
2613 // [stack] VAL ISCALLABLE UNDEFINED VAL
2614 return false;
2615 }
2616 return emitCall(JSOp::Call, 1);
2617 // [stack] VAL ISCALLABLE_RESULT
2618}
2619
2620bool BytecodeEmitter::getNslots(uint32_t* nslots) const {
2621 uint64_t nslots64 =
2622 maxFixedSlots + static_cast<uint64_t>(bytecodeSection().maxStackDepth());
2623 if (nslots64 > UINT32_MAX(4294967295U)) {
2624 reportError(nullptr, JSMSG_NEED_DIET, "script");
2625 return false;
2626 }
2627 *nslots = nslots64;
2628 return true;
2629}
2630
2631bool BytecodeEmitter::emitFunctionScript(FunctionNode* funNode) {
2632 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"
, 2632); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inPrologue()"
")"); do { MOZ_CrashSequence(__null, 2632); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2633
2634 if (!fc->checkCompilationCancellation()) {
2635 return false;
2636 }
2637
2638 ParamsBodyNode* paramsBody = funNode->body();
2639 FunctionBox* funbox = sc->asFunctionBox();
2640
2641 setScriptStartOffsetIfUnset(paramsBody->pn_pos.begin);
2642
2643 // [stack]
2644
2645 FunctionScriptEmitter fse(this, funbox, Some(paramsBody->pn_pos.begin),
2646 Some(paramsBody->pn_pos.end));
2647 if (!fse.prepareForParameters()) {
2648 // [stack]
2649 return false;
2650 }
2651
2652 if (!emitFunctionFormalParameters(paramsBody)) {
2653 // [stack]
2654 return false;
2655 }
2656
2657 if (!fse.prepareForBody()) {
2658 // [stack]
2659 return false;
2660 }
2661
2662 if (!emitTree(paramsBody->body())) {
2663 // [stack]
2664 return false;
2665 }
2666
2667 if (!fse.emitEndBody()) {
2668 // [stack]
2669 return false;
2670 }
2671
2672 if (funbox->index() == CompilationStencil::TopLevelIndex) {
2673 if (!NameFunctions(fc, parserAtoms(), funNode)) {
2674 return false;
2675 }
2676 }
2677
2678 return fse.intoStencil();
2679}
2680
2681class js::frontend::DestructuringLHSRef {
2682 struct None {
2683 size_t numReferenceSlots() const { return 0; }
2684 };
2685
2686 mozilla::Variant<None, NameOpEmitter, PropOpEmitter, ElemOpEmitter,
2687 PrivateOpEmitter>
2688 emitter_ = AsVariant(None{});
2689
2690 public:
2691 template <typename T>
2692 void from(T&& emitter) {
2693 emitter_.emplace<T>(std::forward<T>(emitter));
2694 }
2695
2696 template <typename T>
2697 T& emitter() {
2698 return emitter_.as<T>();
2699 }
2700
2701 /**
2702 * Return the number of values pushed onto the stack.
2703 */
2704 size_t numReferenceSlots() const {
2705 return emitter_.match([](auto& e) { return e.numReferenceSlots(); });
2706 }
2707};
2708
2709bool BytecodeEmitter::emitDestructuringLHSRef(ParseNode* target,
2710 DestructuringFlavor flav,
2711 DestructuringLHSRef& lref) {
2712#ifdef DEBUG1
2713 int depth = bytecodeSection().stackDepth();
2714#endif
2715
2716 switch (target->getKind()) {
2717 case ParseNodeKind::ArrayExpr:
2718 case ParseNodeKind::ObjectExpr:
2719 // No need to recurse into ParseNodeKind::Array and ParseNodeKind::Object
2720 // subpatterns here, since emitSetOrInitializeDestructuring does the
2721 // recursion when setting or initializing the value.
2722 break;
2723
2724 case ParseNodeKind::Name: {
2725 auto* name = &target->as<NameNode>();
2726 NameOpEmitter noe(this, name->atom(),
2727 flav == DestructuringFlavor::Assignment
2728 ? NameOpEmitter::Kind::SimpleAssignment
2729 : NameOpEmitter::Kind::Initialize);
2730 if (!noe.prepareForRhs()) {
2731 return false;
2732 }
2733
2734 lref.from(std::move(noe));
2735 return true;
2736 }
2737
2738 case ParseNodeKind::ArgumentsLength:
2739 case ParseNodeKind::DotExpr: {
2740 NonOptionalPropertyAccessBase* prop =
2741 &target->as<NonOptionalPropertyAccessBase>();
2742 bool isSuper = prop->isSuper();
2743 PropOpEmitter poe(this, PropOpEmitter::Kind::SimpleAssignment,
2744 isSuper ? PropOpEmitter::ObjKind::Super
2745 : PropOpEmitter::ObjKind::Other);
2746 if (!poe.prepareForObj()) {
2747 return false;
2748 }
2749 if (isSuper) {
2750 UnaryNode* base = &prop->expression().as<UnaryNode>();
2751 if (!emitGetThisForSuperBase(base)) {
2752 // [stack] THIS SUPERBASE
2753 return false;
2754 }
2755 } else {
2756 if (!emitTree(&prop->expression())) {
2757 // [stack] OBJ
2758 return false;
2759 }
2760 }
2761 if (!poe.prepareForRhs()) {
2762 // [stack] # if Super
2763 // [stack] THIS SUPERBASE
2764 // [stack] # otherwise
2765 // [stack] OBJ
2766 return false;
2767 }
2768
2769 lref.from(std::move(poe));
2770 break;
2771 }
2772
2773 case ParseNodeKind::ElemExpr: {
2774 PropertyByValue* elem = &target->as<PropertyByValue>();
2775 bool isSuper = elem->isSuper();
2776 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", 2776);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)"
")"); do { MOZ_CrashSequence(__null, 2776); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2777 ElemOpEmitter eoe(this, ElemOpEmitter::Kind::SimpleAssignment,
2778 isSuper ? ElemOpEmitter::ObjKind::Super
2779 : ElemOpEmitter::ObjKind::Other);
2780 if (!emitElemObjAndKey(elem, eoe)) {
2781 // [stack] # if Super
2782 // [stack] THIS KEY
2783 // [stack] # otherwise
2784 // [stack] OBJ KEY
2785 return false;
2786 }
2787 if (!eoe.prepareForRhs()) {
2788 // [stack] # if Super
2789 // [stack] THIS KEY SUPERBASE
2790 // [stack] # otherwise
2791 // [stack] OBJ KEY
2792 return false;
2793 }
2794
2795 lref.from(std::move(eoe));
2796 break;
2797 }
2798
2799 case ParseNodeKind::PrivateMemberExpr: {
2800 PrivateMemberAccess* privateExpr = &target->as<PrivateMemberAccess>();
2801 PrivateOpEmitter xoe(this, PrivateOpEmitter::Kind::SimpleAssignment,
2802 privateExpr->privateName().name());
2803 if (!emitTree(&privateExpr->expression())) {
2804 // [stack] OBJ
2805 return false;
2806 }
2807 if (!xoe.emitReference()) {
2808 // [stack] OBJ NAME
2809 return false;
2810 }
2811
2812 lref.from(std::move(xoe));
2813 break;
2814 }
2815
2816 case ParseNodeKind::CallExpr:
2817 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"
, 2820); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget "
"rejects function calls as assignment " "targets in destructuring assignments"
")"); do { MOZ_CrashSequence(__null, 2820); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2818 "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"
, 2820); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget "
"rejects function calls as assignment " "targets in destructuring assignments"
")"); do { MOZ_CrashSequence(__null, 2820); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2819 "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"
, 2820); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget "
"rejects function calls as assignment " "targets in destructuring assignments"
")"); do { MOZ_CrashSequence(__null, 2820); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2820 "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"
, 2820); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget "
"rejects function calls as assignment " "targets in destructuring assignments"
")"); do { MOZ_CrashSequence(__null, 2820); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2821 break;
2822
2823 default:
2824 MOZ_CRASH("emitDestructuringLHSRef: bad lhs kind")do { do { } while (false); MOZ_ReportCrash("" "emitDestructuringLHSRef: bad lhs kind"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 2824);
AnnotateMozCrashReason("MOZ_CRASH(" "emitDestructuringLHSRef: bad lhs kind"
")"); do { MOZ_CrashSequence(__null, 2824); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
2825 }
2826
2827 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", 2828);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == depth + int(lref.numReferenceSlots())"
")"); do { MOZ_CrashSequence(__null, 2828); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2828 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", 2828);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == depth + int(lref.numReferenceSlots())"
")"); do { MOZ_CrashSequence(__null, 2828); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2829
2830 return true;
2831}
2832
2833bool BytecodeEmitter::emitSetOrInitializeDestructuring(
2834 ParseNode* target, DestructuringFlavor flav, DestructuringLHSRef& lref) {
2835 // Now emit the lvalue opcode sequence. If the lvalue is a nested
2836 // destructuring initialiser-form, call ourselves to handle it, then pop
2837 // the matched value. Otherwise emit an lvalue bytecode sequence followed
2838 // by an assignment op.
2839
2840 switch (target->getKind()) {
2841 case ParseNodeKind::ArrayExpr:
2842 case ParseNodeKind::ObjectExpr:
2843 if (!emitDestructuringOps(&target->as<ListNode>(), flav,
2844 SelfHostedIter::Deny)) {
2845 return false;
2846 }
2847 // emitDestructuringOps leaves the assigned (to-be-destructured) value on
2848 // top of the stack.
2849 break;
2850
2851 case ParseNodeKind::Name: {
2852 // The environment is already pushed by emitDestructuringLHSRef.
2853 // [stack] ENV? VAL
2854 auto& noe = lref.emitter<NameOpEmitter>();
2855
2856 if (!noe.emitAssignment()) {
2857 // [stack] VAL
2858 return false;
2859 }
2860 break;
2861 }
2862
2863 case ParseNodeKind::ArgumentsLength:
2864 case ParseNodeKind::DotExpr: {
2865 // The reference is already pushed by emitDestructuringLHSRef.
2866 // [stack] # if Super
2867 // [stack] THIS SUPERBASE VAL
2868 // [stack] # otherwise
2869 // [stack] OBJ VAL
2870 auto& poe = lref.emitter<PropOpEmitter>();
2871 auto* prop = &target->as<NonOptionalPropertyAccessBase>();
2872
2873 if (!poe.emitAssignment(prop->key().atom())) {
2874 // [stack] # VAL
2875 return false;
2876 }
2877 break;
2878 }
2879
2880 case ParseNodeKind::ElemExpr: {
2881 // The reference is already pushed by emitDestructuringLHSRef.
2882 // [stack] # if Super
2883 // [stack] THIS KEY SUPERBASE VAL
2884 // [stack] # otherwise
2885 // [stack] OBJ KEY VAL
2886 auto& eoe = lref.emitter<ElemOpEmitter>();
2887
2888 if (!eoe.emitAssignment()) {
2889 // [stack] VAL
2890 return false;
2891 }
2892 break;
2893 }
2894
2895 case ParseNodeKind::PrivateMemberExpr: {
2896 // The reference is already pushed by emitDestructuringLHSRef.
2897 // [stack] OBJ NAME VAL
2898 auto& xoe = lref.emitter<PrivateOpEmitter>();
2899
2900 if (!xoe.emitAssignment()) {
2901 // [stack] VAL
2902 return false;
2903 }
2904 break;
2905 }
2906
2907 case ParseNodeKind::CallExpr:
2908 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"
, 2911); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget "
"rejects function calls as assignment " "targets in destructuring assignments"
")"); do { MOZ_CrashSequence(__null, 2911); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2909 "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"
, 2911); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget "
"rejects function calls as assignment " "targets in destructuring assignments"
")"); do { MOZ_CrashSequence(__null, 2911); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2910 "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"
, 2911); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget "
"rejects function calls as assignment " "targets in destructuring assignments"
")"); do { MOZ_CrashSequence(__null, 2911); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2911 "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"
, 2911); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget "
"rejects function calls as assignment " "targets in destructuring assignments"
")"); do { MOZ_CrashSequence(__null, 2911); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2912 break;
2913
2914 default:
2915 MOZ_CRASH("emitSetOrInitializeDestructuring: bad lhs kind")do { do { } while (false); MOZ_ReportCrash("" "emitSetOrInitializeDestructuring: bad lhs kind"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 2915);
AnnotateMozCrashReason("MOZ_CRASH(" "emitSetOrInitializeDestructuring: bad lhs kind"
")"); do { MOZ_CrashSequence(__null, 2915); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
2916 }
2917
2918 // Pop the assigned value.
2919 if (!emit1(JSOp::Pop)) {
2920 // [stack] # empty
2921 return false;
2922 }
2923
2924 return true;
2925}
2926
2927JSOp BytecodeEmitter::getIterCallOp(JSOp callOp,
2928 SelfHostedIter selfHostedIter) const {
2929 if (emitterMode == BytecodeEmitter::SelfHosting) {
2930 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", 2930);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny"
")"); do { MOZ_CrashSequence(__null, 2930); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2931
2932 switch (callOp) {
2933 case JSOp::Call:
2934 return JSOp::CallContent;
2935 case JSOp::CallIter:
2936 return JSOp::CallContentIter;
2937 default:
2938 MOZ_CRASH("Unknown iterator call op")do { do { } while (false); MOZ_ReportCrash("" "Unknown iterator call op"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 2938);
AnnotateMozCrashReason("MOZ_CRASH(" "Unknown iterator call op"
")"); do { MOZ_CrashSequence(__null, 2938); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
2939 }
2940 }
2941
2942 return callOp;
2943}
2944
2945bool BytecodeEmitter::emitIteratorNext(
2946 const Maybe<uint32_t>& callSourceCoordOffset, IteratorKind iterKind,
2947 SelfHostedIter selfHostedIter) {
2948 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"
, 2951); 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, 2951); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
2949 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"
, 2951); 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, 2951); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
2950 ".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"
, 2951); 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, 2951); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
2951 "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"
, 2951); 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, 2951); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2952
2953 // [stack] ... NEXT ITER
2954 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", 2954);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() >= 2"
")"); do { MOZ_CrashSequence(__null, 2954); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2955
2956 if (!emitCall(getIterCallOp(JSOp::Call, selfHostedIter), 0,
2957 callSourceCoordOffset)) {
2958 // [stack] ... RESULT
2959 return false;
2960 }
2961
2962 if (iterKind == IteratorKind::Async) {
2963 if (!emitAwaitInInnermostScope()) {
2964 // [stack] ... RESULT
2965 return false;
2966 }
2967 }
2968
2969 if (!emitCheckIsObj(CheckIsObjectKind::IteratorNext)) {
2970 // [stack] ... RESULT
2971 return false;
2972 }
2973 return true;
2974}
2975
2976bool BytecodeEmitter::emitIteratorCloseInScope(EmitterScope& currentScope,
2977 IteratorKind iterKind,
2978 CompletionKind completionKind,
2979 SelfHostedIter selfHostedIter) {
2980 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"
, 2983); 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, 2983); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
2981 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"
, 2983); 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, 2983); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
2982 ".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"
, 2983); 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, 2983); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
2983 "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"
, 2983); 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, 2983); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2984
2985 if (iterKind == IteratorKind::Sync) {
2986 return emit2(JSOp::CloseIter, uint8_t(completionKind));
2987 }
2988
2989 // Generate inline logic corresponding to IteratorClose (ES2021 7.4.6) and
2990 // AsyncIteratorClose (ES2021 7.4.7). Steps numbers apply to both operations.
2991 //
2992 // Callers need to ensure that the iterator object is at the top of the
2993 // stack.
2994
2995 // For non-Throw completions, we emit the equivalent of:
2996 //
2997 // var returnMethod = GetMethod(iterator, "return");
2998 // if (returnMethod !== undefined) {
2999 // var innerResult = [Await] Call(returnMethod, iterator);
3000 // CheckIsObj(innerResult);
3001 // }
3002 //
3003 // Whereas for Throw completions, we emit:
3004 //
3005 // try {
3006 // var returnMethod = GetMethod(iterator, "return");
3007 // if (returnMethod !== undefined) {
3008 // [Await] Call(returnMethod, iterator);
3009 // }
3010 // } catch {}
3011
3012 Maybe<TryEmitter> tryCatch;
3013
3014 if (completionKind == CompletionKind::Throw) {
3015 tryCatch.emplace(this, TryEmitter::Kind::TryCatch,
3016 TryEmitter::ControlKind::NonSyntactic);
3017
3018 if (!tryCatch->emitTry()) {
3019 // [stack] ... ITER
3020 return false;
3021 }
3022 }
3023
3024 if (!emit1(JSOp::Dup)) {
3025 // [stack] ... ITER ITER
3026 return false;
3027 }
3028
3029 // Steps 1-2 are assertions, step 3 is implicit.
3030
3031 // Step 4.
3032 //
3033 // Get the "return" method.
3034 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::return_())) {
3035 // [stack] ... ITER RET
3036 return false;
3037 }
3038
3039 // Step 5.
3040 //
3041 // Do nothing if "return" is undefined or null.
3042 InternalIfEmitter ifReturnMethodIsDefined(this);
3043 if (!emit1(JSOp::IsNullOrUndefined)) {
3044 // [stack] ... ITER RET NULL-OR-UNDEF
3045 return false;
3046 }
3047
3048 if (!ifReturnMethodIsDefined.emitThenElse(
3049 IfEmitter::ConditionKind::Negative)) {
3050 // [stack] ... ITER RET
3051 return false;
3052 }
3053
3054 // Steps 5.c, 7.
3055 //
3056 // Call the "return" method.
3057 if (!emit1(JSOp::Swap)) {
3058 // [stack] ... RET ITER
3059 return false;
3060 }
3061
3062 if (!emitCall(getIterCallOp(JSOp::Call, selfHostedIter), 0)) {
3063 // [stack] ... RESULT
3064 return false;
3065 }
3066
3067 // 7.4.7 AsyncIteratorClose, step 5.d.
3068 if (iterKind == IteratorKind::Async) {
3069 if (completionKind != CompletionKind::Throw) {
3070 // Await clobbers rval, so save the current rval.
3071 if (!emit1(JSOp::GetRval)) {
3072 // [stack] ... RESULT RVAL
3073 return false;
3074 }
3075 if (!emit1(JSOp::Swap)) {
3076 // [stack] ... RVAL RESULT
3077 return false;
3078 }
3079 }
3080
3081 if (!emitAwaitInScope(currentScope)) {
3082 // [stack] ... RVAL? RESULT
3083 return false;
3084 }
3085
3086 if (completionKind != CompletionKind::Throw) {
3087 if (!emit1(JSOp::Swap)) {
3088 // [stack] ... RESULT RVAL
3089 return false;
3090 }
3091 if (!emit1(JSOp::SetRval)) {
3092 // [stack] ... RESULT
3093 return false;
3094 }
3095 }
3096 }
3097
3098 // Step 6 (Handled in caller).
3099
3100 // Step 8.
3101 if (completionKind != CompletionKind::Throw) {
3102 // Check that the "return" result is an object.
3103 if (!emitCheckIsObj(CheckIsObjectKind::IteratorReturn)) {
3104 // [stack] ... RESULT
3105 return false;
3106 }
3107 }
3108
3109 if (!ifReturnMethodIsDefined.emitElse()) {
3110 // [stack] ... ITER RET
3111 return false;
3112 }
3113
3114 if (!emit1(JSOp::Pop)) {
3115 // [stack] ... ITER
3116 return false;
3117 }
3118
3119 if (!ifReturnMethodIsDefined.emitEnd()) {
3120 return false;
3121 }
3122
3123 if (completionKind == CompletionKind::Throw) {
3124 if (!tryCatch->emitCatch()) {
3125 // [stack] ... ITER EXC
3126 return false;
3127 }
3128
3129 // Just ignore the exception thrown by call and await.
3130 if (!emit1(JSOp::Pop)) {
3131 // [stack] ... ITER
3132 return false;
3133 }
3134
3135 if (!tryCatch->emitEnd()) {
3136 // [stack] ... ITER
3137 return false;
3138 }
3139 }
3140
3141 // Step 9 (Handled in caller).
3142
3143 return emit1(JSOp::Pop);
3144 // [stack] ...
3145}
3146
3147bool BytecodeEmitter::emitDestructuringIteratorClose(
3148 SelfHostedIter selfHostedIter) {
3149 // [stack] ... OBJ NEXT ITER DONE
3150
3151 InternalIfEmitter ifDone(this);
3152 if (!ifDone.emitThenElse()) {
3153 // [stack] ... OBJ NEXT ITER
3154 return false;
3155 }
3156 if (!emitPopN(2)) {
3157 // [stack] ... OBJ
3158 return false;
3159 }
3160 if (!ifDone.emitElse()) {
3161 // [stack] ... OBJ NEXT ITER
3162 return false;
3163 }
3164 if (!emit1(JSOp::Swap)) {
3165 // [stack] ... OBJ ITER NEXT
3166 return false;
3167 }
3168 if (!emit1(JSOp::Pop)) {
3169 // [stack] ... OBJ ITER
3170 return false;
3171 }
3172 if (!emitIteratorCloseInInnermostScope(
3173 IteratorKind::Sync, CompletionKind::Normal, selfHostedIter)) {
3174 // [stack] ... OBJ
3175 return false;
3176 }
3177 return ifDone.emitEnd();
3178}
3179
3180template <typename InnerEmitter>
3181bool BytecodeEmitter::wrapWithDestructuringTryNote(int32_t iterDepth,
3182 InnerEmitter emitter) {
3183 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", 3183);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() >= iterDepth"
")"); do { MOZ_CrashSequence(__null, 3183); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3184#ifdef DEBUG1
3185 auto* control = findInnermostNestableControl<DestructuringControl>();
3186 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", 3186);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "*control->nonLocalExitStackDepth() == iterDepth"
")"); do { MOZ_CrashSequence(__null, 3186); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3187#endif
3188
3189 // Pad a nop at the beginning of the bytecode covered by the trynote so
3190 // that when unwinding environments, we may unwind to the scope
3191 // corresponding to the pc *before* the start, in case the first bytecode
3192 // emitted by |emitter| is the start of an inner scope. See comment above
3193 // UnwindEnvironmentToTryPc.
3194 if (!emit1(JSOp::TryDestructuring)) {
3195 return false;
3196 }
3197
3198 BytecodeOffset start = bytecodeSection().offset();
3199 if (!emitter(this)) {
3200 return false;
3201 }
3202 BytecodeOffset end = bytecodeSection().offset();
3203 if (start != end) {
3204 return addTryNote(TryNoteKind::Destructuring, iterDepth, start, end);
3205 }
3206 return true;
3207}
3208
3209bool BytecodeEmitter::emitDefault(ParseNode* defaultExpr, ParseNode* pattern) {
3210 // [stack] VALUE
3211
3212 DefaultEmitter de(this);
3213 if (!de.prepareForDefault()) {
3214 // [stack]
3215 return false;
3216 }
3217 if (!emitInitializer(defaultExpr, pattern)) {
3218 // [stack] DEFAULTVALUE
3219 return false;
3220 }
3221 if (!de.emitEnd()) {
3222 // [stack] VALUE/DEFAULTVALUE
3223 return false;
3224 }
3225 return true;
3226}
3227
3228bool BytecodeEmitter::emitAnonymousFunctionWithName(
3229 ParseNode* node, TaggedParserAtomIndex name) {
3230 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"
, 3230); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isDirectRHSAnonFunction()"
")"); do { MOZ_CrashSequence(__null, 3230); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3231
3232 if (node->is<FunctionNode>()) {
3233 // Function doesn't have 'name' property at this point.
3234 // Set function's name at compile time.
3235 setFunName(node->as<FunctionNode>().funbox(), name);
3236
3237 return emitTree(node);
3238 }
3239
3240 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"
, 3240); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->is<ClassNode>()"
")"); do { MOZ_CrashSequence(__null, 3240); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3241
3242 return emitClass(&node->as<ClassNode>(), ClassNameKind::InferredName, name);
3243}
3244
3245bool BytecodeEmitter::emitAnonymousFunctionWithComputedName(
3246 ParseNode* node, FunctionPrefixKind prefixKind) {
3247 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"
, 3247); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isDirectRHSAnonFunction()"
")"); do { MOZ_CrashSequence(__null, 3247); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3248
3249 if (node->is<FunctionNode>()) {
3250 if (!emitTree(node)) {
3251 // [stack] NAME FUN
3252 return false;
3253 }
3254 if (!emitDupAt(1)) {
3255 // [stack] NAME FUN NAME
3256 return false;
3257 }
3258 if (!emit2(JSOp::SetFunName, uint8_t(prefixKind))) {
3259 // [stack] NAME FUN
3260 return false;
3261 }
3262 return true;
3263 }
3264
3265 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"
, 3265); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->is<ClassNode>()"
")"); do { MOZ_CrashSequence(__null, 3265); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3266 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", 3266);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "prefixKind == FunctionPrefixKind::None"
")"); do { MOZ_CrashSequence(__null, 3266); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3267
3268 return emitClass(&node->as<ClassNode>(), ClassNameKind::ComputedName);
3269}
3270
3271void BytecodeEmitter::setFunName(FunctionBox* funbox,
3272 TaggedParserAtomIndex name) const {
3273 // The inferred name may already be set if this function is an interpreted
3274 // lazy function and we OOM'ed after we set the inferred name the first
3275 // time.
3276 if (funbox->hasInferredName()) {
3277 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", 3277);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!funbox->emitBytecode"
")"); do { MOZ_CrashSequence(__null, 3277); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3278 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"
, 3278); AnnotateMozCrashReason("MOZ_ASSERT" "(" "funbox->displayAtom() == name"
")"); do { MOZ_CrashSequence(__null, 3278); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3279 } else {
3280 funbox->setInferredName(name);
3281 }
3282}
3283
3284bool BytecodeEmitter::emitInitializer(ParseNode* initializer,
3285 ParseNode* pattern) {
3286 if (initializer->isDirectRHSAnonFunction()) {
3287 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", 3287);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!pattern->isInParens()"
")"); do { MOZ_CrashSequence(__null, 3287); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3288 auto name = pattern->as<NameNode>().name();
3289 if (!emitAnonymousFunctionWithName(initializer, name)) {
3290 return false;
3291 }
3292 } else {
3293 if (!emitTree(initializer)) {
3294 return false;
3295 }
3296 }
3297
3298 return true;
3299}
3300
3301bool BytecodeEmitter::emitDestructuringOpsArray(ListNode* pattern,
3302 DestructuringFlavor flav,
3303 SelfHostedIter selfHostedIter) {
3304 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", 3304);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "pattern->isKind(ParseNodeKind::ArrayExpr)"
")"); do { MOZ_CrashSequence(__null, 3304); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3305 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"
, 3305); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() != 0"
")"); do { MOZ_CrashSequence(__null, 3305); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3306
3307 // Here's pseudo code for |let [a, b, , c=y, ...d] = x;|
3308 //
3309 // Lines that are annotated "covered by trynote" mean that upon throwing
3310 // an exception, IteratorClose is called on iter only if done is false.
3311 //
3312 // let x, y;
3313 // let a, b, c, d;
3314 // let iter, next, lref, result, done, value; // stack values
3315 //
3316 // // NOTE: the fast path for this example is not applicable, because of
3317 // // the spread and the assignment |c=y|, but it is documented here for a
3318 // // simpler example, |let [a,b] = x;|
3319 // //
3320 // // if (IsOptimizableArray(x)) {
3321 // // a = x[0];
3322 // // b = x[1];
3323 // // goto end: // (skip everything below)
3324 // // }
3325 //
3326 // iter = x[Symbol.iterator]();
3327 // next = iter.next;
3328 //
3329 // // ==== emitted by loop for a ====
3330 // lref = GetReference(a); // covered by trynote
3331 //
3332 // result = Call(next, iter);
3333 // done = result.done;
3334 //
3335 // if (done)
3336 // value = undefined;
3337 // else
3338 // value = result.value;
3339 //
3340 // SetOrInitialize(lref, value); // covered by trynote
3341 //
3342 // // ==== emitted by loop for b ====
3343 // lref = GetReference(b); // covered by trynote
3344 //
3345 // if (done) {
3346 // value = undefined;
3347 // } else {
3348 // result = Call(next, iter);
3349 // done = result.done;
3350 // if (done)
3351 // value = undefined;
3352 // else
3353 // value = result.value;
3354 // }
3355 //
3356 // SetOrInitialize(lref, value); // covered by trynote
3357 //
3358 // // ==== emitted by loop for elision ====
3359 // if (done) {
3360 // value = undefined;
3361 // } else {
3362 // result = Call(next, iter);
3363 // done = result.done;
3364 // if (done)
3365 // value = undefined;
3366 // else
3367 // value = result.value;
3368 // }
3369 //
3370 // // ==== emitted by loop for c ====
3371 // lref = GetReference(c); // covered by trynote
3372 //
3373 // if (done) {
3374 // value = undefined;
3375 // } else {
3376 // result = Call(next, iter);
3377 // done = result.done;
3378 // if (done)
3379 // value = undefined;
3380 // else
3381 // value = result.value;
3382 // }
3383 //
3384 // if (value === undefined)
3385 // value = y; // covered by trynote
3386 //
3387 // SetOrInitialize(lref, value); // covered by trynote
3388 //
3389 // // ==== emitted by loop for d ====
3390 // lref = GetReference(d); // covered by trynote
3391 //
3392 // if (done)
3393 // value = [];
3394 // else
3395 // value = [...iter];
3396 //
3397 // SetOrInitialize(lref, value); // covered by trynote
3398 //
3399 // // === emitted after loop ===
3400 // if (!done)
3401 // IteratorClose(iter);
3402 //
3403 // end:
3404
3405 bool isEligibleForArrayOptimizations = true;
3406 for (ParseNode* member : pattern->contents()) {
3407 switch (member->getKind()) {
3408 case ParseNodeKind::Elision:
3409 break;
3410 case ParseNodeKind::Name: {
3411 auto name = member->as<NameNode>().name();
3412 NameLocation loc = lookupName(name);
3413 if (loc.kind() != NameLocation::Kind::ArgumentSlot &&
3414 loc.kind() != NameLocation::Kind::FrameSlot &&
3415 loc.kind() != NameLocation::Kind::EnvironmentCoordinate) {
3416 isEligibleForArrayOptimizations = false;
3417 }
3418 break;
3419 }
3420 default:
3421 // Unfortunately we can't handle any recursive destructuring,
3422 // because we can't guarantee that the recursed-into parts
3423 // won't run code which invalidates our constraints. We also
3424 // cannot handle ParseNodeKind::AssignExpr for similar reasons.
3425 isEligibleForArrayOptimizations = false;
3426 break;
3427 }
3428 if (!isEligibleForArrayOptimizations) {
3429 break;
3430 }
3431 }
3432
3433 // Use an iterator to destructure the RHS, instead of index lookup. We
3434 // must leave the *original* value on the stack.
3435 if (!emit1(JSOp::Dup)) {
3436 // [stack] ... OBJ OBJ
3437 return false;
3438 }
3439
3440 Maybe<InternalIfEmitter> ifArrayOptimizable;
3441
3442 if (isEligibleForArrayOptimizations) {
3443 ifArrayOptimizable.emplace(
3444 this, BranchEmitterBase::LexicalKind::MayContainLexicalAccessInBranch);
3445
3446 if (!emit1(JSOp::Dup)) {
3447 // [stack] OBJ OBJ
3448 return false;
3449 }
3450
3451 if (!emit1(JSOp::OptimizeGetIterator)) {
3452 // [stack] OBJ OBJ IS_OPTIMIZABLE
3453 return false;
3454 }
3455
3456 if (!ifArrayOptimizable->emitThenElse()) {
3457 // [stack] OBJ OBJ
3458 return false;
3459 }
3460
3461 if (!emitAtomOp(JSOp::GetProp,
3462 TaggedParserAtomIndex::WellKnown::length())) {
3463 // [stack] OBJ LENGTH
3464 return false;
3465 }
3466
3467 if (!emit1(JSOp::Swap)) {
3468 // [stack] LENGTH OBJ
3469 return false;
3470 }
3471
3472 uint32_t idx = 0;
3473 for (ParseNode* member : pattern->contents()) {
3474 if (member->isKind(ParseNodeKind::Elision)) {
3475 idx += 1;
3476 continue;
3477 }
3478 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", 3478);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "member->isKind(ParseNodeKind::Name)"
")"); do { MOZ_CrashSequence(__null, 3478); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3479
3480 if (!emit1(JSOp::Dup)) {
3481 // [stack] LENGTH OBJ OBJ
3482 return false;
3483 }
3484
3485 if (!emitNumberOp(idx)) {
3486 // [stack] LENGTH OBJ OBJ IDX
3487 return false;
3488 }
3489
3490 if (!emit1(JSOp::Dup)) {
3491 // [stack] LENGTH OBJ OBJ IDX IDX
3492 return false;
3493 }
3494
3495 if (!emitDupAt(4)) {
3496 // [stack] LENGTH OBJ OBJ IDX IDX LENGTH
3497 return false;
3498 }
3499
3500 if (!emit1(JSOp::Lt)) {
3501 // [stack] LENGTH OBJ OBJ IDX IS_IN_DENSE_BOUNDS
3502 return false;
3503 }
3504
3505 InternalIfEmitter isInDenseBounds(this);
3506 if (!isInDenseBounds.emitThenElse()) {
3507 // [stack] LENGTH OBJ OBJ IDX
3508 return false;
3509 }
3510
3511 if (!emit1(JSOp::GetElem)) {
3512 // [stack] LENGTH OBJ VALUE
3513 return false;
3514 }
3515
3516 if (!isInDenseBounds.emitElse()) {
3517 // [stack] LENGTH OBJ OBJ IDX
3518 return false;
3519 }
3520
3521 if (!emitPopN(2)) {
3522 // [stack] LENGTH OBJ
3523 return false;
3524 }
3525
3526 if (!emit1(JSOp::Undefined)) {
3527 // [stack] LENGTH OBJ UNDEFINED
3528 return false;
3529 }
3530
3531 if (!isInDenseBounds.emitEnd()) {
3532 // [stack] LENGTH OBJ VALUE|UNDEFINED
3533 return false;
3534 }
3535
3536 DestructuringLHSRef lref;
3537 if (!emitDestructuringLHSRef(member, flav, lref)) {
3538 // [stack] LENGTH OBJ
3539 return false;
3540 }
3541
3542 if (!emitSetOrInitializeDestructuring(member, flav, lref)) {
3543 // [stack] LENGTH OBJ
3544 return false;
3545 }
3546
3547 idx += 1;
3548 }
3549
3550 if (!emit1(JSOp::Swap)) {
3551 // [stack] OBJ LENGTH
3552 return false;
3553 }
3554
3555 if (!emit1(JSOp::Pop)) {
3556 // [stack] OBJ
3557 return false;
3558 }
3559
3560 if (!ifArrayOptimizable->emitElse()) {
3561 // [stack] OBJ OBJ
3562 return false;
3563 }
3564 }
3565
3566 if (!emitIterator(selfHostedIter)) {
3567 // [stack] ... OBJ NEXT ITER
3568 return false;
3569 }
3570
3571 // For an empty pattern [], call IteratorClose unconditionally. Nothing
3572 // else needs to be done.
3573 if (!pattern->head()) {
3574 if (!emit1(JSOp::Swap)) {
3575 // [stack] ... OBJ ITER NEXT
3576 return false;
3577 }
3578 if (!emit1(JSOp::Pop)) {
3579 // [stack] ... OBJ ITER
3580 return false;
3581 }
3582
3583 if (!emitIteratorCloseInInnermostScope(
3584 IteratorKind::Sync, CompletionKind::Normal, selfHostedIter)) {
3585 // [stack] ... OBJ
3586 return false;
3587 }
3588
3589 if (ifArrayOptimizable.isSome()) {
3590 if (!ifArrayOptimizable->emitEnd()) {
3591 // [stack] OBJ
3592 return false;
3593 }
3594 }
3595
3596 return true;
3597 }
3598
3599 // Push an initial FALSE value for DONE.
3600 if (!emit1(JSOp::False)) {
3601 // [stack] ... OBJ NEXT ITER FALSE
3602 return false;
3603 }
3604
3605 // TryNoteKind::Destructuring expects the iterator and the done value
3606 // to be the second to top and the top of the stack, respectively.
3607 // IteratorClose is called upon exception only if done is false.
3608 int32_t tryNoteDepth = bytecodeSection().stackDepth();
3609
3610 // A forced return from a `yield` will jump out of the destructuring region,
3611 // so in that case DestructuringControl emits the IteratorClose after the
3612 // loop.
3613 DestructuringControl control(this, selfHostedIter);
3614 control.setNonLocalExitStackDepth(tryNoteDepth);
3615
3616 for (ParseNode* member : pattern->contents()) {
3617 bool isFirst = member == pattern->head();
3618 DebugOnly<bool> hasNext = !!member->pn_next;
3619
3620 ParseNode* subpattern;
3621 if (member->isKind(ParseNodeKind::Spread)) {
3622 subpattern = member->as<UnaryNode>().kid();
3623
3624 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", 3624);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!subpattern->isKind(ParseNodeKind::AssignExpr)"
")"); do { MOZ_CrashSequence(__null, 3624); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3625 } else {
3626 subpattern = member;
3627 }
3628
3629 ParseNode* lhsPattern = subpattern;
3630 ParseNode* pndefault = nullptr;
3631 if (subpattern->isKind(ParseNodeKind::AssignExpr)) {
3632 lhsPattern = subpattern->as<AssignmentNode>().left();
3633 pndefault = subpattern->as<AssignmentNode>().right();
3634 }
3635
3636 // Spec requires LHS reference to be evaluated first.
3637 DestructuringLHSRef lref;
3638 bool isElision = lhsPattern->isKind(ParseNodeKind::Elision);
3639 if (!isElision) {
3640 auto emitLHSRef = [lhsPattern, flav, &lref](BytecodeEmitter* bce) {
3641 return bce->emitDestructuringLHSRef(lhsPattern, flav, lref);
3642 // [stack] ... OBJ NEXT ITER DONE LREF*
3643 };
3644 if (!wrapWithDestructuringTryNote(tryNoteDepth, emitLHSRef)) {
3645 return false;
3646 }
3647 }
3648
3649 // Number of stack slots emitted for the LHS reference.
3650 size_t emitted = lref.numReferenceSlots();
3651
3652 // Pick the DONE value to the top of the stack.
3653 if (emitted) {
3654 if (!emitPickN(emitted)) {
3655 // [stack] ... OBJ NEXT ITER LREF* DONE
3656 return false;
3657 }
3658 }
3659
3660 if (isFirst) {
3661 // If this element is the first, DONE is always FALSE, so pop it.
3662 //
3663 // Non-first elements should emit if-else depending on the
3664 // member pattern, below.
3665 if (!emit1(JSOp::Pop)) {
3666 // [stack] ... OBJ NEXT ITER LREF*
3667 return false;
3668 }
3669 }
3670
3671 if (member->isKind(ParseNodeKind::Spread)) {
3672 InternalIfEmitter ifThenElse(this);
3673 if (!isFirst) {
3674 // If spread is not the first element of the pattern,
3675 // iterator can already be completed.
3676 // [stack] ... OBJ NEXT ITER LREF* DONE
3677
3678 if (!ifThenElse.emitThenElse()) {
3679 // [stack] ... OBJ NEXT ITER LREF*
3680 return false;
3681 }
3682
3683 if (!emitUint32Operand(JSOp::NewArray, 0)) {
3684 // [stack] ... OBJ NEXT ITER LREF* ARRAY
3685 return false;
3686 }
3687 if (!ifThenElse.emitElse()) {
3688 // [stack] ... OBJ NEXT ITER LREF*
3689 return false;
3690 }
3691 }
3692
3693 // If iterator is not completed, create a new array with the rest
3694 // of the iterator.
3695 if (!emitDupAt(emitted + 1, 2)) {
3696 // [stack] ... OBJ NEXT ITER LREF* NEXT ITER
3697 return false;
3698 }
3699 if (!emitUint32Operand(JSOp::NewArray, 0)) {
3700 // [stack] ... OBJ NEXT ITER LREF* NEXT ITER ARRAY
3701 return false;
3702 }
3703 if (!emitNumberOp(0)) {
3704 // [stack] ... OBJ NEXT ITER LREF* NEXT ITER ARRAY INDEX
3705 return false;
3706 }
3707 if (!emitSpread(SelfHostedIter::Deny)) {
3708 // [stack] ... OBJ NEXT ITER LREF* ARRAY INDEX
3709 return false;
3710 }
3711 if (!emit1(JSOp::Pop)) {
3712 // [stack] ... OBJ NEXT ITER LREF* ARRAY
3713 return false;
3714 }
3715
3716 if (!isFirst) {
3717 if (!ifThenElse.emitEnd()) {
3718 return false;
3719 }
3720 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", 3720);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "ifThenElse.pushed() == 1"
")"); do { MOZ_CrashSequence(__null, 3720); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3721 }
3722
3723 // At this point the iterator is done. Unpick a TRUE value for DONE above
3724 // ITER.
3725 if (!emit1(JSOp::True)) {
3726 // [stack] ... OBJ NEXT ITER LREF* ARRAY TRUE
3727 return false;
3728 }
3729 if (!emitUnpickN(emitted + 1)) {
3730 // [stack] ... OBJ NEXT ITER TRUE LREF* ARRAY
3731 return false;
3732 }
3733
3734 auto emitAssignment = [lhsPattern, flav, &lref](BytecodeEmitter* bce) {
3735 return bce->emitSetOrInitializeDestructuring(lhsPattern, flav, lref);
3736 // [stack] ... OBJ NEXT ITER TRUE
3737 };
3738 if (!wrapWithDestructuringTryNote(tryNoteDepth, emitAssignment)) {
3739 return false;
3740 }
3741
3742 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"
, 3742); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!hasNext" ")"
); do { MOZ_CrashSequence(__null, 3742); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3743 break;
3744 }
3745
3746 InternalIfEmitter ifAlreadyDone(this);
3747 if (!isFirst) {
3748 // [stack] ... OBJ NEXT ITER LREF* DONE
3749
3750 if (!ifAlreadyDone.emitThenElse()) {
3751 // [stack] ... OBJ NEXT ITER LREF*
3752 return false;
3753 }
3754
3755 if (!emit1(JSOp::Undefined)) {
3756 // [stack] ... OBJ NEXT ITER LREF* UNDEF
3757 return false;
3758 }
3759 if (!emit1(JSOp::NopDestructuring)) {
3760 // [stack] ... OBJ NEXT ITER LREF* UNDEF
3761 return false;
3762 }
3763
3764 // The iterator is done. Unpick a TRUE value for DONE above ITER.
3765 if (!emit1(JSOp::True)) {
3766 // [stack] ... OBJ NEXT ITER LREF* UNDEF TRUE
3767 return false;
3768 }
3769 if (!emitUnpickN(emitted + 1)) {
3770 // [stack] ... OBJ NEXT ITER TRUE LREF* UNDEF
3771 return false;
3772 }
3773
3774 if (!ifAlreadyDone.emitElse()) {
3775 // [stack] ... OBJ NEXT ITER LREF*
3776 return false;
3777 }
3778 }
3779
3780 if (!emitDupAt(emitted + 1, 2)) {
3781 // [stack] ... OBJ NEXT ITER LREF* NEXT
3782 return false;
3783 }
3784 if (!emitIteratorNext(Some(pattern->pn_pos.begin), IteratorKind::Sync,
3785 selfHostedIter)) {
3786 // [stack] ... OBJ NEXT ITER LREF* RESULT
3787 return false;
3788 }
3789 if (!emit1(JSOp::Dup)) {
3790 // [stack] ... OBJ NEXT ITER LREF* RESULT RESULT
3791 return false;
3792 }
3793 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::done())) {
3794 // [stack] ... OBJ NEXT ITER LREF* RESULT DONE
3795 return false;
3796 }
3797
3798 if (!emit1(JSOp::Dup)) {
3799 // [stack] ... OBJ NEXT ITER LREF* RESULT DONE DONE
3800 return false;
3801 }
3802 if (!emitUnpickN(emitted + 2)) {
3803 // [stack] ... OBJ NEXT ITER DONE LREF* RESULT DONE
3804 return false;
3805 }
3806
3807 InternalIfEmitter ifDone(this);
3808 if (!ifDone.emitThenElse()) {
3809 // [stack] ... OBJ NEXT ITER DONE LREF* RESULT
3810 return false;
3811 }
3812
3813 if (!emit1(JSOp::Pop)) {
3814 // [stack] ... OBJ NEXT ITER DONE LREF*
3815 return false;
3816 }
3817 if (!emit1(JSOp::Undefined)) {
3818 // [stack] ... OBJ NEXT ITER DONE LREF* UNDEF
3819 return false;
3820 }
3821 if (!emit1(JSOp::NopDestructuring)) {
3822 // [stack] ... OBJ NEXT ITER DONE LREF* UNDEF
3823 return false;
3824 }
3825
3826 if (!ifDone.emitElse()) {
3827 // [stack] ... OBJ NEXT ITER DONE LREF* RESULT
3828 return false;
3829 }
3830
3831 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::value())) {
3832 // [stack] ... OBJ NEXT ITER DONE LREF* VALUE
3833 return false;
3834 }
3835
3836 if (!ifDone.emitEnd()) {
3837 return false;
3838 }
3839 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", 3839);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "ifDone.pushed() == 0"
")"); do { MOZ_CrashSequence(__null, 3839); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3840
3841 if (!isFirst) {
3842 if (!ifAlreadyDone.emitEnd()) {
3843 return false;
3844 }
3845 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", 3845);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "ifAlreadyDone.pushed() == 2"
")"); do { MOZ_CrashSequence(__null, 3845); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3846 }
3847
3848 if (pndefault) {
3849 auto emitDefault = [pndefault, lhsPattern](BytecodeEmitter* bce) {
3850 return bce->emitDefault(pndefault, lhsPattern);
3851 // [stack] ... OBJ NEXT ITER DONE LREF* VALUE
3852 };
3853
3854 if (!wrapWithDestructuringTryNote(tryNoteDepth, emitDefault)) {
3855 return false;
3856 }
3857 }
3858
3859 if (!isElision) {
3860 auto emitAssignment = [lhsPattern, flav, &lref](BytecodeEmitter* bce) {
3861 return bce->emitSetOrInitializeDestructuring(lhsPattern, flav, lref);
3862 // [stack] ... OBJ NEXT ITER DONE
3863 };
3864
3865 if (!wrapWithDestructuringTryNote(tryNoteDepth, emitAssignment)) {
3866 return false;
3867 }
3868 } else {
3869 if (!emit1(JSOp::Pop)) {
3870 // [stack] ... OBJ NEXT ITER DONE
3871 return false;
3872 }
3873 }
3874 }
3875
3876 // The last DONE value is on top of the stack. If not DONE, call
3877 // IteratorClose.
3878 // [stack] ... OBJ NEXT ITER DONE
3879 if (!control.emitEnd(this)) {
3880 // [stack] ... OBJ
3881 return false;
3882 }
3883
3884 if (ifArrayOptimizable.isSome()) {
3885 if (!ifArrayOptimizable->emitEnd()) {
3886 // [stack] OBJ
3887 return false;
3888 }
3889 }
3890
3891 return true;
3892}
3893
3894bool BytecodeEmitter::emitComputedPropertyName(UnaryNode* computedPropName) {
3895 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"
, 3895); AnnotateMozCrashReason("MOZ_ASSERT" "(" "computedPropName->isKind(ParseNodeKind::ComputedName)"
")"); do { MOZ_CrashSequence(__null, 3895); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3896 return emitTree(computedPropName->kid()) && emit1(JSOp::ToPropertyKey);
3897}
3898
3899bool BytecodeEmitter::emitDestructuringOpsObject(ListNode* pattern,
3900 DestructuringFlavor flav) {
3901 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", 3901);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "pattern->isKind(ParseNodeKind::ObjectExpr)"
")"); do { MOZ_CrashSequence(__null, 3901); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3902
3903 // [stack] ... RHS
3904 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", 3904);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() > 0"
")"); do { MOZ_CrashSequence(__null, 3904); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3905
3906 if (!emit1(JSOp::CheckObjCoercible)) {
3907 // [stack] ... RHS
3908 return false;
3909 }
3910
3911 // To understand why we chose '4', please see the discussion on Bug 1948959.
3912 const uint8_t estimatedRestSize = 4;
3913
3914 bool needsRestPropertyExcludedSet =
3915 pattern->count() > 1 && pattern->last()->isKind(ParseNodeKind::Spread);
3916 if (needsRestPropertyExcludedSet) {
3917 if (!emitDestructuringObjRestExclusionSet(pattern, estimatedRestSize)) {
3918 // [stack] ... RHS SET
3919 return false;
3920 }
3921
3922 if (!emit1(JSOp::Swap)) {
3923 // [stack] ... SET RHS
3924 return false;
3925 }
3926 }
3927
3928 for (ParseNode* member : pattern->contents()) {
3929 ParseNode* subpattern;
3930 bool hasKeyOnStack = false;
3931 if (member->isKind(ParseNodeKind::MutateProto) ||
3932 member->isKind(ParseNodeKind::Spread)) {
3933 subpattern = member->as<UnaryNode>().kid();
3934
3935 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"
, 3936); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!subpattern->isKind(ParseNodeKind::AssignExpr)"
")"); do { MOZ_CrashSequence(__null, 3936); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3936 !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"
, 3936); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!subpattern->isKind(ParseNodeKind::AssignExpr)"
")"); do { MOZ_CrashSequence(__null, 3936); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
3937 } else {
3938 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", 3939);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)"
")"); do { MOZ_CrashSequence(__null, 3939); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3939 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", 3939);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)"
")"); do { MOZ_CrashSequence(__null, 3939); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3940 subpattern = member->as<BinaryNode>().right();
3941
3942 // Computed property names are evaluated before the subpattern.
3943 ParseNode* key = member->as<BinaryNode>().left();
3944 if (key->isKind(ParseNodeKind::ComputedName)) {
3945 if (!emitComputedPropertyName(&key->as<UnaryNode>())) {
3946 // [stack] ... SET? RHS KEY
3947 return false;
3948 }
3949 hasKeyOnStack = true;
3950 }
3951 }
3952
3953 ParseNode* lhs = subpattern;
3954 ParseNode* pndefault = nullptr;
3955 if (subpattern->isKind(ParseNodeKind::AssignExpr)) {
3956 lhs = subpattern->as<AssignmentNode>().left();
3957 pndefault = subpattern->as<AssignmentNode>().right();
3958 }
3959
3960 // Spec requires LHS reference to be evaluated first.
3961 DestructuringLHSRef lref;
3962 if (!emitDestructuringLHSRef(lhs, flav, lref)) {
3963 // [stack] ... SET? RHS KEY? LREF*
3964 return false;
3965 }
3966
3967 // Number of stack slots emitted for the LHS reference.
3968 size_t emitted = lref.numReferenceSlots();
3969
3970 // Duplicate the value being destructured to use as a reference base.
3971 if (!emitDupAt(emitted + hasKeyOnStack)) {
3972 // [stack] ... SET? RHS KEY? LREF* RHS
3973 return false;
3974 }
3975
3976 if (member->isKind(ParseNodeKind::Spread)) {
3977 if (!updateSourceCoordNotes(member->pn_pos.begin)) {
3978 return false;
3979 }
3980
3981 if (!emit2(JSOp::NewInit, estimatedRestSize)) {
3982 // [stack] ... SET? RHS LREF* RHS TARGET
3983 return false;
3984 }
3985 if (!emit1(JSOp::Dup)) {
3986 // [stack] ... SET? RHS LREF* RHS TARGET TARGET
3987 return false;
3988 }
3989 if (!emit2(JSOp::Pick, 2)) {
3990 // [stack] ... SET? RHS LREF* TARGET TARGET RHS
3991 return false;
3992 }
3993
3994 if (needsRestPropertyExcludedSet) {
3995 if (!emit2(JSOp::Pick, emitted + 4)) {
3996 // [stack] ... RHS LREF* TARGET TARGET RHS SET
3997 return false;
3998 }
3999 }
4000
4001 CopyOption option = needsRestPropertyExcludedSet ? CopyOption::Filtered
4002 : CopyOption::Unfiltered;
4003 if (!emitCopyDataProperties(option)) {
4004 // [stack] ... RHS LREF* TARGET
4005 return false;
4006 }
4007
4008 // Destructure TARGET per this member's lhs.
4009 if (!emitSetOrInitializeDestructuring(lhs, flav, lref)) {
4010 // [stack] ... RHS
4011 return false;
4012 }
4013
4014 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", 4014
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "member == pattern->last()"
") (" "Rest property is always last" ")"); do { MOZ_CrashSequence
(__null, 4014); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4015 break;
4016 }
4017
4018 // Now push the property value currently being matched, which is the value
4019 // of the current property name "label" on the left of a colon in the object
4020 // initialiser.
4021 if (member->isKind(ParseNodeKind::MutateProto)) {
4022 if (!emitAtomOp(JSOp::GetProp,
4023 TaggedParserAtomIndex::WellKnown::proto_())) {
4024 // [stack] ... SET? RHS LREF* PROP
4025 return false;
4026 }
4027 } else {
4028 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", 4029);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)"
")"); do { MOZ_CrashSequence(__null, 4029); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4029 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", 4029);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)"
")"); do { MOZ_CrashSequence(__null, 4029); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4030
4031 ParseNode* key = member->as<BinaryNode>().left();
4032 if (key->isKind(ParseNodeKind::ObjectPropertyName) ||
4033 key->isKind(ParseNodeKind::StringExpr)) {
4034 if (!emitAtomOp(JSOp::GetProp, key->as<NameNode>().atom())) {
4035 // [stack] ... SET? RHS LREF* PROP
4036 return false;
4037 }
4038 } else {
4039 if (key->isKind(ParseNodeKind::NumberExpr)) {
4040 if (!emitNumberOp(key->as<NumericLiteral>().value())) {
4041 // [stack]... SET? RHS LREF* RHS KEY
4042 return false;
4043 }
4044 } else {
4045 // Otherwise this is a computed property name. BigInt keys are parsed
4046 // as (synthetic) computed property names, too.
4047 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", 4047);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::ComputedName)"
")"); do { MOZ_CrashSequence(__null, 4047); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4048 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", 4048); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "hasKeyOnStack" ")"); do { MOZ_CrashSequence
(__null, 4048); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4049
4050 if (!emit2(JSOp::Pick, emitted + 1)) {
4051 // [stack] ... SET? RHS LREF* RHS KEY
4052 return false;
4053 }
4054
4055 // Add the computed property key to the exclusion set.
4056 if (needsRestPropertyExcludedSet) {
4057 if (!emitDupAt(emitted + 3)) {
4058 // [stack] ... SET RHS LREF* RHS KEY SET
4059 return false;
4060 }
4061 if (!emitDupAt(1)) {
4062 // [stack] ... SET RHS LREF* RHS KEY SET KEY
4063 return false;
4064 }
4065 if (!emit1(JSOp::Undefined)) {
4066 // [stack] ... SET RHS LREF* RHS KEY SET KEY UNDEFINED
4067 return false;
4068 }
4069 if (!emit1(JSOp::InitElem)) {
4070 // [stack] ... SET RHS LREF* RHS KEY SET
4071 return false;
4072 }
4073 if (!emit1(JSOp::Pop)) {
4074 // [stack] ... SET RHS LREF* RHS KEY
4075 return false;
4076 }
4077 }
4078 }
4079
4080 // Get the property value.
4081 if (!emitElemOpBase(JSOp::GetElem)) {
4082 // [stack] ... SET? RHS LREF* PROP
4083 return false;
4084 }
4085 }
4086 }
4087
4088 if (pndefault) {
4089 if (!emitDefault(pndefault, lhs)) {
4090 // [stack] ... SET? RHS LREF* VALUE
4091 return false;
4092 }
4093 }
4094
4095 // Destructure PROP per this member's lhs.
4096 if (!emitSetOrInitializeDestructuring(lhs, flav, lref)) {
4097 // [stack] ... SET? RHS
4098 return false;
4099 }
4100 }
4101
4102 return true;
4103}
4104
4105static bool IsDestructuringRestExclusionSetObjLiteralCompatible(
4106 ListNode* pattern) {
4107 uint32_t propCount = 0;
4108 for (ParseNode* member : pattern->contents()) {
4109 if (member->isKind(ParseNodeKind::Spread)) {
4110 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"
, 4110); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!member->pn_next"
") (" "unexpected trailing element after spread" ")"); do { MOZ_CrashSequence
(__null, 4110); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4111 break;
4112 }
4113
4114 propCount++;
4115
4116 if (member->isKind(ParseNodeKind::MutateProto)) {
4117 continue;
4118 }
4119
4120 ParseNode* key = member->as<BinaryNode>().left();
4121 if (key->isKind(ParseNodeKind::ObjectPropertyName) ||
4122 key->isKind(ParseNodeKind::StringExpr)) {
4123 continue;
4124 }
4125
4126 // Number and BigInt keys aren't yet supported. Computed property names need
4127 // to be added dynamically.
4128 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", 4130);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr) || key->isKind(ParseNodeKind::ComputedName)"
")"); do { MOZ_CrashSequence(__null, 4130); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4129 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", 4130);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr) || key->isKind(ParseNodeKind::ComputedName)"
")"); do { MOZ_CrashSequence(__null, 4130); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4130 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", 4130);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr) || key->isKind(ParseNodeKind::ComputedName)"
")"); do { MOZ_CrashSequence(__null, 4130); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4131 return false;
4132 }
4133
4134 if (propCount > SharedPropMap::MaxPropsForNonDictionary) {
4135 // JSOp::NewObject cannot accept dictionary-mode objects.
4136 return false;
4137 }
4138
4139 return true;
4140}
4141
4142bool BytecodeEmitter::emitDestructuringObjRestExclusionSet(
4143 ListNode* pattern, uint8_t estimatedRestSize) {
4144 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", 4144);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "pattern->isKind(ParseNodeKind::ObjectExpr)"
")"); do { MOZ_CrashSequence(__null, 4144); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4145 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"
, 4145); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pattern->last()->isKind(ParseNodeKind::Spread)"
")"); do { MOZ_CrashSequence(__null, 4145); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4146
4147 // See if we can use ObjLiteral to construct the exclusion set object.
4148 if (IsDestructuringRestExclusionSetObjLiteralCompatible(pattern)) {
4149 if (!emitDestructuringRestExclusionSetObjLiteral(pattern)) {
4150 // [stack] OBJ
4151 return false;
4152 }
4153 } else {
4154 // Take the slow but sure way and start off with a blank object.
4155 if (!emit2(JSOp::NewInit, estimatedRestSize)) {
4156 // [stack] OBJ
4157 return false;
4158 }
4159 }
4160
4161 for (ParseNode* member : pattern->contents()) {
4162 if (member->isKind(ParseNodeKind::Spread)) {
4163 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"
, 4163); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!member->pn_next"
") (" "unexpected trailing element after spread" ")"); do { MOZ_CrashSequence
(__null, 4163); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4164 break;
4165 }
4166
4167 TaggedParserAtomIndex pnatom;
4168 if (member->isKind(ParseNodeKind::MutateProto)) {
4169 pnatom = TaggedParserAtomIndex::WellKnown::proto_();
4170 } else {
4171 ParseNode* key = member->as<BinaryNode>().left();
4172 if (key->isKind(ParseNodeKind::ObjectPropertyName) ||
4173 key->isKind(ParseNodeKind::StringExpr)) {
4174 pnatom = key->as<NameNode>().atom();
4175 } else if (key->isKind(ParseNodeKind::NumberExpr)) {
4176 if (!emitNumberOp(key->as<NumericLiteral>().value())) {
4177 return false;
4178 }
4179 } else {
4180 // Otherwise this is a computed property name which needs to be added
4181 // dynamically. BigInt keys are parsed as (synthetic) computed property
4182 // names, too.
4183 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", 4183);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::ComputedName)"
")"); do { MOZ_CrashSequence(__null, 4183); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4184 continue;
4185 }
4186 }
4187
4188 // Initialize elements with |undefined|.
4189 if (!emit1(JSOp::Undefined)) {
4190 return false;
4191 }
4192
4193 if (!pnatom) {
4194 if (!emit1(JSOp::InitElem)) {
4195 return false;
4196 }
4197 } else {
4198 if (!emitAtomOp(JSOp::InitProp, pnatom)) {
4199 return false;
4200 }
4201 }
4202 }
4203
4204 return true;
4205}
4206
4207bool BytecodeEmitter::emitDestructuringOps(ListNode* pattern,
4208 DestructuringFlavor flav,
4209 SelfHostedIter selfHostedIter) {
4210 if (pattern->isKind(ParseNodeKind::ArrayExpr)) {
4211 return emitDestructuringOpsArray(pattern, flav, selfHostedIter);
4212 }
4213 return emitDestructuringOpsObject(pattern, flav);
4214}
4215
4216bool BytecodeEmitter::emitTemplateString(ListNode* templateString) {
4217 bool pushedString = false;
4218
4219 for (ParseNode* item : templateString->contents()) {
4220 bool isString = (item->getKind() == ParseNodeKind::StringExpr ||
4221 item->getKind() == ParseNodeKind::TemplateStringExpr);
4222
4223 // Skip empty strings. These are very common: a template string like
4224 // `${a}${b}` has three empty strings and without this optimization
4225 // we'd emit four JSOp::Add operations instead of just one.
4226 if (isString && item->as<NameNode>().atom() ==
4227 TaggedParserAtomIndex::WellKnown::empty()) {
4228 continue;
4229 }
4230
4231 if (!isString) {
4232 // We update source notes before emitting the expression
4233 if (!updateSourceCoordNotes(item->pn_pos.begin)) {
4234 return false;
4235 }
4236 }
4237
4238 if (!emitTree(item)) {
4239 return false;
4240 }
4241
4242 if (!isString) {
4243 // We need to convert the expression to a string
4244 if (!emit1(JSOp::ToString)) {
4245 return false;
4246 }
4247 }
4248
4249 if (pushedString) {
4250 // We've pushed two strings onto the stack. Add them together, leaving
4251 // just one.
4252 if (!emit1(JSOp::Add)) {
4253 return false;
4254 }
4255 } else {
4256 pushedString = true;
4257 }
4258 }
4259
4260 if (!pushedString) {
4261 // All strings were empty, this can happen for something like `${""}`.
4262 // Just push an empty string.
4263 if (!emitStringOp(JSOp::String,
4264 TaggedParserAtomIndex::WellKnown::empty())) {
4265 return false;
4266 }
4267 }
4268
4269 return true;
4270}
4271
4272bool BytecodeEmitter::emitDeclarationList(ListNode* declList) {
4273 for (ParseNode* decl : declList->contents()) {
4274 ParseNode* pattern;
4275 ParseNode* initializer;
4276 if (decl->isKind(ParseNodeKind::Name)) {
4277 pattern = decl;
4278 initializer = nullptr;
4279 } else {
4280 AssignmentNode* assignNode = &decl->as<AssignmentNode>();
4281 pattern = assignNode->left();
4282 initializer = assignNode->right();
4283 }
4284
4285 if (pattern->isKind(ParseNodeKind::Name)) {
4286 // initializer can be null here.
4287 if (!emitSingleDeclaration(declList, &pattern->as<NameNode>(),
4288 initializer)) {
4289 return false;
4290 }
4291 } else {
4292 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", 4293);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "pattern->isKind(ParseNodeKind::ArrayExpr) || pattern->isKind(ParseNodeKind::ObjectExpr)"
")"); do { MOZ_CrashSequence(__null, 4293); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4293 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", 4293);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "pattern->isKind(ParseNodeKind::ArrayExpr) || pattern->isKind(ParseNodeKind::ObjectExpr)"
")"); do { MOZ_CrashSequence(__null, 4293); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4294 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", 4294);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "initializer != nullptr"
")"); do { MOZ_CrashSequence(__null, 4294); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4295
4296 if (!updateSourceCoordNotes(initializer->pn_pos.begin)) {
4297 return false;
4298 }
4299 if (!markStepBreakpoint()) {
4300 return false;
4301 }
4302 if (!emitTree(initializer)) {
4303 return false;
4304 }
4305
4306 if (!emitDestructuringOps(&pattern->as<ListNode>(),
4307 DestructuringFlavor::Declaration,
4308 getSelfHostedIterFor(initializer))) {
4309 return false;
4310 }
4311
4312 if (!emit1(JSOp::Pop)) {
4313 return false;
4314 }
4315 }
4316 }
4317 return true;
4318}
4319
4320bool BytecodeEmitter::emitSingleDeclaration(ListNode* declList, NameNode* decl,
4321 ParseNode* initializer) {
4322 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"
, 4322); AnnotateMozCrashReason("MOZ_ASSERT" "(" "decl->isKind(ParseNodeKind::Name)"
")"); do { MOZ_CrashSequence(__null, 4322); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4323
4324 // Nothing to do for initializer-less 'var' declarations, as there's no TDZ.
4325 if (!initializer && declList->isKind(ParseNodeKind::VarStmt)) {
4326 return true;
4327 }
4328
4329 auto nameAtom = decl->name();
4330 NameOpEmitter noe(this, nameAtom, NameOpEmitter::Kind::Initialize);
4331 if (!noe.prepareForRhs()) {
4332 // [stack] ENV?
4333 return false;
4334 }
4335 if (!initializer) {
4336 // Lexical declarations are initialized to undefined without an
4337 // initializer.
4338 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"
, 4340); AnnotateMozCrashReason("MOZ_ASSERT" "(" "declList->isKind(ParseNodeKind::LetDecl)"
") (" "var declarations without initializers handled above, "
"and const declarations must have initializers" ")"); do { MOZ_CrashSequence
(__null, 4340); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
4339 "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"
, 4340); AnnotateMozCrashReason("MOZ_ASSERT" "(" "declList->isKind(ParseNodeKind::LetDecl)"
") (" "var declarations without initializers handled above, "
"and const declarations must have initializers" ")"); do { MOZ_CrashSequence
(__null, 4340); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
4340 "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"
, 4340); AnnotateMozCrashReason("MOZ_ASSERT" "(" "declList->isKind(ParseNodeKind::LetDecl)"
") (" "var declarations without initializers handled above, "
"and const declarations must have initializers" ")"); do { MOZ_CrashSequence
(__null, 4340); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4341 if (!emit1(JSOp::Undefined)) {
4342 // [stack] ENV? UNDEF
4343 return false;
4344 }
4345 } else {
4346 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"
, 4346); AnnotateMozCrashReason("MOZ_ASSERT" "(" "initializer"
")"); do { MOZ_CrashSequence(__null, 4346); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4347
4348 if (!updateSourceCoordNotes(initializer->pn_pos.begin)) {
4349 return false;
4350 }
4351 if (!markStepBreakpoint()) {
4352 return false;
4353 }
4354 if (!emitInitializer(initializer, decl)) {
4355 // [stack] ENV? V
4356 return false;
4357 }
4358 }
4359
4360 if (declList->isKind(ParseNodeKind::UsingDecl)) {
4361 if (!innermostEmitterScope()->prepareForDisposableAssignment(
4362 UsingHint::Sync)) {
4363 // [stack] ENV? V
4364 return false;
4365 }
4366 } else if (declList->isKind(ParseNodeKind::AwaitUsingDecl)) {
4367 if (!innermostEmitterScope()->prepareForDisposableAssignment(
4368 UsingHint::Async)) {
4369 // [stack] ENV? V
4370 return false;
4371 }
4372 }
4373
4374 if (!noe.emitAssignment()) {
4375 // [stack] V
4376 return false;
4377 }
4378
4379 if (!emit1(JSOp::Pop)) {
4380 // [stack]
4381 return false;
4382 }
4383
4384 return true;
4385}
4386
4387bool BytecodeEmitter::emitAssignmentRhs(
4388 ParseNode* rhs, TaggedParserAtomIndex anonFunctionName) {
4389 if (rhs->isDirectRHSAnonFunction()) {
4390 if (anonFunctionName) {
4391 return emitAnonymousFunctionWithName(rhs, anonFunctionName);
4392 }
4393 return emitAnonymousFunctionWithComputedName(rhs, FunctionPrefixKind::None);
4394 }
4395 return emitTree(rhs);
4396}
4397
4398// The RHS value to assign is already on the stack, i.e., the next enumeration
4399// value in a for-in or for-of loop. Offset is the location in the stack of the
4400// already-emitted rhs. If we emitted a JSOp::BindUnqualifiedName or
4401// JSOp::BindUnqualifiedGName, then the scope is on the top of the stack and we
4402// need to dig one deeper to get the right RHS value.
4403bool BytecodeEmitter::emitAssignmentRhs(uint8_t offset) {
4404 if (offset != 1) {
4405 return emitPickN(offset - 1);
4406 }
4407
4408 return true;
4409}
4410
4411static inline JSOp CompoundAssignmentParseNodeKindToJSOp(ParseNodeKind pnk) {
4412 switch (pnk) {
4413 case ParseNodeKind::InitExpr:
4414 return JSOp::Nop;
4415 case ParseNodeKind::AssignExpr:
4416 return JSOp::Nop;
4417 case ParseNodeKind::AddAssignExpr:
4418 return JSOp::Add;
4419 case ParseNodeKind::SubAssignExpr:
4420 return JSOp::Sub;
4421 case ParseNodeKind::BitOrAssignExpr:
4422 return JSOp::BitOr;
4423 case ParseNodeKind::BitXorAssignExpr:
4424 return JSOp::BitXor;
4425 case ParseNodeKind::BitAndAssignExpr:
4426 return JSOp::BitAnd;
4427 case ParseNodeKind::LshAssignExpr:
4428 return JSOp::Lsh;
4429 case ParseNodeKind::RshAssignExpr:
4430 return JSOp::Rsh;
4431 case ParseNodeKind::UrshAssignExpr:
4432 return JSOp::Ursh;
4433 case ParseNodeKind::MulAssignExpr:
4434 return JSOp::Mul;
4435 case ParseNodeKind::DivAssignExpr:
4436 return JSOp::Div;
4437 case ParseNodeKind::ModAssignExpr:
4438 return JSOp::Mod;
4439 case ParseNodeKind::PowAssignExpr:
4440 return JSOp::Pow;
4441 case ParseNodeKind::CoalesceAssignExpr:
4442 case ParseNodeKind::OrAssignExpr:
4443 case ParseNodeKind::AndAssignExpr:
4444 // Short-circuit assignment operators are handled elsewhere.
4445 [[fallthrough]];
4446 default:
4447 MOZ_CRASH("unexpected compound assignment op")do { do { } while (false); MOZ_ReportCrash("" "unexpected compound assignment op"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 4447);
AnnotateMozCrashReason("MOZ_CRASH(" "unexpected compound assignment op"
")"); do { MOZ_CrashSequence(__null, 4447); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
4448 }
4449}
4450
4451bool BytecodeEmitter::emitAssignmentOrInit(ParseNodeKind kind, ParseNode* lhs,
4452 ParseNode* rhs) {
4453 JSOp compoundOp = CompoundAssignmentParseNodeKindToJSOp(kind);
4454 bool isCompound = compoundOp != JSOp::Nop;
4455 bool isInit = kind == ParseNodeKind::InitExpr;
4456
4457 // We estimate the number of properties this could create
4458 // if used as constructor merely by counting this.foo = assignment
4459 // or init expressions;
4460 //
4461 // This currently doesn't handle this[x] = foo;
4462 if (isInit || kind == ParseNodeKind::AssignExpr) {
4463 if (lhs->isKind(ParseNodeKind::DotExpr)) {
4464 if (lhs->as<PropertyAccess>().expression().isKind(
4465 ParseNodeKind::ThisExpr)) {
4466 propertyAdditionEstimate++;
4467 }
4468 }
4469 }
4470
4471 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", 4473);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "lhs->isKind(ParseNodeKind::DotExpr) || lhs->isKind(ParseNodeKind::ElemExpr) || lhs->isKind(ParseNodeKind::PrivateMemberExpr)"
")"); do { MOZ_CrashSequence(__null, 4473); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4472 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", 4473);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "lhs->isKind(ParseNodeKind::DotExpr) || lhs->isKind(ParseNodeKind::ElemExpr) || lhs->isKind(ParseNodeKind::PrivateMemberExpr)"
")"); do { MOZ_CrashSequence(__null, 4473); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4473 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", 4473);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "lhs->isKind(ParseNodeKind::DotExpr) || lhs->isKind(ParseNodeKind::ElemExpr) || lhs->isKind(ParseNodeKind::PrivateMemberExpr)"
")"); do { MOZ_CrashSequence(__null, 4473); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4474
4475 // |name| is used within NameOpEmitter, so its lifetime must surpass |noe|.
4476 TaggedParserAtomIndex name;
4477
4478 Maybe<NameOpEmitter> noe;
4479 Maybe<PropOpEmitter> poe;
4480 Maybe<ElemOpEmitter> eoe;
4481 Maybe<PrivateOpEmitter> xoe;
4482
4483 // Deal with non-name assignments.
4484 uint8_t offset = 1;
4485
4486 // Purpose of anonFunctionName:
4487 //
4488 // In normal name assignments (`f = function(){}`), an anonymous function gets
4489 // an inferred name based on the left-hand side name node.
4490 //
4491 // In normal property assignments (`obj.x = function(){}`), the anonymous
4492 // function does not have a computed name, and rhs->isDirectRHSAnonFunction()
4493 // will be false (and anonFunctionName will not be used). However, in field
4494 // initializers (`class C { x = function(){} }`), field initialization is
4495 // implemented via a property or elem assignment (where we are now), and
4496 // rhs->isDirectRHSAnonFunction() is set - so we'll assign the name of the
4497 // function.
4498 TaggedParserAtomIndex anonFunctionName;
4499
4500 switch (lhs->getKind()) {
4501 case ParseNodeKind::Name: {
4502 name = lhs->as<NameNode>().name();
4503 anonFunctionName = name;
4504 noe.emplace(this, name,
4505 isCompound ? NameOpEmitter::Kind::CompoundAssignment
4506 : NameOpEmitter::Kind::SimpleAssignment);
4507 break;
4508 }
4509 case ParseNodeKind::ArgumentsLength:
4510 case ParseNodeKind::DotExpr: {
4511 NonOptionalPropertyAccessBase* prop =
4512 &lhs->as<NonOptionalPropertyAccessBase>();
4513 bool isSuper = prop->isSuper();
4514 poe.emplace(this,
4515 isCompound ? PropOpEmitter::Kind::CompoundAssignment
4516 : isInit ? PropOpEmitter::Kind::PropInit
4517 : PropOpEmitter::Kind::SimpleAssignment,
4518 isSuper ? PropOpEmitter::ObjKind::Super
4519 : PropOpEmitter::ObjKind::Other);
4520 if (!poe->prepareForObj()) {
4521 return false;
4522 }
4523 anonFunctionName = prop->name();
4524 if (isSuper) {
4525 UnaryNode* base = &prop->expression().as<UnaryNode>();
4526 if (!emitGetThisForSuperBase(base)) {
4527 // [stack] THIS SUPERBASE
4528 return false;
4529 }
4530 // SUPERBASE is pushed onto THIS later in poe->emitGet below.
4531 offset += 2;
4532 } else {
4533 if (!emitTree(&prop->expression())) {
4534 // [stack] OBJ
4535 return false;
4536 }
4537 offset += 1;
4538 }
4539 break;
4540 }
4541 case ParseNodeKind::ElemExpr: {
4542 PropertyByValue* elem = &lhs->as<PropertyByValue>();
4543 bool isSuper = elem->isSuper();
4544 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", 4544);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)"
")"); do { MOZ_CrashSequence(__null, 4544); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4545 eoe.emplace(this,
4546 isCompound ? ElemOpEmitter::Kind::CompoundAssignment
4547 : isInit ? ElemOpEmitter::Kind::PropInit
4548 : ElemOpEmitter::Kind::SimpleAssignment,
4549 isSuper ? ElemOpEmitter::ObjKind::Super
4550 : ElemOpEmitter::ObjKind::Other);
4551 if (!emitElemObjAndKey(elem, *eoe)) {
4552 // [stack] # if Super
4553 // [stack] THIS KEY
4554 // [stack] # otherwise
4555 // [stack] OBJ KEY
4556 return false;
4557 }
4558 if (isSuper) {
4559 // SUPERBASE is pushed onto KEY in eoe->emitGet below.
4560 offset += 3;
4561 } else {
4562 offset += 2;
4563 }
4564 break;
4565 }
4566 case ParseNodeKind::PrivateMemberExpr: {
4567 PrivateMemberAccess* privateExpr = &lhs->as<PrivateMemberAccess>();
4568 xoe.emplace(this,
4569 isCompound ? PrivateOpEmitter::Kind::CompoundAssignment
4570 : isInit ? PrivateOpEmitter::Kind::PropInit
4571 : PrivateOpEmitter::Kind::SimpleAssignment,
4572 privateExpr->privateName().name());
4573 if (!emitTree(&privateExpr->expression())) {
4574 // [stack] OBJ
4575 return false;
4576 }
4577 if (!xoe->emitReference()) {
4578 // [stack] OBJ KEY
4579 return false;
4580 }
4581 offset += xoe->numReferenceSlots();
4582 break;
4583 }
4584 case ParseNodeKind::ArrayExpr:
4585 case ParseNodeKind::ObjectExpr:
4586 break;
4587 case ParseNodeKind::CallExpr:
4588 if (!emitTree(lhs)) {
4589 return false;
4590 }
4591
4592 // Assignment to function calls is forbidden, but we have to make the
4593 // call first. Now we can throw.
4594 if (!emit2(JSOp::ThrowMsg, uint8_t(ThrowMsgKind::AssignToCall))) {
4595 return false;
4596 }
4597
4598 // Rebalance the stack to placate stack-depth assertions.
4599 if (!emit1(JSOp::Pop)) {
4600 return false;
4601 }
4602 break;
4603 default:
4604 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", 4604
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0" ")"); do { MOZ_CrashSequence
(__null, 4604); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4605 }
4606
4607 if (isCompound) {
4608 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"
, 4608); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rhs" ")"); do
{ MOZ_CrashSequence(__null, 4608); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
4609 switch (lhs->getKind()) {
4610 case ParseNodeKind::ArgumentsLength:
4611 case ParseNodeKind::DotExpr: {
4612 NonOptionalPropertyAccessBase* prop =
4613 &lhs->as<NonOptionalPropertyAccessBase>();
4614 if (!poe->emitGet(prop->key().atom())) {
4615 // [stack] # if Super
4616 // [stack] THIS SUPERBASE PROP
4617 // [stack] # otherwise
4618 // [stack] OBJ PROP
4619 return false;
4620 }
4621 break;
4622 }
4623 case ParseNodeKind::ElemExpr: {
4624 if (!eoe->emitGet()) {
4625 // [stack] KEY THIS OBJ ELEM
4626 return false;
4627 }
4628 break;
4629 }
4630 case ParseNodeKind::PrivateMemberExpr: {
4631 if (!xoe->emitGet()) {
4632 // [stack] OBJ KEY VALUE
4633 return false;
4634 }
4635 break;
4636 }
4637 case ParseNodeKind::CallExpr:
4638 // We just emitted a JSOp::ThrowMsg and popped the call's return
4639 // value. Push a random value to make sure the stack depth is
4640 // correct.
4641 if (!emit1(JSOp::Null)) {
4642 // [stack] NULL
4643 return false;
4644 }
4645 break;
4646 default:;
4647 }
4648 }
4649
4650 switch (lhs->getKind()) {
4651 case ParseNodeKind::Name:
4652 if (!noe->prepareForRhs()) {
4653 // [stack] ENV? VAL?
4654 return false;
4655 }
4656 offset += noe->emittedBindOp();
4657 break;
4658 case ParseNodeKind::ArgumentsLength:
4659 case ParseNodeKind::DotExpr:
4660 if (!poe->prepareForRhs()) {
4661 // [stack] # if Simple Assignment with Super
4662 // [stack] THIS SUPERBASE
4663 // [stack] # if Simple Assignment with other
4664 // [stack] OBJ
4665 // [stack] # if Compound Assignment with Super
4666 // [stack] THIS SUPERBASE PROP
4667 // [stack] # if Compound Assignment with other
4668 // [stack] OBJ PROP
4669 return false;
4670 }
4671 break;
4672 case ParseNodeKind::ElemExpr:
4673 if (!eoe->prepareForRhs()) {
4674 // [stack] # if Simple Assignment with Super
4675 // [stack] THIS KEY SUPERBASE
4676 // [stack] # if Simple Assignment with other
4677 // [stack] OBJ KEY
4678 // [stack] # if Compound Assignment with Super
4679 // [stack] THIS KEY SUPERBASE ELEM
4680 // [stack] # if Compound Assignment with other
4681 // [stack] OBJ KEY ELEM
4682 return false;
4683 }
4684 break;
4685 case ParseNodeKind::PrivateMemberExpr:
4686 // no stack adjustment needed
4687 break;
4688 default:
4689 break;
4690 }
4691
4692 if (rhs) {
4693 if (!emitAssignmentRhs(rhs, anonFunctionName)) {
4694 // [stack] ... VAL? RHS
4695 return false;
4696 }
4697 } else {
4698 // Assumption: Things with pre-emitted RHS values never need to be named.
4699 if (!emitAssignmentRhs(offset)) {
4700 // [stack] ... VAL? RHS
4701 return false;
4702 }
4703 }
4704
4705 /* If += etc., emit the binary operator with a hint for the decompiler. */
4706 if (isCompound) {
4707 if (!emit1(compoundOp)) {
4708 // [stack] ... VAL
4709 return false;
4710 }
4711 if (!emit1(JSOp::NopIsAssignOp)) {
4712 // [stack] ... VAL
4713 return false;
4714 }
4715 }
4716
4717 /* Finally, emit the specialized assignment bytecode. */
4718 switch (lhs->getKind()) {
4719 case ParseNodeKind::Name: {
4720 if (!noe->emitAssignment()) {
4721 // [stack] VAL
4722 return false;
4723 }
4724 break;
4725 }
4726 case ParseNodeKind::ArgumentsLength:
4727 case ParseNodeKind::DotExpr: {
4728 NonOptionalPropertyAccessBase* prop =
4729 &lhs->as<NonOptionalPropertyAccessBase>();
4730 if (!poe->emitAssignment(prop->key().atom())) {
4731 // [stack] VAL
4732 return false;
4733 }
4734 break;
4735 }
4736 case ParseNodeKind::CallExpr:
4737 // We threw above, so nothing to do here.
4738 break;
4739 case ParseNodeKind::ElemExpr: {
4740 if (!eoe->emitAssignment()) {
4741 // [stack] VAL
4742 return false;
4743 }
4744 break;
4745 }
4746 case ParseNodeKind::PrivateMemberExpr:
4747 if (!xoe->emitAssignment()) {
4748 // [stack] VAL
4749 return false;
4750 }
4751 break;
4752 case ParseNodeKind::ArrayExpr:
4753 case ParseNodeKind::ObjectExpr: {
4754 auto selfHostedIter =
4755 rhs ? getSelfHostedIterFor(rhs) : SelfHostedIter::Deny;
4756 if (!emitDestructuringOps(&lhs->as<ListNode>(),
4757 DestructuringFlavor::Assignment,
4758 selfHostedIter)) {
4759 return false;
4760 }
4761 break;
4762 }
4763 default:
4764 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", 4764
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0" ")"); do { MOZ_CrashSequence
(__null, 4764); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4765 }
4766 return true;
4767}
4768
4769bool BytecodeEmitter::emitShortCircuitAssignment(AssignmentNode* node) {
4770 TDZCheckCache tdzCache(this);
4771
4772 JSOp op;
4773 switch (node->getKind()) {
4774 case ParseNodeKind::CoalesceAssignExpr:
4775 op = JSOp::Coalesce;
4776 break;
4777 case ParseNodeKind::OrAssignExpr:
4778 op = JSOp::Or;
4779 break;
4780 case ParseNodeKind::AndAssignExpr:
4781 op = JSOp::And;
4782 break;
4783 default:
4784 MOZ_CRASH("Unexpected ParseNodeKind")do { do { } while (false); MOZ_ReportCrash("" "Unexpected ParseNodeKind"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 4784);
AnnotateMozCrashReason("MOZ_CRASH(" "Unexpected ParseNodeKind"
")"); do { MOZ_CrashSequence(__null, 4784); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
4785 }
4786
4787 ParseNode* lhs = node->left();
4788 ParseNode* rhs = node->right();
4789
4790 // |name| is used within NameOpEmitter, so its lifetime must surpass |noe|.
4791 TaggedParserAtomIndex name;
4792
4793 // Select the appropriate emitter based on the left-hand side.
4794 Maybe<NameOpEmitter> noe;
4795 Maybe<PropOpEmitter> poe;
4796 Maybe<ElemOpEmitter> eoe;
4797 Maybe<PrivateOpEmitter> xoe;
4798
4799 int32_t depth = bytecodeSection().stackDepth();
4800
4801 // Number of values pushed onto the stack in addition to the lhs value.
4802 int32_t numPushed;
4803
4804 // Evaluate the left-hand side expression and compute any stack values needed
4805 // for the assignment.
4806 switch (lhs->getKind()) {
4807 case ParseNodeKind::Name: {
4808 name = lhs->as<NameNode>().name();
4809 noe.emplace(this, name, NameOpEmitter::Kind::CompoundAssignment);
4810
4811 if (!noe->prepareForRhs()) {
4812 // [stack] ENV? LHS
4813 return false;
4814 }
4815
4816 numPushed = noe->emittedBindOp();
4817 break;
4818 }
4819 case ParseNodeKind::ArgumentsLength:
4820 case ParseNodeKind::DotExpr: {
4821 NonOptionalPropertyAccessBase* prop =
4822 &lhs->as<NonOptionalPropertyAccessBase>();
4823 bool isSuper = prop->isSuper();
4824
4825 poe.emplace(this, PropOpEmitter::Kind::CompoundAssignment,
4826 isSuper ? PropOpEmitter::ObjKind::Super
4827 : PropOpEmitter::ObjKind::Other);
4828
4829 if (!poe->prepareForObj()) {
4830 return false;
4831 }
4832
4833 if (isSuper) {
4834 UnaryNode* base = &prop->expression().as<UnaryNode>();
4835 if (!emitGetThisForSuperBase(base)) {
4836 // [stack] THIS SUPERBASE
4837 return false;
4838 }
4839 } else {
4840 if (!emitTree(&prop->expression())) {
4841 // [stack] OBJ
4842 return false;
4843 }
4844 }
4845
4846 if (!poe->emitGet(prop->key().atom())) {
4847 // [stack] # if Super
4848 // [stack] THIS SUPERBASE LHS
4849 // [stack] # otherwise
4850 // [stack] OBJ LHS
4851 return false;
4852 }
4853
4854 if (!poe->prepareForRhs()) {
4855 // [stack] # if Super
4856 // [stack] THIS SUPERBASE LHS
4857 // [stack] # otherwise
4858 // [stack] OBJ LHS
4859 return false;
4860 }
4861
4862 numPushed = 1 + isSuper;
4863 break;
4864 }
4865
4866 case ParseNodeKind::ElemExpr: {
4867 PropertyByValue* elem = &lhs->as<PropertyByValue>();
4868 bool isSuper = elem->isSuper();
4869 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", 4869);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)"
")"); do { MOZ_CrashSequence(__null, 4869); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4870 eoe.emplace(this, ElemOpEmitter::Kind::CompoundAssignment,
4871 isSuper ? ElemOpEmitter::ObjKind::Super
4872 : ElemOpEmitter::ObjKind::Other);
4873
4874 if (!emitElemObjAndKey(elem, *eoe)) {
4875 // [stack] # if Super
4876 // [stack] THIS KEY
4877 // [stack] # otherwise
4878 // [stack] OBJ KEY
4879 return false;
4880 }
4881
4882 if (!eoe->emitGet()) {
4883 // [stack] # if Super
4884 // [stack] THIS KEY SUPERBASE LHS
4885 // [stack] # otherwise
4886 // [stack] OBJ KEY LHS
4887 return false;
4888 }
4889
4890 if (!eoe->prepareForRhs()) {
4891 // [stack] # if Super
4892 // [stack] THIS KEY SUPERBASE LHS
4893 // [stack] # otherwise
4894 // [stack] OBJ KEY LHS
4895 return false;
4896 }
4897
4898 numPushed = 2 + isSuper;
4899 break;
4900 }
4901
4902 case ParseNodeKind::PrivateMemberExpr: {
4903 PrivateMemberAccess* privateExpr = &lhs->as<PrivateMemberAccess>();
4904 xoe.emplace(this, PrivateOpEmitter::Kind::CompoundAssignment,
4905 privateExpr->privateName().name());
4906 if (!emitTree(&privateExpr->expression())) {
4907 // [stack] OBJ
4908 return false;
4909 }
4910 if (!xoe->emitReference()) {
4911 // [stack] OBJ NAME
4912 return false;
4913 }
4914 if (!xoe->emitGet()) {
4915 // [stack] OBJ NAME LHS
4916 return false;
4917 }
4918 numPushed = xoe->numReferenceSlots();
4919 break;
4920 }
4921
4922 default:
4923 MOZ_CRASH()do { do { } while (false); MOZ_ReportCrash("" , "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 4923); AnnotateMozCrashReason("MOZ_CRASH(" ")"); do { MOZ_CrashSequence
(__null, 4923); __attribute__((nomerge)) ::abort(); } while (
false); } while (false)
;
4924 }
4925
4926 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"
, 4926); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == depth + numPushed + 1"
")"); do { MOZ_CrashSequence(__null, 4926); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4927
4928 // Test for the short-circuit condition.
4929 JumpList jump;
4930 if (!emitJump(op, &jump)) {
4931 // [stack] ... LHS
4932 return false;
4933 }
4934
4935 // The short-circuit condition wasn't fulfilled, pop the left-hand side value
4936 // which was kept on the stack.
4937 if (!emit1(JSOp::Pop)) {
4938 // [stack] ...
4939 return false;
4940 }
4941
4942 if (!emitAssignmentRhs(rhs, name)) {
4943 // [stack] ... RHS
4944 return false;
4945 }
4946
4947 // Perform the actual assignment.
4948 switch (lhs->getKind()) {
4949 case ParseNodeKind::Name: {
4950 if (!noe->emitAssignment()) {
4951 // [stack] RHS
4952 return false;
4953 }
4954 break;
4955 }
4956 case ParseNodeKind::ArgumentsLength:
4957 case ParseNodeKind::DotExpr: {
4958 NonOptionalPropertyAccessBase* prop =
4959 &lhs->as<NonOptionalPropertyAccessBase>();
4960
4961 if (!poe->emitAssignment(prop->key().atom())) {
4962 // [stack] RHS
4963 return false;
4964 }
4965 break;
4966 }
4967
4968 case ParseNodeKind::ElemExpr: {
4969 if (!eoe->emitAssignment()) {
4970 // [stack] RHS
4971 return false;
4972 }
4973 break;
4974 }
4975
4976 case ParseNodeKind::PrivateMemberExpr:
4977 if (!xoe->emitAssignment()) {
4978 // [stack] RHS
4979 return false;
4980 }
4981 break;
4982
4983 default:
4984 MOZ_CRASH()do { do { } while (false); MOZ_ReportCrash("" , "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 4984); AnnotateMozCrashReason("MOZ_CRASH(" ")"); do { MOZ_CrashSequence
(__null, 4984); __attribute__((nomerge)) ::abort(); } while (
false); } while (false)
;
4985 }
4986
4987 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", 4987);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == depth + 1"
")"); do { MOZ_CrashSequence(__null, 4987); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4988
4989 // Join with the short-circuit jump and pop anything left on the stack.
4990 if (numPushed > 0) {
4991 JumpList jumpAroundPop;
4992 if (!emitJump(JSOp::Goto, &jumpAroundPop)) {
4993 // [stack] RHS
4994 return false;
4995 }
4996
4997 if (!emitJumpTargetAndPatch(jump)) {
4998 // [stack] ... LHS
4999 return false;
5000 }
5001
5002 // Reconstruct the stack depth after the jump.
5003 bytecodeSection().setStackDepth(depth + 1 + numPushed);
5004
5005 // Move the left-hand side value to the bottom and pop the rest.
5006 if (!emitUnpickN(numPushed)) {
5007 // [stack] LHS ...
5008 return false;
5009 }
5010 if (!emitPopN(numPushed)) {
5011 // [stack] LHS
5012 return false;
5013 }
5014
5015 if (!emitJumpTargetAndPatch(jumpAroundPop)) {
5016 // [stack] LHS | RHS
5017 return false;
5018 }
5019 } else {
5020 if (!emitJumpTargetAndPatch(jump)) {
5021 // [stack] LHS | RHS
5022 return false;
5023 }
5024 }
5025
5026 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", 5026);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == depth + 1"
")"); do { MOZ_CrashSequence(__null, 5026); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5027
5028 return true;
5029}
5030
5031bool BytecodeEmitter::emitCallSiteObjectArray(ObjLiteralWriter& writer,
5032 ListNode* cookedOrRaw,
5033 ParseNode* head, uint32_t count) {
5034 DebugOnly<size_t> idx = 0;
5035 for (ParseNode* pn : cookedOrRaw->contentsFrom(head)) {
5036 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", 5037);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->isKind(ParseNodeKind::TemplateStringExpr) || pn->isKind(ParseNodeKind::RawUndefinedExpr)"
")"); do { MOZ_CrashSequence(__null, 5037); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5037 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", 5037);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->isKind(ParseNodeKind::TemplateStringExpr) || pn->isKind(ParseNodeKind::RawUndefinedExpr)"
")"); do { MOZ_CrashSequence(__null, 5037); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5038
5039 if (!emitObjLiteralValue(writer, pn)) {
5040 return false;
5041 }
5042 idx++;
5043 }
5044 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"
, 5044); AnnotateMozCrashReason("MOZ_ASSERT" "(" "idx == count"
")"); do { MOZ_CrashSequence(__null, 5044); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5045
5046 return true;
5047}
5048
5049bool BytecodeEmitter::emitCallSiteObject(CallSiteNode* callSiteObj) {
5050 constexpr JSOp op = JSOp::CallSiteObj;
5051
5052 // The first element of a call-site node is the raw-values list. Skip over it.
5053 ListNode* raw = callSiteObj->rawNodes();
5054 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", 5054);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "raw->isKind(ParseNodeKind::ArrayExpr)"
")"); do { MOZ_CrashSequence(__null, 5054); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5055 ParseNode* head = callSiteObj->head()->pn_next;
5056
5057 uint32_t count = callSiteObj->count() - 1;
5058 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", 5058);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "count == raw->count()"
")"); do { MOZ_CrashSequence(__null, 5058); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5059
5060 ObjLiteralWriter writer;
5061 writer.beginCallSiteObj(op);
5062 writer.beginDenseArrayElements();
5063
5064 // Write elements of the two arrays: the 'cooked' values followed by the
5065 // 'raw' values.
5066 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", 5067
); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "count < (4294967295U) / 2"
") (" "Number of elements for both arrays must fit in uint32_t"
")"); do { MOZ_CrashSequence(__null, 5067); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5067 "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", 5067
); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "count < (4294967295U) / 2"
") (" "Number of elements for both arrays must fit in uint32_t"
")"); do { MOZ_CrashSequence(__null, 5067); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5068 if (!emitCallSiteObjectArray(writer, callSiteObj, head, count)) {
5069 return false;
5070 }
5071 if (!emitCallSiteObjectArray(writer, raw, raw->head(), count)) {
5072 return false;
5073 }
5074
5075 GCThingIndex cookedIndex;
5076 if (!addObjLiteralData(writer, &cookedIndex)) {
5077 return false;
5078 }
5079
5080 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", 5080);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->hasCallSiteObj()"
")"); do { MOZ_CrashSequence(__null, 5080); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5081
5082 return emitInternedObjectOp(cookedIndex, op);
5083}
5084
5085bool BytecodeEmitter::emitCatch(BinaryNode* catchClause) {
5086 // We must be nested under a try-finally statement.
5087 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", 5087);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "innermostNestableControl->is<TryFinallyControl>()"
")"); do { MOZ_CrashSequence(__null, 5087); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5088
5089 ParseNode* param = catchClause->left();
5090 if (!param) {
5091 // Catch parameter was omitted; just discard the exception.
5092 if (!emit1(JSOp::Pop)) {
5093 return false;
5094 }
5095 } else {
5096 switch (param->getKind()) {
5097 case ParseNodeKind::ArrayExpr:
5098 case ParseNodeKind::ObjectExpr:
5099 if (!emitDestructuringOps(&param->as<ListNode>(),
5100 DestructuringFlavor::Declaration,
5101 SelfHostedIter::Deny)) {
5102 return false;
5103 }
5104 if (!emit1(JSOp::Pop)) {
5105 return false;
5106 }
5107 break;
5108
5109 case ParseNodeKind::Name:
5110 if (!emitLexicalInitialization(&param->as<NameNode>())) {
5111 return false;
5112 }
5113 if (!emit1(JSOp::Pop)) {
5114 return false;
5115 }
5116 break;
5117
5118 default:
5119 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", 5119
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0" ")"); do { MOZ_CrashSequence
(__null, 5119); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
5120 }
5121 }
5122
5123 /* Emit the catch body. */
5124 return emitTree(catchClause->right());
5125}
5126
5127// Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See the
5128// comment on EmitSwitch.
5129MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitTry(TryNode* tryNode) {
5130 LexicalScopeNode* catchScope = tryNode->catchScope();
5131 ParseNode* finallyNode = tryNode->finallyBlock();
5132
5133 TryEmitter::Kind kind;
5134 if (catchScope) {
5135 if (finallyNode) {
5136 kind = TryEmitter::Kind::TryCatchFinally;
5137 } else {
5138 kind = TryEmitter::Kind::TryCatch;
5139 }
5140 } else {
5141 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"
, 5141); AnnotateMozCrashReason("MOZ_ASSERT" "(" "finallyNode"
")"); do { MOZ_CrashSequence(__null, 5141); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5142 kind = TryEmitter::Kind::TryFinally;
5143 }
5144 TryEmitter tryCatch(this, kind, TryEmitter::ControlKind::Syntactic);
5145
5146 if (!tryCatch.emitTry()) {
5147 return false;
5148 }
5149
5150 if (!emitTree(tryNode->body())) {
5151 return false;
5152 }
5153
5154 // If this try has a catch block, emit it.
5155 if (catchScope) {
5156 // The emitted code for a catch block looks like:
5157 //
5158 // [pushlexicalenv] only if any local aliased
5159 // exception
5160 // setlocal 0; pop assign or possibly destructure exception
5161 // < catch block contents >
5162 // debugleaveblock
5163 // [poplexicalenv] only if any local aliased
5164 // if there is a finally block:
5165 // goto <finally>
5166 // [jump target for returning from finally]
5167 // goto <after finally>
5168 if (!tryCatch.emitCatch()) {
5169 return false;
5170 }
5171
5172 // Emit the lexical scope and catch body.
5173 if (!emitTree(catchScope)) {
5174 return false;
5175 }
5176 }
5177
5178 // Emit the finally handler, if there is one.
5179 if (finallyNode) {
5180 if (!tryCatch.emitFinally(Some(finallyNode->pn_pos.begin))) {
5181 return false;
5182 }
5183
5184 if (!emitTree(finallyNode)) {
5185 return false;
5186 }
5187 }
5188
5189 if (!tryCatch.emitEnd()) {
5190 return false;
5191 }
5192
5193 return true;
5194}
5195
5196[[nodiscard]] bool BytecodeEmitter::emitJumpToFinally(JumpList* jump,
5197 uint32_t idx) {
5198 // Push the continuation index.
5199 if (!emitNumberOp(idx)) {
5200 return false;
5201 }
5202
5203 // Push |exception_stack|.
5204 if (!emit1(JSOp::Null)) {
5205 return false;
5206 }
5207
5208 // Push |throwing|.
5209 if (!emit1(JSOp::False)) {
5210 return false;
5211 }
5212
5213 // Jump to the finally block.
5214 if (!emitJumpNoFallthrough(JSOp::Goto, jump)) {
5215 return false;
5216 }
5217
5218 return true;
5219}
5220
5221bool BytecodeEmitter::emitIf(TernaryNode* ifNode) {
5222 IfEmitter ifThenElse(this);
5223
5224 if (!ifThenElse.emitIf(Some(ifNode->kid1()->pn_pos.begin))) {
5225 return false;
5226 }
5227
5228if_again:
5229 ParseNode* testNode = ifNode->kid1();
5230 auto conditionKind = IfEmitter::ConditionKind::Positive;
5231 if (testNode->isKind(ParseNodeKind::NotExpr)) {
5232 testNode = testNode->as<UnaryNode>().kid();
5233 conditionKind = IfEmitter::ConditionKind::Negative;
5234 }
5235
5236 if (!markStepBreakpoint()) {
5237 return false;
5238 }
5239
5240 // Emit code for the condition before pushing stmtInfo.
5241 // NOTE: NotExpr of testNode may be unwrapped, and in that case the negation
5242 // is handled by conditionKind.
5243 if (!emitTree(testNode)) {
5244 return false;
5245 }
5246
5247 ParseNode* elseNode = ifNode->kid3();
5248 if (elseNode) {
5249 if (!ifThenElse.emitThenElse(conditionKind)) {
5250 return false;
5251 }
5252 } else {
5253 if (!ifThenElse.emitThen(conditionKind)) {
5254 return false;
5255 }
5256 }
5257
5258 /* Emit code for the then part. */
5259 if (!emitTree(ifNode->kid2())) {
5260 return false;
5261 }
5262
5263 if (elseNode) {
5264 if (elseNode->isKind(ParseNodeKind::IfStmt)) {
5265 ifNode = &elseNode->as<TernaryNode>();
5266
5267 if (!ifThenElse.emitElseIf(Some(ifNode->kid1()->pn_pos.begin))) {
5268 return false;
5269 }
5270
5271 goto if_again;
5272 }
5273
5274 if (!ifThenElse.emitElse()) {
5275 return false;
5276 }
5277
5278 /* Emit code for the else part. */
5279 if (!emitTree(elseNode)) {
5280 return false;
5281 }
5282 }
5283
5284 if (!ifThenElse.emitEnd()) {
5285 return false;
5286 }
5287
5288 return true;
5289}
5290
5291bool BytecodeEmitter::emitHoistedFunctionsInList(ListNode* stmtList) {
5292 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", 5292);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "stmtList->hasTopLevelFunctionDeclarations()"
")"); do { MOZ_CrashSequence(__null, 5292); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5293
5294 // We can call this multiple times for sloppy eval scopes.
5295 if (stmtList->emittedTopLevelFunctionDeclarations()) {
5296 return true;
5297 }
5298
5299 stmtList->setEmittedTopLevelFunctionDeclarations();
5300
5301 for (ParseNode* stmt : stmtList->contents()) {
5302 ParseNode* maybeFun = stmt;
5303
5304 if (!sc->strict()) {
5305 while (maybeFun->isKind(ParseNodeKind::LabelStmt)) {
5306 maybeFun = maybeFun->as<LabeledStatement>().statement();
5307 }
5308 }
5309
5310 if (maybeFun->is<FunctionNode>() &&
5311 maybeFun->as<FunctionNode>().functionIsHoisted()) {
5312 if (!emitTree(maybeFun)) {
5313 return false;
5314 }
5315 }
5316 }
5317
5318 return true;
5319}
5320
5321bool BytecodeEmitter::emitLexicalScopeBody(
5322 ParseNode* body, EmitLineNumberNote emitLineNote /* = EMIT_LINENOTE */) {
5323 if (body->isKind(ParseNodeKind::StatementList) &&
5324 body->as<ListNode>().hasTopLevelFunctionDeclarations()) {
5325 // This block contains function statements whose definitions are
5326 // hoisted to the top of the block. Emit these as a separate pass
5327 // before the rest of the block.
5328 if (!emitHoistedFunctionsInList(&body->as<ListNode>())) {
5329 return false;
5330 }
5331 }
5332
5333 // Line notes were updated by emitLexicalScope or emitScript.
5334 return emitTree(body, ValueUsage::WantValue, emitLineNote);
5335}
5336
5337// Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See
5338// the comment on emitSwitch.
5339MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitLexicalScope(
5340 LexicalScopeNode* lexicalScope) {
5341 LexicalScopeEmitter lse(this);
5342
5343 ParseNode* body = lexicalScope->scopeBody();
5344 if (lexicalScope->isEmptyScope()) {
5345 if (!lse.emitEmptyScope()) {
5346 return false;
5347 }
5348
5349 if (!emitLexicalScopeBody(body)) {
5350 return false;
5351 }
5352
5353 if (!lse.emitEnd()) {
5354 return false;
5355 }
5356
5357 return true;
5358 }
5359
5360 // We are about to emit some bytecode for what the spec calls "declaration
5361 // instantiation". Assign these instructions to the opening `{` of the
5362 // block. (Using the location of each declaration we're instantiating is
5363 // too weird when stepping in the debugger.)
5364 if (!ParseNodeRequiresSpecialLineNumberNotes(body)) {
5365 if (!updateSourceCoordNotes(lexicalScope->pn_pos.begin)) {
5366 return false;
5367 }
5368 }
5369
5370 ScopeKind kind;
5371 if (body->isKind(ParseNodeKind::Catch)) {
5372 BinaryNode* catchNode = &body->as<BinaryNode>();
5373 kind =
5374 (!catchNode->left() || catchNode->left()->isKind(ParseNodeKind::Name))
5375 ? ScopeKind::SimpleCatch
5376 : ScopeKind::Catch;
5377 } else {
5378 kind = lexicalScope->kind();
5379 }
5380
5381 BlockKind blockKind = BlockKind::Other;
5382 if (body->isKind(ParseNodeKind::ForStmt) &&
5383 body->as<ForNode>().head()->isKind(ParseNodeKind::ForOf)) {
5384 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", 5384);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "kind == ScopeKind::Lexical"
")"); do { MOZ_CrashSequence(__null, 5384); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5385 blockKind = BlockKind::ForOf;
5386 }
5387
5388 if (!lse.emitScope(kind, lexicalScope->scopeBindings(), blockKind)) {
5389 return false;
5390 }
5391
5392 if (body->isKind(ParseNodeKind::ForStmt)) {
5393 // for loops need to emit JSOp::FreshenLexicalEnv/JSOp::RecreateLexicalEnv
5394 // if there are lexical declarations in the head. Signal this by passing a
5395 // non-nullptr lexical scope.
5396 if (!emitFor(&body->as<ForNode>(), &lse.emitterScope())) {
5397 return false;
5398 }
5399 } else {
5400 if (!emitLexicalScopeBody(body, SUPPRESS_LINENOTE)) {
5401 return false;
5402 }
5403 }
5404
5405 if (!lse.emitEnd()) {
5406 return false;
5407 }
5408 return true;
5409}
5410
5411bool BytecodeEmitter::emitWith(BinaryNode* withNode) {
5412 // Ensure that the column of the 'with' is set properly.
5413 if (!updateSourceCoordNotes(withNode->left()->pn_pos.begin)) {
5414 return false;
5415 }
5416
5417 if (!markStepBreakpoint()) {
5418 return false;
5419 }
5420
5421 if (!emitTree(withNode->left())) {
5422 return false;
5423 }
5424
5425 EmitterScope emitterScope(this);
5426 if (!emitterScope.enterWith(this)) {
5427 return false;
5428 }
5429
5430 if (!emitTree(withNode->right())) {
5431 return false;
5432 }
5433
5434 return emitterScope.leave(this);
5435}
5436
5437bool BytecodeEmitter::emitCopyDataProperties(CopyOption option) {
5438 DebugOnly<int32_t> depth = bytecodeSection().stackDepth();
5439
5440 uint32_t argc;
5441 if (option == CopyOption::Filtered) {
5442 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"
, 5442); AnnotateMozCrashReason("MOZ_ASSERT" "(" "depth > 2"
")"); do { MOZ_CrashSequence(__null, 5442); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5443 // [stack] TARGET SOURCE SET
5444 argc = 3;
5445
5446 if (!emitAtomOp(JSOp::GetIntrinsic,
5447 TaggedParserAtomIndex::WellKnown::CopyDataProperties())) {
5448 // [stack] TARGET SOURCE SET COPYDATAPROPERTIES
5449 return false;
5450 }
5451 } else {
5452 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"
, 5452); AnnotateMozCrashReason("MOZ_ASSERT" "(" "depth > 1"
")"); do { MOZ_CrashSequence(__null, 5452); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5453 // [stack] TARGET SOURCE
5454 argc = 2;
5455
5456 if (!emitAtomOp(
5457 JSOp::GetIntrinsic,
5458 TaggedParserAtomIndex::WellKnown::CopyDataPropertiesUnfiltered())) {
5459 // [stack] TARGET SOURCE COPYDATAPROPERTIES
5460 return false;
5461 }
5462 }
5463
5464 if (!emit1(JSOp::Undefined)) {
5465 // [stack] TARGET SOURCE SET? COPYDATAPROPERTIES
5466 // UNDEFINED
5467 return false;
5468 }
5469 if (!emit2(JSOp::Pick, argc + 1)) {
5470 // [stack] SOURCE SET? COPYDATAPROPERTIES UNDEFINED
5471 // TARGET
5472 return false;
5473 }
5474 if (!emit2(JSOp::Pick, argc + 1)) {
5475 // [stack] SET? COPYDATAPROPERTIES UNDEFINED TARGET
5476 // SOURCE
5477 return false;
5478 }
5479 if (option == CopyOption::Filtered) {
5480 if (!emit2(JSOp::Pick, argc + 1)) {
5481 // [stack] COPYDATAPROPERTIES UNDEFINED TARGET SOURCE SET
5482 return false;
5483 }
5484 }
5485 // Callee is always self-hosted instrinsic, and cannot be content function.
5486 if (!emitCall(JSOp::CallIgnoresRv, argc)) {
5487 // [stack] IGNORED
5488 return false;
5489 }
5490
5491 if (!emit1(JSOp::Pop)) {
5492 // [stack]
5493 return false;
5494 }
5495
5496 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", 5496);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "depth - int(argc) == bytecodeSection().stackDepth()"
")"); do { MOZ_CrashSequence(__null, 5496); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5497 return true;
5498}
5499
5500bool BytecodeEmitter::emitBigIntOp(BigIntLiteral* bigint) {
5501 GCThingIndex index;
5502 if (!perScriptData().gcThingList().append(bigint, &index)) {
5503 return false;
5504 }
5505 return emitGCIndexOp(JSOp::BigInt, index);
5506}
5507
5508bool BytecodeEmitter::emitIterable(ParseNode* value,
5509 SelfHostedIter selfHostedIter,
5510 IteratorKind iterKind) {
5511 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", 5511);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "getSelfHostedIterFor(value) == selfHostedIter"
")"); do { MOZ_CrashSequence(__null, 5511); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5512
5513 if (!emitTree(value)) {
5514 // [stack] ITERABLE
5515 return false;
5516 }
5517
5518 switch (selfHostedIter) {
5519 case SelfHostedIter::Deny:
5520 case SelfHostedIter::AllowContent:
5521 // [stack] ITERABLE
5522 return true;
5523
5524 case SelfHostedIter::AllowContentWith: {
5525 // This is the following case:
5526 //
5527 // for (const nextValue of allowContentIterWith(items, usingIterator)) {
5528 //
5529 // `items` is emitted by `emitTree(value)` above, and the result is on the
5530 // stack as ITERABLE.
5531 // `usingIterator` is the value of `items[Symbol.iterator]`, that's
5532 // already retrieved.
5533 ListNode* argsList = value->as<CallNode>().args();
5534 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", 5534);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2"
")"); do { MOZ_CrashSequence(__null, 5534); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
5535 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", 5535);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 3"
")"); do { MOZ_CrashSequence(__null, 5535); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
5536
5537 if (!emitTree(argsList->head()->pn_next)) {
5538 // [stack] ITERABLE ITERFN
5539 return false;
5540 }
5541
5542 // Async iterator has two possible iterators: An async iterator and a sync
5543 // iterator.
5544 if (iterKind == IteratorKind::Async) {
5545 if (!emitTree(argsList->head()->pn_next->pn_next)) {
5546 // [stack] ITERABLE ASYNC_ITERFN SYNC_ITERFN
5547 return false;
5548 }
5549 }
5550
5551 // [stack] ITERABLE ASYNC_ITERFN? SYNC_ITERFN
5552 return true;
5553 }
5554
5555 case SelfHostedIter::AllowContentWithNext: {
5556 // This is the following case:
5557 //
5558 // for (const nextValue of allowContentIterWithNext(iterator, next)) {
5559 //
5560 // `iterator` is emitted by `emitTree(value)` above, and the result is on
5561 // the stack as ITER.
5562 // `next` is the value of `iterator.next`, that's already retrieved.
5563 ListNode* argsList = value->as<CallNode>().args();
5564 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", 5564);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2"
")"); do { MOZ_CrashSequence(__null, 5564); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5565
5566 if (!emitTree(argsList->head()->pn_next)) {
5567 // [stack] ITER NEXT
5568 return false;
5569 }
5570
5571 if (!emit1(JSOp::Swap)) {
5572 // [stack] NEXT ITER
5573 return false;
5574 }
5575
5576 // [stack] NEXT ITER
5577 return true;
5578 }
5579 }
5580
5581 MOZ_CRASH("invalid self-hosted iteration kind")do { do { } while (false); MOZ_ReportCrash("" "invalid self-hosted iteration kind"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 5581);
AnnotateMozCrashReason("MOZ_CRASH(" "invalid self-hosted iteration kind"
")"); do { MOZ_CrashSequence(__null, 5581); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
5582}
5583
5584bool BytecodeEmitter::emitIterator(SelfHostedIter selfHostedIter) {
5585 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"
, 5588); 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, 5588); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
5586 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"
, 5588); 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, 5588); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
5587 "[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"
, 5588); 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, 5588); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
5588 "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"
, 5588); 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, 5588); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
5589
5590 if (selfHostedIter == SelfHostedIter::AllowContentWithNext) {
5591 // [stack] NEXT ITER
5592
5593 // Nothing to do, stack already contains the iterator and its `next` method.
5594 return true;
5595 }
5596
5597 if (selfHostedIter != SelfHostedIter::AllowContentWith) {
5598 // [stack] OBJ
5599
5600 // Convert iterable to iterator.
5601 if (!emit1(JSOp::Dup)) {
5602 // [stack] OBJ OBJ
5603 return false;
5604 }
5605 if (!emit2(JSOp::Symbol, uint8_t(JS::SymbolCode::iterator))) {
5606 // [stack] OBJ OBJ @@ITERATOR
5607 return false;
5608 }
5609 if (!emitElemOpBase(JSOp::GetElem)) {
5610 // [stack] OBJ ITERFN
5611 return false;
5612 }
5613 }
5614
5615 if (!emit1(JSOp::Swap)) {
5616 // [stack] ITERFN OBJ
5617 return false;
5618 }
5619 if (!emitCall(getIterCallOp(JSOp::CallIter, selfHostedIter), 0)) {
5620 // [stack] ITER
5621 return false;
5622 }
5623 if (!emitCheckIsObj(CheckIsObjectKind::GetIterator)) {
5624 // [stack] ITER
5625 return false;
5626 }
5627 if (!emit1(JSOp::Dup)) {
5628 // [stack] ITER ITER
5629 return false;
5630 }
5631 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::next())) {
5632 // [stack] ITER NEXT
5633 return false;
5634 }
5635 if (!emit1(JSOp::Swap)) {
5636 // [stack] NEXT ITER
5637 return false;
5638 }
5639 return true;
5640}
5641
5642bool BytecodeEmitter::emitAsyncIterator(SelfHostedIter selfHostedIter) {
5643 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"
, 5643); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::AllowContentWithNext"
")"); do { MOZ_CrashSequence(__null, 5643); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5644 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"
, 5647); 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, 5647); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
5645 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"
, 5647); 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, 5647); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
5646 "[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"
, 5647); 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, 5647); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
5647 "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"
, 5647); 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, 5647); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
5648
5649 if (selfHostedIter != SelfHostedIter::AllowContentWith) {
5650 // [stack] OBJ
5651
5652 // Convert iterable to iterator.
5653 if (!emit1(JSOp::Dup)) {
5654 // [stack] OBJ OBJ
5655 return false;
5656 }
5657 if (!emit2(JSOp::Symbol, uint8_t(JS::SymbolCode::asyncIterator))) {
5658 // [stack] OBJ OBJ @@ASYNCITERATOR
5659 return false;
5660 }
5661 if (!emitElemOpBase(JSOp::GetElem)) {
5662 // [stack] OBJ ASYNC_ITERFN
5663 return false;
5664 }
5665 } else {
5666 // [stack] OBJ ASYNC_ITERFN SYNC_ITERFN
5667
5668 if (!emitElemOpBase(JSOp::Swap)) {
5669 // [stack] OBJ SYNC_ITERFN ASYNC_ITERFN
5670 return false;
5671 }
5672 }
5673
5674 InternalIfEmitter ifAsyncIterIsUndefined(this);
5675 if (!emit1(JSOp::IsNullOrUndefined)) {
5676 // [stack] OBJ SYNC_ITERFN? ASYNC_ITERFN NULL-OR-UNDEF
5677 return false;
5678 }
5679 if (!ifAsyncIterIsUndefined.emitThenElse()) {
5680 // [stack] OBJ SYNC_ITERFN? ASYNC_ITERFN
5681 return false;
5682 }
5683
5684 if (!emit1(JSOp::Pop)) {
5685 // [stack] OBJ SYNC_ITERFN?
5686 return false;
5687 }
5688
5689 if (selfHostedIter != SelfHostedIter::AllowContentWith) {
5690 if (!emit1(JSOp::Dup)) {
5691 // [stack] OBJ OBJ
5692 return false;
5693 }
5694 if (!emit2(JSOp::Symbol, uint8_t(JS::SymbolCode::iterator))) {
5695 // [stack] OBJ OBJ @@ITERATOR
5696 return false;
5697 }
5698 if (!emitElemOpBase(JSOp::GetElem)) {
5699 // [stack] OBJ SYNC_ITERFN
5700 return false;
5701 }
5702 } else {
5703 // [stack] OBJ SYNC_ITERFN
5704 }
5705
5706 if (!emit1(JSOp::Swap)) {
5707 // [stack] SYNC_ITERFN OBJ
5708 return false;
5709 }
5710 if (!emitCall(getIterCallOp(JSOp::CallIter, selfHostedIter), 0)) {
5711 // [stack] ITER
5712 return false;
5713 }
5714 if (!emitCheckIsObj(CheckIsObjectKind::GetIterator)) {
5715 // [stack] ITER
5716 return false;
5717 }
5718
5719 if (!emit1(JSOp::Dup)) {
5720 // [stack] ITER ITER
5721 return false;
5722 }
5723 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::next())) {
5724 // [stack] ITER SYNCNEXT
5725 return false;
5726 }
5727
5728 if (!emit1(JSOp::ToAsyncIter)) {
5729 // [stack] ITER
5730 return false;
5731 }
5732
5733 if (!ifAsyncIterIsUndefined.emitElse()) {
5734 // [stack] OBJ SYNC_ITERFN? ASYNC_ITERFN
5735 return false;
5736 }
5737
5738 if (selfHostedIter == SelfHostedIter::AllowContentWith) {
5739 if (!emit1(JSOp::Swap)) {
5740 // [stack] OBJ ASYNC_ITERFN SYNC_ITERFN
5741 return false;
5742 }
5743 if (!emit1(JSOp::Pop)) {
5744 // [stack] OBJ ASYNC_ITERFN
5745 return false;
5746 }
5747 }
5748
5749 if (!emit1(JSOp::Swap)) {
5750 // [stack] ASYNC_ITERFN OBJ
5751 return false;
5752 }
5753 if (!emitCall(getIterCallOp(JSOp::CallIter, selfHostedIter), 0)) {
5754 // [stack] ITER
5755 return false;
5756 }
5757 if (!emitCheckIsObj(CheckIsObjectKind::GetAsyncIterator)) {
5758 // [stack] ITER
5759 return false;
5760 }
5761
5762 if (!ifAsyncIterIsUndefined.emitEnd()) {
5763 // [stack] ITER
5764 return false;
5765 }
5766
5767 if (!emit1(JSOp::Dup)) {
5768 // [stack] ITER ITER
5769 return false;
5770 }
5771 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::next())) {
5772 // [stack] ITER NEXT
5773 return false;
5774 }
5775 if (!emit1(JSOp::Swap)) {
5776 // [stack] NEXT ITER
5777 return false;
5778 }
5779
5780 return true;
5781}
5782
5783bool BytecodeEmitter::emitSpread(SelfHostedIter selfHostedIter) {
5784 LoopControl loopInfo(this, StatementKind::Spread);
5785
5786 if (!loopInfo.emitLoopHead(this, Nothing())) {
5787 // [stack] NEXT ITER ARR I
5788 return false;
5789 }
5790
5791 {
5792#ifdef DEBUG1
5793 auto loopDepth = bytecodeSection().stackDepth();
5794#endif
5795
5796 // Spread operations can't contain |continue|, so don't bother setting loop
5797 // and enclosing "update" offsets, as we do with for-loops.
5798
5799 if (!emitDupAt(3, 2)) {
5800 // [stack] NEXT ITER ARR I NEXT ITER
5801 return false;
5802 }
5803 if (!emitIteratorNext(Nothing(), IteratorKind::Sync, selfHostedIter)) {
5804 // [stack] NEXT ITER ARR I RESULT
5805 return false;
5806 }
5807 if (!emit1(JSOp::Dup)) {
5808 // [stack] NEXT ITER ARR I RESULT RESULT
5809 return false;
5810 }
5811 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::done())) {
5812 // [stack] NEXT ITER ARR I RESULT DONE
5813 return false;
5814 }
5815 if (!emitJump(JSOp::JumpIfTrue, &loopInfo.breaks)) {
5816 // [stack] NEXT ITER ARR I RESULT
5817 return false;
5818 }
5819
5820 // Emit code to assign result.value to the iteration variable.
5821 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::value())) {
5822 // [stack] NEXT ITER ARR I VALUE
5823 return false;
5824 }
5825 if (!emit1(JSOp::InitElemInc)) {
5826 // [stack] NEXT ITER ARR I
5827 return false;
5828 }
5829
5830 if (!loopInfo.emitLoopEnd(this, JSOp::Goto, TryNoteKind::ForOf)) {
5831 // [stack] NEXT ITER ARR I
5832 return false;
5833 }
5834
5835 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", 5835);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == loopDepth"
")"); do { MOZ_CrashSequence(__null, 5835); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5836 }
5837
5838 // When we leave the loop body and jump to this point, the result value is
5839 // still on the stack. Account for that by updating the stack depth
5840 // manually.
5841 bytecodeSection().setStackDepth(bytecodeSection().stackDepth() + 1);
5842
5843 // No continues should occur in spreads.
5844 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"
, 5844); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!loopInfo.continues.offset.valid()"
")"); do { MOZ_CrashSequence(__null, 5844); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5845
5846 if (!emit2(JSOp::Pick, 4)) {
5847 // [stack] ITER ARR I RESULT NEXT
5848 return false;
5849 }
5850 if (!emit2(JSOp::Pick, 4)) {
5851 // [stack] ARR I RESULT NEXT ITER
5852 return false;
5853 }
5854
5855 return emitPopN(3);
5856 // [stack] ARR I
5857}
5858
5859bool BytecodeEmitter::emitInitializeForInOrOfTarget(TernaryNode* forHead) {
5860 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", 5861);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "forHead->isKind(ParseNodeKind::ForIn) || forHead->isKind(ParseNodeKind::ForOf)"
")"); do { MOZ_CrashSequence(__null, 5861); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5861 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", 5861);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "forHead->isKind(ParseNodeKind::ForIn) || forHead->isKind(ParseNodeKind::ForOf)"
")"); do { MOZ_CrashSequence(__null, 5861); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5862
5863 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", 5864); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() >= 1" ") ("
"must have a per-iteration value for initializing" ")"); do {
MOZ_CrashSequence(__null, 5864); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
5864 "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", 5864); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() >= 1" ") ("
"must have a per-iteration value for initializing" ")"); do {
MOZ_CrashSequence(__null, 5864); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
5865
5866 ParseNode* target = forHead->kid1();
5867 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", 5867);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!forHead->kid2()"
")"); do { MOZ_CrashSequence(__null, 5867); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5868
5869 // If the for-in/of loop didn't have a variable declaration, per-loop
5870 // initialization is just assigning the iteration value to a target
5871 // expression.
5872 if (!target->is<DeclarationListNode>()) {
5873 return emitAssignmentOrInit(ParseNodeKind::AssignExpr, target, nullptr);
5874 // [stack] ... ITERVAL
5875 }
5876
5877 // Otherwise, per-loop initialization is (possibly) declaration
5878 // initialization. If the declaration is a lexical declaration, it must be
5879 // initialized. If the declaration is a variable declaration, an
5880 // assignment to that name (which does *not* necessarily assign to the
5881 // variable!) must be generated.
5882
5883 auto* declarationList = &target->as<DeclarationListNode>();
5884 if (!updateSourceCoordNotes(declarationList->pn_pos.begin)) {
5885 return false;
5886 }
5887
5888 target = declarationList->singleBinding();
5889
5890 NameNode* nameNode = nullptr;
5891 if (target->isKind(ParseNodeKind::Name)) {
5892 nameNode = &target->as<NameNode>();
5893 } else if (target->isKind(ParseNodeKind::AssignExpr)) {
5894 BinaryNode* assignNode = &target->as<BinaryNode>();
5895 if (assignNode->left()->is<NameNode>()) {
5896 nameNode = &assignNode->left()->as<NameNode>();
5897 }
5898 }
5899
5900 if (nameNode) {
5901 auto nameAtom = nameNode->name();
5902 NameOpEmitter noe(this, nameAtom, NameOpEmitter::Kind::Initialize);
5903 if (!noe.prepareForRhs()) {
5904 return false;
5905 }
5906 if (noe.emittedBindOp()) {
5907 // Per-iteration initialization in for-in/of loops computes the
5908 // iteration value *before* initializing. Thus the initializing
5909 // value may be buried under a bind-specific value on the stack.
5910 // Swap it to the top of the stack.
5911 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", 5911);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() >= 2"
")"); do { MOZ_CrashSequence(__null, 5911); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5912 if (!emit1(JSOp::Swap)) {
5913 return false;
5914 }
5915 } else {
5916 // In cases of emitting a frame slot or environment slot,
5917 // nothing needs be done.
5918 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", 5918);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() >= 1"
")"); do { MOZ_CrashSequence(__null, 5918); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5919 }
5920
5921 if (declarationList->isKind(ParseNodeKind::UsingDecl)) {
5922 if (!innermostEmitterScope()->prepareForDisposableAssignment(
5923 UsingHint::Sync)) {
5924 // [stack] ENV? V
5925 return false;
5926 }
5927 } else if (declarationList->isKind(ParseNodeKind::AwaitUsingDecl)) {
5928 if (!innermostEmitterScope()->prepareForDisposableAssignment(
5929 UsingHint::Async)) {
5930 // [stack] ENV? V
5931 return false;
5932 }
5933 }
5934
5935 if (!noe.emitAssignment()) {
5936 return false;
5937 }
5938
5939 // The caller handles removing the iteration value from the stack.
5940 return true;
5941 }
5942
5943 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", 5945
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!target->isKind(ParseNodeKind::AssignExpr)"
") (" "for-in/of loop destructuring declarations can't have initializers"
")"); do { MOZ_CrashSequence(__null, 5945); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5944 !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", 5945
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!target->isKind(ParseNodeKind::AssignExpr)"
") (" "for-in/of loop destructuring declarations can't have initializers"
")"); do { MOZ_CrashSequence(__null, 5945); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5945 "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", 5945
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!target->isKind(ParseNodeKind::AssignExpr)"
") (" "for-in/of loop destructuring declarations can't have initializers"
")"); do { MOZ_CrashSequence(__null, 5945); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5946
5947 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", 5948);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "target->isKind(ParseNodeKind::ArrayExpr) || target->isKind(ParseNodeKind::ObjectExpr)"
")"); do { MOZ_CrashSequence(__null, 5948); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5948 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", 5948);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "target->isKind(ParseNodeKind::ArrayExpr) || target->isKind(ParseNodeKind::ObjectExpr)"
")"); do { MOZ_CrashSequence(__null, 5948); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5949 return emitDestructuringOps(&target->as<ListNode>(),
5950 DestructuringFlavor::Declaration,
5951 SelfHostedIter::Deny);
5952}
5953
5954bool BytecodeEmitter::emitForOf(ForNode* forOfLoop,
5955 const EmitterScope* headLexicalEmitterScope) {
5956 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", 5956);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfLoop->isKind(ParseNodeKind::ForStmt)"
")"); do { MOZ_CrashSequence(__null, 5956); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5957
5958 TernaryNode* forOfHead = forOfLoop->head();
5959 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", 5959);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfHead->isKind(ParseNodeKind::ForOf)"
")"); do { MOZ_CrashSequence(__null, 5959); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5960
5961 unsigned iflags = forOfLoop->iflags();
5962 IteratorKind iterKind =
5963 (iflags & JSITER_FORAWAITOF0x80) ? IteratorKind::Async : IteratorKind::Sync;
5964 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"
, 5964); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isSuspendableContext()"
")"); do { MOZ_CrashSequence(__null, 5964); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
5965 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"
, 5966); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->asSuspendableContext()->isAsync()"
")"); do { MOZ_CrashSequence(__null, 5966); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
5966 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"
, 5966); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->asSuspendableContext()->isAsync()"
")"); do { MOZ_CrashSequence(__null, 5966); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
5967
5968 ParseNode* forHeadExpr = forOfHead->kid3();
5969
5970 // Certain builtins (e.g. Array.from) are implemented in self-hosting
5971 // as for-of loops.
5972 auto selfHostedIter = getSelfHostedIterFor(forHeadExpr);
5973 ForOfEmitter::HeadUsingDeclarationKind headUsingDeclKind =
5974 ForOfEmitter::HeadUsingDeclarationKind::None;
5975 if (forOfHead->kid1()->isKind(ParseNodeKind::UsingDecl)) {
5976 headUsingDeclKind = ForOfEmitter::HeadUsingDeclarationKind::Sync;
5977 } else if (forOfHead->kid1()->isKind(ParseNodeKind::AwaitUsingDecl)) {
5978 headUsingDeclKind = ForOfEmitter::HeadUsingDeclarationKind::Async;
5979 }
5980
5981 ForOfEmitter forOf(this, headLexicalEmitterScope, selfHostedIter, iterKind,
5982 headUsingDeclKind);
5983
5984 if (!forOf.emitIterated()) {
5985 // [stack]
5986 return false;
5987 }
5988
5989 if (!updateSourceCoordNotes(forHeadExpr->pn_pos.begin)) {
5990 return false;
5991 }
5992 if (!markStepBreakpoint()) {
5993 return false;
5994 }
5995 if (!emitIterable(forHeadExpr, selfHostedIter, iterKind)) {
5996 // [stack] ITERABLE
5997 return false;
5998 }
5999
6000 if (headLexicalEmitterScope) {
6001 DebugOnly<ParseNode*> forOfTarget = forOfHead->kid1();
6002 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", 6005);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl) || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)"
")"); do { MOZ_CrashSequence(__null, 6005); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6003 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", 6005);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl) || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)"
")"); do { MOZ_CrashSequence(__null, 6005); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6004 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", 6005);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl) || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)"
")"); do { MOZ_CrashSequence(__null, 6005); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6005 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", 6005);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl) || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)"
")"); do { MOZ_CrashSequence(__null, 6005); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6006 }
6007
6008 if (!forOf.emitInitialize(forOfHead->pn_pos.begin)) {
6009 // [stack] NEXT ITER VALUE
6010 return false;
6011 }
6012
6013 if (!emitInitializeForInOrOfTarget(forOfHead)) {
6014 // [stack] NEXT ITER VALUE
6015 return false;
6016 }
6017
6018 if (!forOf.emitBody()) {
6019 // [stack] NEXT ITER UNDEF
6020 return false;
6021 }
6022
6023 // Perform the loop body.
6024 ParseNode* forBody = forOfLoop->body();
6025 if (!emitTree(forBody)) {
6026 // [stack] NEXT ITER UNDEF
6027 return false;
6028 }
6029
6030 if (!forOf.emitEnd(forHeadExpr->pn_pos.begin)) {
6031 // [stack]
6032 return false;
6033 }
6034
6035 return true;
6036}
6037
6038bool BytecodeEmitter::emitForIn(ForNode* forInLoop,
6039 const EmitterScope* headLexicalEmitterScope) {
6040 TernaryNode* forInHead = forInLoop->head();
6041 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", 6041);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInHead->isKind(ParseNodeKind::ForIn)"
")"); do { MOZ_CrashSequence(__null, 6041); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6042
6043 ForInEmitter forIn(this, headLexicalEmitterScope);
6044
6045 // Annex B: Evaluate the var-initializer expression if present.
6046 // |for (var i = initializer in expr) { ... }|
6047 ParseNode* forInTarget = forInHead->kid1();
6048 if (forInTarget->is<DeclarationListNode>()) {
6049 auto* declarationList = &forInTarget->as<DeclarationListNode>();
6050
6051 ParseNode* decl = declarationList->singleBinding();
6052 if (decl->isKind(ParseNodeKind::AssignExpr)) {
6053 BinaryNode* assignNode = &decl->as<BinaryNode>();
6054 if (assignNode->left()->is<NameNode>()) {
6055 NameNode* nameNode = &assignNode->left()->as<NameNode>();
6056 ParseNode* initializer = assignNode->right();
6057 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", 6059
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInTarget->isKind(ParseNodeKind::VarStmt)"
") (" "for-in initializers are only permitted for |var| declarations"
")"); do { MOZ_CrashSequence(__null, 6059); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6058 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", 6059
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInTarget->isKind(ParseNodeKind::VarStmt)"
") (" "for-in initializers are only permitted for |var| declarations"
")"); do { MOZ_CrashSequence(__null, 6059); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6059 "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", 6059
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInTarget->isKind(ParseNodeKind::VarStmt)"
") (" "for-in initializers are only permitted for |var| declarations"
")"); do { MOZ_CrashSequence(__null, 6059); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6060
6061 if (!updateSourceCoordNotes(decl->pn_pos.begin)) {
6062 return false;
6063 }
6064
6065 auto nameAtom = nameNode->name();
6066 NameOpEmitter noe(this, nameAtom, NameOpEmitter::Kind::Initialize);
6067 if (!noe.prepareForRhs()) {
6068 return false;
6069 }
6070 if (!emitInitializer(initializer, nameNode)) {
6071 return false;
6072 }
6073 if (!noe.emitAssignment()) {
6074 return false;
6075 }
6076
6077 // Pop the initializer.
6078 if (!emit1(JSOp::Pop)) {
6079 return false;
6080 }
6081 }
6082 }
6083 }
6084
6085 if (!forIn.emitIterated()) {
6086 // [stack]
6087 return false;
6088 }
6089
6090 // Evaluate the expression being iterated.
6091 ParseNode* expr = forInHead->kid3();
6092
6093 if (!updateSourceCoordNotes(expr->pn_pos.begin)) {
6094 return false;
6095 }
6096 if (!markStepBreakpoint()) {
6097 return false;
6098 }
6099 if (!emitTree(expr)) {
6100 // [stack] EXPR
6101 return false;
6102 }
6103
6104 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", 6104);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInLoop->iflags() == 0"
")"); do { MOZ_CrashSequence(__null, 6104); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6105
6106 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", 6108);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInTarget->isKind(ParseNodeKind::LetDecl) || forInTarget->isKind(ParseNodeKind::ConstDecl)"
")"); do { MOZ_CrashSequence(__null, 6108); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
6107 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", 6108);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInTarget->isKind(ParseNodeKind::LetDecl) || forInTarget->isKind(ParseNodeKind::ConstDecl)"
")"); do { MOZ_CrashSequence(__null, 6108); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
6108 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", 6108);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInTarget->isKind(ParseNodeKind::LetDecl) || forInTarget->isKind(ParseNodeKind::ConstDecl)"
")"); do { MOZ_CrashSequence(__null, 6108); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
6109
6110 if (!forIn.emitInitialize()) {
6111 // [stack] ITER ITERVAL
6112 return false;
6113 }
6114
6115 if (!emitInitializeForInOrOfTarget(forInHead)) {
6116 // [stack] ITER ITERVAL
6117 return false;
6118 }
6119
6120 if (!forIn.emitBody()) {
6121 // [stack] ITER ITERVAL
6122 return false;
6123 }
6124
6125 // Perform the loop body.
6126 ParseNode* forBody = forInLoop->body();
6127 if (!emitTree(forBody)) {
6128 // [stack] ITER ITERVAL
6129 return false;
6130 }
6131
6132 if (!forIn.emitEnd(forInHead->pn_pos.begin)) {
6133 // [stack]
6134 return false;
6135 }
6136
6137 return true;
6138}
6139
6140/* C-style `for (init; cond; update) ...` loop. */
6141bool BytecodeEmitter::emitCStyleFor(
6142 ForNode* forNode, const EmitterScope* headLexicalEmitterScope) {
6143 TernaryNode* forHead = forNode->head();
6144 ParseNode* forBody = forNode->body();
6145 ParseNode* init = forHead->kid1();
6146 ParseNode* cond = forHead->kid2();
6147 ParseNode* update = forHead->kid3();
6148 bool isLet = init && init->isKind(ParseNodeKind::LetDecl);
6149
6150 CForEmitter cfor(this, isLet ? headLexicalEmitterScope : nullptr);
6151
6152 if (!cfor.emitInit(init ? Some(init->pn_pos.begin) : Nothing())) {
6153 // [stack]
6154 return false;
6155 }
6156
6157 // If the head of this for-loop declared any lexical variables, the parser
6158 // wrapped this ParseNodeKind::For node in a ParseNodeKind::LexicalScope
6159 // representing the implicit scope of those variables. By the time we get
6160 // here, we have already entered that scope. So far, so good.
6161 if (init) {
6162 // Emit the `init` clause, whether it's an expression or a variable
6163 // declaration. (The loop variables were hoisted into an enclosing
6164 // scope, but we still need to emit code for the initializers.)
6165 if (init->is<DeclarationListNode>()) {
6166 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", 6166);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!init->as<DeclarationListNode>().empty()"
")"); do { MOZ_CrashSequence(__null, 6166); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6167
6168 if (!emitTree(init)) {
6169 // [stack]
6170 return false;
6171 }
6172 } else {
6173 if (!updateSourceCoordNotes(init->pn_pos.begin)) {
6174 return false;
6175 }
6176 if (!markStepBreakpoint()) {
6177 return false;
6178 }
6179
6180 // 'init' is an expression, not a declaration. emitTree left its
6181 // value on the stack.
6182 if (!emitTree(init, ValueUsage::IgnoreValue)) {
6183 // [stack] VAL
6184 return false;
6185 }
6186 if (!emit1(JSOp::Pop)) {
6187 // [stack]
6188 return false;
6189 }
6190 }
6191 }
6192
6193 if (!cfor.emitCond(cond ? Some(cond->pn_pos.begin) : Nothing())) {
6194 // [stack]
6195 return false;
6196 }
6197
6198 if (cond) {
6199 if (!updateSourceCoordNotes(cond->pn_pos.begin)) {
6200 return false;
6201 }
6202 if (!markStepBreakpoint()) {
6203 return false;
6204 }
6205 if (!emitTree(cond)) {
6206 // [stack] VAL
6207 return false;
6208 }
6209 }
6210
6211 if (!cfor.emitBody(cond ? CForEmitter::Cond::Present
6212 : CForEmitter::Cond::Missing)) {
6213 // [stack]
6214 return false;
6215 }
6216
6217 if (!emitTree(forBody)) {
6218 // [stack]
6219 return false;
6220 }
6221
6222 if (!cfor.emitUpdate(
6223 update ? CForEmitter::Update::Present : CForEmitter::Update::Missing,
6224 update ? Some(update->pn_pos.begin) : Nothing())) {
6225 // [stack]
6226 return false;
6227 }
6228
6229 // Check for update code to do before the condition (if any).
6230 if (update) {
6231 if (!updateSourceCoordNotes(update->pn_pos.begin)) {
6232 return false;
6233 }
6234 if (!markStepBreakpoint()) {
6235 return false;
6236 }
6237 if (!emitTree(update, ValueUsage::IgnoreValue)) {
6238 // [stack] VAL
6239 return false;
6240 }
6241 }
6242
6243 if (!cfor.emitEnd(forNode->pn_pos.begin)) {
6244 // [stack]
6245 return false;
6246 }
6247
6248 return true;
6249}
6250
6251bool BytecodeEmitter::emitFor(ForNode* forNode,
6252 const EmitterScope* headLexicalEmitterScope) {
6253 if (forNode->head()->isKind(ParseNodeKind::ForHead)) {
6254 return emitCStyleFor(forNode, headLexicalEmitterScope);
6255 }
6256
6257 if (!updateLineNumberNotes(forNode->pn_pos.begin)) {
6258 return false;
6259 }
6260
6261 if (forNode->head()->isKind(ParseNodeKind::ForIn)) {
6262 return emitForIn(forNode, headLexicalEmitterScope);
6263 }
6264
6265 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", 6265);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "forNode->head()->isKind(ParseNodeKind::ForOf)"
")"); do { MOZ_CrashSequence(__null, 6265); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6266 return emitForOf(forNode, headLexicalEmitterScope);
6267}
6268
6269MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitFunction(
6270 FunctionNode* funNode, bool needsProto /* = false */) {
6271 FunctionBox* funbox = funNode->funbox();
6272
6273 // [stack]
6274
6275 FunctionEmitter fe(this, funbox, funNode->syntaxKind(),
6276 funNode->functionIsHoisted()
6277 ? FunctionEmitter::IsHoisted::Yes
6278 : FunctionEmitter::IsHoisted::No);
6279
6280 // |wasEmittedByEnclosingScript| flag is set to true once the function has
6281 // been emitted. Function definitions that need hoisting to the top of the
6282 // function will be seen by emitFunction in two places.
6283 if (funbox->wasEmittedByEnclosingScript()) {
6284 if (!fe.emitAgain()) {
6285 // [stack]
6286 return false;
6287 }
6288 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"
, 6288); AnnotateMozCrashReason("MOZ_ASSERT" "(" "funNode->functionIsHoisted()"
")"); do { MOZ_CrashSequence(__null, 6288); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6289 } else {
6290 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", 6290);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "funbox->isInterpreted()"
")"); do { MOZ_CrashSequence(__null, 6290); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6291 if (!funbox->emitBytecode) {
6292 return fe.emitLazy();
6293 // [stack] FUN?
6294 }
6295
6296 if (!fe.prepareForNonLazy()) {
6297 // [stack]
6298 return false;
6299 }
6300
6301 BytecodeEmitter bce2(this, funbox);
6302 if (!bce2.init(funNode->pn_pos)) {
6303 return false;
6304 }
6305
6306 /* We measured the max scope depth when we parsed the function. */
6307 if (!bce2.emitFunctionScript(funNode)) {
6308 return false;
6309 }
6310
6311 if (!fe.emitNonLazyEnd()) {
6312 // [stack] FUN?
6313 return false;
6314 }
6315 }
6316
6317 // Track the last emitted top-level self-hosted function, so that intrinsics
6318 // can adjust attributes at parse time.
6319 //
6320 // NOTE: We also disallow lambda functions in the top-level body. This is done
6321 // to simplify handling of the self-hosted stencil. Within normal function
6322 // declarations there are no such restrictions.
6323 if (emitterMode == EmitterMode::SelfHosting) {
6324 if (sc->isTopLevelContext()) {
6325 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", 6325);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!funbox->isLambda()"
")"); do { MOZ_CrashSequence(__null, 6325); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6326 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", 6326);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "funbox->explicitName()"
")"); do { MOZ_CrashSequence(__null, 6326); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6327 prevSelfHostedTopLevelFunction = funbox;
6328 }
6329 }
6330
6331 return true;
6332}
6333
6334bool BytecodeEmitter::emitDo(BinaryNode* doNode) {
6335 ParseNode* bodyNode = doNode->left();
6336
6337 DoWhileEmitter doWhile(this);
6338 if (!doWhile.emitBody(doNode->pn_pos.begin, getOffsetForLoop(bodyNode))) {
6339 return false;
6340 }
6341
6342 if (!emitTree(bodyNode)) {
6343 return false;
6344 }
6345
6346 if (!doWhile.emitCond()) {
6347 return false;
6348 }
6349
6350 ParseNode* condNode = doNode->right();
6351 if (!updateSourceCoordNotes(condNode->pn_pos.begin)) {
6352 return false;
6353 }
6354 if (!markStepBreakpoint()) {
6355 return false;
6356 }
6357 if (!emitTree(condNode)) {
6358 return false;
6359 }
6360
6361 if (!doWhile.emitEnd()) {
6362 return false;
6363 }
6364
6365 return true;
6366}
6367
6368bool BytecodeEmitter::emitWhile(BinaryNode* whileNode) {
6369 ParseNode* bodyNode = whileNode->right();
6370
6371 WhileEmitter wh(this);
6372
6373 ParseNode* condNode = whileNode->left();
6374 if (!wh.emitCond(whileNode->pn_pos.begin, getOffsetForLoop(condNode),
6375 whileNode->pn_pos.end)) {
6376 return false;
6377 }
6378
6379 if (!updateSourceCoordNotes(condNode->pn_pos.begin)) {
6380 return false;
6381 }
6382 if (!markStepBreakpoint()) {
6383 return false;
6384 }
6385 if (!emitTree(condNode)) {
6386 return false;
6387 }
6388
6389 if (!wh.emitBody()) {
6390 return false;
6391 }
6392 if (!emitTree(bodyNode)) {
6393 return false;
6394 }
6395
6396 if (!wh.emitEnd()) {
6397 return false;
6398 }
6399
6400 return true;
6401}
6402
6403bool BytecodeEmitter::emitBreak(TaggedParserAtomIndex label) {
6404 BreakableControl* target;
6405 if (label) {
6406 // Any statement with the matching label may be the break target.
6407 auto hasSameLabel = [label](LabelControl* labelControl) {
6408 return labelControl->label() == label;
6409 };
6410 target = findInnermostNestableControl<LabelControl>(hasSameLabel);
6411 } else {
6412 auto isNotLabel = [](BreakableControl* control) {
6413 return !control->is<LabelControl>();
6414 };
6415 target = findInnermostNestableControl<BreakableControl>(isNotLabel);
6416 }
6417
6418 return emitGoto(target, GotoKind::Break);
6419}
6420
6421bool BytecodeEmitter::emitContinue(TaggedParserAtomIndex label) {
6422 LoopControl* target = nullptr;
6423 if (label) {
6424 // Find the loop statement enclosed by the matching label.
6425 NestableControl* control = innermostNestableControl;
6426 while (!control->is<LabelControl>() ||
6427 control->as<LabelControl>().label() != label) {
6428 if (control->is<LoopControl>()) {
6429 target = &control->as<LoopControl>();
6430 }
6431 control = control->enclosing();
6432 }
6433 } else {
6434 target = findInnermostNestableControl<LoopControl>();
6435 }
6436 return emitGoto(target, GotoKind::Continue);
6437}
6438
6439bool BytecodeEmitter::emitGetFunctionThis(NameNode* thisName) {
6440 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"
, 6440); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->hasFunctionThisBinding()"
")"); do { MOZ_CrashSequence(__null, 6440); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6441 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", 6441);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "thisName->isName(TaggedParserAtomIndex::WellKnown::dot_this_())"
")"); do { MOZ_CrashSequence(__null, 6441); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6442
6443 if (!updateLineNumberNotes(thisName->pn_pos.begin)) {
6444 return false;
6445 }
6446
6447 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_this_())) {
6448 // [stack] THIS
6449 return false;
6450 }
6451 if (sc->needsThisTDZChecks()) {
6452 if (!emit1(JSOp::CheckThis)) {
6453 // [stack] THIS
6454 return false;
6455 }
6456 }
6457
6458 return true;
6459}
6460
6461bool BytecodeEmitter::emitGetThisForSuperBase(UnaryNode* superBase) {
6462 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", 6462);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "superBase->isKind(ParseNodeKind::SuperBase)"
")"); do { MOZ_CrashSequence(__null, 6462); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6463 NameNode* nameNode = &superBase->kid()->as<NameNode>();
6464 return emitGetFunctionThis(nameNode);
6465 // [stack] THIS
6466}
6467
6468bool BytecodeEmitter::emitThisLiteral(ThisLiteral* pn) {
6469 if (ParseNode* kid = pn->kid()) {
6470 NameNode* thisName = &kid->as<NameNode>();
6471 return emitGetFunctionThis(thisName);
6472 // [stack] THIS
6473 }
6474
6475 if (sc->thisBinding() == ThisBinding::Module) {
6476 return emit1(JSOp::Undefined);
6477 // [stack] UNDEF
6478 }
6479
6480 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", 6480);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->thisBinding() == ThisBinding::Global"
")"); do { MOZ_CrashSequence(__null, 6480); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6481
6482 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", 6483);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "outermostScope().hasNonSyntacticScopeOnChain() == sc->hasNonSyntacticScope()"
")"); do { MOZ_CrashSequence(__null, 6483); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6483 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", 6483);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "outermostScope().hasNonSyntacticScopeOnChain() == sc->hasNonSyntacticScope()"
")"); do { MOZ_CrashSequence(__null, 6483); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6484 if (sc->hasNonSyntacticScope()) {
6485 return emit1(JSOp::NonSyntacticGlobalThis);
6486 // [stack] THIS
6487 }
6488
6489 return emit1(JSOp::GlobalThis);
6490 // [stack] THIS
6491}
6492
6493bool BytecodeEmitter::emitCheckDerivedClassConstructorReturn() {
6494 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", 6495);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "lookupName(TaggedParserAtomIndex::WellKnown::dot_this_()).hasKnownSlot()"
")"); do { MOZ_CrashSequence(__null, 6495); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6495 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", 6495);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "lookupName(TaggedParserAtomIndex::WellKnown::dot_this_()).hasKnownSlot()"
")"); do { MOZ_CrashSequence(__null, 6495); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6496 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_this_())) {
6497 return false;
6498 }
6499 if (!emit1(JSOp::CheckReturn)) {
6500 return false;
6501 }
6502 if (!emit1(JSOp::SetRval)) {
6503 return false;
6504 }
6505 return true;
6506}
6507
6508bool BytecodeEmitter::emitNewTarget() {
6509 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", 6509);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->allowNewTarget()"
")"); do { MOZ_CrashSequence(__null, 6509); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6510
6511 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_newTarget_())) {
6512 // [stack] NEW.TARGET
6513 return false;
6514 }
6515 return true;
6516}
6517
6518bool BytecodeEmitter::emitNewTarget(NewTargetNode* pn) {
6519 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", 6520);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->newTargetName()->isName( TaggedParserAtomIndex::WellKnown::dot_newTarget_())"
")"); do { MOZ_CrashSequence(__null, 6520); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6520 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", 6520);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->newTargetName()->isName( TaggedParserAtomIndex::WellKnown::dot_newTarget_())"
")"); do { MOZ_CrashSequence(__null, 6520); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6521
6522 return emitNewTarget();
6523}
6524
6525bool BytecodeEmitter::emitNewTarget(CallNode* pn) {
6526 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", 6527);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->callOp() == JSOp::SuperCall || pn->callOp() == JSOp::SpreadSuperCall"
")"); do { MOZ_CrashSequence(__null, 6527); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6527 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", 6527);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->callOp() == JSOp::SuperCall || pn->callOp() == JSOp::SpreadSuperCall"
")"); do { MOZ_CrashSequence(__null, 6527); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6528
6529 // The parser is responsible for marking the "new.target" binding as being
6530 // implicitly used in super() calls.
6531 return emitNewTarget();
6532}
6533
6534bool BytecodeEmitter::emitReturn(UnaryNode* returnNode) {
6535 if (!updateSourceCoordNotes(returnNode->pn_pos.begin)) {
6536 return false;
6537 }
6538
6539 if (!markStepBreakpoint()) {
6540 return false;
6541 }
6542
6543 /* Push a return value */
6544 if (ParseNode* expr = returnNode->kid()) {
6545 if (!emitTree(expr)) {
6546 return false;
6547 }
6548
6549 if (sc->asSuspendableContext()->isAsync() &&
6550 sc->asSuspendableContext()->isGenerator()) {
6551 if (!emitAwaitInInnermostScope()) {
6552 return false;
6553 }
6554 }
6555 } else {
6556 /* No explicit return value provided */
6557 if (!emit1(JSOp::Undefined)) {
6558 return false;
6559 }
6560 }
6561
6562 // We know functionBodyEndPos is set because "return" is only
6563 // valid in a function, and so we've passed through
6564 // emitFunctionScript.
6565 if (!updateSourceCoordNotes(*functionBodyEndPos)) {
6566 return false;
6567 }
6568
6569 /*
6570 * The return value is currently on the stack. We would like to
6571 * generate JSOp::Return, but if we have work to do before returning,
6572 * we will instead generate JSOp::SetRval / JSOp::RetRval.
6573 *
6574 * We don't know whether we will need fixup code until after calling
6575 * prepareForNonLocalJumpToOutermost, so we start by generating
6576 * JSOp::SetRval, then mutate it to JSOp::Return in finishReturn if it
6577 * wasn't needed.
6578 */
6579 BytecodeOffset setRvalOffset = bytecodeSection().offset();
6580 if (!emit1(JSOp::SetRval)) {
6581 return false;
6582 }
6583
6584 NonLocalExitControl nle(this, NonLocalExitKind::Return);
6585 return nle.emitReturn(setRvalOffset);
6586}
6587
6588bool BytecodeEmitter::finishReturn(BytecodeOffset setRvalOffset) {
6589 // The return value is currently in rval. Depending on the current function,
6590 // we may have to do additional work before returning:
6591 // - Derived class constructors must check if the return value is an object.
6592 // - Generators and async functions must do a final yield.
6593 // - Non-async generators must return the value as an iterator result:
6594 // { value: <rval>, done: true }
6595 // - Non-generator async functions must resolve the function's result promise
6596 // with the value.
6597 //
6598 // If we have not generated any code since the SetRval that stored the return
6599 // value, we can also optimize the bytecode by rewriting that SetRval as a
6600 // JSOp::Return. See |emitReturn| above.
6601
6602 bool isDerivedClassConstructor =
6603 sc->isFunctionBox() && sc->asFunctionBox()->isDerivedClassConstructor();
6604 bool needsFinalYield =
6605 sc->isFunctionBox() && sc->asFunctionBox()->needsFinalYield();
6606 bool isSimpleReturn =
6607 setRvalOffset.valid() &&
6608 setRvalOffset + BytecodeOffsetDiff(JSOpLength_SetRval) ==
6609 bytecodeSection().offset();
6610
6611 if (isDerivedClassConstructor) {
6612 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", 6612);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!needsFinalYield" ")"
); do { MOZ_CrashSequence(__null, 6612); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6613 if (!emitJump(JSOp::Goto, &endOfDerivedClassConstructorBody)) {
6614 return false;
6615 }
6616 return true;
6617 }
6618
6619 if (needsFinalYield) {
6620 // A forced return from a `yield` expression can have extra values on the
6621 // expression stack. Pop them here.
6622 int32_t nvalues = bytecodeSection().stackDepth();
6623 if (nvalues > 0 && !emitPopN(nvalues)) {
6624 return false;
6625 }
6626 if (!emitJump(JSOp::Goto, &finalYields)) {
6627 return false;
6628 }
6629 return true;
6630 }
6631
6632 if (isSimpleReturn) {
6633 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", 6634);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "JSOp(bytecodeSection().code()[setRvalOffset.value()]) == JSOp::SetRval"
")"); do { MOZ_CrashSequence(__null, 6634); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6634 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", 6634);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "JSOp(bytecodeSection().code()[setRvalOffset.value()]) == JSOp::SetRval"
")"); do { MOZ_CrashSequence(__null, 6634); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6635 bytecodeSection().code()[setRvalOffset.value()] = jsbytecode(JSOp::Return);
6636 return true;
6637 }
6638
6639 // Nothing special needs to be done.
6640 return emitReturnRval();
6641}
6642
6643bool BytecodeEmitter::emitCheckYieldResumeKind() {
6644 // The bytecode below relies on Next being falsy and Throw/Return being
6645 // truthy.
6646 static_assert(uint8_t(GeneratorResumeKind::Next) == 0);
6647 static_assert(uint8_t(GeneratorResumeKind::Throw) != 0);
6648 static_assert(uint8_t(GeneratorResumeKind::Return) != 0);
6649
6650 const int32_t startDepth = bytecodeSection().stackDepth();
6651 // [stack] RVAL RESUMEKIND
6652
6653 if (!emit1(JSOp::Dup)) {
6654 // [stack] RVAL RESUMEKIND RESUMEKIND
6655 return false;
6656 }
6657 InternalIfEmitter ifNotNext(this);
6658 if (!ifNotNext.emitThen()) {
6659 // [stack] RVAL RESUMEKIND
6660 return false;
6661 }
6662
6663 // Handle Throw and Return.
6664 if (!emitPushResumeKind(GeneratorResumeKind::Throw)) {
6665 // [stack] RVAL RESUMEKIND THROW
6666 return false;
6667 }
6668 if (!emit1(JSOp::StrictEq)) {
6669 // [stack] RVAL (RESUMEKIND==Throw)
6670 return false;
6671 }
6672 InternalIfEmitter ifThrow(this);
6673 if (!ifThrow.emitThen()) {
6674 // [stack] RVAL
6675 return false;
6676 }
6677 if (!emit1(JSOp::Throw)) {
6678 // [stack]
6679 return false;
6680 }
6681 bytecodeSection().setStackDepth(startDepth - 1);
6682 if (!ifThrow.emitEnd()) {
6683 // [stack] RVAL
6684 return false;
6685 }
6686 if (!emit1(JSOp::SetRval)) {
6687 // [stack]
6688 return false;
6689 }
6690 {
6691 NonLocalExitControl nle(this, NonLocalExitKind::Return);
6692 if (!nle.emitReturn()) {
6693 return false;
6694 }
6695 }
6696
6697 bytecodeSection().setStackDepth(startDepth);
6698 if (!ifNotNext.emitEnd()) {
6699 // [stack] RVAL RESUMEKIND
6700 return false;
6701 }
6702 if (!emit1(JSOp::Pop)) {
6703 // [stack] RVAL
6704 return false;
6705 }
6706 return true;
6707}
6708
6709bool BytecodeEmitter::emitCheckAwaitResumeKind() {
6710 // An `await` is only resumed by a promise reaction, so we don't have to
6711 // handle the Return resume kind here, only Next and Throw.
6712 // See https://tc39.es/ecma262/#await.
6713
6714 // The bytecode below relies on Next being falsy and Throw being truthy.
6715 static_assert(uint8_t(GeneratorResumeKind::Next) == 0);
6716 static_assert(uint8_t(GeneratorResumeKind::Throw) != 0);
6717
6718 const int32_t startDepth = bytecodeSection().stackDepth();
6719 // [stack] RVAL RESUMEKIND
6720
6721 InternalIfEmitter ifThrow(this);
6722 if (!ifThrow.emitThen()) {
6723 // [stack] RVAL
6724 return false;
6725 }
6726 if (!emit1(JSOp::Throw)) {
6727 // [stack]
6728 return false;
6729 }
6730 bytecodeSection().setStackDepth(startDepth - 1);
6731 if (!ifThrow.emitEnd()) {
6732 // [stack] RVAL
6733 return false;
6734 }
6735 return true;
6736}
6737
6738bool BytecodeEmitter::emitGetDotGeneratorInScope(EmitterScope& currentScope) {
6739 if (!sc->isFunction() && sc->isModuleContext() &&
6740 sc->asModuleContext()->isAsync()) {
6741 NameLocation loc = *locationOfNameBoundInScopeType<ModuleScope>(
6742 TaggedParserAtomIndex::WellKnown::dot_generator_(), &currentScope);
6743 return emitGetNameAtLocation(
6744 TaggedParserAtomIndex::WellKnown::dot_generator_(), loc);
6745 }
6746 NameLocation loc = *locationOfNameBoundInScopeType<FunctionScope>(
6747 TaggedParserAtomIndex::WellKnown::dot_generator_(), &currentScope);
6748 return emitGetNameAtLocation(
6749 TaggedParserAtomIndex::WellKnown::dot_generator_(), loc);
6750}
6751
6752bool BytecodeEmitter::emitInitialYield(UnaryNode* yieldNode) {
6753 if (!emitTree(yieldNode->kid())) {
6754 return false;
6755 }
6756
6757 if (!emitYieldOp(JSOp::InitialYield)) {
6758 // [stack] RVAL RESUMEKIND
6759 return false;
6760 }
6761 if (!emitCheckYieldResumeKind()) {
6762 // [stack] RVAL
6763 return false;
6764 }
6765 if (!emit1(JSOp::Pop)) {
6766 // [stack]
6767 return false;
6768 }
6769
6770 return true;
6771}
6772
6773bool BytecodeEmitter::emitYield(UnaryNode* yieldNode) {
6774 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", 6774);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isFunctionBox()"
")"); do { MOZ_CrashSequence(__null, 6774); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6775 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", 6775);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->asFunctionBox()->isGenerator()"
")"); do { MOZ_CrashSequence(__null, 6775); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6776 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", 6776);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "yieldNode->isKind(ParseNodeKind::YieldExpr)"
")"); do { MOZ_CrashSequence(__null, 6776); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6777
6778 bool needsIteratorResult = sc->asFunctionBox()->needsIteratorResult();
6779 if (needsIteratorResult) {
6780 if (!emitPrepareIteratorResult()) {
6781 // [stack] ITEROBJ
6782 return false;
6783 }
6784 }
6785 if (ParseNode* expr = yieldNode->kid()) {
6786 if (!emitTree(expr)) {
6787 // [stack] ITEROBJ? VAL
6788 return false;
6789 }
6790 } else {
6791 if (!emit1(JSOp::Undefined)) {
6792 // [stack] ITEROBJ? UNDEFINED
6793 return false;
6794 }
6795 }
6796
6797 if (sc->asSuspendableContext()->isAsync()) {
6798 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", 6798);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!needsIteratorResult"
")"); do { MOZ_CrashSequence(__null, 6798); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6799 if (!emitAwaitInInnermostScope()) {
6800 // [stack] RESULT
6801 return false;
6802 }
6803 }
6804
6805 if (needsIteratorResult) {
6806 if (!emitFinishIteratorResult(false)) {
6807 // [stack] ITEROBJ
6808 return false;
6809 }
6810 }
6811
6812 if (!emitGetDotGeneratorInInnermostScope()) {
6813 // [stack] # if needsIteratorResult
6814 // [stack] ITEROBJ .GENERATOR
6815 // [stack] # else
6816 // [stack] RESULT .GENERATOR
6817 return false;
6818 }
6819
6820 if (!emitYieldOp(JSOp::Yield)) {
6821 // [stack] YIELDRESULT RESUMEKIND
6822 return false;
6823 }
6824
6825 if (!emitCheckYieldResumeKind()) {
6826 // [stack] YIELDRESULT
6827 return false;
6828 }
6829
6830 return true;
6831}
6832
6833bool BytecodeEmitter::emitAwaitInInnermostScope(UnaryNode* awaitNode) {
6834 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"
, 6834); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isSuspendableContext()"
")"); do { MOZ_CrashSequence(__null, 6834); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6835 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", 6835);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "awaitNode->isKind(ParseNodeKind::AwaitExpr)"
")"); do { MOZ_CrashSequence(__null, 6835); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6836
6837 if (!emitTree(awaitNode->kid())) {
6838 return false;
6839 }
6840 return emitAwaitInInnermostScope();
6841}
6842
6843bool BytecodeEmitter::emitAwaitInScope(EmitterScope& currentScope) {
6844 // Emit the CanSkipAwait fast path if this is a function script. The await
6845 // can't be skipped for modules: during InnerModuleEvaluation, we must yield
6846 // execution so other modules in the same module graph can run.
6847 mozilla::Maybe<InternalIfEmitter> ifCanSkip;
6848 if (sc->isFunctionBox()) {
6849 if (!emit1(JSOp::CanSkipAwait)) {
6850 // [stack] VALUE CANSKIP
6851 return false;
6852 }
6853
6854 if (!emit1(JSOp::MaybeExtractAwaitValue)) {
6855 // [stack] VALUE_OR_RESOLVED CANSKIP
6856 return false;
6857 }
6858
6859 ifCanSkip.emplace(this);
6860 if (!ifCanSkip->emitThen(IfEmitter::ConditionKind::Negative)) {
6861 // [stack] VALUE_OR_RESOLVED
6862 return false;
6863 }
6864 }
6865
6866 if (sc->asSuspendableContext()->needsPromiseResult()) {
6867 if (!emitGetDotGeneratorInScope(currentScope)) {
6868 // [stack] VALUE GENERATOR
6869 return false;
6870 }
6871 if (!emit1(JSOp::AsyncAwait)) {
6872 // [stack] PROMISE
6873 return false;
6874 }
6875 }
6876
6877 if (!emitGetDotGeneratorInScope(currentScope)) {
6878 // [stack] VALUE|PROMISE GENERATOR
6879 return false;
6880 }
6881 if (!emitYieldOp(JSOp::Await)) {
6882 // [stack] RESOLVED RESUMEKIND
6883 return false;
6884 }
6885 if (!emitCheckAwaitResumeKind()) {
6886 // [stack] RESOLVED
6887 return false;
6888 }
6889
6890 if (ifCanSkip.isSome()) {
6891 if (!ifCanSkip->emitEnd()) {
6892 return false;
6893 }
6894 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", 6894);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "ifCanSkip->popped() == 0"
")"); do { MOZ_CrashSequence(__null, 6894); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6895 }
6896
6897 return true;
6898}
6899
6900// ES2019 draft rev 49b781ec80117b60f73327ef3054703a3111e40c
6901// 14.4.14 Runtime Semantics: Evaluation
6902// YieldExpression : yield* AssignmentExpression
6903bool BytecodeEmitter::emitYieldStar(ParseNode* iter) {
6904 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"
, 6906); 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, 6906); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
6905 "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"
, 6906); 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, 6906); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
6906 "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"
, 6906); 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, 6906); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6907
6908 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"
, 6908); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isSuspendableContext()"
")"); do { MOZ_CrashSequence(__null, 6908); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6909 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", 6909);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->asSuspendableContext()->isGenerator()"
")"); do { MOZ_CrashSequence(__null, 6909); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6910
6911 // Step 1.
6912 IteratorKind iterKind = sc->asSuspendableContext()->isAsync()
6913 ? IteratorKind::Async
6914 : IteratorKind::Sync;
6915 // Steps 2-5.
6916 if (!emitTree(iter)) {
6917 // [stack] ITERABLE
6918 return false;
6919 }
6920 if (iterKind == IteratorKind::Async) {
6921 if (!emitAsyncIterator(SelfHostedIter::Deny)) {
6922 // [stack] NEXT ITER
6923 return false;
6924 }
6925 } else {
6926 if (!emitIterator(SelfHostedIter::Deny)) {
6927 // [stack] NEXT ITER
6928 return false;
6929 }
6930 }
6931
6932 // Step 6.
6933 // Start with NormalCompletion(undefined).
6934 if (!emit1(JSOp::Undefined)) {
6935 // [stack] NEXT ITER RECEIVED
6936 return false;
6937 }
6938 if (!emitPushResumeKind(GeneratorResumeKind::Next)) {
6939 // [stack] NEXT ITER RECEIVED RESUMEKIND
6940 return false;
6941 }
6942
6943 const int32_t startDepth = bytecodeSection().stackDepth();
6944 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", 6944);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "startDepth >= 4"
")"); do { MOZ_CrashSequence(__null, 6944); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6945
6946 // Step 7 is a loop.
6947 LoopControl loopInfo(this, StatementKind::YieldStar);
6948 if (!loopInfo.emitLoopHead(this, Nothing())) {
6949 // [stack] NEXT ITER RECEIVED RESUMEKIND
6950 return false;
6951 }
6952
6953 // Step 7.a. Check for Normal completion.
6954 if (!emit1(JSOp::Dup)) {
6955 // [stack] NEXT ITER RECEIVED RESUMEKIND RESUMEKIND
6956 return false;
6957 }
6958 if (!emitPushResumeKind(GeneratorResumeKind::Next)) {
6959 // [stack] NEXT ITER RECEIVED RESUMEKIND RESUMEKIND NORMAL
6960 return false;
6961 }
6962 if (!emit1(JSOp::StrictEq)) {
6963 // [stack] NEXT ITER RECEIVED RESUMEKIND IS_NORMAL
6964 return false;
6965 }
6966
6967 InternalIfEmitter ifKind(this);
6968 if (!ifKind.emitThenElse()) {
6969 // [stack] NEXT ITER RECEIVED RESUMEKIND
6970 return false;
6971 }
6972 {
6973 if (!emit1(JSOp::Pop)) {
6974 // [stack] NEXT ITER RECEIVED
6975 return false;
6976 }
6977
6978 // Step 7.a.i.
6979 // result = iter.next(received)
6980 if (!emit2(JSOp::Unpick, 2)) {
6981 // [stack] RECEIVED NEXT ITER
6982 return false;
6983 }
6984 if (!emit1(JSOp::Dup2)) {
6985 // [stack] RECEIVED NEXT ITER NEXT ITER
6986 return false;
6987 }
6988 if (!emit2(JSOp::Pick, 4)) {
6989 // [stack] NEXT ITER NEXT ITER RECEIVED
6990 return false;
6991 }
6992 if (!emitCall(JSOp::Call, 1, iter)) {
6993 // [stack] NEXT ITER RESULT
6994 return false;
6995 }
6996
6997 // Step 7.a.ii.
6998 if (iterKind == IteratorKind::Async) {
6999 if (!emitAwaitInInnermostScope()) {
7000 // [stack] NEXT ITER RESULT
7001 return false;
7002 }
7003 }
7004
7005 // Step 7.a.iii.
7006 if (!emitCheckIsObj(CheckIsObjectKind::IteratorNext)) {
7007 // [stack] NEXT ITER RESULT
7008 return false;
7009 }
7010
7011 // Bytecode for steps 7.a.iv-vii is emitted after the ifKind if-else because
7012 // it's shared with other branches.
7013 }
7014
7015 // Step 7.b. Check for Throw completion.
7016 if (!ifKind.emitElseIf(Nothing())) {
7017 // [stack] NEXT ITER RECEIVED RESUMEKIND
7018 return false;
7019 }
7020 if (!emit1(JSOp::Dup)) {
7021 // [stack] NEXT ITER RECEIVED RESUMEKIND RESUMEKIND
7022 return false;
7023 }
7024 if (!emitPushResumeKind(GeneratorResumeKind::Throw)) {
7025 // [stack] NEXT ITER RECEIVED RESUMEKIND RESUMEKIND THROW
7026 return false;
7027 }
7028 if (!emit1(JSOp::StrictEq)) {
7029 // [stack] NEXT ITER RECEIVED RESUMEKIND IS_THROW
7030 return false;
7031 }
7032 if (!ifKind.emitThenElse()) {
7033 // [stack] NEXT ITER RECEIVED RESUMEKIND
7034 return false;
7035 }
7036 {
7037 if (!emit1(JSOp::Pop)) {
7038 // [stack] NEXT ITER RECEIVED
7039 return false;
7040 }
7041 // Step 7.b.i.
7042 if (!emitDupAt(1)) {
7043 // [stack] NEXT ITER RECEIVED ITER
7044 return false;
7045 }
7046 if (!emit1(JSOp::Dup)) {
7047 // [stack] NEXT ITER RECEIVED ITER ITER
7048 return false;
7049 }
7050 if (!emitAtomOp(JSOp::GetProp,
7051 TaggedParserAtomIndex::WellKnown::throw_())) {
7052 // [stack] NEXT ITER RECEIVED ITER THROW
7053 return false;
7054 }
7055
7056 // Step 7.b.ii.
7057 InternalIfEmitter ifThrowMethodIsNotDefined(this);
7058 if (!emit1(JSOp::IsNullOrUndefined)) {
7059 // [stack] NEXT ITER RECEIVED ITER THROW NULL-OR-UNDEF
7060 return false;
7061 }
7062
7063 if (!ifThrowMethodIsNotDefined.emitThenElse(
7064 IfEmitter::ConditionKind::Negative)) {
7065 // [stack] NEXT ITER RECEIVED ITER THROW
7066 return false;
7067 }
7068
7069 // Step 7.b.ii.1.
7070 // RESULT = ITER.throw(EXCEPTION)
7071 if (!emit1(JSOp::Swap)) {
7072 // [stack] NEXT ITER RECEIVED THROW ITER
7073 return false;
7074 }
7075 if (!emit2(JSOp::Pick, 2)) {
7076 // [stack] NEXT ITER THROW ITER RECEIVED
7077 return false;
7078 }
7079 if (!emitCall(JSOp::Call, 1, iter)) {
7080 // [stack] NEXT ITER RESULT
7081 return false;
7082 }
7083
7084 // Step 7.b.ii.2.
7085 if (iterKind == IteratorKind::Async) {
7086 if (!emitAwaitInInnermostScope()) {
7087 // [stack] NEXT ITER RESULT
7088 return false;
7089 }
7090 }
7091
7092 // Step 7.b.ii.4.
7093 if (!emitCheckIsObj(CheckIsObjectKind::IteratorThrow)) {
7094 // [stack] NEXT ITER RESULT
7095 return false;
7096 }
7097
7098 // Bytecode for steps 7.b.ii.5-8 is emitted after the ifKind if-else because
7099 // it's shared with other branches.
7100
7101 // Step 7.b.iii.
7102 if (!ifThrowMethodIsNotDefined.emitElse()) {
7103 // [stack] NEXT ITER RECEIVED ITER THROW
7104 return false;
7105 }
7106 if (!emit1(JSOp::Pop)) {
7107 // [stack] NEXT ITER RECEIVED ITER
7108 return false;
7109 }
7110
7111 // Steps 7.b.iii.1-4.
7112 //
7113 // If the iterator does not have a "throw" method, it calls IteratorClose
7114 // and then throws a TypeError.
7115 if (!emitIteratorCloseInInnermostScope(iterKind, CompletionKind::Normal,
7116 SelfHostedIter::Deny)) {
7117 // [stack] NEXT ITER RECEIVED ITER
7118 return false;
7119 }
7120 // Steps 7.b.iii.5-6.
7121 if (!emit2(JSOp::ThrowMsg, uint8_t(ThrowMsgKind::IteratorNoThrow))) {
7122 // [stack] NEXT ITER RECEIVED ITER
7123 // [stack] # throw
7124 return false;
7125 }
7126
7127 if (!ifThrowMethodIsNotDefined.emitEnd()) {
7128 return false;
7129 }
7130 }
7131
7132 // Step 7.c. It must be a Return completion.
7133 if (!ifKind.emitElse()) {
7134 // [stack] NEXT ITER RECEIVED RESUMEKIND
7135 return false;
7136 }
7137 {
7138 if (!emit1(JSOp::Pop)) {
7139 // [stack] NEXT ITER RECEIVED
7140 return false;
7141 }
7142
7143 // Step 7.c.i.
7144 //
7145 // Call iterator.return() for receiving a "forced return" completion from
7146 // the generator.
7147
7148 // Step 7.c.ii.
7149 //
7150 // Get the "return" method.
7151 if (!emitDupAt(1)) {
7152 // [stack] NEXT ITER RECEIVED ITER
7153 return false;
7154 }
7155 if (!emit1(JSOp::Dup)) {
7156 // [stack] NEXT ITER RECEIVED ITER ITER
7157 return false;
7158 }
7159 if (!emitAtomOp(JSOp::GetProp,
7160 TaggedParserAtomIndex::WellKnown::return_())) {
7161 // [stack] NEXT ITER RECEIVED ITER RET
7162 return false;
7163 }
7164
7165 // Step 7.c.iii.
7166 //
7167 // Do nothing if "return" is undefined or null.
7168 InternalIfEmitter ifReturnMethodIsDefined(this);
7169 if (!emit1(JSOp::IsNullOrUndefined)) {
7170 // [stack] NEXT ITER RECEIVED ITER RET NULL-OR-UNDEF
7171 return false;
7172 }
7173
7174 // Step 7.c.iv.
7175 //
7176 // Call "return" with the argument passed to Generator.prototype.return.
7177 if (!ifReturnMethodIsDefined.emitThenElse(
7178 IfEmitter::ConditionKind::Negative)) {
7179 // [stack] NEXT ITER RECEIVED ITER RET
7180 return false;
7181 }
7182 if (!emit1(JSOp::Swap)) {
7183 // [stack] NEXT ITER RECEIVED RET ITER
7184 return false;
7185 }
7186 if (!emit2(JSOp::Pick, 2)) {
7187 // [stack] NEXT ITER RET ITER RECEIVED
7188 return false;
7189 }
7190 if (!emitCall(JSOp::Call, 1)) {
7191 // [stack] NEXT ITER RESULT
7192 return false;
7193 }
7194
7195 // Step 7.c.v.
7196 if (iterKind == IteratorKind::Async) {
7197 if (!emitAwaitInInnermostScope()) {
7198 // [stack] NEXT ITER RESULT
7199 return false;
7200 }
7201 }
7202
7203 // Step 7.c.vi.
7204 if (!emitCheckIsObj(CheckIsObjectKind::IteratorReturn)) {
7205 // [stack] NEXT ITER RESULT
7206 return false;
7207 }
7208
7209 // Check if the returned object from iterator.return() is done. If not,
7210 // continue yielding.
7211
7212 // Steps 7.c.vii-viii.
7213 InternalIfEmitter ifReturnDone(this);
7214 if (!emit1(JSOp::Dup)) {
7215 // [stack] NEXT ITER RESULT RESULT
7216 return false;
7217 }
7218 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::done())) {
7219 // [stack] NEXT ITER RESULT DONE
7220 return false;
7221 }
7222 if (!ifReturnDone.emitThenElse()) {
7223 // [stack] NEXT ITER RESULT
7224 return false;
7225 }
7226
7227 // Step 7.c.viii.1.
7228 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::value())) {
7229 // [stack] NEXT ITER VALUE
7230 return false;
7231 }
7232 if (!ifReturnDone.emitElse()) {
7233 // [stack] NEXT ITER RESULT
7234 return false;
7235 }
7236
7237 // Jump to continue label for steps 7.c.ix-x.
7238 if (!emitJump(JSOp::Goto, &loopInfo.continues)) {
7239 // [stack] NEXT ITER RESULT
7240 return false;
7241 }
7242
7243 if (!ifReturnDone.emitEnd()) {
7244 // [stack] NEXT ITER VALUE
7245 return false;
7246 }
7247
7248 // Step 7.c.iii.
7249 if (!ifReturnMethodIsDefined.emitElse()) {
7250 // [stack] NEXT ITER RECEIVED ITER RET
7251 return false;
7252 }
7253 if (!emitPopN(2)) {
7254 // [stack] NEXT ITER RECEIVED
7255 return false;
7256 }
7257 if (iterKind == IteratorKind::Async) {
7258 // Step 7.c.iii.1.
7259 if (!emitAwaitInInnermostScope()) {
7260 // [stack] NEXT ITER RECEIVED
7261 return false;
7262 }
7263 }
7264 if (!ifReturnMethodIsDefined.emitEnd()) {
7265 // [stack] NEXT ITER RECEIVED
7266 return false;
7267 }
7268
7269 // Perform a "forced generator return".
7270 //
7271 // Step 7.c.iii.2.
7272 // Step 7.c.viii.2.
7273 if (!emit1(JSOp::SetRval)) {
7274 // [stack] NEXT ITER
7275 return false;
7276 }
7277 {
7278 NonLocalExitControl nle(this, NonLocalExitKind::Return);
7279 if (!nle.emitReturn()) {
7280 return false;
7281 }
7282 }
7283 bytecodeSection().setStackDepth(startDepth - 1);
7284 }
7285
7286 if (!ifKind.emitEnd()) {
7287 // [stack] NEXT ITER RESULT
7288 return false;
7289 }
7290
7291 // Shared tail for Normal/Throw completions.
7292 //
7293 // Steps 7.a.iv-v.
7294 // Steps 7.b.ii.5-6.
7295 //
7296 // [stack] NEXT ITER RESULT
7297
7298 // if (result.done) break;
7299 if (!emit1(JSOp::Dup)) {
7300 // [stack] NEXT ITER RESULT RESULT
7301 return false;
7302 }
7303 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::done())) {
7304 // [stack] NEXT ITER RESULT DONE
7305 return false;
7306 }
7307 if (!emitJump(JSOp::JumpIfTrue, &loopInfo.breaks)) {
7308 // [stack] NEXT ITER RESULT
7309 return false;
7310 }
7311
7312 // Steps 7.a.vi-vii.
7313 // Steps 7.b.ii.7-8.
7314 // Steps 7.c.ix-x.
7315 if (!loopInfo.emitContinueTarget(this)) {
7316 // [stack] NEXT ITER RESULT
7317 return false;
7318 }
7319 if (iterKind == IteratorKind::Async) {
7320 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::value())) {
7321 // [stack] NEXT ITER RESULT
7322 return false;
7323 }
7324 }
7325 if (!emitGetDotGeneratorInInnermostScope()) {
7326 // [stack] NEXT ITER RESULT GENOBJ
7327 return false;
7328 }
7329 if (!emitYieldOp(JSOp::Yield)) {
7330 // [stack] NEXT ITER RVAL RESUMEKIND
7331 return false;
7332 }
7333 if (!loopInfo.emitLoopEnd(this, JSOp::Goto, TryNoteKind::Loop)) {
7334 // [stack] NEXT ITER RVAL RESUMEKIND
7335 return false;
7336 }
7337
7338 // Jumps to this point have 3 (instead of 4) values on the stack.
7339 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", 7339);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == startDepth"
")"); do { MOZ_CrashSequence(__null, 7339); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7340 bytecodeSection().setStackDepth(startDepth - 1);
7341
7342 // [stack] NEXT ITER RESULT
7343
7344 // Step 7.a.v.1.
7345 // Step 7.b.ii.6.a.
7346 //
7347 // result.value
7348 if (!emit2(JSOp::Unpick, 2)) {
7349 // [stack] RESULT NEXT ITER
7350 return false;
7351 }
7352 if (!emitPopN(2)) {
7353 // [stack] RESULT
7354 return false;
7355 }
7356 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::value())) {
7357 // [stack] VALUE
7358 return false;
7359 }
7360
7361 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", 7361);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == startDepth - 3"
")"); do { MOZ_CrashSequence(__null, 7361); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7362
7363 return true;
7364}
7365
7366bool BytecodeEmitter::emitStatementList(ListNode* stmtList) {
7367 for (ParseNode* stmt : stmtList->contents()) {
7368 if (!emitTree(stmt)) {
7369 return false;
7370 }
7371 }
7372 return true;
7373}
7374
7375bool BytecodeEmitter::emitExpressionStatement(UnaryNode* exprStmt) {
7376 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", 7376);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "exprStmt->isKind(ParseNodeKind::ExpressionStmt)"
")"); do { MOZ_CrashSequence(__null, 7376); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7377
7378 /*
7379 * Top-level or called-from-a-native JS_Execute/EvaluateScript,
7380 * debugger, and eval frames may need the value of the ultimate
7381 * expression statement as the script's result, despite the fact
7382 * that it appears useless to the compiler.
7383 *
7384 * API users may also set the ReadOnlyCompileOptions::noScriptRval option when
7385 * calling JS_Compile* to suppress JSOp::SetRval.
7386 */
7387 bool wantval = false;
7388 bool useful = false;
7389 if (sc->isTopLevelContext()) {
7390 useful = wantval = !sc->noScriptRval();
7391 }
7392
7393 /* Don't eliminate expressions with side effects. */
7394 ParseNode* expr = exprStmt->kid();
7395 if (!useful) {
7396 if (!checkSideEffects(expr, &useful)) {
7397 return false;
7398 }
7399
7400 /*
7401 * Don't eliminate apparently useless expressions if they are labeled
7402 * expression statements. The startOffset() test catches the case
7403 * where we are nesting in emitTree for a labeled compound statement.
7404 */
7405 if (innermostNestableControl &&
7406 innermostNestableControl->is<LabelControl>() &&
7407 innermostNestableControl->as<LabelControl>().startOffset() >=
7408 bytecodeSection().offset()) {
7409 useful = true;
7410 }
7411 }
7412
7413 if (useful) {
7414 ValueUsage valueUsage =
7415 wantval ? ValueUsage::WantValue : ValueUsage::IgnoreValue;
7416 ExpressionStatementEmitter ese(this, valueUsage);
7417 if (!ese.prepareForExpr(exprStmt->pn_pos.begin)) {
7418 return false;
7419 }
7420 if (!markStepBreakpoint()) {
7421 return false;
7422 }
7423 if (!emitTree(expr, valueUsage)) {
7424 return false;
7425 }
7426 if (!ese.emitEnd()) {
7427 return false;
7428 }
7429 }
7430
7431 return true;
7432}
7433
7434bool BytecodeEmitter::emitDeleteName(UnaryNode* deleteNode) {
7435 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"
, 7435); AnnotateMozCrashReason("MOZ_ASSERT" "(" "deleteNode->isKind(ParseNodeKind::DeleteNameExpr)"
")"); do { MOZ_CrashSequence(__null, 7435); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7436
7437 NameNode* nameExpr = &deleteNode->kid()->as<NameNode>();
7438 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", 7438);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "nameExpr->isKind(ParseNodeKind::Name)"
")"); do { MOZ_CrashSequence(__null, 7438); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7439
7440 return emitAtomOp(JSOp::DelName, nameExpr->atom());
7441}
7442
7443bool BytecodeEmitter::emitDeleteProperty(UnaryNode* deleteNode) {
7444 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"
, 7444); AnnotateMozCrashReason("MOZ_ASSERT" "(" "deleteNode->isKind(ParseNodeKind::DeletePropExpr)"
")"); do { MOZ_CrashSequence(__null, 7444); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7445
7446 NonOptionalPropertyAccessBase* propExpr =
7447 &deleteNode->kid()->as<NonOptionalPropertyAccessBase>();
7448 PropOpEmitter poe(this, PropOpEmitter::Kind::Delete,
7449 propExpr->isSuper() ? PropOpEmitter::ObjKind::Super
7450 : PropOpEmitter::ObjKind::Other);
7451
7452 if (!poe.prepareForObj()) {
7453 return false;
7454 }
7455
7456 if (propExpr->isSuper()) {
7457 // The expression |delete super.foo;| has to evaluate |super.foo|, which
7458 // could throw if |this| hasn't yet been set by a |super(...)| call.
7459 auto* base = &propExpr->expression().as<UnaryNode>();
7460 if (!emitGetThisForSuperBase(base)) {
7461 // [stack] THIS
7462 return false;
7463 }
7464 } else {
7465 if (!emitPropLHS(propExpr)) {
7466 // [stack] OBJ
7467 return false;
7468 }
7469 }
7470
7471 if (!poe.emitDelete(propExpr->key().atom())) {
7472 // [stack] # if Super
7473 // [stack] THIS
7474 // [stack] # otherwise
7475 // [stack] SUCCEEDED
7476 return false;
7477 }
7478
7479 return true;
7480}
7481
7482bool BytecodeEmitter::emitDeleteElement(UnaryNode* deleteNode) {
7483 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"
, 7483); AnnotateMozCrashReason("MOZ_ASSERT" "(" "deleteNode->isKind(ParseNodeKind::DeleteElemExpr)"
")"); do { MOZ_CrashSequence(__null, 7483); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7484
7485 auto* elemExpr = &deleteNode->kid()->as<PropertyByValue>();
7486 bool isSuper = elemExpr->isSuper();
7487 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"
, 7487); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elemExpr->key().isKind(ParseNodeKind::PrivateName)"
")"); do { MOZ_CrashSequence(__null, 7487); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7488 ElemOpEmitter eoe(
7489 this, ElemOpEmitter::Kind::Delete,
7490 isSuper ? ElemOpEmitter::ObjKind::Super : ElemOpEmitter::ObjKind::Other);
7491
7492 if (!emitElemObjAndKey(elemExpr, eoe)) {
7493 // [stack] # if Super
7494 // [stack] THIS KEY
7495 // [stack] # otherwise
7496 // [stack] OBJ KEY
7497 return false;
7498 }
7499
7500 if (!eoe.emitDelete()) {
7501 // [stack] # if Super
7502 // [stack] THIS
7503 // [stack] # otherwise
7504 // [stack] SUCCEEDED
7505 return false;
7506 }
7507
7508 return true;
7509}
7510
7511bool BytecodeEmitter::emitDeleteExpression(UnaryNode* deleteNode) {
7512 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", 7512);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "deleteNode->isKind(ParseNodeKind::DeleteExpr)"
")"); do { MOZ_CrashSequence(__null, 7512); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7513
7514 ParseNode* expression = deleteNode->kid();
7515
7516 // If useless, just emit JSOp::True; otherwise convert |delete <expr>| to
7517 // effectively |<expr>, true|.
7518 bool useful = false;
7519 if (!checkSideEffects(expression, &useful)) {
7520 return false;
7521 }
7522
7523 if (useful) {
7524 if (!emitTree(expression)) {
7525 return false;
7526 }
7527 if (!emit1(JSOp::Pop)) {
7528 return false;
7529 }
7530 }
7531
7532 return emit1(JSOp::True);
7533}
7534
7535bool BytecodeEmitter::emitDeleteOptionalChain(UnaryNode* deleteNode) {
7536 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", 7536);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "deleteNode->isKind(ParseNodeKind::DeleteOptionalChainExpr)"
")"); do { MOZ_CrashSequence(__null, 7536); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7537
7538 OptionalEmitter oe(this, bytecodeSection().stackDepth());
7539
7540 ParseNode* kid = deleteNode->kid();
7541 switch (kid->getKind()) {
7542 case ParseNodeKind::ElemExpr:
7543 case ParseNodeKind::OptionalElemExpr: {
7544 auto* elemExpr = &kid->as<PropertyByValueBase>();
7545 if (!emitDeleteElementInOptChain(elemExpr, oe)) {
7546 // [stack] # If shortcircuit
7547 // [stack] UNDEFINED-OR-NULL
7548 // [stack] # otherwise
7549 // [stack] SUCCEEDED
7550 return false;
7551 }
7552
7553 break;
7554 }
7555 case ParseNodeKind::ArgumentsLength:
7556 case ParseNodeKind::DotExpr:
7557 case ParseNodeKind::OptionalDotExpr: {
7558 auto* propExpr = &kid->as<PropertyAccessBase>();
7559 if (!emitDeletePropertyInOptChain(propExpr, oe)) {
7560 // [stack] # If shortcircuit
7561 // [stack] UNDEFINED-OR-NULL
7562 // [stack] # otherwise
7563 // [stack] SUCCEEDED
7564 return false;
7565 }
7566 break;
7567 }
7568 default:
7569 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"
, 7569); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Unrecognized optional delete ParseNodeKind"
")"); do { MOZ_CrashSequence(__null, 7569); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7570 }
7571
7572 if (!oe.emitOptionalJumpTarget(JSOp::True)) {
7573 // [stack] # If shortcircuit
7574 // [stack] TRUE
7575 // [stack] # otherwise
7576 // [stack] SUCCEEDED
7577 return false;
7578 }
7579
7580 return true;
7581}
7582
7583bool BytecodeEmitter::emitDeletePropertyInOptChain(PropertyAccessBase* propExpr,
7584 OptionalEmitter& oe) {
7585 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", 7585);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!propExpr->isSuper()"
")"); do { MOZ_CrashSequence(__null, 7585); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7586 PropOpEmitter poe(this, PropOpEmitter::Kind::Delete,
7587 PropOpEmitter::ObjKind::Other);
7588
7589 if (!poe.prepareForObj()) {
7590 // [stack]
7591 return false;
7592 }
7593 if (!emitOptionalTree(&propExpr->expression(), oe)) {
7594 // [stack] OBJ
7595 return false;
7596 }
7597 if (propExpr->isKind(ParseNodeKind::OptionalDotExpr)) {
7598 if (!oe.emitJumpShortCircuit()) {
7599 // [stack] # if Jump
7600 // [stack] UNDEFINED-OR-NULL
7601 // [stack] # otherwise
7602 // [stack] OBJ
7603 return false;
7604 }
7605 }
7606
7607 if (!poe.emitDelete(propExpr->key().atom())) {
7608 // [stack] SUCCEEDED
7609 return false;
7610 }
7611
7612 return true;
7613}
7614
7615bool BytecodeEmitter::emitDeleteElementInOptChain(PropertyByValueBase* elemExpr,
7616 OptionalEmitter& oe) {
7617 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"
, 7618); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elemExpr->as<PropertyByValue>().isSuper()"
")"); do { MOZ_CrashSequence(__null, 7618); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
7618 !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"
, 7618); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elemExpr->as<PropertyByValue>().isSuper()"
")"); do { MOZ_CrashSequence(__null, 7618); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
7619 ElemOpEmitter eoe(this, ElemOpEmitter::Kind::Delete,
7620 ElemOpEmitter::ObjKind::Other);
7621
7622 if (!eoe.prepareForObj()) {
7623 // [stack]
7624 return false;
7625 }
7626
7627 if (!emitOptionalTree(&elemExpr->expression(), oe)) {
7628 // [stack] OBJ
7629 return false;
7630 }
7631
7632 if (elemExpr->isKind(ParseNodeKind::OptionalElemExpr)) {
7633 if (!oe.emitJumpShortCircuit()) {
7634 // [stack] # if Jump
7635 // [stack] UNDEFINED-OR-NULL
7636 // [stack] # otherwise
7637 // [stack] OBJ
7638 return false;
7639 }
7640 }
7641
7642 if (!eoe.prepareForKey()) {
7643 // [stack] OBJ
7644 return false;
7645 }
7646
7647 if (!emitTree(&elemExpr->key())) {
7648 // [stack] OBJ KEY
7649 return false;
7650 }
7651
7652 if (!eoe.emitDelete()) {
7653 // [stack] SUCCEEDED
7654 return false;
7655 }
7656
7657 return true;
7658}
7659
7660bool BytecodeEmitter::emitDebugCheckSelfHosted() {
7661 // [stack] CALLEE
7662
7663#ifdef DEBUG1
7664 if (!emit1(JSOp::DebugCheckSelfHosted)) {
7665 // [stack] CALLEE
7666 return false;
7667 }
7668#endif
7669
7670 return true;
7671}
7672
7673bool BytecodeEmitter::emitSelfHostedCallFunction(CallNode* callNode, JSOp op) {
7674 // Special-casing of callFunction to emit bytecode that directly
7675 // invokes the callee with the correct |this| object and arguments.
7676 // callFunction(fun, thisArg, arg0, arg1) thus becomes:
7677 // - emit lookup for fun
7678 // - emit lookup for thisArg
7679 // - emit lookups for arg0, arg1
7680 //
7681 // argc is set to the amount of actually emitted args and the
7682 // emitting of args below is disabled by setting emitArgs to false.
7683 NameNode* calleeNode = &callNode->callee()->as<NameNode>();
7684 ListNode* argsList = callNode->args();
7685
7686 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"
, 7686); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() >= 2"
")"); do { MOZ_CrashSequence(__null, 7686); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7687
7688 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"
, 7688); AnnotateMozCrashReason("MOZ_ASSERT" "(" "callNode->callOp() == JSOp::Call"
")"); do { MOZ_CrashSequence(__null, 7688); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7689
7690 bool constructing =
7691 calleeNode->name() ==
7692 TaggedParserAtomIndex::WellKnown::constructContentFunction();
7693 ParseNode* funNode = argsList->head();
7694
7695 if (!emitTree(funNode)) {
7696 // [stack] CALLEE
7697 return false;
7698 }
7699
7700#ifdef DEBUG1
7701 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", 7702);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::Call || op == JSOp::CallContent || op == JSOp::NewContent"
")"); do { MOZ_CrashSequence(__null, 7702); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7702 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", 7702);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::Call || op == JSOp::CallContent || op == JSOp::NewContent"
")"); do { MOZ_CrashSequence(__null, 7702); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7703 if (op == JSOp::Call) {
7704 if (!emitDebugCheckSelfHosted()) {
7705 // [stack] CALLEE
7706 return false;
7707 }
7708 }
7709#endif
7710
7711 ParseNode* thisOrNewTarget = funNode->pn_next;
7712 if (constructing) {
7713 // Save off the new.target value, but here emit a proper |this| for a
7714 // constructing call.
7715 if (!emit1(JSOp::IsConstructing)) {
7716 // [stack] CALLEE IS_CONSTRUCTING
7717 return false;
7718 }
7719 } else {
7720 // It's |this|, emit it.
7721 if (!emitTree(thisOrNewTarget)) {
7722 // [stack] CALLEE THIS
7723 return false;
7724 }
7725 }
7726
7727 for (ParseNode* argpn : argsList->contentsFrom(thisOrNewTarget->pn_next)) {
7728 if (!emitTree(argpn)) {
7729 // [stack] CALLEE ... ARGS...
7730 return false;
7731 }
7732 }
7733
7734 if (constructing) {
7735 if (!emitTree(thisOrNewTarget)) {
7736 // [stack] CALLEE IS_CONSTRUCTING ARGS... NEW.TARGET
7737 return false;
7738 }
7739 }
7740
7741 uint32_t argc = argsList->count() - 2;
7742 if (!emitCall(op, argc)) {
7743 // [stack] RVAL
7744 return false;
7745 }
7746
7747 return true;
7748}
7749
7750bool BytecodeEmitter::emitSelfHostedResumeGenerator(CallNode* callNode) {
7751 ListNode* argsList = callNode->args();
7752
7753 // Syntax: resumeGenerator(gen, value, 'next'|'throw'|'return')
7754 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", 7754);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 3"
")"); do { MOZ_CrashSequence(__null, 7754); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7755
7756 ParseNode* genNode = argsList->head();
7757 if (!emitTree(genNode)) {
7758 // [stack] GENERATOR
7759 return false;
7760 }
7761
7762 ParseNode* valNode = genNode->pn_next;
7763 if (!emitTree(valNode)) {
7764 // [stack] GENERATOR VALUE
7765 return false;
7766 }
7767
7768 ParseNode* kindNode = valNode->pn_next;
7769 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", 7769);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "kindNode->isKind(ParseNodeKind::StringExpr)"
")"); do { MOZ_CrashSequence(__null, 7769); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7770 GeneratorResumeKind kind =
7771 ParserAtomToResumeKind(kindNode->as<NameNode>().atom());
7772 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", 7772);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!kindNode->pn_next"
")"); do { MOZ_CrashSequence(__null, 7772); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7773
7774 if (!emitPushResumeKind(kind)) {
7775 // [stack] GENERATOR VALUE RESUMEKIND
7776 return false;
7777 }
7778
7779 if (!emit1(JSOp::Resume)) {
7780 // [stack] RVAL
7781 return false;
7782 }
7783
7784 return true;
7785}
7786
7787bool BytecodeEmitter::emitSelfHostedAllowContentIter(CallNode* callNode) {
7788 ListNode* argsList = callNode->args();
7789
7790 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", 7790);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1"
")"); do { MOZ_CrashSequence(__null, 7790); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7791
7792 // We're just here as a sentinel. Pass the value through directly.
7793 return emitTree(argsList->head());
7794}
7795
7796bool BytecodeEmitter::emitSelfHostedAllowContentIterWith(CallNode* callNode) {
7797 ListNode* argsList = callNode->args();
7798
7799 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"
, 7799); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2 || argsList->count() == 3"
")"); do { MOZ_CrashSequence(__null, 7799); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7800
7801 // We're just here as a sentinel. Pass the value through directly.
7802 return emitTree(argsList->head());
7803}
7804
7805bool BytecodeEmitter::emitSelfHostedAllowContentIterWithNext(
7806 CallNode* callNode) {
7807 ListNode* argsList = callNode->args();
7808
7809 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", 7809);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2"
")"); do { MOZ_CrashSequence(__null, 7809); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7810
7811 // We're just here as a sentinel. Pass the value through directly.
7812 return emitTree(argsList->head());
7813}
7814
7815bool BytecodeEmitter::emitSelfHostedDefineDataProperty(CallNode* callNode) {
7816 ListNode* argsList = callNode->args();
7817
7818 // Only optimize when 3 arguments are passed.
7819 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", 7819);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 3"
")"); do { MOZ_CrashSequence(__null, 7819); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7820
7821 ParseNode* objNode = argsList->head();
7822 if (!emitTree(objNode)) {
7823 return false;
7824 }
7825
7826 ParseNode* idNode = objNode->pn_next;
7827 if (!emitTree(idNode)) {
7828 return false;
7829 }
7830
7831 ParseNode* valNode = idNode->pn_next;
7832 if (!emitTree(valNode)) {
7833 return false;
7834 }
7835
7836 // This will leave the object on the stack instead of pushing |undefined|,
7837 // but that's fine because the self-hosted code doesn't use the return
7838 // value.
7839 return emit1(JSOp::InitElem);
7840}
7841
7842bool BytecodeEmitter::emitSelfHostedHasOwn(CallNode* callNode) {
7843 ListNode* argsList = callNode->args();
7844
7845 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", 7845);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2"
")"); do { MOZ_CrashSequence(__null, 7845); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7846
7847 ParseNode* idNode = argsList->head();
7848 if (!emitTree(idNode)) {
7849 return false;
7850 }
7851
7852 ParseNode* objNode = idNode->pn_next;
7853 if (!emitTree(objNode)) {
7854 return false;
7855 }
7856
7857 return emit1(JSOp::HasOwn);
7858}
7859
7860bool BytecodeEmitter::emitSelfHostedGetPropertySuper(CallNode* callNode) {
7861 ListNode* argsList = callNode->args();
7862
7863 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", 7863);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 3"
")"); do { MOZ_CrashSequence(__null, 7863); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7864
7865 ParseNode* objNode = argsList->head();
7866 ParseNode* idNode = objNode->pn_next;
7867 ParseNode* receiverNode = idNode->pn_next;
7868
7869 if (!emitTree(receiverNode)) {
7870 return false;
7871 }
7872
7873 if (!emitTree(idNode)) {
7874 return false;
7875 }
7876
7877 if (!emitTree(objNode)) {
7878 return false;
7879 }
7880
7881 return emitElemOpBase(JSOp::GetElemSuper);
7882}
7883
7884bool BytecodeEmitter::emitSelfHostedToNumeric(CallNode* callNode) {
7885 ListNode* argsList = callNode->args();
7886
7887 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", 7887);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1"
")"); do { MOZ_CrashSequence(__null, 7887); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7888
7889 ParseNode* argNode = argsList->head();
7890
7891 if (!emitTree(argNode)) {
7892 return false;
7893 }
7894
7895 return emit1(JSOp::ToNumeric);
7896}
7897
7898bool BytecodeEmitter::emitSelfHostedToString(CallNode* callNode) {
7899 ListNode* argsList = callNode->args();
7900
7901 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", 7901);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1"
")"); do { MOZ_CrashSequence(__null, 7901); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7902
7903 ParseNode* argNode = argsList->head();
7904
7905 if (!emitTree(argNode)) {
7906 return false;
7907 }
7908
7909 return emit1(JSOp::ToString);
7910}
7911
7912bool BytecodeEmitter::emitSelfHostedIsNullOrUndefined(CallNode* callNode) {
7913 ListNode* argsList = callNode->args();
7914
7915 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", 7915);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1"
")"); do { MOZ_CrashSequence(__null, 7915); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7916
7917 ParseNode* argNode = argsList->head();
7918
7919 if (!emitTree(argNode)) {
7920 // [stack] ARG
7921 return false;
7922 }
7923 if (!emit1(JSOp::IsNullOrUndefined)) {
7924 // [stack] ARG IS_NULL_OR_UNDEF
7925 return false;
7926 }
7927 if (!emit1(JSOp::Swap)) {
7928 // [stack] IS_NULL_OR_UNDEF ARG
7929 return false;
7930 }
7931 if (!emit1(JSOp::Pop)) {
7932 // [stack] IS_NULL_OR_UNDEF
7933 return false;
7934 }
7935 return true;
7936}
7937
7938bool BytecodeEmitter::emitSelfHostedIteratorClose(CallNode* callNode) {
7939 ListNode* argsList = callNode->args();
7940 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", 7940);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1"
")"); do { MOZ_CrashSequence(__null, 7940); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7941
7942 ParseNode* argNode = argsList->head();
7943 if (!emitTree(argNode)) {
7944 // [stack] ARG
7945 return false;
7946 }
7947
7948 if (!emit2(JSOp::CloseIter, uint8_t(CompletionKind::Normal))) {
7949 // [stack]
7950 return false;
7951 }
7952
7953 // This is still a call node, so we must generate a stack value.
7954 if (!emit1(JSOp::Undefined)) {
7955 // [stack] RVAL
7956 return false;
7957 }
7958
7959 return true;
7960}
7961
7962bool BytecodeEmitter::emitSelfHostedGetBuiltinConstructorOrPrototype(
7963 CallNode* callNode, bool isConstructor) {
7964 ListNode* argsList = callNode->args();
7965
7966 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", 7966);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1"
")"); do { MOZ_CrashSequence(__null, 7966); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7967
7968 ParseNode* argNode = argsList->head();
7969
7970 if (!argNode->isKind(ParseNodeKind::StringExpr)) {
7971 reportError(callNode, JSMSG_UNEXPECTED_TYPE, "built-in name",
7972 "not a string constant");
7973 return false;
7974 }
7975
7976 auto name = argNode->as<NameNode>().atom();
7977
7978 BuiltinObjectKind kind;
7979 if (isConstructor) {
7980 kind = BuiltinConstructorForName(name);
7981 } else {
7982 kind = BuiltinPrototypeForName(name);
7983 }
7984
7985 if (kind == BuiltinObjectKind::None) {
7986 reportError(callNode, JSMSG_UNEXPECTED_TYPE, "built-in name",
7987 "not a valid built-in");
7988 return false;
7989 }
7990
7991 return emitBuiltinObject(kind);
7992}
7993
7994bool BytecodeEmitter::emitSelfHostedGetBuiltinConstructor(CallNode* callNode) {
7995 return emitSelfHostedGetBuiltinConstructorOrPrototype(
7996 callNode, /* isConstructor = */ true);
7997}
7998
7999bool BytecodeEmitter::emitSelfHostedGetBuiltinPrototype(CallNode* callNode) {
8000 return emitSelfHostedGetBuiltinConstructorOrPrototype(
8001 callNode, /* isConstructor = */ false);
8002}
8003
8004JS::SymbolCode ParserAtomToSymbolCode(TaggedParserAtomIndex atom) {
8005 // NOTE: This is a linear search, but the set of entries is quite small and
8006 // this is only used for initial self-hosted parse.
8007#define MATCH_WELL_KNOWN_SYMBOL(NAME) \
8008 if (atom == TaggedParserAtomIndex::WellKnown::NAME()) { \
8009 return JS::SymbolCode::NAME; \
8010 }
8011 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)
8012#undef MATCH_WELL_KNOWN_SYMBOL
8013
8014 return JS::SymbolCode::Limit;
8015}
8016
8017bool BytecodeEmitter::emitSelfHostedGetBuiltinSymbol(CallNode* callNode) {
8018 ListNode* argsList = callNode->args();
8019
8020 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", 8020);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1"
")"); do { MOZ_CrashSequence(__null, 8020); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8021
8022 ParseNode* argNode = argsList->head();
8023
8024 if (!argNode->isKind(ParseNodeKind::StringExpr)) {
8025 reportError(callNode, JSMSG_UNEXPECTED_TYPE, "built-in name",
8026 "not a string constant");
8027 return false;
8028 }
8029
8030 auto name = argNode->as<NameNode>().atom();
8031
8032 JS::SymbolCode code = ParserAtomToSymbolCode(name);
8033 if (code == JS::SymbolCode::Limit) {
8034 reportError(callNode, JSMSG_UNEXPECTED_TYPE, "built-in name",
8035 "not a valid built-in");
8036 return false;
8037 }
8038
8039 return emit2(JSOp::Symbol, uint8_t(code));
8040}
8041
8042bool BytecodeEmitter::emitSelfHostedArgumentsLength(CallNode* callNode) {
8043 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", 8043);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sc->asFunctionBox()->needsArgsObj()"
")"); do { MOZ_CrashSequence(__null, 8043); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8044 sc->asFunctionBox()->setUsesArgumentsIntrinsics();
8045
8046 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"
, 8046); AnnotateMozCrashReason("MOZ_ASSERT" "(" "callNode->args()->count() == 0"
")"); do { MOZ_CrashSequence(__null, 8046); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8047
8048 return emit1(JSOp::ArgumentsLength);
8049}
8050
8051bool BytecodeEmitter::emitSelfHostedGetArgument(CallNode* callNode) {
8052 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", 8052);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sc->asFunctionBox()->needsArgsObj()"
")"); do { MOZ_CrashSequence(__null, 8052); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8053 sc->asFunctionBox()->setUsesArgumentsIntrinsics();
8054
8055 ListNode* argsList = callNode->args();
8056 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", 8056);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1"
")"); do { MOZ_CrashSequence(__null, 8056); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8057
8058 ParseNode* argNode = argsList->head();
8059 if (!emitTree(argNode)) {
8060 return false;
8061 }
8062
8063 return emit1(JSOp::GetActualArg);
8064}
8065
8066#ifdef DEBUG1
8067void BytecodeEmitter::assertSelfHostedExpectedTopLevel(ParseNode* node) {
8068 // The function argument is expected to be a simple binding/function name.
8069 // Eg. `function foo() { }; SpecialIntrinsic(foo)`
8070 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", 8071
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::Name)"
") (" "argument must be a function name" ")"); do { MOZ_CrashSequence
(__null, 8071); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
8071 "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", 8071
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::Name)"
") (" "argument must be a function name" ")"); do { MOZ_CrashSequence
(__null, 8071); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
8072 TaggedParserAtomIndex targetName = node->as<NameNode>().name();
8073
8074 // The special intrinsics must follow the target functions definition. A
8075 // simple assert is fine here since any hoisted function will cause a non-null
8076 // value to be set here.
8077 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"
, 8077); AnnotateMozCrashReason("MOZ_ASSERT" "(" "prevSelfHostedTopLevelFunction"
")"); do { MOZ_CrashSequence(__null, 8077); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8078
8079 // The target function must match the most recently defined top-level
8080 // self-hosted function.
8081 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", 8082
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "prevSelfHostedTopLevelFunction->explicitName() == targetName"
") (" "selfhost decorator must immediately follow target function"
")"); do { MOZ_CrashSequence(__null, 8082); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8082 "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", 8082
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "prevSelfHostedTopLevelFunction->explicitName() == targetName"
") (" "selfhost decorator must immediately follow target function"
")"); do { MOZ_CrashSequence(__null, 8082); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8083}
8084#endif
8085
8086bool BytecodeEmitter::emitSelfHostedSetIsInlinableLargeFunction(
8087 CallNode* callNode) {
8088#ifdef DEBUG1
8089 ListNode* argsList = callNode->args();
8090
8091 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", 8091);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1"
")"); do { MOZ_CrashSequence(__null, 8091); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8092
8093 assertSelfHostedExpectedTopLevel(argsList->head());
8094#endif
8095
8096 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"
, 8096); AnnotateMozCrashReason("MOZ_ASSERT" "(" "prevSelfHostedTopLevelFunction->isInitialCompilation"
")"); do { MOZ_CrashSequence(__null, 8096); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8097 prevSelfHostedTopLevelFunction->setIsInlinableLargeFunction();
8098
8099 // This is still a call node, so we must generate a stack value.
8100 return emit1(JSOp::Undefined);
8101}
8102
8103bool BytecodeEmitter::emitSelfHostedSetCanonicalName(CallNode* callNode) {
8104 ListNode* argsList = callNode->args();
8105
8106 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", 8106);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2"
")"); do { MOZ_CrashSequence(__null, 8106); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8107
8108#ifdef DEBUG1
8109 assertSelfHostedExpectedTopLevel(argsList->head());
8110#endif
8111
8112 ParseNode* nameNode = argsList->last();
8113 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", 8113);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "nameNode->isKind(ParseNodeKind::StringExpr)"
")"); do { MOZ_CrashSequence(__null, 8113); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8114 TaggedParserAtomIndex specName = nameNode->as<NameNode>().atom();
8115 // Canonical name must be atomized.
8116 compilationState.parserAtoms.markUsedByStencil(specName,
8117 ParserAtom::Atomize::Yes);
8118
8119 // Store the canonical name for instantiation.
8120 prevSelfHostedTopLevelFunction->functionStencil().setSelfHostedCanonicalName(
8121 specName);
8122
8123 return emit1(JSOp::Undefined);
8124}
8125
8126#ifdef DEBUG1
8127void BytecodeEmitter::assertSelfHostedUnsafeGetReservedSlot(
8128 ListNode* argsList) {
8129 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", 8129);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2"
")"); do { MOZ_CrashSequence(__null, 8129); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8130
8131 ParseNode* objNode = argsList->head();
8132 ParseNode* slotNode = objNode->pn_next;
8133
8134 // Ensure that the slot argument is fixed, this is required by the JITs.
8135 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"
, 8136); AnnotateMozCrashReason("MOZ_ASSERT" "(" "slotNode->isKind(ParseNodeKind::NumberExpr)"
") (" "slot argument must be a constant" ")"); do { MOZ_CrashSequence
(__null, 8136); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
8136 "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"
, 8136); AnnotateMozCrashReason("MOZ_ASSERT" "(" "slotNode->isKind(ParseNodeKind::NumberExpr)"
") (" "slot argument must be a constant" ")"); do { MOZ_CrashSequence
(__null, 8136); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
8137}
8138
8139void BytecodeEmitter::assertSelfHostedUnsafeSetReservedSlot(
8140 ListNode* argsList) {
8141 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", 8141);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 3"
")"); do { MOZ_CrashSequence(__null, 8141); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8142
8143 ParseNode* objNode = argsList->head();
8144 ParseNode* slotNode = objNode->pn_next;
8145
8146 // Ensure that the slot argument is fixed, this is required by the JITs.
8147 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"
, 8148); AnnotateMozCrashReason("MOZ_ASSERT" "(" "slotNode->isKind(ParseNodeKind::NumberExpr)"
") (" "slot argument must be a constant" ")"); do { MOZ_CrashSequence
(__null, 8148); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
8148 "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"
, 8148); AnnotateMozCrashReason("MOZ_ASSERT" "(" "slotNode->isKind(ParseNodeKind::NumberExpr)"
") (" "slot argument must be a constant" ")"); do { MOZ_CrashSequence
(__null, 8148); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
8149}
8150#endif
8151
8152/* A version of emitCalleeAndThis for the optional cases:
8153 * * a?.()
8154 * * a?.b()
8155 * * a?.["b"]()
8156 * * (a?.b)()
8157 * * a?.#b()
8158 *
8159 * See emitCallOrNew and emitOptionalCall for more context.
8160 */
8161bool BytecodeEmitter::emitOptionalCalleeAndThis(ParseNode* callee,
8162 CallNode* call,
8163 CallOrNewEmitter& cone,
8164 OptionalEmitter& oe) {
8165 AutoCheckRecursionLimit recursion(fc);
8166 if (!recursion.check(fc)) {
8167 return false;
8168 }
8169
8170 switch (ParseNodeKind kind = callee->getKind()) {
8171 case ParseNodeKind::Name: {
8172 auto name = callee->as<NameNode>().name();
8173 if (!cone.emitNameCallee(name)) {
8174 // [stack] CALLEE THIS
8175 return false;
8176 }
8177 break;
8178 }
8179
8180 case ParseNodeKind::OptionalDotExpr: {
8181 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", 8181);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode != BytecodeEmitter::SelfHosting"
")"); do { MOZ_CrashSequence(__null, 8181); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8182 OptionalPropertyAccess* prop = &callee->as<OptionalPropertyAccess>();
8183 bool isSuper = false;
8184
8185 PropOpEmitter& poe = cone.prepareForPropCallee(isSuper);
8186 if (!emitOptionalDotExpression(prop, poe, isSuper, oe)) {
8187 // [stack] CALLEE THIS
8188 return false;
8189 }
8190 break;
8191 }
8192 case ParseNodeKind::ArgumentsLength: {
8193 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", 8193);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode != BytecodeEmitter::SelfHosting"
")"); do { MOZ_CrashSequence(__null, 8193); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8194 if (!cone.prepareForOtherCallee()) {
8195 return false;
8196 }
8197 if (!emitArgumentsLength()) {
8198 // [stack] ARGUMENTS_LENGTH
8199 return false;
8200 }
8201 break;
8202 }
8203 case ParseNodeKind::DotExpr: {
8204 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", 8204);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode != BytecodeEmitter::SelfHosting"
")"); do { MOZ_CrashSequence(__null, 8204); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8205 PropertyAccess* prop = &callee->as<PropertyAccess>();
8206 bool isSuper = prop->isSuper();
8207
8208 PropOpEmitter& poe = cone.prepareForPropCallee(isSuper);
8209 if (!emitOptionalDotExpression(prop, poe, isSuper, oe)) {
8210 // [stack] CALLEE THIS
8211 return false;
8212 }
8213 break;
8214 }
8215
8216 case ParseNodeKind::OptionalElemExpr: {
8217 OptionalPropertyByValue* elem = &callee->as<OptionalPropertyByValue>();
8218 bool isSuper = false;
8219 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", 8219);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)"
")"); do { MOZ_CrashSequence(__null, 8219); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8220 ElemOpEmitter& eoe = cone.prepareForElemCallee(isSuper);
8221 if (!emitOptionalElemExpression(elem, eoe, isSuper, oe)) {
8222 // [stack] CALLEE THIS
8223 return false;
8224 }
8225 break;
8226 }
8227 case ParseNodeKind::ElemExpr: {
8228 PropertyByValue* elem = &callee->as<PropertyByValue>();
8229 bool isSuper = elem->isSuper();
8230 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", 8230);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)"
")"); do { MOZ_CrashSequence(__null, 8230); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8231 ElemOpEmitter& eoe = cone.prepareForElemCallee(isSuper);
8232 if (!emitOptionalElemExpression(elem, eoe, isSuper, oe)) {
8233 // [stack] CALLEE THIS
8234 return false;
8235 }
8236 break;
8237 }
8238
8239 case ParseNodeKind::PrivateMemberExpr:
8240 case ParseNodeKind::OptionalPrivateMemberExpr: {
8241 PrivateMemberAccessBase* privateExpr =
8242 &callee->as<PrivateMemberAccessBase>();
8243 PrivateOpEmitter& xoe =
8244 cone.prepareForPrivateCallee(privateExpr->privateName().name());
8245 if (!emitOptionalPrivateExpression(privateExpr, xoe, oe)) {
8246 // [stack] CALLEE THIS
8247 return false;
8248 }
8249 break;
8250 }
8251
8252 case ParseNodeKind::Function:
8253 if (!cone.prepareForFunctionCallee()) {
8254 return false;
8255 }
8256 if (!emitOptionalTree(callee, oe)) {
8257 // [stack] CALLEE
8258 return false;
8259 }
8260 break;
8261
8262 case ParseNodeKind::OptionalChain: {
8263 return emitCalleeAndThisForOptionalChain(&callee->as<UnaryNode>(), call,
8264 cone);
8265 }
8266
8267 default:
8268 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"
, 8268); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "kind != ParseNodeKind::SuperBase"
")"); do { MOZ_CrashSequence(__null, 8268); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8269
8270 if (!cone.prepareForOtherCallee()) {
8271 return false;
8272 }
8273 if (!emitOptionalTree(callee, oe)) {
8274 // [stack] CALLEE
8275 return false;
8276 }
8277 break;
8278 }
8279
8280 if (!cone.emitThis()) {
8281 // [stack] CALLEE THIS
8282 return false;
8283 }
8284
8285 return true;
8286}
8287
8288bool BytecodeEmitter::emitCalleeAndThis(ParseNode* callee, CallNode* maybeCall,
8289 CallOrNewEmitter& cone) {
8290 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"
, 8290); AnnotateMozCrashReason("MOZ_ASSERT" "(" "maybeCall->callee() == callee"
")"); do { MOZ_CrashSequence(__null, 8290); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
8291
8292 switch (callee->getKind()) {
8293 case ParseNodeKind::Name: {
8294 auto name = callee->as<NameNode>().name();
8295 if (!cone.emitNameCallee(name)) {
8296 // [stack] CALLEE THIS?
8297 return false;
8298 }
8299 break;
8300 }
8301 case ParseNodeKind::ArgumentsLength: {
8302 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", 8302);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode != BytecodeEmitter::SelfHosting"
")"); do { MOZ_CrashSequence(__null, 8302); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8303 if (!cone.prepareForOtherCallee()) {
8304 return false;
8305 }
8306 if (!emitArgumentsLength()) {
8307 // [stack] ARGUMENTS_LENGTH
8308 return false;
8309 }
8310 break;
8311 }
8312 case ParseNodeKind::DotExpr: {
8313 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", 8313);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode != BytecodeEmitter::SelfHosting"
")"); do { MOZ_CrashSequence(__null, 8313); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8314 PropertyAccess* prop = &callee->as<PropertyAccess>();
8315 bool isSuper = prop->isSuper();
8316
8317 PropOpEmitter& poe = cone.prepareForPropCallee(isSuper);
8318 if (!poe.prepareForObj()) {
8319 return false;
8320 }
8321 if (isSuper) {
8322 UnaryNode* base = &prop->expression().as<UnaryNode>();
8323 if (!emitGetThisForSuperBase(base)) {
8324 // [stack] THIS
8325 return false;
8326 }
8327 } else {
8328 if (!emitPropLHS(prop)) {
8329 // [stack] OBJ
8330 return false;
8331 }
8332 }
8333 if (!poe.emitGet(prop->key().atom())) {
8334 // [stack] CALLEE THIS?
8335 return false;
8336 }
8337
8338 break;
8339 }
8340 case ParseNodeKind::ElemExpr: {
8341 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", 8341);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode != BytecodeEmitter::SelfHosting"
")"); do { MOZ_CrashSequence(__null, 8341); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8342 PropertyByValue* elem = &callee->as<PropertyByValue>();
8343 bool isSuper = elem->isSuper();
8344 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", 8344);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)"
")"); do { MOZ_CrashSequence(__null, 8344); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8345 ElemOpEmitter& eoe = cone.prepareForElemCallee(isSuper);
8346 if (!emitElemObjAndKey(elem, eoe)) {
8347 // [stack] # if Super
8348 // [stack] THIS? THIS KEY
8349 // [stack] # otherwise
8350 // [stack] OBJ? OBJ KEY
8351 return false;
8352 }
8353 if (!eoe.emitGet()) {
8354 // [stack] CALLEE THIS?
8355 return false;
8356 }
8357
8358 break;
8359 }
8360 case ParseNodeKind::PrivateMemberExpr: {
8361 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", 8361);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode != BytecodeEmitter::SelfHosting"
")"); do { MOZ_CrashSequence(__null, 8361); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8362 PrivateMemberAccessBase* privateExpr =
8363 &callee->as<PrivateMemberAccessBase>();
8364 PrivateOpEmitter& xoe =
8365 cone.prepareForPrivateCallee(privateExpr->privateName().name());
8366 if (!emitTree(&privateExpr->expression())) {
8367 // [stack] OBJ
8368 return false;
8369 }
8370 if (!xoe.emitReference()) {
8371 // [stack] OBJ NAME
8372 return false;
8373 }
8374 if (!xoe.emitGetForCallOrNew()) {
8375 // [stack] CALLEE THIS
8376 return false;
8377 }
8378
8379 break;
8380 }
8381 case ParseNodeKind::Function:
8382 if (!cone.prepareForFunctionCallee()) {
8383 return false;
8384 }
8385 if (!emitTree(callee)) {
8386 // [stack] CALLEE
8387 return false;
8388 }
8389 break;
8390 case ParseNodeKind::SuperBase:
8391 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"
, 8391); AnnotateMozCrashReason("MOZ_ASSERT" "(" "maybeCall" ")"
); do { MOZ_CrashSequence(__null, 8391); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8392 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", 8392);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "maybeCall->isKind(ParseNodeKind::SuperCallExpr)"
")"); do { MOZ_CrashSequence(__null, 8392); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8393 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", 8393);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "callee->isKind(ParseNodeKind::SuperBase)"
")"); do { MOZ_CrashSequence(__null, 8393); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8394 if (!cone.emitSuperCallee()) {
8395 // [stack] CALLEE IsConstructing
8396 return false;
8397 }
8398 break;
8399 case ParseNodeKind::OptionalChain: {
8400 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"
, 8400); AnnotateMozCrashReason("MOZ_ASSERT" "(" "maybeCall" ")"
); do { MOZ_CrashSequence(__null, 8400); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8401 return emitCalleeAndThisForOptionalChain(&callee->as<UnaryNode>(),
8402 maybeCall, cone);
8403 }
8404 default:
8405 if (!cone.prepareForOtherCallee()) {
8406 return false;
8407 }
8408 if (!emitTree(callee)) {
8409 return false;
8410 }
8411 break;
8412 }
8413
8414 if (!cone.emitThis()) {
8415 // [stack] CALLEE THIS
8416 return false;
8417 }
8418
8419 return true;
8420}
8421
8422ParseNode* BytecodeEmitter::getCoordNode(ParseNode* callNode,
8423 ParseNode* calleeNode, JSOp op,
8424 ListNode* argsList) const {
8425 ParseNode* coordNode = callNode;
8426 if (op == JSOp::Call || op == JSOp::SpreadCall) {
8427 // Default to using the location of the `(` itself.
8428 // obj[expr]() // expression
8429 // ^ // column coord
8430 coordNode = argsList;
8431
8432 switch (calleeNode->getKind()) {
8433 case ParseNodeKind::ArgumentsLength:
8434 case ParseNodeKind::DotExpr:
8435 // Use the position of a property access identifier.
8436 //
8437 // obj().aprop() // expression
8438 // ^ // column coord
8439 //
8440 // Note: Because of the constant folding logic in FoldElement,
8441 // this case also applies for constant string properties.
8442 //
8443 // obj()['aprop']() // expression
8444 // ^ // column coord
8445 coordNode = &calleeNode->as<NonOptionalPropertyAccessBase>().key();
8446 break;
8447 case ParseNodeKind::Name: {
8448 // Use the start of callee name unless it is at a separator
8449 // or has no args.
8450 //
8451 // 2 + obj() // expression
8452 // ^ // column coord
8453 //
8454 if (argsList->empty() ||
8455 !bytecodeSection().atSeparator(calleeNode->pn_pos.begin)) {
8456 // Use the start of callee names.
8457 coordNode = calleeNode;
8458 }
8459 break;
8460 }
8461
8462 default:
8463 break;
8464 }
8465 }
8466 return coordNode;
8467}
8468
8469bool BytecodeEmitter::emitArguments(ListNode* argsList, bool isCall,
8470 bool isSpread, CallOrNewEmitter& cone) {
8471 uint32_t argc = argsList->count();
8472 if (argc >= ARGC_LIMIT) {
8473 reportError(argsList,
8474 isCall ? JSMSG_TOO_MANY_FUN_ARGS : JSMSG_TOO_MANY_CON_ARGS);
8475 return false;
8476 }
8477 if (!isSpread) {
8478 if (!cone.prepareForNonSpreadArguments()) {
8479 // [stack] CALLEE THIS
8480 return false;
8481 }
8482 for (ParseNode* arg : argsList->contents()) {
8483 if (!updateSourceCoordNotesIfNonLiteral(arg)) {
8484 return false;
8485 }
8486 if (!emitTree(arg)) {
8487 // [stack] CALLEE THIS ARG*
8488 return false;
8489 }
8490 }
8491 } else if (cone.wantSpreadOperand()) {
8492 auto* spreadNode = &argsList->head()->as<UnaryNode>();
8493 if (!updateSourceCoordNotesIfNonLiteral(spreadNode->kid())) {
8494 return false;
8495 }
8496 if (!emitTree(spreadNode->kid())) {
8497 // [stack] CALLEE THIS ARG0
8498 return false;
8499 }
8500
8501 if (!cone.emitSpreadArgumentsTest()) {
8502 // [stack] CALLEE THIS ARG0
8503 return false;
8504 }
8505
8506 if (cone.wantSpreadIteration()) {
8507 if (!emitSpreadIntoArray(spreadNode)) {
8508 // [stack] CALLEE THIS ARR
8509 return false;
8510 }
8511 }
8512
8513 if (!cone.emitSpreadArgumentsTestEnd()) {
8514 // [stack] CALLEE THIS ARR
8515 return false;
8516 }
8517 } else {
8518 if (!cone.prepareForSpreadArguments()) {
8519 // [stack] CALLEE THIS
8520 return false;
8521 }
8522 if (!emitArray(argsList)) {
8523 // [stack] CALLEE THIS ARR
8524 return false;
8525 }
8526 }
8527
8528 return true;
8529}
8530
8531bool BytecodeEmitter::emitOptionalCall(CallNode* callNode, OptionalEmitter& oe,
8532 ValueUsage valueUsage) {
8533 /*
8534 * A modified version of emitCallOrNew that handles optional calls.
8535 *
8536 * These include the following:
8537 * a?.()
8538 * a.b?.()
8539 * a.["b"]?.()
8540 * (a?.b)?.()
8541 *
8542 * See CallOrNewEmitter for more context.
8543 */
8544 ParseNode* calleeNode = callNode->callee();
8545 ListNode* argsList = callNode->args();
8546 bool isSpread = IsSpreadOp(callNode->callOp());
8547 JSOp op = callNode->callOp();
8548 uint32_t argc = argsList->count();
8549 bool isOptimizableSpread = isSpread && argc == 1;
8550
8551 CallOrNewEmitter cone(this, op,
8552 isOptimizableSpread
8553 ? CallOrNewEmitter::ArgumentsKind::SingleSpread
8554 : CallOrNewEmitter::ArgumentsKind::Other,
8555 valueUsage);
8556
8557 ParseNode* coordNode = getCoordNode(callNode, calleeNode, op, argsList);
8558
8559 if (!emitOptionalCalleeAndThis(calleeNode, callNode, cone, oe)) {
8560 // [stack] CALLEE THIS
8561 return false;
8562 }
8563
8564 if (callNode->isKind(ParseNodeKind::OptionalCallExpr)) {
8565 if (!oe.emitJumpShortCircuitForCall()) {
8566 // [stack] CALLEE THIS
8567 return false;
8568 }
8569 }
8570
8571 if (!emitArguments(argsList, /* isCall = */ true, isSpread, cone)) {
8572 // [stack] CALLEE THIS ARGS...
8573 return false;
8574 }
8575
8576 if (!cone.emitEnd(argc, coordNode->pn_pos.begin)) {
8577 // [stack] RVAL
8578 return false;
8579 }
8580
8581 return true;
8582}
8583
8584bool BytecodeEmitter::emitSelfHostedDisposeResources(CallNode* callNode,
8585 DisposalKind kind) {
8586 ListNode* argsList = callNode->args();
8587 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", 8587);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2"
")"); do { MOZ_CrashSequence(__null, 8587); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8588
8589 ParseNode* resourcesNode = argsList->head();
8590 ParseNode* countNode = resourcesNode->pn_next;
8591
8592 DisposalEmitter de(this, bool(kind));
8593
8594 if (!emit1(JSOp::False)) {
8595 // [stack] THROWING
8596 return false;
8597 }
8598
8599 if (!emit1(JSOp::Undefined)) {
8600 // [stack] THROWING UNDEF
8601 return false;
8602 }
8603
8604 if (!de.prepareForDisposeCapability()) {
8605 // [stack] RVAL? NEEDS-AWAIT? HAS-AWAITED? THROWING UNDEF
8606 return false;
8607 }
8608
8609 if (!emitTree(resourcesNode)) {
8610 // [stack] RVAL? NEEDS-AWAIT? HAS-AWAITED? THROWING UNDEF RESOURCES
8611 return false;
8612 }
8613
8614 if (!emitTree(countNode)) {
8615 // [stack] RVAL? NEEDS-AWAIT? HAS-AWAITED? THROWING UNDEF RESOURCES COUNT
8616 return false;
8617 }
8618
8619 if (!de.emitEnd(*innermostEmitterScope())) {
8620 // [stack] EXC THROWING
8621 return false;
8622 }
8623
8624 // [stack] EXC THROWING
8625
8626 InternalIfEmitter ifThrow(this);
8627
8628 if (!ifThrow.emitThenElse()) {
8629 // [stack] EXC
8630 return false;
8631 }
8632
8633 if (!emit1(JSOp::Throw)) {
8634 // [stack]
8635 return false;
8636 }
8637
8638 if (!ifThrow.emitElse()) {
8639 // [stack] EXC
8640 return false;
8641 }
8642
8643 if (!emit1(JSOp::Pop)) {
8644 // [stack]
8645 return false;
8646 }
8647
8648 if (!ifThrow.emitEnd()) {
8649 // [stack]
8650 return false;
8651 }
8652
8653 if (!emit1(JSOp::Undefined)) {
8654 // [stack] RVAL
8655 return false;
8656 }
8657
8658 return true;
8659}
8660
8661bool BytecodeEmitter::emitCallOrNew(CallNode* callNode, ValueUsage valueUsage) {
8662 /*
8663 * Emit callable invocation or operator new (constructor call) code.
8664 * First, emit code for the left operand to evaluate the callable or
8665 * constructable object expression.
8666 *
8667 * Then (or in a call case that has no explicit reference-base
8668 * object) we emit JSOp::Undefined to produce the undefined |this|
8669 * value required for calls (which non-strict mode functions
8670 * will box into the global object).
8671 */
8672 bool isCall = callNode->isKind(ParseNodeKind::CallExpr) ||
8673 callNode->isKind(ParseNodeKind::TaggedTemplateExpr);
8674 ParseNode* calleeNode = callNode->callee();
8675 ListNode* argsList = callNode->args();
8676 JSOp op = callNode->callOp();
8677
8678 if (calleeNode->isKind(ParseNodeKind::Name) &&
8679 emitterMode == BytecodeEmitter::SelfHosting && op == JSOp::Call) {
8680 // Calls to "callFunction", "callContentFunction", or "resumeGenerator" in
8681 // self-hosted code generate inline bytecode.
8682 //
8683 // NOTE: The list of special instruction names has to be kept in sync with
8684 // "js/src/builtin/.eslintrc.js".
8685 auto calleeName = calleeNode->as<NameNode>().name();
8686 if (calleeName == TaggedParserAtomIndex::WellKnown::callFunction()) {
8687 return emitSelfHostedCallFunction(callNode, JSOp::Call);
8688 }
8689 if (calleeName == TaggedParserAtomIndex::WellKnown::callContentFunction()) {
8690 return emitSelfHostedCallFunction(callNode, JSOp::CallContent);
8691 }
8692 if (calleeName ==
8693 TaggedParserAtomIndex::WellKnown::constructContentFunction()) {
8694 return emitSelfHostedCallFunction(callNode, JSOp::NewContent);
8695 }
8696 if (calleeName == TaggedParserAtomIndex::WellKnown::resumeGenerator()) {
8697 return emitSelfHostedResumeGenerator(callNode);
8698 }
8699 if (calleeName == TaggedParserAtomIndex::WellKnown::allowContentIter()) {
8700 return emitSelfHostedAllowContentIter(callNode);
8701 }
8702 if (calleeName ==
8703 TaggedParserAtomIndex::WellKnown::allowContentIterWith()) {
8704 return emitSelfHostedAllowContentIterWith(callNode);
8705 }
8706 if (calleeName ==
8707 TaggedParserAtomIndex::WellKnown::allowContentIterWithNext()) {
8708 return emitSelfHostedAllowContentIterWithNext(callNode);
8709 }
8710 if (calleeName == TaggedParserAtomIndex::WellKnown::DefineDataProperty() &&
8711 argsList->count() == 3) {
8712 return emitSelfHostedDefineDataProperty(callNode);
8713 }
8714 if (calleeName == TaggedParserAtomIndex::WellKnown::hasOwn()) {
8715 return emitSelfHostedHasOwn(callNode);
8716 }
8717 if (calleeName == TaggedParserAtomIndex::WellKnown::getPropertySuper()) {
8718 return emitSelfHostedGetPropertySuper(callNode);
8719 }
8720 if (calleeName == TaggedParserAtomIndex::WellKnown::ToNumeric()) {
8721 return emitSelfHostedToNumeric(callNode);
8722 }
8723 if (calleeName == TaggedParserAtomIndex::WellKnown::ToString()) {
8724 return emitSelfHostedToString(callNode);
8725 }
8726 if (calleeName ==
8727 TaggedParserAtomIndex::WellKnown::GetBuiltinConstructor()) {
8728 return emitSelfHostedGetBuiltinConstructor(callNode);
8729 }
8730 if (calleeName == TaggedParserAtomIndex::WellKnown::GetBuiltinPrototype()) {
8731 return emitSelfHostedGetBuiltinPrototype(callNode);
8732 }
8733 if (calleeName == TaggedParserAtomIndex::WellKnown::GetBuiltinSymbol()) {
8734 return emitSelfHostedGetBuiltinSymbol(callNode);
8735 }
8736 if (calleeName == TaggedParserAtomIndex::WellKnown::ArgumentsLength()) {
8737 return emitSelfHostedArgumentsLength(callNode);
8738 }
8739 if (calleeName == TaggedParserAtomIndex::WellKnown::GetArgument()) {
8740 return emitSelfHostedGetArgument(callNode);
8741 }
8742 if (calleeName ==
8743 TaggedParserAtomIndex::WellKnown::SetIsInlinableLargeFunction()) {
8744 return emitSelfHostedSetIsInlinableLargeFunction(callNode);
8745 }
8746 if (calleeName == TaggedParserAtomIndex::WellKnown::SetCanonicalName()) {
8747 return emitSelfHostedSetCanonicalName(callNode);
8748 }
8749 if (calleeName == TaggedParserAtomIndex::WellKnown::IsNullOrUndefined()) {
8750 return emitSelfHostedIsNullOrUndefined(callNode);
8751 }
8752 if (calleeName == TaggedParserAtomIndex::WellKnown::IteratorClose()) {
8753 return emitSelfHostedIteratorClose(callNode);
8754 }
8755 if (calleeName ==
8756 TaggedParserAtomIndex::WellKnown::DisposeResourcesAsync()) {
8757 return emitSelfHostedDisposeResources(callNode, DisposalKind::Async);
8758 }
8759 if (calleeName ==
8760 TaggedParserAtomIndex::WellKnown::DisposeResourcesSync()) {
8761 return emitSelfHostedDisposeResources(callNode, DisposalKind::Sync);
8762 }
8763#ifdef DEBUG1
8764 if (calleeName ==
8765 TaggedParserAtomIndex::WellKnown::UnsafeGetReservedSlot() ||
8766 calleeName == TaggedParserAtomIndex::WellKnown::
8767 UnsafeGetObjectFromReservedSlot() ||
8768 calleeName == TaggedParserAtomIndex::WellKnown::
8769 UnsafeGetInt32FromReservedSlot() ||
8770 calleeName == TaggedParserAtomIndex::WellKnown::
8771 UnsafeGetStringFromReservedSlot()) {
8772 // Make sure that this call is correct, but don't emit any special code.
8773 assertSelfHostedUnsafeGetReservedSlot(argsList);
8774 }
8775 if (calleeName ==
8776 TaggedParserAtomIndex::WellKnown::UnsafeSetReservedSlot()) {
8777 // Make sure that this call is correct, but don't emit any special code.
8778 assertSelfHostedUnsafeSetReservedSlot(argsList);
8779 }
8780#endif
8781 // Fall through
8782 }
8783
8784 uint32_t argc = argsList->count();
8785 bool isSpread = IsSpreadOp(op);
8786 bool isOptimizableSpread = isSpread && argc == 1;
8787 bool isDefaultDerivedClassConstructor =
8788 sc->isFunctionBox() && sc->asFunctionBox()->isDerivedClassConstructor() &&
8789 sc->asFunctionBox()->isSyntheticFunction();
8790 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"
, 8790); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isOptimizableSpread"
")"); do { MOZ_CrashSequence(__null, 8790); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
8791 CallOrNewEmitter cone(
8792 this, op,
8793 isOptimizableSpread
8794 ? isDefaultDerivedClassConstructor
8795 ? CallOrNewEmitter::ArgumentsKind::PassthroughRest
8796 : CallOrNewEmitter::ArgumentsKind::SingleSpread
8797 : CallOrNewEmitter::ArgumentsKind::Other,
8798 valueUsage);
8799
8800 if (!emitCalleeAndThis(calleeNode, callNode, cone)) {
8801 // [stack] CALLEE THIS
8802 return false;
8803 }
8804 if (!emitArguments(argsList, isCall, isSpread, cone)) {
8805 // [stack] CALLEE THIS ARGS...
8806 return false;
8807 }
8808
8809 // Push new.target for construct calls.
8810 if (IsConstructOp(op)) {
8811 if (op == JSOp::SuperCall || op == JSOp::SpreadSuperCall) {
8812 if (!emitNewTarget(callNode)) {
8813 // [stack] CALLEE THIS ARGS.. NEW.TARGET
8814 return false;
8815 }
8816 } else {
8817 // Repush the callee as new.target
8818 uint32_t effectiveArgc = isSpread ? 1 : argc;
8819 if (!emitDupAt(effectiveArgc + 1)) {
8820 // [stack] CALLEE THIS ARGS.. CALLEE
8821 return false;
8822 }
8823 }
8824 }
8825
8826 ParseNode* coordNode = getCoordNode(callNode, calleeNode, op, argsList);
8827
8828 if (!cone.emitEnd(argc, coordNode->pn_pos.begin)) {
8829 // [stack] RVAL
8830 return false;
8831 }
8832
8833 return true;
8834}
8835
8836// This list must be kept in the same order in several places:
8837// - The binary operators in ParseNode.h ,
8838// - the binary operators in TokenKind.h
8839// - the precedence list in Parser.cpp
8840static const JSOp ParseNodeKindToJSOp[] = {
8841 // Some binary ops require special code generation (PrivateIn);
8842 // these should not use BinaryOpParseNodeKindToJSOp. This table fills those
8843 // slots with Nops to make the rest of the table lookup work.
8844 JSOp::Coalesce, JSOp::Or, JSOp::And, JSOp::BitOr, JSOp::BitXor,
8845 JSOp::BitAnd, JSOp::StrictEq, JSOp::Eq, JSOp::StrictNe, JSOp::Ne,
8846 JSOp::Lt, JSOp::Le, JSOp::Gt, JSOp::Ge, JSOp::Instanceof,
8847 JSOp::In, JSOp::Nop, JSOp::Lsh, JSOp::Rsh, JSOp::Ursh,
8848 JSOp::Add, JSOp::Sub, JSOp::Mul, JSOp::Div, JSOp::Mod,
8849 JSOp::Pow};
8850
8851static inline JSOp BinaryOpParseNodeKindToJSOp(ParseNodeKind pnk) {
8852 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"
, 8852); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pnk >= ParseNodeKind::BinOpFirst"
")"); do { MOZ_CrashSequence(__null, 8852); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8853 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"
, 8853); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pnk <= ParseNodeKind::BinOpLast"
")"); do { MOZ_CrashSequence(__null, 8853); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8854 int parseNodeFirst = size_t(ParseNodeKind::BinOpFirst);
8855#ifdef DEBUG1
8856 int jsopArraySize = std::size(ParseNodeKindToJSOp);
8857 int parseNodeKindListSize =
8858 size_t(ParseNodeKind::BinOpLast) - parseNodeFirst + 1;
8859 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", 8859);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "jsopArraySize == parseNodeKindListSize"
")"); do { MOZ_CrashSequence(__null, 8859); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8860 // Ensure we don't use this to find an op for a parse node
8861 // requiring special emission rules.
8862 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", 8862);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "ParseNodeKindToJSOp[size_t(pnk) - parseNodeFirst] != JSOp::Nop"
")"); do { MOZ_CrashSequence(__null, 8862); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8863#endif
8864 return ParseNodeKindToJSOp[size_t(pnk) - parseNodeFirst];
8865}
8866
8867bool BytecodeEmitter::emitRightAssociative(ListNode* node) {
8868 // ** is the only right-associative operator.
8869 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", 8869);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::PowExpr)"
")"); do { MOZ_CrashSequence(__null, 8869); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8870
8871 // Right-associative operator chain.
8872 for (ParseNode* subexpr : node->contents()) {
8873 if (!updateSourceCoordNotesIfNonLiteral(subexpr)) {
8874 return false;
8875 }
8876 if (!emitTree(subexpr)) {
8877 return false;
8878 }
8879 }
8880 for (uint32_t i = 0; i < node->count() - 1; i++) {
8881 if (!emit1(JSOp::Pow)) {
8882 return false;
8883 }
8884 }
8885 return true;
8886}
8887
8888Maybe<ConstantCompareOperand>
8889BytecodeEmitter::parseNodeToConstantCompareOperand(ParseNode* constant) {
8890 switch (constant->getKind()) {
8891 case ParseNodeKind::NumberExpr: {
8892 double d = constant->as<NumericLiteral>().value();
8893 int32_t ival;
8894 if (NumberEqualsInt32(d, &ival)) {
8895 if (ConstantCompareOperand::CanEncodeInt32ValueAsOperand(ival)) {
8896 return Some(ConstantCompareOperand(int8_t(ival)));
8897 }
8898 }
8899 return Nothing();
8900 }
8901 case ParseNodeKind::TrueExpr:
8902 case ParseNodeKind::FalseExpr:
8903 return Some(
8904 ConstantCompareOperand(constant->isKind(ParseNodeKind::TrueExpr)));
8905 case ParseNodeKind::NullExpr:
8906 return Some(
8907 ConstantCompareOperand(ConstantCompareOperand::EncodedType::Null));
8908 case ParseNodeKind::RawUndefinedExpr:
8909 return Some(ConstantCompareOperand(
8910 ConstantCompareOperand::EncodedType::Undefined));
8911 case ParseNodeKind::Name: {
8912 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", 8913);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "constant->as<NameNode>().name() == TaggedParserAtomIndex::WellKnown::undefined()"
")"); do { MOZ_CrashSequence(__null, 8913); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8913 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", 8913);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "constant->as<NameNode>().name() == TaggedParserAtomIndex::WellKnown::undefined()"
")"); do { MOZ_CrashSequence(__null, 8913); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8914 NameLocation loc = lookupName(constant->as<NameNode>().name());
8915 switch (loc.kind()) {
8916 case NameLocation::Kind::Global:
8917 if (!sc->hasNonSyntacticScope()) {
8918 return Some(ConstantCompareOperand(
8919 ConstantCompareOperand::EncodedType::Undefined));
8920 }
8921 return Nothing();
8922 case NameLocation::Kind::Intrinsic:
8923 return Some(ConstantCompareOperand(
8924 ConstantCompareOperand::EncodedType::Undefined));
8925 default:
8926 return Nothing();
8927 }
8928 }
8929 default:
8930 return Nothing();
8931 }
8932}
8933
8934bool BytecodeEmitter::tryEmitConstantEq(ListNode* node, JSOp op,
8935 bool* emitted) {
8936 // We ignore long chains of === or !==, we
8937 // only optimise cases a === b or a !== b
8938 if (node->count() != 2) {
8939 *emitted = false;
8940 return true;
8941 }
8942
8943 JSOp constantOp;
8944 switch (op) {
8945 case JSOp::StrictEq:
8946 constantOp = JSOp::StrictConstantEq;
8947 break;
8948 case JSOp::StrictNe:
8949 constantOp = JSOp::StrictConstantNe;
8950 break;
8951 default:
8952 *emitted = false;
8953 return true;
8954 }
8955
8956 ParseNode* left = node->head();
8957 ParseNode* right = node->head()->pn_next;
8958
8959 ParseNode* expressionNode;
8960 ParseNode* constantNode;
8961 if (left->isConstant() || left->isUndefinedLiteral()) {
8962 expressionNode = right;
8963 constantNode = left;
8964 } else if (right->isConstant() || right->isUndefinedLiteral()) {
8965 expressionNode = left;
8966 constantNode = right;
8967 } else {
8968 *emitted = false;
8969 return true;
8970 }
8971
8972 Maybe<ConstantCompareOperand> operand =
8973 parseNodeToConstantCompareOperand(constantNode);
8974 if (operand.isNothing()) {
8975 *emitted = false;
8976 return true;
8977 }
8978
8979 if (!emitTree(expressionNode)) {
8980 return false;
8981 }
8982
8983 if (!emitUint16Operand(constantOp, operand->rawValue())) {
8984 return false;
8985 }
8986
8987 *emitted = true;
8988 return true;
8989}
8990
8991bool BytecodeEmitter::emitLeftAssociative(ListNode* node) {
8992 JSOp op = BinaryOpParseNodeKindToJSOp(node->getKind());
8993 bool constantEqEmitted = false;
8994 if (!tryEmitConstantEq(node, op, &constantEqEmitted)) {
8995 return false;
8996 }
8997 if (constantEqEmitted) {
8998 return true;
8999 }
9000 // Left-associative operator chain.
9001 if (!emitTree(node->head())) {
9002 return false;
9003 }
9004 ParseNode* nextExpr = node->head()->pn_next;
9005 do {
9006 if (!updateSourceCoordNotesIfNonLiteral(nextExpr)) {
9007 return false;
9008 }
9009 if (!emitTree(nextExpr)) {
9010 return false;
9011 }
9012 if (!emit1(op)) {
9013 return false;
9014 }
9015 } while ((nextExpr = nextExpr->pn_next));
9016 return true;
9017}
9018
9019bool BytecodeEmitter::emitPrivateInExpr(ListNode* node) {
9020 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"
, 9020); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->head()->isKind(ParseNodeKind::PrivateName)"
")"); do { MOZ_CrashSequence(__null, 9020); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9021
9022 NameNode& privateNameNode = node->head()->as<NameNode>();
9023 TaggedParserAtomIndex privateName = privateNameNode.name();
9024
9025 PrivateOpEmitter xoe(this, PrivateOpEmitter::Kind::ErgonomicBrandCheck,
9026 privateName);
9027
9028 ParseNode* valueNode = node->head()->pn_next;
9029 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"
, 9029); AnnotateMozCrashReason("MOZ_ASSERT" "(" "valueNode->pn_next == nullptr"
")"); do { MOZ_CrashSequence(__null, 9029); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9030
9031 if (!emitTree(valueNode)) {
9032 // [stack] OBJ
9033 return false;
9034 }
9035
9036 if (!xoe.emitReference()) {
9037 // [stack] OBJ BRAND if private method
9038 // [stack] OBJ NAME if private field or accessor.
9039 return false;
9040 }
9041
9042 if (!xoe.emitBrandCheck()) {
9043 // [stack] OBJ BRAND BOOL if private method
9044 // [stack] OBJ NAME BOOL if private field or accessor.
9045 return false;
9046 }
9047
9048 if (!emitUnpickN(2)) {
9049 // [stack] BOOL OBJ BRAND if private method
9050 // [stack] BOOL OBJ NAME if private field or accessor.
9051 return false;
9052 }
9053
9054 if (!emitPopN(2)) {
9055 // [stack] BOOL
9056 return false;
9057 }
9058
9059 return true;
9060}
9061
9062/*
9063 * Special `emitTree` for Optional Chaining case.
9064 * Examples of this are `emitOptionalChain`, `emitDeleteOptionalChain` and
9065 * `emitCalleeAndThisForOptionalChain`.
9066 */
9067bool BytecodeEmitter::emitOptionalTree(
9068 ParseNode* pn, OptionalEmitter& oe,
9069 ValueUsage valueUsage /* = ValueUsage::WantValue */) {
9070 AutoCheckRecursionLimit recursion(fc);
9071 if (!recursion.check(fc)) {
9072 return false;
9073 }
9074 ParseNodeKind kind = pn->getKind();
9075 switch (kind) {
9076 case ParseNodeKind::OptionalDotExpr: {
9077 OptionalPropertyAccess* prop = &pn->as<OptionalPropertyAccess>();
9078 bool isSuper = false;
9079 PropOpEmitter poe(this, PropOpEmitter::Kind::Get,
9080 PropOpEmitter::ObjKind::Other);
9081 if (!emitOptionalDotExpression(prop, poe, isSuper, oe)) {
9082 return false;
9083 }
9084 break;
9085 }
9086 case ParseNodeKind::ArgumentsLength: {
9087 // Emit via emitArgumentsLength to handle elided arguments bindings;
9088 // emitOptionalDotExpression would instead emit a plain GetName of
9089 // |arguments|.
9090 if (!emitArgumentsLength()) {
9091 return false;
9092 }
9093 break;
9094 }
9095 case ParseNodeKind::DotExpr: {
9096 PropertyAccess* prop = &pn->as<PropertyAccess>();
9097 bool isSuper = prop->isSuper();
9098 PropOpEmitter poe(this, PropOpEmitter::Kind::Get,
9099 isSuper ? PropOpEmitter::ObjKind::Super
9100 : PropOpEmitter::ObjKind::Other);
9101 if (!emitOptionalDotExpression(prop, poe, isSuper, oe)) {
9102 return false;
9103 }
9104 break;
9105 }
9106
9107 case ParseNodeKind::OptionalElemExpr: {
9108 OptionalPropertyByValue* elem = &pn->as<OptionalPropertyByValue>();
9109 bool isSuper = false;
9110 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", 9110);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)"
")"); do { MOZ_CrashSequence(__null, 9110); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9111 ElemOpEmitter eoe(this, ElemOpEmitter::Kind::Get,
9112 ElemOpEmitter::ObjKind::Other);
9113
9114 if (!emitOptionalElemExpression(elem, eoe, isSuper, oe)) {
9115 return false;
9116 }
9117 break;
9118 }
9119 case ParseNodeKind::ElemExpr: {
9120 PropertyByValue* elem = &pn->as<PropertyByValue>();
9121 bool isSuper = elem->isSuper();
9122 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", 9122);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)"
")"); do { MOZ_CrashSequence(__null, 9122); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9123 ElemOpEmitter eoe(this, ElemOpEmitter::Kind::Get,
9124 isSuper ? ElemOpEmitter::ObjKind::Super
9125 : ElemOpEmitter::ObjKind::Other);
9126
9127 if (!emitOptionalElemExpression(elem, eoe, isSuper, oe)) {
9128 return false;
9129 }
9130 break;
9131 }
9132 case ParseNodeKind::PrivateMemberExpr:
9133 case ParseNodeKind::OptionalPrivateMemberExpr: {
9134 PrivateMemberAccessBase* privateExpr = &pn->as<PrivateMemberAccessBase>();
9135 PrivateOpEmitter xoe(this, PrivateOpEmitter::Kind::Get,
9136 privateExpr->privateName().name());
9137 if (!emitOptionalPrivateExpression(privateExpr, xoe, oe)) {
9138 return false;
9139 }
9140 break;
9141 }
9142 case ParseNodeKind::CallExpr:
9143 case ParseNodeKind::OptionalCallExpr:
9144 if (!emitOptionalCall(&pn->as<CallNode>(), oe, valueUsage)) {
9145 return false;
9146 }
9147 break;
9148 // List of accepted ParseNodeKinds that might appear only at the beginning
9149 // of an Optional Chain.
9150 // For example, a taggedTemplateExpr node might occur if we have
9151 // `test`?.b, with `test` as the taggedTemplateExpr ParseNode.
9152 default:
9153#ifdef DEBUG1
9154 // https://tc39.es/ecma262/#sec-primary-expression
9155 bool isPrimaryExpression =
9156 kind == ParseNodeKind::ThisExpr || kind == ParseNodeKind::Name ||
9157 kind == ParseNodeKind::PrivateName ||
9158 kind == ParseNodeKind::NullExpr || kind == ParseNodeKind::TrueExpr ||
9159 kind == ParseNodeKind::FalseExpr ||
9160 kind == ParseNodeKind::NumberExpr ||
9161 kind == ParseNodeKind::BigIntExpr ||
9162 kind == ParseNodeKind::StringExpr ||
9163 kind == ParseNodeKind::ArrayExpr ||
9164 kind == ParseNodeKind::ObjectExpr ||
9165 kind == ParseNodeKind::Function || kind == ParseNodeKind::ClassDecl ||
9166 kind == ParseNodeKind::RegExpExpr ||
9167 kind == ParseNodeKind::TemplateStringExpr ||
9168 kind == ParseNodeKind::TemplateStringListExpr ||
9169 kind == ParseNodeKind::RawUndefinedExpr || pn->isInParens();
9170
9171 // https://tc39.es/ecma262/#sec-left-hand-side-expressions
9172 bool isMemberExpression = isPrimaryExpression ||
9173 kind == ParseNodeKind::TaggedTemplateExpr ||
9174 kind == ParseNodeKind::NewExpr ||
9175 kind == ParseNodeKind::NewTargetExpr ||
9176 kind == ParseNodeKind::ImportMetaExpr;
9177
9178 bool isCallExpression = kind == ParseNodeKind::SetThis ||
9179 kind == ParseNodeKind::CallImportExpr;
9180
9181 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"
, 9182); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isMemberExpression || isCallExpression"
") (" "Unknown ParseNodeKind for OptionalChain" ")"); do { MOZ_CrashSequence
(__null, 9182); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
9182 "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"
, 9182); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isMemberExpression || isCallExpression"
") (" "Unknown ParseNodeKind for OptionalChain" ")"); do { MOZ_CrashSequence
(__null, 9182); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
9183#endif
9184 return emitTree(pn);
9185 }
9186 return true;
9187}
9188
9189// Handle the case of a call made on a OptionalChainParseNode.
9190// For example `(a?.b)()` and `(a?.b)?.()`.
9191bool BytecodeEmitter::emitCalleeAndThisForOptionalChain(
9192 UnaryNode* optionalChain, CallNode* callNode, CallOrNewEmitter& cone) {
9193 ParseNode* calleeNode = optionalChain->kid();
9194
9195 // Create a new OptionalEmitter, in order to emit the right bytecode
9196 // in isolation.
9197 OptionalEmitter oe(this, bytecodeSection().stackDepth());
9198
9199 if (!emitOptionalCalleeAndThis(calleeNode, callNode, cone, oe)) {
9200 // [stack] CALLEE THIS
9201 return false;
9202 }
9203
9204 // complete the jump if necessary. This will set both the "this" value
9205 // and the "callee" value to undefined, if the callee is undefined. It
9206 // does not matter much what the this value is, the function call will
9207 // fail if it is not optional, and be set to undefined otherwise.
9208 if (!oe.emitOptionalJumpTarget(JSOp::Undefined,
9209 OptionalEmitter::Kind::Reference)) {
9210 // [stack] # If shortcircuit
9211 // [stack] UNDEFINED UNDEFINED
9212 // [stack] # otherwise
9213 // [stack] CALLEE THIS
9214 return false;
9215 }
9216 return true;
9217}
9218
9219bool BytecodeEmitter::emitOptionalChain(UnaryNode* optionalChain,
9220 ValueUsage valueUsage) {
9221 ParseNode* expr = optionalChain->kid();
9222
9223 OptionalEmitter oe(this, bytecodeSection().stackDepth());
9224
9225 if (!emitOptionalTree(expr, oe, valueUsage)) {
9226 // [stack] VAL
9227 return false;
9228 }
9229
9230 if (!oe.emitOptionalJumpTarget(JSOp::Undefined)) {
9231 // [stack] # If shortcircuit
9232 // [stack] UNDEFINED
9233 // [stack] # otherwise
9234 // [stack] VAL
9235 return false;
9236 }
9237
9238 return true;
9239}
9240
9241bool BytecodeEmitter::emitOptionalDotExpression(PropertyAccessBase* prop,
9242 PropOpEmitter& poe,
9243 bool isSuper,
9244 OptionalEmitter& oe) {
9245 if (!poe.prepareForObj()) {
9246 // [stack]
9247 return false;
9248 }
9249
9250 if (isSuper) {
9251 UnaryNode* base = &prop->expression().as<UnaryNode>();
9252 if (!emitGetThisForSuperBase(base)) {
9253 // [stack] OBJ
9254 return false;
9255 }
9256 } else {
9257 if (!emitOptionalTree(&prop->expression(), oe)) {
9258 // [stack] OBJ
9259 return false;
9260 }
9261 }
9262
9263 if (prop->isKind(ParseNodeKind::OptionalDotExpr)) {
9264 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"
, 9264); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!isSuper" ")"
); do { MOZ_CrashSequence(__null, 9264); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9265 if (!oe.emitJumpShortCircuit()) {
9266 // [stack] # if Jump
9267 // [stack] UNDEFINED-OR-NULL
9268 // [stack] # otherwise
9269 // [stack] OBJ
9270 return false;
9271 }
9272 }
9273
9274 if (!poe.emitGet(prop->key().atom())) {
9275 // [stack] PROP
9276 return false;
9277 }
9278
9279 return true;
9280}
9281
9282bool BytecodeEmitter::emitOptionalElemExpression(PropertyByValueBase* elem,
9283 ElemOpEmitter& eoe,
9284 bool isSuper,
9285 OptionalEmitter& oe) {
9286 if (!eoe.prepareForObj()) {
9287 // [stack]
9288 return false;
9289 }
9290
9291 if (isSuper) {
9292 UnaryNode* base = &elem->expression().as<UnaryNode>();
9293 if (!emitGetThisForSuperBase(base)) {
9294 // [stack] OBJ
9295 return false;
9296 }
9297 } else {
9298 if (!emitOptionalTree(&elem->expression(), oe)) {
9299 // [stack] OBJ
9300 return false;
9301 }
9302 }
9303
9304 if (elem->isKind(ParseNodeKind::OptionalElemExpr)) {
9305 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"
, 9305); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!isSuper" ")"
); do { MOZ_CrashSequence(__null, 9305); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9306 if (!oe.emitJumpShortCircuit()) {
9307 // [stack] # if Jump
9308 // [stack] UNDEFINED-OR-NULL
9309 // [stack] # otherwise
9310 // [stack] OBJ
9311 return false;
9312 }
9313 }
9314
9315 if (!eoe.prepareForKey()) {
9316 // [stack] OBJ? OBJ
9317 return false;
9318 }
9319
9320 if (!emitTree(&elem->key())) {
9321 // [stack] OBJ? OBJ KEY
9322 return false;
9323 }
9324
9325 if (!eoe.emitGet()) {
9326 // [stack] ELEM
9327 return false;
9328 }
9329
9330 return true;
9331}
9332
9333bool BytecodeEmitter::emitOptionalPrivateExpression(
9334 PrivateMemberAccessBase* privateExpr, PrivateOpEmitter& xoe,
9335 OptionalEmitter& oe) {
9336 if (!emitOptionalTree(&privateExpr->expression(), oe)) {
9337 // [stack] OBJ
9338 return false;
9339 }
9340
9341 if (privateExpr->isKind(ParseNodeKind::OptionalPrivateMemberExpr)) {
9342 if (!oe.emitJumpShortCircuit()) {
9343 // [stack] # if Jump
9344 // [stack] UNDEFINED-OR-NULL
9345 // [stack] # otherwise
9346 // [stack] OBJ
9347 return false;
9348 }
9349 }
9350
9351 if (!xoe.emitReference()) {
9352 // [stack] OBJ NAME
9353 return false;
9354 }
9355 if (!xoe.emitGet()) {
9356 // [stack] CALLEE THIS # if call
9357 // [stack] VALUE # otherwise
9358 return false;
9359 }
9360
9361 return true;
9362}
9363
9364bool BytecodeEmitter::emitShortCircuit(ListNode* node, ValueUsage valueUsage) {
9365 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", 9367);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::OrExpr) || node->isKind(ParseNodeKind::CoalesceExpr) || node->isKind(ParseNodeKind::AndExpr)"
")"); do { MOZ_CrashSequence(__null, 9367); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9366 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", 9367);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::OrExpr) || node->isKind(ParseNodeKind::CoalesceExpr) || node->isKind(ParseNodeKind::AndExpr)"
")"); do { MOZ_CrashSequence(__null, 9367); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9367 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", 9367);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::OrExpr) || node->isKind(ParseNodeKind::CoalesceExpr) || node->isKind(ParseNodeKind::AndExpr)"
")"); do { MOZ_CrashSequence(__null, 9367); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9368
9369 /*
9370 * JSOp::Or converts the operand on the stack to boolean, leaves the original
9371 * value on the stack and jumps if true; otherwise it falls into the next
9372 * bytecode, which pops the left operand and then evaluates the right operand.
9373 * The jump goes around the right operand evaluation.
9374 *
9375 * JSOp::And converts the operand on the stack to boolean and jumps if false;
9376 * otherwise it falls into the right operand's bytecode.
9377 */
9378
9379 TDZCheckCache tdzCache(this);
9380
9381 JSOp op;
9382 switch (node->getKind()) {
9383 case ParseNodeKind::OrExpr:
9384 op = JSOp::Or;
9385 break;
9386 case ParseNodeKind::CoalesceExpr:
9387 op = JSOp::Coalesce;
9388 break;
9389 case ParseNodeKind::AndExpr:
9390 op = JSOp::And;
9391 break;
9392 default:
9393 MOZ_CRASH("Unexpected ParseNodeKind")do { do { } while (false); MOZ_ReportCrash("" "Unexpected ParseNodeKind"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 9393);
AnnotateMozCrashReason("MOZ_CRASH(" "Unexpected ParseNodeKind"
")"); do { MOZ_CrashSequence(__null, 9393); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
9394 }
9395
9396 JumpList jump;
9397
9398 // Left-associative operator chain: avoid too much recursion.
9399 //
9400 // Emit all nodes but the last.
9401 for (ParseNode* expr : node->contentsTo(node->last())) {
9402 if (!emitTree(expr)) {
9403 return false;
9404 }
9405 if (!emitJump(op, &jump)) {
9406 return false;
9407 }
9408 if (!emit1(JSOp::Pop)) {
9409 return false;
9410 }
9411 }
9412
9413 // Emit the last node
9414 if (!emitTree(node->last(), valueUsage)) {
9415 return false;
9416 }
9417
9418 if (!emitJumpTargetAndPatch(jump)) {
9419 return false;
9420 }
9421 return true;
9422}
9423
9424bool BytecodeEmitter::emitSequenceExpr(ListNode* node, ValueUsage valueUsage) {
9425 for (ParseNode* child : node->contentsTo(node->last())) {
9426 if (!updateSourceCoordNotes(child->pn_pos.begin)) {
9427 return false;
9428 }
9429 if (!emitTree(child, ValueUsage::IgnoreValue)) {
9430 return false;
9431 }
9432 if (!emit1(JSOp::Pop)) {
9433 return false;
9434 }
9435 }
9436
9437 ParseNode* child = node->last();
9438 if (!updateSourceCoordNotes(child->pn_pos.begin)) {
9439 return false;
9440 }
9441 if (!emitTree(child, valueUsage)) {
9442 return false;
9443 }
9444 return true;
9445}
9446
9447// Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See
9448// the comment on emitSwitch.
9449MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitIncOrDec(UnaryNode* incDec,
9450 ValueUsage valueUsage) {
9451 switch (incDec->kid()->getKind()) {
9452 case ParseNodeKind::ArgumentsLength:
9453 case ParseNodeKind::DotExpr:
9454 return emitPropIncDec(incDec, valueUsage);
9455 case ParseNodeKind::ElemExpr:
9456 return emitElemIncDec(incDec, valueUsage);
9457 case ParseNodeKind::PrivateMemberExpr:
9458 return emitPrivateIncDec(incDec, valueUsage);
9459 case ParseNodeKind::CallExpr:
9460 return emitCallIncDec(incDec);
9461 default:
9462 return emitNameIncDec(incDec, valueUsage);
9463 }
9464}
9465
9466// Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See
9467// the comment on emitSwitch.
9468MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitLabeledStatement(
9469 const LabeledStatement* labeledStmt) {
9470 auto name = labeledStmt->label();
9471 LabelEmitter label(this);
9472
9473 label.emitLabel(name);
9474
9475 if (!emitTree(labeledStmt->statement())) {
9476 return false;
9477 }
9478 if (!label.emitEnd()) {
9479 return false;
9480 }
9481
9482 return true;
9483}
9484
9485bool BytecodeEmitter::emitConditionalExpression(
9486 ConditionalExpression& conditional, ValueUsage valueUsage) {
9487 CondEmitter cond(this);
9488 if (!cond.emitCond()) {
9489 return false;
9490 }
9491
9492 ParseNode* conditionNode = &conditional.condition();
9493 auto conditionKind = IfEmitter::ConditionKind::Positive;
9494 if (conditionNode->isKind(ParseNodeKind::NotExpr)) {
9495 conditionNode = conditionNode->as<UnaryNode>().kid();
9496 conditionKind = IfEmitter::ConditionKind::Negative;
9497 }
9498
9499 // NOTE: NotExpr of conditionNode may be unwrapped, and in that case the
9500 // negation is handled by conditionKind.
9501 if (!emitTree(conditionNode)) {
9502 return false;
9503 }
9504
9505 if (!cond.emitThenElse(conditionKind)) {
9506 return false;
9507 }
9508
9509 if (!emitTree(&conditional.thenExpression(), valueUsage)) {
9510 return false;
9511 }
9512
9513 if (!cond.emitElse()) {
9514 return false;
9515 }
9516
9517 if (!emitTree(&conditional.elseExpression(), valueUsage)) {
9518 return false;
9519 }
9520
9521 if (!cond.emitEnd()) {
9522 return false;
9523 }
9524 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", 9524);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "cond.pushed() == 1"
")"); do { MOZ_CrashSequence(__null, 9524); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9525
9526 return true;
9527}
9528
9529// Check for an object-literal property list that can be handled by the
9530// ObjLiteral writer. We ensure that for each `prop: value` pair, the key is a
9531// constant name or numeric index, there is no accessor specified, and the value
9532// can be encoded by an ObjLiteral instruction (constant number, string,
9533// boolean, null/undefined).
9534void BytecodeEmitter::isPropertyListObjLiteralCompatible(
9535 ListNode* obj, bool* withValues, bool* withoutValues) const {
9536 bool keysOK = true;
9537 bool valuesOK = true;
9538 uint32_t propCount = 0;
9539
9540 for (ParseNode* propdef : obj->contents()) {
9541 if (!propdef->is<BinaryNode>()) {
9542 keysOK = false;
9543 break;
9544 }
9545 propCount++;
9546
9547 BinaryNode* prop = &propdef->as<BinaryNode>();
9548 ParseNode* key = prop->left();
9549 ParseNode* value = prop->right();
9550
9551 // Computed keys not OK (ObjLiteral data stores constant keys).
9552 if (key->isKind(ParseNodeKind::ComputedName)) {
9553 keysOK = false;
9554 break;
9555 }
9556
9557 // BigIntExprs should have been lowered to computed names at parse
9558 // time, and so should be excluded above.
9559 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", 9559);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!key->isKind(ParseNodeKind::BigIntExpr)"
")"); do { MOZ_CrashSequence(__null, 9559); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9560
9561 // Numeric keys OK as long as they are integers and in range.
9562 if (key->isKind(ParseNodeKind::NumberExpr)) {
9563 double numValue = key->as<NumericLiteral>().value();
9564 int32_t i = 0;
9565 if (!NumberIsInt32(numValue, &i)) {
9566 keysOK = false;
9567 break;
9568 }
9569 if (!ObjLiteralWriter::arrayIndexInRange(i)) {
9570 keysOK = false;
9571 break;
9572 }
9573 }
9574
9575 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", 9577);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr)"
")"); do { MOZ_CrashSequence(__null, 9577); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9576 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", 9577);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr)"
")"); do { MOZ_CrashSequence(__null, 9577); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9577 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", 9577);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr)"
")"); do { MOZ_CrashSequence(__null, 9577); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9578
9579 AccessorType accessorType =
9580 prop->is<PropertyDefinition>()
9581 ? prop->as<PropertyDefinition>().accessorType()
9582 : AccessorType::None;
9583 if (accessorType != AccessorType::None) {
9584 keysOK = false;
9585 break;
9586 }
9587
9588 if (!isRHSObjLiteralCompatible(value)) {
9589 valuesOK = false;
9590 }
9591 }
9592
9593 if (propCount > SharedPropMap::MaxPropsForNonDictionary) {
9594 // JSOp::NewObject cannot accept dictionary-mode objects.
9595 keysOK = false;
9596 }
9597
9598 *withValues = keysOK && valuesOK;
9599 *withoutValues = keysOK;
9600}
9601
9602bool BytecodeEmitter::isArrayObjLiteralCompatible(ListNode* array) const {
9603 for (ParseNode* elem : array->contents()) {
9604 if (elem->isKind(ParseNodeKind::Spread)) {
9605 return false;
9606 }
9607 if (!isRHSObjLiteralCompatible(elem)) {
9608 return false;
9609 }
9610 }
9611 return true;
9612}
9613
9614bool BytecodeEmitter::emitPropertyList(ListNode* obj, PropertyEmitter& pe,
9615 PropListType type) {
9616 // [stack] CTOR? OBJ
9617
9618 size_t curFieldKeyIndex = 0;
9619 size_t curStaticFieldKeyIndex = 0;
9620 for (ParseNode* propdef : obj->contents()) {
9621 if (propdef->is<ClassField>()) {
9622 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", 9622);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == ClassBody" ")"
); do { MOZ_CrashSequence(__null, 9622); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9623 // Only handle computing field keys here: the .initializers lambda array
9624 // is created elsewhere.
9625 ClassField* field = &propdef->as<ClassField>();
9626 if (field->name().getKind() == ParseNodeKind::ComputedName) {
9627 auto fieldKeys =
9628 field->isStatic()
9629 ? TaggedParserAtomIndex::WellKnown::dot_staticFieldKeys_()
9630 : TaggedParserAtomIndex::WellKnown::dot_fieldKeys_();
9631 if (!emitGetName(fieldKeys)) {
9632 // [stack] CTOR OBJ ARRAY
9633 return false;
9634 }
9635
9636 ParseNode* nameExpr = field->name().as<UnaryNode>().kid();
9637
9638 if (!emitTree(nameExpr, ValueUsage::WantValue)) {
9639 // [stack] CTOR OBJ ARRAY KEY
9640 return false;
9641 }
9642
9643 if (!emit1(JSOp::ToPropertyKey)) {
9644 // [stack] CTOR OBJ ARRAY KEY
9645 return false;
9646 }
9647
9648 size_t fieldKeysIndex;
9649 if (field->isStatic()) {
9650 fieldKeysIndex = curStaticFieldKeyIndex++;
9651 } else {
9652 fieldKeysIndex = curFieldKeyIndex++;
9653 }
9654
9655 if (!emitUint32Operand(JSOp::InitElemArray, fieldKeysIndex)) {
9656 // [stack] CTOR OBJ ARRAY
9657 return false;
9658 }
9659
9660 if (!emit1(JSOp::Pop)) {
9661 // [stack] CTOR OBJ
9662 return false;
9663 }
9664 }
9665 continue;
9666 }
9667
9668 if (propdef->isKind(ParseNodeKind::StaticClassBlock)) {
9669 // Static class blocks are emitted as part of
9670 // emitCreateMemberInitializers.
9671 continue;
9672 }
9673
9674 if (propdef->is<LexicalScopeNode>()) {
9675 // Constructors are sometimes wrapped in LexicalScopeNodes. As we
9676 // already handled emitting the constructor, skip it.
9677 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", 9678);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "propdef->as<LexicalScopeNode>().scopeBody()->is<ClassMethod>()"
")"); do { MOZ_CrashSequence(__null, 9678); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9678 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", 9678);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "propdef->as<LexicalScopeNode>().scopeBody()->is<ClassMethod>()"
")"); do { MOZ_CrashSequence(__null, 9678); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9679 continue;
9680 }
9681
9682 // Handle __proto__: v specially because *only* this form, and no other
9683 // involving "__proto__", performs [[Prototype]] mutation.
9684 if (propdef->isKind(ParseNodeKind::MutateProto)) {
9685 // [stack] OBJ
9686 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", 9686);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == ObjectLiteral"
")"); do { MOZ_CrashSequence(__null, 9686); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9687 if (!pe.prepareForProtoValue(propdef->pn_pos.begin)) {
9688 // [stack] OBJ
9689 return false;
9690 }
9691 if (!emitTree(propdef->as<UnaryNode>().kid())) {
9692 // [stack] OBJ PROTO
9693 return false;
9694 }
9695 if (!pe.emitMutateProto()) {
9696 // [stack] OBJ
9697 return false;
9698 }
9699 continue;
9700 }
9701
9702 if (propdef->isKind(ParseNodeKind::Spread)) {
9703 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", 9703);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == ObjectLiteral"
")"); do { MOZ_CrashSequence(__null, 9703); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9704 // [stack] OBJ
9705 if (!pe.prepareForSpreadOperand(propdef->pn_pos.begin)) {
9706 // [stack] OBJ OBJ
9707 return false;
9708 }
9709 if (!emitTree(propdef->as<UnaryNode>().kid())) {
9710 // [stack] OBJ OBJ VAL
9711 return false;
9712 }
9713 if (!pe.emitSpread()) {
9714 // [stack] OBJ
9715 return false;
9716 }
9717 continue;
9718 }
9719
9720 BinaryNode* prop = &propdef->as<BinaryNode>();
9721
9722 ParseNode* key = prop->left();
9723 AccessorType accessorType;
9724 if (prop->is<ClassMethod>()) {
9725 ClassMethod& method = prop->as<ClassMethod>();
9726 accessorType = method.accessorType();
9727
9728 if (!method.isStatic() && key->isKind(ParseNodeKind::PrivateName) &&
9729 accessorType != AccessorType::None) {
9730 // Private non-static accessors are stamped onto instances from
9731 // initializers; see emitCreateMemberInitializers.
9732 continue;
9733 }
9734 } else if (prop->is<PropertyDefinition>()) {
9735 accessorType = prop->as<PropertyDefinition>().accessorType();
9736 } else {
9737 accessorType = AccessorType::None;
9738 }
9739
9740 auto emitValue = [this, &key, &prop, accessorType, &pe]() {
9741 // [stack] CTOR? OBJ CTOR? KEY?
9742
9743 ParseNode* propVal = prop->right();
9744 if (propVal->isDirectRHSAnonFunction()) {
9745 // The following branches except for the last `else` clause emit the
9746 // cases handled in NameResolver::resolveFun (see NameFunctions.cpp)
9747 if (key->isKind(ParseNodeKind::ObjectPropertyName) ||
9748 key->isKind(ParseNodeKind::PrivateName) ||
9749 key->isKind(ParseNodeKind::StringExpr)) {
9750 auto keyAtom = key->as<NameNode>().atom();
9751 if (!emitAnonymousFunctionWithName(propVal, keyAtom)) {
9752 // [stack] CTOR? OBJ CTOR? VAL
9753 return false;
9754 }
9755 } else if (key->isKind(ParseNodeKind::NumberExpr)) {
9756 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"
, 9756); AnnotateMozCrashReason("MOZ_ASSERT" "(" "accessorType == AccessorType::None"
")"); do { MOZ_CrashSequence(__null, 9756); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9757
9758 auto keyAtom = key->as<NumericLiteral>().toAtom(fc, parserAtoms());
9759 if (!keyAtom) {
9760 return false;
9761 }
9762 if (!emitAnonymousFunctionWithName(propVal, keyAtom)) {
9763 // [stack] CTOR? OBJ CTOR? KEY VAL
9764 return false;
9765 }
9766 } else if (key->isKind(ParseNodeKind::ComputedName) &&
9767 (key->as<UnaryNode>().kid()->isKind(
9768 ParseNodeKind::NumberExpr) ||
9769 key->as<UnaryNode>().kid()->isKind(
9770 ParseNodeKind::StringExpr)) &&
9771 accessorType == AccessorType::None) {
9772 ParseNode* keyKid = key->as<UnaryNode>().kid();
9773 if (keyKid->isKind(ParseNodeKind::NumberExpr)) {
9774 auto keyAtom =
9775 keyKid->as<NumericLiteral>().toAtom(fc, parserAtoms());
9776 if (!keyAtom) {
9777 return false;
9778 }
9779 if (!emitAnonymousFunctionWithName(propVal, keyAtom)) {
9780 // [stack] CTOR? OBJ CTOR? KEY VAL
9781 return false;
9782 }
9783 } else {
9784 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", 9784);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "keyKid->isKind(ParseNodeKind::StringExpr)"
")"); do { MOZ_CrashSequence(__null, 9784); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9785 auto keyAtom = keyKid->as<NameNode>().atom();
9786 if (!emitAnonymousFunctionWithName(propVal, keyAtom)) {
9787 // [stack] CTOR? OBJ CTOR? KEY VAL
9788 return false;
9789 }
9790 }
9791 } else {
9792 // Either a proper computed property name or a synthetic computed
9793 // property name for BigInt keys.
9794 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", 9794);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::ComputedName)"
")"); do { MOZ_CrashSequence(__null, 9794); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9795
9796 FunctionPrefixKind prefix =
9797 accessorType == AccessorType::None ? FunctionPrefixKind::None
9798 : accessorType == AccessorType::Getter ? FunctionPrefixKind::Get
9799 : FunctionPrefixKind::Set;
9800
9801 if (!emitAnonymousFunctionWithComputedName(propVal, prefix)) {
9802 // [stack] CTOR? OBJ CTOR? KEY VAL
9803 return false;
9804 }
9805 }
9806 } else {
9807 if (!emitTree(propVal)) {
9808 // [stack] CTOR? OBJ CTOR? KEY? VAL
9809 return false;
9810 }
9811 }
9812
9813 if (propVal->is<FunctionNode>() &&
9814 propVal->as<FunctionNode>().funbox()->needsHomeObject()) {
9815 if (!pe.emitInitHomeObject()) {
9816 // [stack] CTOR? OBJ CTOR? KEY? FUN
9817 return false;
9818 }
9819 }
9820
9821#ifdef ENABLE_DECORATORS
9822 if (prop->is<ClassMethod>()) {
9823 ClassMethod& method = prop->as<ClassMethod>();
9824 if (method.decorators() && !method.decorators()->empty()) {
9825 DecoratorEmitter::Kind kind;
9826 switch (method.accessorType()) {
9827 case AccessorType::Getter:
9828 kind = DecoratorEmitter::Getter;
9829 break;
9830 case AccessorType::Setter:
9831 kind = DecoratorEmitter::Setter;
9832 break;
9833 case AccessorType::None:
9834 kind = DecoratorEmitter::Method;
9835 break;
9836 }
9837
9838 if (!method.isStatic()) {
9839 bool hasKeyOnStack = key->isKind(ParseNodeKind::NumberExpr) ||
9840 key->isKind(ParseNodeKind::ComputedName);
9841 if (!emitDupAt(hasKeyOnStack ? 4 : 3)) {
9842 // [stack] ADDINIT OBJ KEY? VAL ADDINIT
9843 return false;
9844 }
9845 } else {
9846 // TODO: See bug 1868220 for support for static methods.
9847 // Note: Key will be present if this has a private name.
9848 if (!emit1(JSOp::Undefined)) {
9849 // [stack] CTOR OBJ CTOR KEY? VAL ADDINIT
9850 return false;
9851 }
9852 }
9853
9854 if (!emit1(JSOp::Swap)) {
9855 // [stack] ADDINIT CTOR? OBJ CTOR? KEY? ADDINIT VAL
9856 return false;
9857 }
9858
9859 // The decorators are applied to the current value on the stack,
9860 // possibly replacing it.
9861 DecoratorEmitter de(this);
9862 if (!de.emitApplyDecoratorsToElementDefinition(
9863 kind, key, method.decorators(), method.isStatic())) {
9864 // [stack] ADDINIT CTOR? OBJ CTOR? KEY? ADDINIT VAL
9865 return false;
9866 }
9867
9868 if (!emit1(JSOp::Swap)) {
9869 // [stack] ADDINIT CTOR? OBJ CTOR? KEY? VAL ADDINIT
9870 return false;
9871 }
9872
9873 if (!emitPopN(1)) {
9874 // [stack] ADDINIT CTOR? OBJ CTOR? KEY? VAL
9875 return false;
9876 }
9877 }
9878 }
9879#endif
9880
9881 return true;
9882 };
9883
9884 PropertyEmitter::Kind kind =
9885 (type == ClassBody && propdef->as<ClassMethod>().isStatic())
9886 ? PropertyEmitter::Kind::Static
9887 : PropertyEmitter::Kind::Prototype;
9888 if (key->isKind(ParseNodeKind::ObjectPropertyName) ||
9889 key->isKind(ParseNodeKind::StringExpr)) {
9890 // [stack] CTOR? OBJ
9891
9892 auto keyAtom = key->as<NameNode>().atom();
9893
9894 // emitClass took care of constructor already.
9895 if (type == ClassBody &&
9896 keyAtom == TaggedParserAtomIndex::WellKnown::constructor() &&
9897 !propdef->as<ClassMethod>().isStatic()) {
9898 continue;
9899 }
9900
9901 if (!pe.prepareForPropValue(propdef->pn_pos.begin, kind)) {
9902 // [stack] CTOR? OBJ CTOR?
9903 return false;
9904 }
9905
9906 if (!emitValue()) {
9907 // [stack] CTOR? OBJ CTOR? VAL
9908 return false;
9909 }
9910
9911 if (!pe.emitInit(accessorType, keyAtom)) {
9912 // [stack] CTOR? OBJ
9913 return false;
9914 }
9915
9916 continue;
9917 }
9918
9919 if (key->isKind(ParseNodeKind::NumberExpr)) {
9920 // [stack] CTOR? OBJ
9921 if (!pe.prepareForIndexPropKey(propdef->pn_pos.begin, kind)) {
9922 // [stack] CTOR? OBJ CTOR?
9923 return false;
9924 }
9925 if (!emitNumberOp(key->as<NumericLiteral>().value())) {
9926 // [stack] CTOR? OBJ CTOR? KEY
9927 return false;
9928 }
9929 if (!pe.prepareForIndexPropValue()) {
9930 // [stack] CTOR? OBJ CTOR? KEY
9931 return false;
9932 }
9933 if (!emitValue()) {
9934 // [stack] CTOR? OBJ CTOR? KEY VAL
9935 return false;
9936 }
9937
9938 if (!pe.emitInitIndexOrComputed(accessorType)) {
9939 // [stack] CTOR? OBJ
9940 return false;
9941 }
9942
9943 continue;
9944 }
9945
9946 if (key->isKind(ParseNodeKind::ComputedName)) {
9947 // Either a proper computed property name or a synthetic computed property
9948 // name for BigInt keys.
9949
9950 // [stack] CTOR? OBJ
9951
9952 if (!pe.prepareForComputedPropKey(propdef->pn_pos.begin, kind)) {
9953 // [stack] CTOR? OBJ CTOR?
9954 return false;
9955 }
9956 if (!emitTree(key->as<UnaryNode>().kid())) {
9957 // [stack] CTOR? OBJ CTOR? KEY
9958 return false;
9959 }
9960 if (!pe.prepareForComputedPropValue()) {
9961 // [stack] CTOR? OBJ CTOR? KEY
9962 return false;
9963 }
9964 if (!emitValue()) {
9965 // [stack] CTOR? OBJ CTOR? KEY VAL
9966 return false;
9967 }
9968
9969 if (!pe.emitInitIndexOrComputed(accessorType)) {
9970 // [stack] CTOR? OBJ
9971 return false;
9972 }
9973
9974 continue;
9975 }
9976
9977 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", 9977);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::PrivateName)"
")"); do { MOZ_CrashSequence(__null, 9977); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9978 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", 9978);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == ClassBody" ")"
); do { MOZ_CrashSequence(__null, 9978); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9979
9980 auto* privateName = &key->as<NameNode>();
9981
9982 if (kind == PropertyEmitter::Kind::Prototype) {
9983 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"
, 9983); AnnotateMozCrashReason("MOZ_ASSERT" "(" "accessorType == AccessorType::None"
")"); do { MOZ_CrashSequence(__null, 9983); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9984 if (!pe.prepareForPrivateMethod()) {
9985 // [stack] CTOR OBJ
9986 return false;
9987 }
9988 NameOpEmitter noe(this, privateName->atom(),
9989 NameOpEmitter::Kind::SimpleAssignment);
9990
9991 // Ensure the NameOp emitter doesn't push an environment onto the stack,
9992 // because that would change the stack location of the home object.
9993 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", 9994);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "noe.loc().kind() == NameLocation::Kind::FrameSlot || noe.loc().kind() == NameLocation::Kind::EnvironmentCoordinate"
")"); do { MOZ_CrashSequence(__null, 9994); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9994 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", 9994);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "noe.loc().kind() == NameLocation::Kind::FrameSlot || noe.loc().kind() == NameLocation::Kind::EnvironmentCoordinate"
")"); do { MOZ_CrashSequence(__null, 9994); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9995
9996 if (!noe.prepareForRhs()) {
9997 // [stack] CTOR OBJ
9998 return false;
9999 }
10000 if (!emitValue()) {
10001 // [stack] CTOR OBJ METHOD
10002 return false;
10003 }
10004 if (!noe.emitAssignment()) {
10005 // [stack] CTOR OBJ METHOD
10006 return false;
10007 }
10008 if (!emit1(JSOp::Pop)) {
10009 // [stack] CTOR OBJ
10010 return false;
10011 }
10012 if (!pe.skipInit()) {
10013 // [stack] CTOR OBJ
10014 return false;
10015 }
10016 continue;
10017 }
10018
10019 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", 10019)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "kind == PropertyEmitter::Kind::Static"
")"); do { MOZ_CrashSequence(__null, 10019); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10020
10021 // [stack] CTOR OBJ
10022
10023 if (!pe.prepareForPrivateStaticMethod(propdef->pn_pos.begin)) {
10024 // [stack] CTOR OBJ CTOR
10025 return false;
10026 }
10027 if (!emitGetPrivateName(privateName)) {
10028 // [stack] CTOR OBJ CTOR KEY
10029 return false;
10030 }
10031 if (!emitValue()) {
10032 // [stack] CTOR OBJ CTOR KEY VAL
10033 return false;
10034 }
10035
10036 if (!pe.emitPrivateStaticMethod(accessorType)) {
10037 // [stack] CTOR OBJ
10038 return false;
10039 }
10040
10041 if (privateName->privateNameKind() == PrivateNameKind::Setter) {
10042 if (!emitDupAt(1)) {
10043 // [stack] CTOR OBJ CTOR
10044 return false;
10045 }
10046 if (!emitGetPrivateName(privateName)) {
10047 // [stack] CTOR OBJ CTOR NAME
10048 return false;
10049 }
10050 if (!emitAtomOp(JSOp::GetIntrinsic,
10051 TaggedParserAtomIndex::WellKnown::NoPrivateGetter())) {
10052 // [stack] CTOR OBJ CTOR NAME FUN
10053 return false;
10054 }
10055 if (!emit1(JSOp::InitHiddenElemGetter)) {
10056 // [stack] CTOR OBJ CTOR
10057 return false;
10058 }
10059 if (!emit1(JSOp::Pop)) {
10060 // [stack] CTOR OBJ
10061 return false;
10062 }
10063 }
10064 }
10065
10066 return true;
10067}
10068
10069bool BytecodeEmitter::emitPropertyListObjLiteral(ListNode* obj, JSOp op,
10070 bool useObjLiteralValues) {
10071 ObjLiteralWriter writer;
10072
10073#ifdef DEBUG1
10074 // In self-hosted JS, we check duplication only on debug build.
10075 mozilla::Maybe<mozilla::HashSet<frontend::TaggedParserAtomIndex,
10076 frontend::TaggedParserAtomIndexHasher>>
10077 selfHostedPropNames;
10078 if (emitterMode == BytecodeEmitter::SelfHosting) {
10079 selfHostedPropNames.emplace();
10080 }
10081#endif
10082
10083 if (op == JSOp::Object) {
10084 writer.beginObject(op);
10085 } else {
10086 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", 10086)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::NewObject"
")"); do { MOZ_CrashSequence(__null, 10086); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10087 writer.beginShape(op);
10088 }
10089
10090 for (ParseNode* propdef : obj->contents()) {
10091 BinaryNode* prop = &propdef->as<BinaryNode>();
10092 ParseNode* key = prop->left();
10093
10094 if (key->is<NameNode>()) {
10095 if (emitterMode == BytecodeEmitter::SelfHosting) {
10096 auto propName = key->as<NameNode>().atom();
10097#ifdef DEBUG1
10098 // Self-hosted JS shouldn't contain duplicate properties.
10099 auto p = selfHostedPropNames->lookupForAdd(propName);
10100 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"
, 10100); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!p" ")"); do
{ MOZ_CrashSequence(__null, 10100); __attribute__((nomerge))
::abort(); } while (false); } } while (false)
;
10101 if (!selfHostedPropNames->add(p, propName)) {
10102 js::ReportOutOfMemory(fc);
10103 return false;
10104 }
10105#endif
10106 writer.setPropNameNoDuplicateCheck(parserAtoms(), propName);
10107 } else {
10108 if (!writer.setPropName(parserAtoms(), key->as<NameNode>().atom())) {
10109 return false;
10110 }
10111 }
10112 } else {
10113 double numValue = key->as<NumericLiteral>().value();
10114 int32_t i = 0;
10115 DebugOnly<bool> numIsInt =
10116 NumberIsInt32(numValue, &i); // checked previously.
10117 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"
, 10117); AnnotateMozCrashReason("MOZ_ASSERT" "(" "numIsInt" ")"
); do { MOZ_CrashSequence(__null, 10117); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10118 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", 10119)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "ObjLiteralWriter::arrayIndexInRange(i)"
")"); do { MOZ_CrashSequence(__null, 10119); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10119 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", 10119)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "ObjLiteralWriter::arrayIndexInRange(i)"
")"); do { MOZ_CrashSequence(__null, 10119); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
; // checked previously.
10120
10121 // Ignore indexed properties if we're not storing property values, and
10122 // rely on InitElem ops to define those. These properties will be either
10123 // dense elements (not possible to represent in the literal's shape) or
10124 // sparse elements (enumerated separately, so this doesn't affect property
10125 // iteration order).
10126 if (!useObjLiteralValues) {
10127 continue;
10128 }
10129
10130 writer.setPropIndex(i);
10131 }
10132
10133 if (useObjLiteralValues) {
10134 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", 10134)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::Object"
")"); do { MOZ_CrashSequence(__null, 10134); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10135 ParseNode* value = prop->right();
10136 if (!emitObjLiteralValue(writer, value)) {
10137 return false;
10138 }
10139 } else {
10140 if (!writer.propWithUndefinedValue(fc)) {
10141 return false;
10142 }
10143 }
10144 }
10145
10146 GCThingIndex index;
10147 if (!addObjLiteralData(writer, &index)) {
10148 return false;
10149 }
10150
10151 // JSOp::Object may only be used by (top-level) run-once scripts.
10152 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", 10153)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isTopLevelContext() && sc->treatAsRunOnce()"
")"); do { MOZ_CrashSequence(__null, 10153); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
10153 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", 10153)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isTopLevelContext() && sc->treatAsRunOnce()"
")"); do { MOZ_CrashSequence(__null, 10153); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
10154
10155 if (!emitGCIndexOp(op, index)) {
10156 // [stack] OBJ
10157 return false;
10158 }
10159
10160 return true;
10161}
10162
10163bool BytecodeEmitter::emitDestructuringRestExclusionSetObjLiteral(
10164 ListNode* pattern) {
10165 // Note: if we want to squeeze out a little more performance, we could switch
10166 // to the `JSOp::Object` opcode, because the exclusion set object is never
10167 // exposed to the user, so it's safe to bake the object into the bytecode.
10168 constexpr JSOp op = JSOp::NewObject;
10169
10170 ObjLiteralWriter writer;
10171 writer.beginShape(op);
10172
10173 for (ParseNode* member : pattern->contents()) {
10174 if (member->isKind(ParseNodeKind::Spread)) {
10175 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"
, 10175); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!member->pn_next"
") (" "unexpected trailing element after spread" ")"); do { MOZ_CrashSequence
(__null, 10175); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10176 break;
10177 }
10178
10179 TaggedParserAtomIndex atom;
10180 if (member->isKind(ParseNodeKind::MutateProto)) {
10181 atom = TaggedParserAtomIndex::WellKnown::proto_();
10182 } else {
10183 ParseNode* key = member->as<BinaryNode>().left();
10184 atom = key->as<NameNode>().atom();
10185 }
10186
10187 if (!writer.setPropName(parserAtoms(), atom)) {
10188 return false;
10189 }
10190
10191 if (!writer.propWithUndefinedValue(fc)) {
10192 return false;
10193 }
10194 }
10195
10196 GCThingIndex index;
10197 if (!addObjLiteralData(writer, &index)) {
10198 return false;
10199 }
10200
10201 if (!emitGCIndexOp(op, index)) {
10202 // [stack] OBJ
10203 return false;
10204 }
10205
10206 return true;
10207}
10208
10209bool BytecodeEmitter::emitObjLiteralArray(ListNode* array) {
10210 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", 10210)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "checkSingletonContext()"
")"); do { MOZ_CrashSequence(__null, 10210); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10211
10212 constexpr JSOp op = JSOp::Object;
10213
10214 ObjLiteralWriter writer;
10215 writer.beginArray(op);
10216
10217 writer.beginDenseArrayElements();
10218 for (ParseNode* elem : array->contents()) {
10219 if (!emitObjLiteralValue(writer, elem)) {
10220 return false;
10221 }
10222 }
10223
10224 GCThingIndex index;
10225 if (!addObjLiteralData(writer, &index)) {
10226 return false;
10227 }
10228
10229 if (!emitGCIndexOp(op, index)) {
10230 // [stack] OBJ
10231 return false;
10232 }
10233
10234 return true;
10235}
10236
10237bool BytecodeEmitter::isRHSObjLiteralCompatible(ParseNode* value) const {
10238 return value->isKind(ParseNodeKind::NumberExpr) ||
10239 value->isKind(ParseNodeKind::TrueExpr) ||
10240 value->isKind(ParseNodeKind::FalseExpr) ||
10241 value->isKind(ParseNodeKind::NullExpr) ||
10242 value->isKind(ParseNodeKind::RawUndefinedExpr) ||
10243 value->isKind(ParseNodeKind::StringExpr) ||
10244 value->isKind(ParseNodeKind::TemplateStringExpr);
10245}
10246
10247bool BytecodeEmitter::emitObjLiteralValue(ObjLiteralWriter& writer,
10248 ParseNode* value) {
10249 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"
, 10249); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isRHSObjLiteralCompatible(value)"
")"); do { MOZ_CrashSequence(__null, 10249); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10250 if (value->isKind(ParseNodeKind::NumberExpr)) {
10251 double numValue = value->as<NumericLiteral>().value();
10252 int32_t i = 0;
10253 js::Value v;
10254 if (NumberIsInt32(numValue, &i)) {
10255 v.setInt32(i);
10256 } else {
10257 v.setDouble(numValue);
10258 }
10259 if (!writer.propWithConstNumericValue(fc, v)) {
10260 return false;
10261 }
10262 } else if (value->isKind(ParseNodeKind::TrueExpr)) {
10263 if (!writer.propWithTrueValue(fc)) {
10264 return false;
10265 }
10266 } else if (value->isKind(ParseNodeKind::FalseExpr)) {
10267 if (!writer.propWithFalseValue(fc)) {
10268 return false;
10269 }
10270 } else if (value->isKind(ParseNodeKind::NullExpr)) {
10271 if (!writer.propWithNullValue(fc)) {
10272 return false;
10273 }
10274 } else if (value->isKind(ParseNodeKind::RawUndefinedExpr)) {
10275 if (!writer.propWithUndefinedValue(fc)) {
10276 return false;
10277 }
10278 } else if (value->isKind(ParseNodeKind::StringExpr) ||
10279 value->isKind(ParseNodeKind::TemplateStringExpr)) {
10280 if (!writer.propWithAtomValue(fc, parserAtoms(),
10281 value->as<NameNode>().atom())) {
10282 return false;
10283 }
10284 } else {
10285 MOZ_CRASH("Unexpected parse node")do { do { } while (false); MOZ_ReportCrash("" "Unexpected parse node"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 10285)
; AnnotateMozCrashReason("MOZ_CRASH(" "Unexpected parse node"
")"); do { MOZ_CrashSequence(__null, 10285); __attribute__((
nomerge)) ::abort(); } while (false); } while (false)
;
10286 }
10287 return true;
10288}
10289
10290static bool NeedsPrivateBrand(ParseNode* member) {
10291 return member->is<ClassMethod>() &&
10292 member->as<ClassMethod>().name().isKind(ParseNodeKind::PrivateName) &&
10293 !member->as<ClassMethod>().isStatic();
10294}
10295
10296#ifdef ENABLE_DECORATORS
10297static bool HasDecorators(ParseNode* member) {
10298 return member->is<ClassMethod>() && member->as<ClassMethod>().decorators();
10299}
10300#endif
10301
10302mozilla::Maybe<MemberInitializers> BytecodeEmitter::setupMemberInitializers(
10303 ListNode* classMembers, FieldPlacement placement) const {
10304 bool isStatic = placement == FieldPlacement::Static;
10305
10306 size_t numFields = 0;
10307 size_t numPrivateInitializers = 0;
10308 bool hasPrivateBrand = false;
10309#ifdef ENABLE_DECORATORS
10310 bool hasDecorators = false;
10311#endif
10312 for (ParseNode* member : classMembers->contents()) {
10313 if (NeedsFieldInitializer(member, isStatic)) {
10314 numFields++;
10315 } else if (NeedsAccessorInitializer(member, isStatic)) {
10316 numPrivateInitializers++;
10317 hasPrivateBrand = true;
10318 } else if (NeedsPrivateBrand(member)) {
10319 hasPrivateBrand = true;
10320 }
10321#ifdef ENABLE_DECORATORS
10322 if (!hasDecorators && HasDecorators(member)) {
10323 hasDecorators = true;
10324 }
10325#endif
10326 }
10327
10328 // If there are more initializers than can be represented, return invalid.
10329 if (numFields + numPrivateInitializers >
10330 MemberInitializers::MaxInitializers) {
10331 return Nothing();
10332 }
10333 return Some(MemberInitializers(hasPrivateBrand,
10334#ifdef ENABLE_DECORATORS
10335 hasDecorators,
10336#endif
10337 numFields + numPrivateInitializers));
10338}
10339
10340// Purpose of .fieldKeys:
10341// Computed field names (`["x"] = 2;`) must be ran at class-evaluation time,
10342// not object construction time. The transformation to do so is roughly as
10343// follows:
10344//
10345// class C {
10346// [keyExpr] = valueExpr;
10347// }
10348// -->
10349// let .fieldKeys = [keyExpr];
10350// let .initializers = [
10351// () => {
10352// this[.fieldKeys[0]] = valueExpr;
10353// }
10354// ];
10355// class C {
10356// constructor() {
10357// .initializers[0]();
10358// }
10359// }
10360//
10361// BytecodeEmitter::emitCreateFieldKeys does `let .fieldKeys = [...];`
10362// BytecodeEmitter::emitPropertyList fills in the elements of the array.
10363// See GeneralParser::fieldInitializer for the `this[.fieldKeys[0]]` part.
10364bool BytecodeEmitter::emitCreateFieldKeys(ListNode* obj,
10365 FieldPlacement placement) {
10366 bool isStatic = placement == FieldPlacement::Static;
10367 auto isFieldWithComputedName = [isStatic](ParseNode* propdef) {
10368 return propdef->is<ClassField>() &&
10369 propdef->as<ClassField>().isStatic() == isStatic &&
10370 propdef->as<ClassField>().name().getKind() ==
10371 ParseNodeKind::ComputedName;
10372 };
10373
10374 size_t numFieldKeys = std::count_if(
10375 obj->contents().begin(), obj->contents().end(), isFieldWithComputedName);
10376 if (numFieldKeys == 0) {
10377 return true;
10378 }
10379
10380 auto fieldKeys =
10381 isStatic ? TaggedParserAtomIndex::WellKnown::dot_staticFieldKeys_()
10382 : TaggedParserAtomIndex::WellKnown::dot_fieldKeys_();
10383 NameOpEmitter noe(this, fieldKeys, NameOpEmitter::Kind::Initialize);
10384 if (!noe.prepareForRhs()) {
10385 return false;
10386 }
10387
10388 if (!emitUint32Operand(JSOp::NewArray, numFieldKeys)) {
10389 // [stack] ARRAY
10390 return false;
10391 }
10392
10393 if (!noe.emitAssignment()) {
10394 // [stack] ARRAY
10395 return false;
10396 }
10397
10398 if (!emit1(JSOp::Pop)) {
10399 // [stack]
10400 return false;
10401 }
10402
10403 return true;
10404}
10405
10406static bool HasInitializer(ParseNode* node, bool isStaticContext) {
10407 return (node->is<ClassField>() &&
10408 node->as<ClassField>().isStatic() == isStaticContext) ||
10409 (isStaticContext && node->is<StaticClassBlock>());
10410}
10411
10412static FunctionNode* GetInitializer(ParseNode* node, bool isStaticContext) {
10413 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", 10413)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "HasInitializer(node, isStaticContext)"
")"); do { MOZ_CrashSequence(__null, 10413); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10414 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"
, 10414); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isStaticContext"
")"); do { MOZ_CrashSequence(__null, 10414); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
10415 return node->is<ClassField>() ? node->as<ClassField>().initializer()
10416 : node->as<StaticClassBlock>().function();
10417}
10418
10419static bool IsPrivateInstanceAccessor(const ClassMethod* classMethod) {
10420 return !classMethod->isStatic() &&
10421 classMethod->name().isKind(ParseNodeKind::PrivateName) &&
10422 classMethod->accessorType() != AccessorType::None;
10423}
10424
10425bool BytecodeEmitter::emitCreateMemberInitializers(ClassEmitter& ce,
10426 ListNode* obj,
10427 FieldPlacement placement
10428#ifdef ENABLE_DECORATORS
10429 ,
10430 bool hasHeritage
10431#endif
10432) {
10433 // FieldPlacement::Instance, hasHeritage == false
10434 // [stack] HOME
10435 //
10436 // FieldPlacement::Instance, hasHeritage == true
10437 // [stack] HOME HERIT
10438 //
10439 // FieldPlacement::Static
10440 // [stack] CTOR HOME
10441#ifdef ENABLE_DECORATORS
10442 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"
, 10442); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!hasHeritage"
")"); do { MOZ_CrashSequence(__null, 10442); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
10443#endif
10444 mozilla::Maybe<MemberInitializers> memberInitializers =
10445 setupMemberInitializers(obj, placement);
10446 if (!memberInitializers) {
10447 ReportAllocationOverflow(fc);
10448 return false;
10449 }
10450
10451 size_t numInitializers = memberInitializers->numMemberInitializers;
10452 if (numInitializers == 0) {
10453 return true;
10454 }
10455
10456 bool isStatic = placement == FieldPlacement::Static;
10457 if (!ce.prepareForMemberInitializers(numInitializers, isStatic)) {
10458 // [stack] HOME HERIT? ARR
10459 // or:
10460 // [stack] CTOR HOME ARR
10461 return false;
10462 }
10463
10464 // Private accessors could be used in the field initializers, so make sure
10465 // accessor initializers appear earlier in the .initializers array so they
10466 // run first. Static private methods are not initialized using initializers
10467 // (emitPropertyList emits bytecode to stamp them onto the constructor), so
10468 // skip this step if isStatic.
10469 if (!isStatic) {
10470 if (!emitPrivateMethodInitializers(ce, obj)) {
10471 return false;
10472 }
10473 }
10474
10475 for (ParseNode* propdef : obj->contents()) {
10476 if (!HasInitializer(propdef, isStatic)) {
10477 continue;
10478 }
10479
10480 FunctionNode* initializer = GetInitializer(propdef, isStatic);
10481
10482 if (!ce.prepareForMemberInitializer()) {
10483 return false;
10484 }
10485 if (!emitTree(initializer)) {
10486 // [stack] HOME HERIT? ARR LAMBDA
10487 // or:
10488 // [stack] CTOR HOME ARR LAMBDA
10489 return false;
10490 }
10491 if (initializer->funbox()->needsHomeObject()) {
10492 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", 10492)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "initializer->funbox()->allowSuperProperty()"
")"); do { MOZ_CrashSequence(__null, 10492); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10493 if (!ce.emitMemberInitializerHomeObject(isStatic)) {
10494 // [stack] HOME HERIT? ARR LAMBDA
10495 // or:
10496 // [stack] CTOR HOME ARR LAMBDA
10497 return false;
10498 }
10499 }
10500 if (!ce.emitStoreMemberInitializer()) {
10501 // [stack] HOME HERIT? ARR
10502 // or:
10503 // [stack] CTOR HOME ARR
10504 return false;
10505 }
10506 }
10507
10508#ifdef ENABLE_DECORATORS
10509 // Index to use to append new initializers returned by decorators to the array
10510 if (!emitNumberOp(numInitializers)) {
10511 // [stack] HOME HERIT? ARR I
10512 // or:
10513 // [stack] CTOR HOME ARR I
10514 return false;
10515 }
10516
10517 for (ParseNode* propdef : obj->contents()) {
10518 if (!propdef->is<ClassField>()) {
10519 continue;
10520 }
10521 ClassField* field = &propdef->as<ClassField>();
10522 if (field->isStatic() != isStatic) {
10523 continue;
10524 }
10525 if (field->decorators() && !field->decorators()->empty()) {
10526 DecoratorEmitter de(this);
10527 if (!field->hasAccessor()) {
10528 if (!emitDupAt((hasHeritage || isStatic) ? 4 : 3)) {
10529 // [stack] ADDINIT HOME HERIT? ARR I ADDINIT
10530 // or:
10531 // [stack] ADDINIT CTOR HOME ARR I ADDINIT
10532 return false;
10533 }
10534 if (!de.emitApplyDecoratorsToFieldDefinition(
10535 &field->name(), field->decorators(), field->isStatic())) {
10536 // [stack] HOME HERIT? ARR I ADDINIT INITS
10537 // or:
10538 // [stack] CTOR HOME ARR I ADDINIT INITS
10539 return false;
10540 }
10541 if (!emit1(JSOp::Swap)) {
10542 // [stack] HOME HERIT? ARR I INITS ADDINIT
10543 // or:
10544 // [stack] CTOR HOME ARR I INITS ADDINIT
10545 return false;
10546 }
10547 if (!emitPopN(1)) {
10548 // [stack] ADDINIT HOME HERIT? ARR I INITS
10549 // or:
10550 // [stack] ADDINIT CTOR HOME ARR I INITS
10551 return false;
10552 }
10553 } else {
10554 ClassMethod* accessorGetterNode = field->accessorGetterNode();
10555 auto accessorGetterKeyAtom =
10556 accessorGetterNode->left()->as<NameNode>().atom();
10557 ClassMethod* accessorSetterNode = field->accessorSetterNode();
10558 auto accessorSetterKeyAtom =
10559 accessorSetterNode->left()->as<NameNode>().atom();
10560 if (!IsPrivateInstanceAccessor(accessorGetterNode)) {
10561 if (!emitTree(&accessorGetterNode->method())) {
10562 // [stack] ADDINIT HOME HERIT? ARR I GET
10563 // or:
10564 // [stack] ADDINIT CTOR HOME ARR I GET
10565 return false;
10566 }
10567 if (!emitTree(&accessorSetterNode->method())) {
10568 // [stack] ADDINIT HOME HERIT? ARR I GET
10569 // SET
10570 // or:
10571 // [stack] ADDINIT CTOR HOME ARR I GET SET
10572 return false;
10573 }
10574 } else {
10575 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", 10575)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsPrivateInstanceAccessor(accessorSetterNode)"
")"); do { MOZ_CrashSequence(__null, 10575); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10576 auto getAccessor = [this](
10577 ClassMethod* classMethod,
10578 TaggedParserAtomIndex& updatedAtom) -> bool {
10579 // [stack]
10580
10581 // Synthesize a name for the lexical variable that will store the
10582 // private method body.
10583 TaggedParserAtomIndex name =
10584 classMethod->name().as<NameNode>().atom();
10585 AccessorType accessorType = classMethod->accessorType();
10586 StringBuilder storedMethodName(fc);
10587 if (!storedMethodName.append(parserAtoms(), name)) {
10588 return false;
10589 }
10590 if (!storedMethodName.append(accessorType == AccessorType::Getter
10591 ? ".getter"
10592 : ".setter")) {
10593 return false;
10594 }
10595 updatedAtom = storedMethodName.finishParserAtom(parserAtoms(), fc);
10596 if (!updatedAtom) {
10597 return false;
10598 }
10599
10600 return emitGetName(updatedAtom);
10601 // [stack] ACCESSOR
10602 };
10603
10604 if (!getAccessor(accessorGetterNode, accessorGetterKeyAtom)) {
10605 // [stack] ADDINIT HOME HERIT? ARR I GET
10606 // or:
10607 // [stack] ADDINIT CTOR HOME ARR I GET
10608 return false;
10609 };
10610
10611 if (!getAccessor(accessorSetterNode, accessorSetterKeyAtom)) {
10612 // [stack] ADDINIT HOME HERIT? ARR I GET SET
10613 // or:
10614 // [stack] ADDINIT CTOR HOME ARR I GET SET
10615 return false;
10616 };
10617 }
10618
10619 if (!emitDupAt((hasHeritage || isStatic) ? 6 : 5)) {
10620 // [stack] ADDINIT HOME HERIT? ARR I GET SET ADDINIT
10621 // or:
10622 // [stack] ADDINIT CTOR HOME ARR I GET SET ADDINIT
10623 return false;
10624 }
10625
10626 if (!emitUnpickN(2)) {
10627 // [stack] ADDINIT HOME HERIT? ARR I ADDINIT GET SET
10628 // or:
10629 // [stack] ADDINIT CTOR HOME ARR I ADDINIT GET SET
10630 return false;
10631 }
10632
10633 if (!de.emitApplyDecoratorsToAccessorDefinition(
10634 &field->name(), field->decorators(), field->isStatic())) {
10635 // [stack] ADDINIT HOME HERIT? ARR I ADDINIT GET SET INITS
10636 // or:
10637 // [stack] ADDINIT CTOR HOME ARR I ADDINIT GET SET INITS
10638 return false;
10639 }
10640
10641 if (!emitPickN(3)) {
10642 // [stack] HOME HERIT? ARR I GET SET INITS ADDINIT
10643 // or:
10644 // [stack] CTOR HOME ARR I GET SET INITS ADDINIT
10645 return false;
10646 }
10647
10648 if (!emitPopN(1)) {
10649 // [stack] ADDINIT HOME HERIT? ARR I GET SET INITS
10650 // or:
10651 // [stack] ADDINIT CTOR HOME ARR I GET SET INITS
10652 return false;
10653 }
10654
10655 if (!emitUnpickN(2)) {
10656 // [stack] ADDINIT HOME HERIT? ARR I INITS GET SET
10657 // or:
10658 // [stack] ADDINIT CTOR HOME ARR I INITS GET SET
10659 return false;
10660 }
10661
10662 if (!IsPrivateInstanceAccessor(accessorGetterNode)) {
10663 if (!isStatic) {
10664 if (!emitDupAt(hasHeritage ? 6 : 5)) {
10665 // [stack] ADDINIT HOME HERIT? ARR I INITS GET SET HOME
10666 return false;
10667 }
10668 } else {
10669 if (!emitDupAt(6)) {
10670 // [stack] ADDINIT CTOR HOME ARR I INITS GET SET CTOR
10671 return false;
10672 }
10673 if (!emitDupAt(6)) {
10674 // [stack] ADDINIT CTOR HOME ARR I INITS GET SET CTOR HOME
10675 return false;
10676 }
10677 }
10678
10679 PropertyEmitter::Kind kind = field->isStatic()
10680 ? PropertyEmitter::Kind::Static
10681 : PropertyEmitter::Kind::Prototype;
10682 if (!accessorGetterNode->name().isKind(ParseNodeKind::PrivateName)) {
10683 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", 10684)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "!accessorSetterNode->name().isKind(ParseNodeKind::PrivateName)"
")"); do { MOZ_CrashSequence(__null, 10684); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10684 !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", 10684)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "!accessorSetterNode->name().isKind(ParseNodeKind::PrivateName)"
")"); do { MOZ_CrashSequence(__null, 10684); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10685
10686 if (!ce.prepareForPropValue(propdef->pn_pos.begin, kind)) {
10687 // [stack] ADDINIT HOME HERIT? ARR I INITS GET SET HOME
10688 // or:
10689 // [stack] ADDINIT CTOR HOME ARR I INITS GET SET CTOR HOME CTOR
10690 return false;
10691 }
10692 if (!emitPickN(isStatic ? 3 : 1)) {
10693 // [stack] ADDINIT HOME HERIT? ARR I INITS GET HOME SET
10694 // or:
10695 // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME CTOR SET
10696 return false;
10697 }
10698 if (!ce.emitInit(AccessorType::Setter, accessorSetterKeyAtom)) {
10699 // [stack] ADDINIT HOME HERIT? ARR I INITS GET HOME
10700 // or:
10701 // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME
10702 return false;
10703 }
10704
10705 if (!ce.prepareForPropValue(propdef->pn_pos.begin, kind)) {
10706 // [stack] ADDINIT HOME HERIT? ARR I INITS GET HOME
10707 // or:
10708 // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME CTOR
10709 return false;
10710 }
10711 if (!emitPickN(isStatic ? 3 : 1)) {
10712 // [stack] ADDINIT HOME HERIT? ARR I INITS HOME GET
10713 // or:
10714 // [stack] ADDINIT CTOR HOME ARR I INITS CTOR HOME CTOR GET
10715 return false;
10716 }
10717 if (!ce.emitInit(AccessorType::Getter, accessorGetterKeyAtom)) {
10718 // [stack] ADDINIT HOME HERIT? ARR I INITS HOME
10719 // or:
10720 // [stack] ADDINIT CTOR HOME ARR I INITS CTOR HOME
10721 return false;
10722 }
10723 } else {
10724 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"
, 10724); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isStatic" ")"
); do { MOZ_CrashSequence(__null, 10724); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10725 // The getter and setter share the same name.
10726 if (!emitNewPrivateName(accessorSetterKeyAtom,
10727 accessorSetterKeyAtom)) {
10728 return false;
10729 }
10730 if (!ce.prepareForPrivateStaticMethod(propdef->pn_pos.begin)) {
10731 // [stack] ADDINIT CTOR HOME ARR I INITS GET SET CTOR HOME CTOR
10732 return false;
10733 }
10734 if (!emitGetPrivateName(
10735 &accessorSetterNode->name().as<NameNode>())) {
10736 // [stack] ADDINIT CTOR HOME ARR I INITS GET SET CTOR HOME CTOR
10737 // KEY
10738 return false;
10739 }
10740 if (!emitPickN(4)) {
10741 // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME CTOR KEY
10742 // SET
10743 return false;
10744 }
10745 if (!ce.emitPrivateStaticMethod(AccessorType::Setter)) {
10746 // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME
10747 return false;
10748 }
10749
10750 if (!ce.prepareForPrivateStaticMethod(propdef->pn_pos.begin)) {
10751 // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME CTOR
10752 return false;
10753 }
10754 if (!emitGetPrivateName(
10755 &accessorGetterNode->name().as<NameNode>())) {
10756 // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME CTOR KEY
10757 return false;
10758 }
10759 if (!emitPickN(4)) {
10760 // [stack] ADDINIT CTOR HOME ARR I INITS CTOR HOME CTOR KEY GET
10761 return false;
10762 }
10763 if (!ce.emitPrivateStaticMethod(AccessorType::Getter)) {
10764 // [stack] ADDINIT CTOR HOME ARR I INITS CTOR HOME
10765 return false;
10766 }
10767 }
10768
10769 if (!isStatic) {
10770 if (!emitPopN(1)) {
10771 // [stack] ADDINIT HOME HERIT? ARR I INITS
10772 return false;
10773 }
10774 } else {
10775 if (!emitPopN(2)) {
10776 // [stack] ADDINIT CTOR HOME ARR I INITS
10777 return false;
10778 }
10779 }
10780 } else {
10781 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", 10781)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsPrivateInstanceAccessor(accessorSetterNode)"
")"); do { MOZ_CrashSequence(__null, 10781); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10782
10783 if (!emitLexicalInitialization(accessorSetterKeyAtom)) {
10784 // [stack] ADDINIT HOME HERIT? ARR I INITS GET SET
10785 // or:
10786 // [stack] ADDINIT CTOR HOME ARR I INITS GET SET
10787 return false;
10788 }
10789
10790 if (!emitPopN(1)) {
10791 // [stack] ADDINIT HOME HERIT? ARR I INITS GET
10792 // or:
10793 // [stack] ADDINIT CTOR HOME ARR I INITS GET
10794 return false;
10795 }
10796
10797 if (!emitLexicalInitialization(accessorGetterKeyAtom)) {
10798 // [stack] ADDINIT HOME HERIT? ARR I INITS GET
10799 // or:
10800 // [stack] ADDINIT CTOR HOME ARR I INITS GET
10801 return false;
10802 }
10803
10804 if (!emitPopN(1)) {
10805 // [stack] ADDINIT HOME HERIT? ARR I INITS
10806 // or:
10807 // [stack] ADDINIT CTOR HOME ARR I INITS
10808 return false;
10809 }
10810 }
10811 }
10812 if (!emit1(JSOp::InitElemInc)) {
10813 // [stack] ADDINIT HOME HERIT? ARR I
10814 // or:
10815 // [stack] ADDINIT CTOR HOME ARR I
10816 return false;
10817 }
10818 }
10819 }
10820
10821 // Pop I
10822 if (!emitPopN(1)) {
10823 // [stack] ADDINIT HOME HERIT? ARR
10824 // or:
10825 // [stack] ADDINIT CTOR HOME ARR
10826 return false;
10827 }
10828#endif
10829
10830 if (!ce.emitMemberInitializersEnd()) {
10831 // [stack] ADDINIT HOME HERIT?
10832 // or:
10833 // [stack] ADDINIT CTOR HOME
10834 return false;
10835 }
10836
10837 return true;
10838}
10839
10840bool BytecodeEmitter::emitPrivateMethodInitializers(ClassEmitter& ce,
10841 ListNode* obj) {
10842 for (ParseNode* propdef : obj->contents()) {
10843 if (!propdef->is<ClassMethod>()) {
10844 continue;
10845 }
10846 auto* classMethod = &propdef->as<ClassMethod>();
10847
10848 // Skip over anything which isn't a private instance accessor.
10849 if (!IsPrivateInstanceAccessor(classMethod)) {
10850 continue;
10851 }
10852
10853 if (!ce.prepareForMemberInitializer()) {
10854 // [stack] HOMEOBJ HERITAGE? ARRAY
10855 // or:
10856 // [stack] CTOR HOMEOBJ ARRAY
10857 return false;
10858 }
10859
10860 // Synthesize a name for the lexical variable that will store the
10861 // private method body.
10862 TaggedParserAtomIndex name = classMethod->name().as<NameNode>().atom();
10863 AccessorType accessorType = classMethod->accessorType();
10864 StringBuilder storedMethodName(fc);
10865 if (!storedMethodName.append(parserAtoms(), name)) {
10866 return false;
10867 }
10868 if (!storedMethodName.append(
10869 accessorType == AccessorType::Getter ? ".getter" : ".setter")) {
10870 return false;
10871 }
10872 auto storedMethodAtom =
10873 storedMethodName.finishParserAtom(parserAtoms(), fc);
10874
10875 // Emit the private method body and store it as a lexical var.
10876 if (!emitFunction(&classMethod->method())) {
10877 // [stack] HOMEOBJ HERITAGE? ARRAY METHOD
10878 // or:
10879 // [stack] CTOR HOMEOBJ ARRAY METHOD
10880 return false;
10881 }
10882 // The private method body needs to access the home object,
10883 // and the CE knows where that is on the stack.
10884 if (classMethod->method().funbox()->needsHomeObject()) {
10885 if (!ce.emitMemberInitializerHomeObject(false)) {
10886 // [stack] HOMEOBJ HERITAGE? ARRAY METHOD
10887 // or:
10888 // [stack] CTOR HOMEOBJ ARRAY METHOD
10889 return false;
10890 }
10891 }
10892 if (!emitLexicalInitialization(storedMethodAtom)) {
10893 // [stack] HOMEOBJ HERITAGE? ARRAY METHOD
10894 // or:
10895 // [stack] CTOR HOMEOBJ ARRAY METHOD
10896 return false;
10897 }
10898 if (!emit1(JSOp::Pop)) {
10899 // [stack] HOMEOBJ HERITAGE? ARRAY
10900 // or:
10901 // [stack] CTOR HOMEOBJ ARRAY
10902 return false;
10903 }
10904
10905 if (!emitPrivateMethodInitializer(classMethod, storedMethodAtom)) {
10906 // [stack] HOMEOBJ HERITAGE? ARRAY
10907 // or:
10908 // [stack] CTOR HOMEOBJ ARRAY
10909 return false;
10910 }
10911
10912 // Store the emitted initializer function into the .initializers array.
10913 if (!ce.emitStoreMemberInitializer()) {
10914 // [stack] HOMEOBJ HERITAGE? ARRAY
10915 // or:
10916 // [stack] CTOR HOMEOBJ ARRAY
10917 return false;
10918 }
10919 }
10920
10921 return true;
10922}
10923
10924bool BytecodeEmitter::emitPrivateMethodInitializer(
10925 ClassMethod* classMethod, TaggedParserAtomIndex storedMethodAtom) {
10926 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", 10926)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsPrivateInstanceAccessor(classMethod)"
")"); do { MOZ_CrashSequence(__null, 10926); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10927
10928 auto* name = &classMethod->name().as<NameNode>();
10929
10930 // Emit the synthesized initializer function.
10931 FunctionNode* funNode = classMethod->initializerIfPrivate();
10932 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"
, 10932); AnnotateMozCrashReason("MOZ_ASSERT" "(" "funNode" ")"
); do { MOZ_CrashSequence(__null, 10932); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10933 FunctionBox* funbox = funNode->funbox();
10934 FunctionEmitter fe(this, funbox, funNode->syntaxKind(),
10935 FunctionEmitter::IsHoisted::No);
10936 if (!fe.prepareForNonLazy()) {
10937 // [stack]
10938 return false;
10939 }
10940
10941 BytecodeEmitter bce2(this, funbox);
10942 if (!bce2.init(funNode->pn_pos)) {
10943 return false;
10944 }
10945 ParamsBodyNode* paramsBody = funNode->body();
10946 FunctionScriptEmitter fse(&bce2, funbox, Nothing(), Nothing());
10947 if (!fse.prepareForParameters()) {
10948 // [stack]
10949 return false;
10950 }
10951 if (!bce2.emitFunctionFormalParameters(paramsBody)) {
10952 // [stack]
10953 return false;
10954 }
10955 if (!fse.prepareForBody()) {
10956 // [stack]
10957 return false;
10958 }
10959
10960 if (!bce2.emit1(JSOp::FunctionThis)) {
10961 // [stack] THIS
10962 return false;
10963 }
10964 if (!bce2.emitGetPrivateName(name)) {
10965 // [stack] THIS NAME
10966 return false;
10967 }
10968 if (!bce2.emitGetName(storedMethodAtom)) {
10969 // [stack] THIS NAME METHOD
10970 return false;
10971 }
10972
10973 switch (name->privateNameKind()) {
10974 case PrivateNameKind::Setter:
10975 if (!bce2.emit1(JSOp::InitHiddenElemSetter)) {
10976 // [stack] THIS
10977 return false;
10978 }
10979 if (!bce2.emitGetPrivateName(name)) {
10980 // [stack] THIS NAME
10981 return false;
10982 }
10983 if (!bce2.emitAtomOp(
10984 JSOp::GetIntrinsic,
10985 TaggedParserAtomIndex::WellKnown::NoPrivateGetter())) {
10986 // [stack] THIS NAME FUN
10987 return false;
10988 }
10989 if (!bce2.emit1(JSOp::InitHiddenElemGetter)) {
10990 // [stack] THIS
10991 return false;
10992 }
10993 break;
10994 case PrivateNameKind::Getter:
10995 case PrivateNameKind::GetterSetter:
10996 if (classMethod->accessorType() == AccessorType::Getter) {
10997 if (!bce2.emit1(JSOp::InitHiddenElemGetter)) {
10998 // [stack] THIS
10999 return false;
11000 }
11001 } else {
11002 if (!bce2.emit1(JSOp::InitHiddenElemSetter)) {
11003 // [stack] THIS
11004 return false;
11005 }
11006 }
11007 break;
11008 default:
11009 MOZ_CRASH("Invalid op")do { do { } while (false); MOZ_ReportCrash("" "Invalid op", "./../../../../js/src/frontend/BytecodeEmitter.cpp"
, 11009); AnnotateMozCrashReason("MOZ_CRASH(" "Invalid op" ")"
); do { MOZ_CrashSequence(__null, 11009); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
11010 }
11011
11012 // Pop remaining THIS.
11013 if (!bce2.emit1(JSOp::Pop)) {
11014 // [stack]
11015 return false;
11016 }
11017
11018 if (!fse.emitEndBody()) {
11019 // [stack]
11020 return false;
11021 }
11022 if (!fse.intoStencil()) {
11023 return false;
11024 }
11025
11026 if (!fe.emitNonLazyEnd()) {
11027 // [stack] HOMEOBJ HERITAGE? ARRAY FUN
11028 // or:
11029 // [stack] CTOR HOMEOBJ ARRAY FUN
11030 return false;
11031 }
11032
11033 return true;
11034}
11035
11036const MemberInitializers& BytecodeEmitter::findMemberInitializersForCall()
11037 const {
11038 for (const auto* current = this; current; current = current->parent) {
11039 if (current->sc->isFunctionBox()) {
11040 FunctionBox* funbox = current->sc->asFunctionBox();
11041
11042 if (funbox->isArrow()) {
11043 continue;
11044 }
11045
11046 // If we found a non-arrow / non-constructor we were never allowed to
11047 // expect fields in the first place.
11048 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"
, 11048); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "funbox->isClassConstructor()"
")"); do { MOZ_CrashSequence(__null, 11048); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11049
11050 return funbox->useMemberInitializers() ? funbox->memberInitializers()
11051 : MemberInitializers::Empty();
11052 }
11053 }
11054
11055 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", 11055)
; AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "compilationState.scopeContext.memberInitializers"
")"); do { MOZ_CrashSequence(__null, 11055); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11056 return *compilationState.scopeContext.memberInitializers;
11057}
11058
11059bool BytecodeEmitter::emitInitializeInstanceMembers(
11060 bool isDerivedClassConstructor) {
11061 const MemberInitializers& memberInitializers =
11062 findMemberInitializersForCall();
11063 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", 11063)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "memberInitializers.valid"
")"); do { MOZ_CrashSequence(__null, 11063); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11064
11065 if (memberInitializers.hasPrivateBrand) {
11066 // This is guaranteed to run after super(), so we don't need TDZ checks.
11067 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_this_())) {
11068 // [stack] THIS
11069 return false;
11070 }
11071 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_privateBrand_())) {
11072 // [stack] THIS BRAND
11073 return false;
11074 }
11075 if (isDerivedClassConstructor) {
11076 if (!emitCheckPrivateField(ThrowCondition::ThrowHas,
11077 ThrowMsgKind::PrivateBrandDoubleInit)) {
11078 // [stack] THIS BRAND BOOL
11079 return false;
11080 }
11081 if (!emit1(JSOp::Pop)) {
11082 // [stack] THIS BRAND
11083 return false;
11084 }
11085 }
11086 if (!emit1(JSOp::Null)) {
11087 // [stack] THIS BRAND NULL
11088 return false;
11089 }
11090 if (!emit1(JSOp::InitHiddenElem)) {
11091 // [stack] THIS
11092 return false;
11093 }
11094 if (!emit1(JSOp::Pop)) {
11095 // [stack]
11096 return false;
11097 }
11098 }
11099
11100 size_t numInitializers = memberInitializers.numMemberInitializers;
11101 if (numInitializers > 0) {
11102 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_initializers_())) {
11103 // [stack] ARRAY
11104 return false;
11105 }
11106
11107 for (size_t index = 0; index < numInitializers; index++) {
11108 if (index < numInitializers - 1) {
11109 // We Dup to keep the array around (it is consumed in the bytecode
11110 // below) for next iterations of this loop, except for the last
11111 // iteration, which avoids an extra Pop at the end of the loop.
11112 if (!emit1(JSOp::Dup)) {
11113 // [stack] ARRAY ARRAY
11114 return false;
11115 }
11116 }
11117
11118 if (!emitNumberOp(index)) {
11119 // [stack] ARRAY? ARRAY INDEX
11120 return false;
11121 }
11122
11123 if (!emit1(JSOp::GetElem)) {
11124 // [stack] ARRAY? FUNC
11125 return false;
11126 }
11127
11128 // This is guaranteed to run after super(), so we don't need TDZ checks.
11129 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_this_())) {
11130 // [stack] ARRAY? FUNC THIS
11131 return false;
11132 }
11133
11134 // Callee is always internal function.
11135 if (!emitCall(JSOp::CallIgnoresRv, 0)) {
11136 // [stack] ARRAY? RVAL
11137 return false;
11138 }
11139
11140 if (!emit1(JSOp::Pop)) {
11141 // [stack] ARRAY?
11142 return false;
11143 }
11144 }
11145#ifdef ENABLE_DECORATORS
11146 if (memberInitializers.hasDecorators) {
11147 // Decorators Proposal
11148 // https://arai-a.github.io/ecma262-compare/?pr=2417&id=sec-initializeinstanceelements
11149 // 4. For each element e of elements, do
11150 // 4.a. If elementRecord.[[Kind]] is field or accessor, then
11151 // 4.a.i. Perform ? InitializeFieldOrAccessor(O, elementRecord).
11152 //
11153
11154 // TODO: (See Bug 1817993) At the moment, we're applying the
11155 // initialization logic in two steps. The pre-decorator initialization
11156 // code runs, stores the initial value, and then we retrieve it here and
11157 // apply the initializers added by decorators. We should unify these two
11158 // steps.
11159 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_initializers_())) {
11160 // [stack] ARRAY
11161 return false;
11162 }
11163
11164 if (!emit1(JSOp::Dup)) {
11165 // [stack] ARRAY ARRAY
11166 return false;
11167 }
11168
11169 if (!emitAtomOp(JSOp::GetProp,
11170 TaggedParserAtomIndex::WellKnown::length())) {
11171 // [stack] ARRAY LENGTH
11172 return false;
11173 }
11174
11175 if (!emitNumberOp(static_cast<double>(numInitializers))) {
11176 // [stack] ARRAY LENGTH INDEX
11177 return false;
11178 }
11179
11180 InternalWhileEmitter wh(this);
11181 // At this point, we have no context to determine offsets in the
11182 // code for this while statement. Ideally, it would correspond to
11183 // the field we're initializing.
11184 if (!wh.emitCond()) {
11185 // [stack] ARRAY LENGTH INDEX
11186 return false;
11187 }
11188
11189 if (!emit1(JSOp::Dup)) {
11190 // [stack] ARRAY LENGTH INDEX INDEX
11191 return false;
11192 }
11193
11194 if (!emitDupAt(2)) {
11195 // [stack] ARRAY LENGTH INDEX INDEX LENGTH
11196 return false;
11197 }
11198
11199 if (!emit1(JSOp::Lt)) {
11200 // [stack] ARRAY LENGTH INDEX BOOL
11201 return false;
11202 }
11203
11204 if (!wh.emitBody()) {
11205 // [stack] ARRAY LENGTH INDEX
11206 return false;
11207 }
11208
11209 if (!emitDupAt(2)) {
11210 // [stack] ARRAY LENGTH INDEX ARRAY
11211 return false;
11212 }
11213
11214 if (!emitDupAt(1)) {
11215 // [stack] ARRAY LENGTH INDEX ARRAY INDEX
11216 return false;
11217 }
11218
11219 // Retrieve initializers for this field
11220 if (!emit1(JSOp::GetElem)) {
11221 // [stack] ARRAY LENGTH INDEX INITIALIZERS
11222 return false;
11223 }
11224
11225 // This is guaranteed to run after super(), so we don't need TDZ checks.
11226 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_this_())) {
11227 // [stack] ARRAY LENGTH INDEX INITIALIZERS THIS
11228 return false;
11229 }
11230
11231 if (!emit1(JSOp::Swap)) {
11232 // [stack] ARRAY LENGTH INDEX THIS INITIALIZERS
11233 return false;
11234 }
11235
11236 DecoratorEmitter de(this);
11237 if (!de.emitInitializeFieldOrAccessor()) {
11238 // [stack] ARRAY LENGTH INDEX
11239 return false;
11240 }
11241
11242 if (!emit1(JSOp::Inc)) {
11243 // [stack] ARRAY LENGTH INDEX
11244 return false;
11245 }
11246
11247 if (!wh.emitEnd()) {
11248 // [stack] ARRAY LENGTH INDEX
11249 return false;
11250 }
11251
11252 if (!emitPopN(3)) {
11253 // [stack]
11254 return false;
11255 }
11256 // 5. Return unused.
11257
11258 if (!de.emitCallExtraInitializers(TaggedParserAtomIndex::WellKnown::
11259 dot_instanceExtraInitializers_())) {
11260 return false;
11261 }
11262 }
11263#endif
11264 }
11265 return true;
11266}
11267
11268bool BytecodeEmitter::emitInitializeStaticFields(ListNode* classMembers) {
11269 auto isStaticField = [](ParseNode* propdef) {
11270 return HasInitializer(propdef, true);
11271 };
11272 size_t numFields =
11273 std::count_if(classMembers->contents().begin(),
11274 classMembers->contents().end(), isStaticField);
11275
11276 if (numFields == 0) {
11277 return true;
11278 }
11279
11280 if (!emitGetName(
11281 TaggedParserAtomIndex::WellKnown::dot_staticInitializers_())) {
11282 // [stack] CTOR ARRAY
11283 return false;
11284 }
11285
11286 for (size_t fieldIndex = 0; fieldIndex < numFields; fieldIndex++) {
11287 bool hasNext = fieldIndex < numFields - 1;
11288 if (hasNext) {
11289 // We Dup to keep the array around (it is consumed in the bytecode below)
11290 // for next iterations of this loop, except for the last iteration, which
11291 // avoids an extra Pop at the end of the loop.
11292 if (!emit1(JSOp::Dup)) {
11293 // [stack] CTOR ARRAY ARRAY
11294 return false;
11295 }
11296 }
11297
11298 if (!emitNumberOp(fieldIndex)) {
11299 // [stack] CTOR ARRAY? ARRAY INDEX
11300 return false;
11301 }
11302
11303 if (!emit1(JSOp::GetElem)) {
11304 // [stack] CTOR ARRAY? FUNC
11305 return false;
11306 }
11307
11308 if (!emitDupAt(1 + hasNext)) {
11309 // [stack] CTOR ARRAY? FUNC CTOR
11310 return false;
11311 }
11312
11313 // Callee is always internal function.
11314 if (!emitCall(JSOp::CallIgnoresRv, 0)) {
11315 // [stack] CTOR ARRAY? RVAL
11316 return false;
11317 }
11318
11319 if (!emit1(JSOp::Pop)) {
11320 // [stack] CTOR ARRAY?
11321 return false;
11322 }
11323 }
11324
11325#ifdef ENABLE_DECORATORS
11326 // Decorators Proposal
11327 // https://arai-a.github.io/ecma262-compare/?pr=2417&id=sec-initializeinstanceelements
11328 // 4. For each element e of elements, do
11329 // 4.a. If elementRecord.[[Kind]] is field or accessor, then
11330 // 4.a.i. Perform ? InitializeFieldOrAccessor(O, elementRecord).
11331 //
11332
11333 // TODO: (See Bug 1817993) At the moment, we're applying the initialization
11334 // logic in two steps. The pre-decorator initialization code runs, stores
11335 // the initial value, and then we retrieve it here and apply the
11336 // initializers added by decorators. We should unify these two steps.
11337 if (!emitGetName(
11338 TaggedParserAtomIndex::WellKnown::dot_staticInitializers_())) {
11339 // [stack] CTOR ARRAY
11340 return false;
11341 }
11342
11343 if (!emit1(JSOp::Dup)) {
11344 // [stack] CTOR ARRAY ARRAY
11345 return false;
11346 }
11347
11348 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::length())) {
11349 // [stack] CTOR ARRAY LENGTH
11350 return false;
11351 }
11352
11353 if (!emitNumberOp(static_cast<double>(numFields))) {
11354 // [stack] CTOR ARRAY LENGTH INDEX
11355 return false;
11356 }
11357
11358 InternalWhileEmitter wh(this);
11359 // At this point, we have no context to determine offsets in the
11360 // code for this while statement. Ideally, it would correspond to
11361 // the field we're initializing.
11362 if (!wh.emitCond()) {
11363 // [stack] CTOR ARRAY LENGTH INDEX
11364 return false;
11365 }
11366
11367 if (!emit1(JSOp::Dup)) {
11368 // [stack] CTOR ARRAY LENGTH INDEX INDEX
11369 return false;
11370 }
11371
11372 if (!emitDupAt(2)) {
11373 // [stack] CTOR ARRAY LENGTH INDEX INDEX LENGTH
11374 return false;
11375 }
11376
11377 if (!emit1(JSOp::Lt)) {
11378 // [stack] CTOR ARRAY LENGTH INDEX BOOL
11379 return false;
11380 }
11381
11382 if (!wh.emitBody()) {
11383 // [stack] CTOR ARRAY LENGTH INDEX
11384 return false;
11385 }
11386
11387 if (!emitDupAt(2)) {
11388 // [stack] CTOR ARRAY LENGTH INDEX ARRAY
11389 return false;
11390 }
11391
11392 if (!emitDupAt(1)) {
11393 // [stack] CTOR ARRAY LENGTH INDEX ARRAY INDEX
11394 return false;
11395 }
11396
11397 // Retrieve initializers for this field
11398 if (!emit1(JSOp::GetElem)) {
11399 // [stack] CTOR ARRAY LENGTH INDEX INITIALIZERS
11400 return false;
11401 }
11402
11403 if (!emitDupAt(4)) {
11404 // [stack] CTOR ARRAY LENGTH INDEX INITIALIZERS CTOR
11405 return false;
11406 }
11407
11408 if (!emit1(JSOp::Swap)) {
11409 // [stack] CTOR ARRAY LENGTH INDEX CTOR INITIALIZERS
11410 return false;
11411 }
11412
11413 DecoratorEmitter de(this);
11414 if (!de.emitInitializeFieldOrAccessor()) {
11415 // [stack] CTOR ARRAY LENGTH INDEX
11416 return false;
11417 }
11418
11419 if (!emit1(JSOp::Inc)) {
11420 // [stack] CTOR ARRAY LENGTH INDEX
11421 return false;
11422 }
11423
11424 if (!wh.emitEnd()) {
11425 // [stack] CTOR ARRAY LENGTH INDEX
11426 return false;
11427 }
11428
11429 if (!emitPopN(3)) {
11430 // [stack] CTOR
11431 return false;
11432 }
11433 // 5. Return unused.
11434#endif
11435
11436 // Overwrite |.staticInitializers| and |.staticFieldKeys| with undefined to
11437 // avoid keeping the arrays alive indefinitely.
11438 auto clearStaticFieldSlot = [&](TaggedParserAtomIndex name) {
11439 NameOpEmitter noe(this, name, NameOpEmitter::Kind::SimpleAssignment);
11440 if (!noe.prepareForRhs()) {
11441 // [stack] ENV? VAL?
11442 return false;
11443 }
11444
11445 if (!emit1(JSOp::Undefined)) {
11446 // [stack] ENV? VAL? UNDEFINED
11447 return false;
11448 }
11449
11450 if (!noe.emitAssignment()) {
11451 // [stack] VAL
11452 return false;
11453 }
11454
11455 if (!emit1(JSOp::Pop)) {
11456 // [stack]
11457 return false;
11458 }
11459
11460 return true;
11461 };
11462
11463 if (!clearStaticFieldSlot(
11464 TaggedParserAtomIndex::WellKnown::dot_staticInitializers_())) {
11465 return false;
11466 }
11467
11468 auto isStaticFieldWithComputedName = [](ParseNode* propdef) {
11469 return propdef->is<ClassField>() && propdef->as<ClassField>().isStatic() &&
11470 propdef->as<ClassField>().name().getKind() ==
11471 ParseNodeKind::ComputedName;
11472 };
11473
11474 if (std::any_of(classMembers->contents().begin(),
11475 classMembers->contents().end(),
11476 isStaticFieldWithComputedName)) {
11477 if (!clearStaticFieldSlot(
11478 TaggedParserAtomIndex::WellKnown::dot_staticFieldKeys_())) {
11479 return false;
11480 }
11481 }
11482
11483 return true;
11484}
11485
11486// Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See
11487// the comment on emitSwitch.
11488MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitObject(ListNode* objNode) {
11489 // Note: this method uses the ObjLiteralWriter and emits ObjLiteralStencil
11490 // objects into the GCThingList, which will evaluate them into real GC objects
11491 // or shapes during JSScript::fullyInitFromEmitter. Eventually we want
11492 // JSOp::Object to be a real opcode, but for now, performance constraints
11493 // limit us to evaluating object literals at the end of parse, when we're
11494 // allowed to allocate GC things.
11495 //
11496 // There are four cases here, in descending order of preference:
11497 //
11498 // 1. The list of property names is "normal" and constant (no computed
11499 // values, no integer indices), the values are all simple constants
11500 // (numbers, booleans, strings), *and* this occurs in a run-once
11501 // (singleton) context. In this case, we can emit ObjLiteral
11502 // instructions to build an object with values, and the object will be
11503 // attached to a JSOp::Object opcode, whose semantics are for the backend
11504 // to simply steal the object from the script.
11505 //
11506 // 2. The list of property names is "normal" and constant as above, *and* this
11507 // occurs in a run-once (singleton) context, but some values are complex
11508 // (computed expressions, sub-objects, functions, etc.). In this case, we
11509 // can still use JSOp::Object (because singleton context), but the object
11510 // has |undefined| property values and InitProp ops are emitted to set the
11511 // values.
11512 //
11513 // 3. The list of property names is "normal" and constant as above, but this
11514 // occurs in a non-run-once (non-singleton) context. In this case, we can
11515 // use the ObjLiteral functionality to describe an *empty* object (all
11516 // values left undefined) with the right fields, which will become a
11517 // JSOp::NewObject opcode using the object's shape to speed up the creation
11518 // of the object each time it executes. The emitted bytecode still needs
11519 // InitProp ops to set the values in this case.
11520 //
11521 // 4. Any other case. As a fallback, we use NewInit to create a new, empty
11522 // object (i.e., `{}`) and then emit bytecode to initialize its properties
11523 // one-by-one.
11524
11525 bool useObjLiteral = false;
11526 bool useObjLiteralValues = false;
11527 isPropertyListObjLiteralCompatible(objNode, &useObjLiteralValues,
11528 &useObjLiteral);
11529
11530 // [stack]
11531 //
11532 ObjectEmitter oe(this);
11533 if (useObjLiteral) {
11534 bool singleton = checkSingletonContext() &&
11535 !objNode->hasNonConstInitializer() && objNode->head();
11536 JSOp op;
11537 if (singleton) {
11538 // Case 1 or 2.
11539 op = JSOp::Object;
11540 } else {
11541 // Case 3.
11542 useObjLiteralValues = false;
11543 op = JSOp::NewObject;
11544 }
11545
11546 // Use an ObjLiteral op. This will record ObjLiteral insns in the
11547 // objLiteralWriter's buffer and add a fixup to the list of ObjLiteral
11548 // fixups so that at GC-publish time at the end of parse, the full object
11549 // (case 1 or 2) or shape (case 3) can be allocated and the bytecode can be
11550 // patched to refer to it.
11551 if (!emitPropertyListObjLiteral(objNode, op, useObjLiteralValues)) {
11552 // [stack] OBJ
11553 return false;
11554 }
11555 // Put the ObjectEmitter in the right state. This tells it that there will
11556 // already be an object on the stack as a result of the (eventual)
11557 // NewObject or Object op, and prepares it to emit values if needed.
11558 if (!oe.emitObjectWithTemplateOnStack()) {
11559 // [stack] OBJ
11560 return false;
11561 }
11562 if (!useObjLiteralValues) {
11563 // Case 2 or 3 above: we still need to emit bytecode to fill in the
11564 // object's property values.
11565 if (!emitPropertyList(objNode, oe, ObjectLiteral)) {
11566 // [stack] OBJ
11567 return false;
11568 }
11569 }
11570 } else {
11571 // Case 4 above: no ObjLiteral use, just bytecode to build the object from
11572 // scratch.
11573 if (!oe.emitObject(objNode->count())) {
11574 // [stack] OBJ
11575 return false;
11576 }
11577 if (!emitPropertyList(objNode, oe, ObjectLiteral)) {
11578 // [stack] OBJ
11579 return false;
11580 }
11581 }
11582
11583 if (!oe.emitEnd()) {
11584 // [stack] OBJ
11585 return false;
11586 }
11587
11588 return true;
11589}
11590
11591bool BytecodeEmitter::emitArrayLiteral(ListNode* array) {
11592 // Emit JSOp::Object if the array consists entirely of primitive values and we
11593 // are in a singleton context.
11594 if (checkSingletonContext() && !array->hasNonConstInitializer() &&
11595 !array->empty() && isArrayObjLiteralCompatible(array)) {
11596 return emitObjLiteralArray(array);
11597 }
11598
11599 return emitArray(array);
11600}
11601
11602bool BytecodeEmitter::emitArray(ListNode* array) {
11603 /*
11604 * Emit code for [a, b, c] that is equivalent to constructing a new
11605 * array and in source order evaluating each element value and adding
11606 * it to the array, without invoking latent setters. We use the
11607 * JSOp::NewInit and JSOp::InitElemArray bytecodes to ignore setters and
11608 * to avoid dup'ing and popping the array as each element is added, as
11609 * JSOp::SetElem/JSOp::SetProp would do.
11610 */
11611
11612 uint32_t nspread = 0;
11613 for (ParseNode* elem : array->contents()) {
11614 if (elem->isKind(ParseNodeKind::Spread)) {
11615 nspread++;
11616 }
11617 }
11618
11619 // Array literal's length is limited to NELEMENTS_LIMIT in parser.
11620 static_assert(NativeObject::MAX_DENSE_ELEMENTS_COUNT <= INT32_MAX(2147483647),
11621 "array literals' maximum length must not exceed limits "
11622 "required by BaselineCompiler::emit_NewArray, "
11623 "BaselineCompiler::emit_InitElemArray, "
11624 "and DoSetElemFallback's handling of JSOp::InitElemArray");
11625
11626 uint32_t count = array->count();
11627 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", 11627)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "count >= nspread"
")"); do { MOZ_CrashSequence(__null, 11627); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11628 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"
, 11630); 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, 11630); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
11629 "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"
, 11630); 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, 11630); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
11630 "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"
, 11630); 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, 11630); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
11631
11632 // For arrays with spread, this is a very pessimistic allocation, the
11633 // minimum possible final size.
11634 if (!emitUint32Operand(JSOp::NewArray, count - nspread)) {
11635 // [stack] ARRAY
11636 return false;
11637 }
11638
11639 uint32_t index = 0;
11640 bool afterSpread = false;
11641 for (ParseNode* elem : array->contents()) {
11642 if (elem->isKind(ParseNodeKind::Spread)) {
11643 if (!afterSpread) {
11644 afterSpread = true;
11645 if (!emitNumberOp(index)) {
11646 // [stack] ARRAY INDEX
11647 return false;
11648 }
11649 }
11650
11651 ParseNode* expr = elem->as<UnaryNode>().kid();
11652 SelfHostedIter selfHostedIter = getSelfHostedIterFor(expr);
11653
11654 if (!updateSourceCoordNotes(elem->pn_pos.begin)) {
11655 return false;
11656 }
11657 if (!emitIterable(expr, selfHostedIter)) {
11658 // [stack] ARRAY INDEX ITERABLE
11659 return false;
11660 }
11661 if (!emitIterator(selfHostedIter)) {
11662 // [stack] ARRAY INDEX NEXT ITER
11663 return false;
11664 }
11665 if (!emit2(JSOp::Pick, 3)) {
11666 // [stack] INDEX NEXT ITER ARRAY
11667 return false;
11668 }
11669 if (!emit2(JSOp::Pick, 3)) {
11670 // [stack] NEXT ITER ARRAY INDEX
11671 return false;
11672 }
11673 if (!emitSpread(selfHostedIter)) {
11674 // [stack] ARRAY INDEX
11675 return false;
11676 }
11677 } else {
11678 if (!updateSourceCoordNotesIfNonLiteral(elem)) {
11679 return false;
11680 }
11681 if (elem->isKind(ParseNodeKind::Elision)) {
11682 if (!emit1(JSOp::Hole)) {
11683 return false;
11684 }
11685 } else {
11686 if (!emitTree(elem, ValueUsage::WantValue)) {
11687 // [stack] ARRAY INDEX? VALUE
11688 return false;
11689 }
11690 }
11691
11692 if (afterSpread) {
11693 if (!emit1(JSOp::InitElemInc)) {
11694 // [stack] ARRAY (INDEX+1)
11695 return false;
11696 }
11697 } else {
11698 if (!emitUint32Operand(JSOp::InitElemArray, index)) {
11699 // [stack] ARRAY
11700 return false;
11701 }
11702 }
11703 }
11704
11705 index++;
11706 }
11707 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", 11707)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "index == count" ")"
); do { MOZ_CrashSequence(__null, 11707); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
11708 if (afterSpread) {
11709 if (!emit1(JSOp::Pop)) {
11710 // [stack] ARRAY
11711 return false;
11712 }
11713 }
11714 return true;
11715}
11716
11717bool BytecodeEmitter::emitSpreadIntoArray(UnaryNode* elem) {
11718 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", 11718)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "elem->isKind(ParseNodeKind::Spread)"
")"); do { MOZ_CrashSequence(__null, 11718); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11719
11720 if (!updateSourceCoordNotes(elem->pn_pos.begin)) {
11721 // [stack] VALUE
11722 return false;
11723 }
11724
11725 SelfHostedIter selfHostedIter = getSelfHostedIterFor(elem->kid());
11726 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", 11727)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter == SelfHostedIter::Deny || selfHostedIter == SelfHostedIter::AllowContent"
")"); do { MOZ_CrashSequence(__null, 11727); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11727 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", 11727)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter == SelfHostedIter::Deny || selfHostedIter == SelfHostedIter::AllowContent"
")"); do { MOZ_CrashSequence(__null, 11727); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11728
11729 if (!emitIterator(selfHostedIter)) {
11730 // [stack] NEXT ITER
11731 return false;
11732 }
11733
11734 if (!emitUint32Operand(JSOp::NewArray, 0)) {
11735 // [stack] NEXT ITER ARRAY
11736 return false;
11737 }
11738
11739 if (!emitNumberOp(0)) {
11740 // [stack] NEXT ITER ARRAY INDEX
11741 return false;
11742 }
11743
11744 if (!emitSpread(selfHostedIter)) {
11745 // [stack] ARRAY INDEX
11746 return false;
11747 }
11748
11749 if (!emit1(JSOp::Pop)) {
11750 // [stack] ARRAY
11751 return false;
11752 }
11753 return true;
11754}
11755
11756static inline JSOp UnaryOpParseNodeKindToJSOp(ParseNodeKind pnk) {
11757 switch (pnk) {
11758 case ParseNodeKind::ThrowStmt:
11759 return JSOp::Throw;
11760 case ParseNodeKind::VoidExpr:
11761 return JSOp::Void;
11762 case ParseNodeKind::NotExpr:
11763 return JSOp::Not;
11764 case ParseNodeKind::BitNotExpr:
11765 return JSOp::BitNot;
11766 case ParseNodeKind::PosExpr:
11767 return JSOp::Pos;
11768 case ParseNodeKind::NegExpr:
11769 return JSOp::Neg;
11770 default:
11771 MOZ_CRASH("unexpected unary op")do { do { } while (false); MOZ_ReportCrash("" "unexpected unary op"
, "./../../../../js/src/frontend/BytecodeEmitter.cpp", 11771)
; AnnotateMozCrashReason("MOZ_CRASH(" "unexpected unary op" ")"
); do { MOZ_CrashSequence(__null, 11771); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
11772 }
11773}
11774
11775bool BytecodeEmitter::emitUnary(UnaryNode* unaryNode) {
11776 if (!updateSourceCoordNotes(unaryNode->pn_pos.begin)) {
11777 return false;
11778 }
11779
11780 JSOp op = UnaryOpParseNodeKindToJSOp(unaryNode->getKind());
11781 ValueUsage valueUsage =
11782 op == JSOp::Void ? ValueUsage::IgnoreValue : ValueUsage::WantValue;
11783 if (!emitTree(unaryNode->kid(), valueUsage)) {
11784 return false;
11785 }
11786 return emit1(op);
11787}
11788
11789bool BytecodeEmitter::emitTypeof(UnaryNode* typeofNode, JSOp op) {
11790 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", 11790)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::Typeof || op == JSOp::TypeofExpr"
")"); do { MOZ_CrashSequence(__null, 11790); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11791
11792 if (!updateSourceCoordNotes(typeofNode->pn_pos.begin)) {
11793 return false;
11794 }
11795
11796 if (!emitTree(typeofNode->kid())) {
11797 return false;
11798 }
11799
11800 return emit1(op);
11801}
11802
11803bool BytecodeEmitter::tryEmitTypeofEq(ListNode* node, bool* emitted) {
11804 // Emit specialized opcode for the following if possible:
11805 // * typeof val == "type"
11806 // * typeof val != "type"
11807 // * typeof val > "u" # minified `typeof val === "undefined"`
11808 // * typeof val < "u" # minified `typeof val !== "undefined"`
11809 //
11810 // NOTE: Given the comparison is done for string, `==` and `===` have
11811 // no difference. Same for `!=` and `!==`.
11812 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", 11817)
; 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, 11817); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11813 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", 11817)
; 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, 11817); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11814 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", 11817)
; 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, 11817); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11815 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", 11817)
; 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, 11817); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11816 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", 11817)
; 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, 11817); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11817 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", 11817)
; 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, 11817); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11818
11819 if (node->count() != 2) {
11820 *emitted = false;
11821 return true;
11822 }
11823
11824 ParseNode* left = node->head();
11825 ParseNode* right = left->pn_next;
11826 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"
, 11826); AnnotateMozCrashReason("MOZ_ASSERT" "(" "right" ")"
); do { MOZ_CrashSequence(__null, 11826); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
11827
11828 UnaryNode* typeofNode;
11829 NameNode* typenameNode;
11830 JSOp op;
11831 JSType type;
11832
11833 if (node->isKind(ParseNodeKind::LtExpr) ||
11834 node->isKind(ParseNodeKind::GtExpr)) {
11835 if (left->isKind(ParseNodeKind::TypeOfNameExpr) &&
11836 right->isKind(ParseNodeKind::StringExpr)) {
11837 typeofNode = &left->as<UnaryNode>();
11838 typenameNode = &right->as<NameNode>();
11839
11840 if (node->isKind(ParseNodeKind::LtExpr)) {
11841 op = JSOp::Ne;
11842 } else {
11843 op = JSOp::Eq;
11844 }
11845 } else if (left->isKind(ParseNodeKind::StringExpr) &&
11846 right->isKind(ParseNodeKind::TypeOfNameExpr)) {
11847 typeofNode = &right->as<UnaryNode>();
11848 typenameNode = &left->as<NameNode>();
11849
11850 if (node->isKind(ParseNodeKind::LtExpr)) {
11851 op = JSOp::Eq;
11852 } else {
11853 op = JSOp::Ne;
11854 }
11855 } else {
11856 *emitted = false;
11857 return true;
11858 }
11859
11860 TaggedParserAtomIndex typeName = typenameNode->atom();
11861 if (typeName.isLength1StaticParserString() &&
11862 typeName.toLength1StaticParserString() ==
11863 Length1StaticParserString('u')) {
11864 type = JSTYPE_UNDEFINED;
11865 } else {
11866 *emitted = false;
11867 return true;
11868 }
11869 } else {
11870 if (node->isKind(ParseNodeKind::StrictEqExpr) ||
11871 node->isKind(ParseNodeKind::EqExpr)) {
11872 op = JSOp::Eq;
11873 } else {
11874 op = JSOp::Ne;
11875 }
11876
11877 // NOTE: ParseNodeKind::TypeOfExpr cannot use JSOp::TypeofEq.
11878 // See JSOp::GetName document.
11879 if (left->isKind(ParseNodeKind::TypeOfNameExpr) &&
11880 right->isKind(ParseNodeKind::StringExpr)) {
11881 typeofNode = &left->as<UnaryNode>();
11882 typenameNode = &right->as<NameNode>();
11883 } else if (right->isKind(ParseNodeKind::TypeOfNameExpr) &&
11884 left->isKind(ParseNodeKind::StringExpr)) {
11885 typeofNode = &right->as<UnaryNode>();
11886 typenameNode = &left->as<NameNode>();
11887 } else {
11888 *emitted = false;
11889 return true;
11890 }
11891
11892 TaggedParserAtomIndex typeName = typenameNode->atom();
11893 if (typeName == TaggedParserAtomIndex::WellKnown::undefined()) {
11894 type = JSTYPE_UNDEFINED;
11895 } else if (typeName == TaggedParserAtomIndex::WellKnown::object()) {
11896 type = JSTYPE_OBJECT;
11897 } else if (typeName == TaggedParserAtomIndex::WellKnown::function()) {
11898 type = JSTYPE_FUNCTION;
11899 } else if (typeName == TaggedParserAtomIndex::WellKnown::string()) {
11900 type = JSTYPE_STRING;
11901 } else if (typeName == TaggedParserAtomIndex::WellKnown::number()) {
11902 type = JSTYPE_NUMBER;
11903 } else if (typeName == TaggedParserAtomIndex::WellKnown::boolean()) {
11904 type = JSTYPE_BOOLEAN;
11905 } else if (typeName == TaggedParserAtomIndex::WellKnown::symbol()) {
11906 type = JSTYPE_SYMBOL;
11907 } else if (typeName == TaggedParserAtomIndex::WellKnown::bigint()) {
11908 type = JSTYPE_BIGINT;
11909 } else {
11910 *emitted = false;
11911 return true;
11912 }
11913 }
11914
11915 if (!updateSourceCoordNotes(typeofNode->pn_pos.begin)) {
11916 return false;
11917 }
11918
11919 if (!emitTree(typeofNode->kid())) {
11920 // [stack] VAL
11921 return false;
11922 }
11923
11924 if (!emit2(JSOp::TypeofEq, TypeofEqOperand(type, op).rawValue())) {
11925 // [stack] CMP
11926 return false;
11927 }
11928
11929 *emitted = true;
11930 return true;
11931}
11932
11933bool BytecodeEmitter::emitFunctionFormalParameters(ParamsBodyNode* paramsBody) {
11934 FunctionBox* funbox = sc->asFunctionBox();
11935
11936 bool hasRest = funbox->hasRest();
11937
11938 FunctionParamsEmitter fpe(this, funbox);
11939 for (ParseNode* arg : paramsBody->parameters()) {
11940 ParseNode* bindingElement = arg;
11941 ParseNode* initializer = nullptr;
11942 if (arg->isKind(ParseNodeKind::AssignExpr)) {
11943 bindingElement = arg->as<BinaryNode>().left();
11944 initializer = arg->as<BinaryNode>().right();
11945 }
11946 bool hasInitializer = !!initializer;
11947 bool isRest =
11948 hasRest && arg->pn_next == *std::end(paramsBody->parameters());
11949 bool isDestructuring = !bindingElement->isKind(ParseNodeKind::Name);
11950
11951 // Left-hand sides are either simple names or destructuring patterns.
11952 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", 11954)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "bindingElement->isKind(ParseNodeKind::Name) || bindingElement->isKind(ParseNodeKind::ArrayExpr) || bindingElement->isKind(ParseNodeKind::ObjectExpr)"
")"); do { MOZ_CrashSequence(__null, 11954); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11953 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", 11954)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "bindingElement->isKind(ParseNodeKind::Name) || bindingElement->isKind(ParseNodeKind::ArrayExpr) || bindingElement->isKind(ParseNodeKind::ObjectExpr)"
")"); do { MOZ_CrashSequence(__null, 11954); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11954 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", 11954)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "bindingElement->isKind(ParseNodeKind::Name) || bindingElement->isKind(ParseNodeKind::ArrayExpr) || bindingElement->isKind(ParseNodeKind::ObjectExpr)"
")"); do { MOZ_CrashSequence(__null, 11954); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11955
11956 auto emitDefaultInitializer = [this, &initializer, &bindingElement]() {
11957 // [stack]
11958
11959 if (!this->emitInitializer(initializer, bindingElement)) {
11960 // [stack] DEFAULT
11961 return false;
11962 }
11963 return true;
11964 };
11965
11966 auto emitDestructuring = [this, &bindingElement]() {
11967 // [stack] ARG
11968
11969 if (!this->emitDestructuringOps(&bindingElement->as<ListNode>(),
11970 DestructuringFlavor::Declaration,
11971 SelfHostedIter::Deny)) {
11972 // [stack] ARG
11973 return false;
11974 }
11975
11976 return true;
11977 };
11978
11979 if (isRest) {
11980 if (isDestructuring) {
11981 if (!fpe.prepareForDestructuringRest()) {
11982 // [stack]
11983 return false;
11984 }
11985 if (!emitDestructuring()) {
11986 // [stack]
11987 return false;
11988 }
11989 if (!fpe.emitDestructuringRestEnd()) {
11990 // [stack]
11991 return false;
11992 }
11993 } else {
11994 auto paramName = bindingElement->as<NameNode>().name();
11995 if (!fpe.emitRest(paramName)) {
11996 // [stack]
11997 return false;
11998 }
11999 }
12000
12001 continue;
12002 }
12003
12004 if (isDestructuring) {
12005 if (hasInitializer) {
12006 if (!fpe.prepareForDestructuringDefaultInitializer()) {
12007 // [stack]
12008 return false;
12009 }
12010 if (!emitDefaultInitializer()) {
12011 // [stack]
12012 return false;
12013 }
12014 if (!fpe.prepareForDestructuringDefault()) {
12015 // [stack]
12016 return false;
12017 }
12018 if (!emitDestructuring()) {
12019 // [stack]
12020 return false;
12021 }
12022 if (!fpe.emitDestructuringDefaultEnd()) {
12023 // [stack]
12024 return false;
12025 }
12026 } else {
12027 if (!fpe.prepareForDestructuring()) {
12028 // [stack]
12029 return false;
12030 }
12031 if (!emitDestructuring()) {
12032 // [stack]
12033 return false;
12034 }
12035 if (!fpe.emitDestructuringEnd()) {
12036 // [stack]
12037 return false;
12038 }
12039 }
12040
12041 continue;
12042 }
12043
12044 if (hasInitializer) {
12045 if (!fpe.prepareForDefault()) {
12046 // [stack]
12047 return false;
12048 }
12049 if (!emitDefaultInitializer()) {
12050 // [stack]
12051 return false;
12052 }
12053 auto paramName = bindingElement->as<NameNode>().name();
12054 if (!fpe.emitDefaultEnd(paramName)) {
12055 // [stack]
12056 return false;
12057 }
12058
12059 continue;
12060 }
12061
12062 auto paramName = bindingElement->as<NameNode>().name();
12063 if (!fpe.emitSimple(paramName)) {
12064 // [stack]
12065 return false;
12066 }
12067 }
12068
12069 return true;
12070}
12071
12072bool BytecodeEmitter::emitInitializeFunctionSpecialNames() {
12073 FunctionBox* funbox = sc->asFunctionBox();
12074
12075 // [stack]
12076
12077 auto emitInitializeFunctionSpecialName =
12078 [](BytecodeEmitter* bce, TaggedParserAtomIndex name, JSOp op) {
12079 // A special name must be slotful, either on the frame or on the
12080 // call environment.
12081 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", 12081)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "bce->lookupName(name).hasKnownSlot()"
")"); do { MOZ_CrashSequence(__null, 12081); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12082
12083 NameOpEmitter noe(bce, name, NameOpEmitter::Kind::Initialize);
12084 if (!noe.prepareForRhs()) {
12085 // [stack]
12086 return false;
12087 }
12088 if (!bce->emit1(op)) {
12089 // [stack] THIS/ARGUMENTS/NEW.TARGET
12090 return false;
12091 }
12092 if (!noe.emitAssignment()) {
12093 // [stack] THIS/ARGUMENTS/NEW.TARGET
12094 return false;
12095 }
12096 if (!bce->emit1(JSOp::Pop)) {
12097 // [stack]
12098 return false;
12099 }
12100
12101 return true;
12102 };
12103
12104 // Do nothing if the function doesn't have an arguments binding.
12105 if (funbox->needsArgsObj()) {
12106 // Self-hosted code should use the more efficient ArgumentsLength and
12107 // GetArgument intrinsics instead of `arguments`.
12108 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", 12108)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode != BytecodeEmitter::SelfHosting"
")"); do { MOZ_CrashSequence(__null, 12108); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12109 if (!emitInitializeFunctionSpecialName(
12110 this, TaggedParserAtomIndex::WellKnown::arguments(),
12111 JSOp::Arguments)) {
12112 // [stack]
12113 return false;
12114 }
12115 }
12116
12117 // Do nothing if the function doesn't have a this-binding (this
12118 // happens for instance if it doesn't use this/eval or if it's an
12119 // arrow function).
12120 if (funbox->functionHasThisBinding()) {
12121 if (!emitInitializeFunctionSpecialName(
12122 this, TaggedParserAtomIndex::WellKnown::dot_this_(),
12123 JSOp::FunctionThis)) {
12124 return false;
12125 }
12126 }
12127
12128 // Do nothing if the function doesn't have a new.target-binding (this happens
12129 // for instance if it doesn't use new.target/eval or if it's an arrow
12130 // function).
12131 if (funbox->functionHasNewTargetBinding()) {
12132 if (!emitInitializeFunctionSpecialName(
12133 this, TaggedParserAtomIndex::WellKnown::dot_newTarget_(),
12134 JSOp::NewTarget)) {
12135 return false;
12136 }
12137 }
12138
12139 // Do nothing if the function doesn't implicitly return a promise result.
12140 if (funbox->needsPromiseResult()) {
12141 if (!emitInitializeFunctionSpecialName(
12142 this, TaggedParserAtomIndex::WellKnown::dot_generator_(),
12143 JSOp::Generator)) {
12144 // [stack]
12145 return false;
12146 }
12147 }
12148 return true;
12149}
12150
12151bool BytecodeEmitter::emitLexicalInitialization(NameNode* name) {
12152 return emitLexicalInitialization(name->name());
12153}
12154
12155bool BytecodeEmitter::emitLexicalInitialization(TaggedParserAtomIndex name) {
12156 NameOpEmitter noe(this, name, NameOpEmitter::Kind::Initialize);
12157 if (!noe.prepareForRhs()) {
12158 return false;
12159 }
12160
12161 // The caller has pushed the RHS to the top of the stack. Assert that the
12162 // binding can be initialized without a binding object on the stack, and that
12163 // no JSOp::BindUnqualifiedName or JSOp::BindUnqualifiedGName ops were
12164 // emitted.
12165 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", 12166)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "noe.loc().isLexical() || noe.loc().isSynthetic() || noe.loc().isPrivateMethod()"
")"); do { MOZ_CrashSequence(__null, 12166); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12166 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", 12166)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "noe.loc().isLexical() || noe.loc().isSynthetic() || noe.loc().isPrivateMethod()"
")"); do { MOZ_CrashSequence(__null, 12166); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12167 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", 12167)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "!noe.emittedBindOp()"
")"); do { MOZ_CrashSequence(__null, 12167); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12168
12169 if (!noe.emitAssignment()) {
12170 return false;
12171 }
12172
12173 return true;
12174}
12175
12176static MOZ_ALWAYS_INLINEinline ParseNode* FindConstructor(ListNode* classMethods) {
12177 for (ParseNode* classElement : classMethods->contents()) {
12178 ParseNode* unwrappedElement = classElement;
12179 if (unwrappedElement->is<LexicalScopeNode>()) {
12180 unwrappedElement = unwrappedElement->as<LexicalScopeNode>().scopeBody();
12181 }
12182 if (unwrappedElement->is<ClassMethod>()) {
12183 ClassMethod& method = unwrappedElement->as<ClassMethod>();
12184 ParseNode& methodName = method.name();
12185 if (!method.isStatic() &&
12186 (methodName.isKind(ParseNodeKind::ObjectPropertyName) ||
12187 methodName.isKind(ParseNodeKind::StringExpr)) &&
12188 methodName.as<NameNode>().atom() ==
12189 TaggedParserAtomIndex::WellKnown::constructor()) {
12190 return classElement;
12191 }
12192 }
12193 }
12194 return nullptr;
12195}
12196
12197bool BytecodeEmitter::emitNewPrivateName(TaggedParserAtomIndex bindingName,
12198 TaggedParserAtomIndex symbolName) {
12199 if (!emitAtomOp(JSOp::NewPrivateName, symbolName)) {
12200 // [stack] HERITAGE PRIVATENAME
12201 return false;
12202 }
12203
12204 // Add a binding for #name => privatename
12205 if (!emitLexicalInitialization(bindingName)) {
12206 // [stack] HERITAGE PRIVATENAME
12207 return false;
12208 }
12209
12210 // Pop Private name off the stack.
12211 if (!emit1(JSOp::Pop)) {
12212 // [stack] HERITAGE
12213 return false;
12214 }
12215
12216 return true;
12217}
12218
12219bool BytecodeEmitter::emitNewPrivateNames(
12220 TaggedParserAtomIndex privateBrandName, ListNode* classMembers) {
12221 bool hasPrivateBrand = false;
12222
12223 for (ParseNode* classElement : classMembers->contents()) {
12224 ParseNode* elementName;
12225 if (classElement->is<ClassMethod>()) {
12226 elementName = &classElement->as<ClassMethod>().name();
12227 } else if (classElement->is<ClassField>()) {
12228 elementName = &classElement->as<ClassField>().name();
12229 } else {
12230 continue;
12231 }
12232
12233 if (!elementName->isKind(ParseNodeKind::PrivateName)) {
12234 continue;
12235 }
12236
12237 // Non-static private methods' private names are optimized away.
12238 bool isOptimized = false;
12239 if (classElement->is<ClassMethod>() &&
12240 !classElement->as<ClassMethod>().isStatic()) {
12241 hasPrivateBrand = true;
12242 if (classElement->as<ClassMethod>().accessorType() ==
12243 AccessorType::None) {
12244 isOptimized = true;
12245 }
12246 }
12247
12248 if (!isOptimized) {
12249 auto privateName = elementName->as<NameNode>().name();
12250 if (!emitNewPrivateName(privateName, privateName)) {
12251 return false;
12252 }
12253 }
12254 }
12255
12256 if (hasPrivateBrand) {
12257 // We don't make a private name for every optimized method, but we need one
12258 // private name per class, the `.privateBrand`.
12259 if (!emitNewPrivateName(
12260 TaggedParserAtomIndex::WellKnown::dot_privateBrand_(),
12261 privateBrandName)) {
12262 return false;
12263 }
12264 }
12265 return true;
12266}
12267
12268// This follows ES6 14.5.14 (ClassDefinitionEvaluation) and ES6 14.5.15
12269// (BindingClassDeclarationEvaluation).
12270bool BytecodeEmitter::emitClass(
12271 ClassNode* classNode,
12272 ClassNameKind nameKind /* = ClassNameKind::BindingName */,
12273 TaggedParserAtomIndex
12274 nameForAnonymousClass /* = TaggedParserAtomIndex::null() */) {
12275 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", 12276)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "(nameKind == ClassNameKind::InferredName) == bool(nameForAnonymousClass)"
")"); do { MOZ_CrashSequence(__null, 12276); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12276 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", 12276)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "(nameKind == ClassNameKind::InferredName) == bool(nameForAnonymousClass)"
")"); do { MOZ_CrashSequence(__null, 12276); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12277
12278 ParseNode* heritageExpression = classNode->heritage();
12279 ListNode* classMembers = classNode->memberList();
12280 ParseNode* constructor = FindConstructor(classMembers);
12281
12282 // If |nameKind != ClassNameKind::ComputedName|
12283 // [stack]
12284 // Else
12285 // [stack] NAME
12286
12287 ClassEmitter ce(this);
12288 TaggedParserAtomIndex innerName;
12289 ClassEmitter::Kind kind = ClassEmitter::Kind::Expression;
12290 if (ClassNames* names = classNode->names()) {
12291 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", 12291)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "nameKind == ClassNameKind::BindingName"
")"); do { MOZ_CrashSequence(__null, 12291); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12292 innerName = names->innerBinding()->name();
12293 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"
, 12293); AnnotateMozCrashReason("MOZ_ASSERT" "(" "innerName"
")"); do { MOZ_CrashSequence(__null, 12293); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12294
12295 if (names->outerBinding()) {
12296 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"
, 12296); AnnotateMozCrashReason("MOZ_ASSERT" "(" "names->outerBinding()->name()"
")"); do { MOZ_CrashSequence(__null, 12296); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12297 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", 12297)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "names->outerBinding()->name() == innerName"
")"); do { MOZ_CrashSequence(__null, 12297); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12298 kind = ClassEmitter::Kind::Declaration;
12299 }
12300 }
12301
12302 if (LexicalScopeNode* scopeBindings = classNode->scopeBindings()) {
12303 if (!ce.emitScope(scopeBindings->scopeBindings())) {
12304 // [stack]
12305 return false;
12306 }
12307 }
12308
12309 bool isDerived = !!heritageExpression;
12310 if (isDerived) {
12311 if (!updateSourceCoordNotes(classNode->pn_pos.begin)) {
12312 return false;
12313 }
12314 if (!markStepBreakpoint()) {
12315 return false;
12316 }
12317 if (!emitTree(heritageExpression)) {
12318 // [stack] HERITAGE
12319 return false;
12320 }
12321 }
12322
12323 // The class body scope holds any private names. Those mustn't be visible in
12324 // the heritage expression and hence the scope must be emitted after the
12325 // heritage expression.
12326 if (ClassBodyScopeNode* bodyScopeBindings = classNode->bodyScopeBindings()) {
12327 if (!ce.emitBodyScope(bodyScopeBindings->scopeBindings())) {
12328 // [stack] HERITAGE
12329 return false;
12330 }
12331
12332 // The spec does not say anything about private brands being symbols. It's
12333 // an implementation detail. So we can give the special private brand
12334 // symbol any description we want and users won't normally see it. For
12335 // debugging, use the class name.
12336 auto privateBrandName = innerName;
12337 if (!innerName) {
12338 privateBrandName = nameForAnonymousClass
12339 ? nameForAnonymousClass
12340 : TaggedParserAtomIndex::WellKnown::anonymous();
12341 }
12342 if (!emitNewPrivateNames(privateBrandName, classMembers)) {
12343 return false;
12344 }
12345 }
12346
12347 bool hasNameOnStack = nameKind == ClassNameKind::ComputedName;
12348 if (isDerived) {
12349 if (!ce.emitDerivedClass(innerName, nameForAnonymousClass,
12350 hasNameOnStack)) {
12351 // [stack] HOMEOBJ HERITAGE
12352 return false;
12353 }
12354 } else {
12355 int membersCount = 0;
12356 for (ParseNode* node : classMembers->contents()) {
12357 if (node->getKind() == ParseNodeKind::ClassField) {
12358 membersCount++;
12359 }
12360 }
12361 membersCount = (membersCount > 255) ? 255 : membersCount;
12362 if (!ce.emitClass(innerName, nameForAnonymousClass, hasNameOnStack,
12363 uint8_t(membersCount))) {
12364 // [stack] HOMEOBJ
12365 return false;
12366 }
12367 }
12368
12369 // Stack currently has HOMEOBJ followed by optional HERITAGE. When HERITAGE
12370 // is not used, an implicit value of %FunctionPrototype% is implied.
12371
12372 // See |Parser::classMember(...)| for the reason why |.initializers| is
12373 // created within its own scope.
12374 Maybe<LexicalScopeEmitter> lse;
12375 FunctionNode* ctor;
12376#ifdef ENABLE_DECORATORS
12377 bool extraInitializersPresent = false;
12378#endif
12379 if (constructor->is<LexicalScopeNode>()) {
12380 LexicalScopeNode* constructorScope = &constructor->as<LexicalScopeNode>();
12381
12382 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"
, 12382); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!constructorScope->isEmptyScope()"
")"); do { MOZ_CrashSequence(__null, 12382); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12383#ifdef ENABLE_DECORATORS
12384 // With decorators enabled we expect to see |.initializers|,
12385 // and |.instanceExtraInitializers| in this scope.
12386 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"
, 12386); AnnotateMozCrashReason("MOZ_ASSERT" "(" "constructorScope->scopeBindings()->length == 2"
")"); do { MOZ_CrashSequence(__null, 12386); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12387 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", 12389)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()"
")"); do { MOZ_CrashSequence(__null, 12389); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12388 .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", 12389)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()"
")"); do { MOZ_CrashSequence(__null, 12389); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12389 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", 12389)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()"
")"); do { MOZ_CrashSequence(__null, 12389); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12390 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", 12393)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_()"
")"); do { MOZ_CrashSequence(__null, 12393); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12391 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", 12393)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_()"
")"); do { MOZ_CrashSequence(__null, 12393); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12392 .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", 12393)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_()"
")"); do { MOZ_CrashSequence(__null, 12393); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12393 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", 12393)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_()"
")"); do { MOZ_CrashSequence(__null, 12393); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12394
12395 // We should only call this code if we know decorators are present, see bug
12396 // 1871147.
12397 lse.emplace(this);
12398 if (!lse->emitScope(ScopeKind::Lexical,
12399 constructorScope->scopeBindings())) {
12400 return false;
12401 }
12402
12403 // TODO: See bug 1868220 for support for static extra initializers.
12404 if (!ce.prepareForExtraInitializers(TaggedParserAtomIndex::WellKnown::
12405 dot_instanceExtraInitializers_())) {
12406 return false;
12407 }
12408
12409 if (classNode->addInitializerFunction()) {
12410 DecoratorEmitter de(this);
12411 if (!de.emitCreateAddInitializerFunction(
12412 classNode->addInitializerFunction(),
12413 TaggedParserAtomIndex::WellKnown::
12414 dot_instanceExtraInitializers_())) {
12415 // [stack] HOMEOBJ HERITAGE? ADDINIT
12416 return false;
12417 }
12418
12419 if (!emitUnpickN(isDerived ? 2 : 1)) {
12420 // [stack] ADDINIT HOMEOBJ HERITAGE?
12421 return false;
12422 }
12423
12424 extraInitializersPresent = true;
12425 }
12426#else
12427 // The constructor scope should only contain the |.initializers| binding.
12428 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"
, 12428); AnnotateMozCrashReason("MOZ_ASSERT" "(" "constructorScope->scopeBindings()->length == 1"
")"); do { MOZ_CrashSequence(__null, 12428); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12429 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", 12431)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()"
")"); do { MOZ_CrashSequence(__null, 12431); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12430 .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", 12431)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()"
")"); do { MOZ_CrashSequence(__null, 12431); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12431 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", 12431)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()"
")"); do { MOZ_CrashSequence(__null, 12431); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12432#endif
12433
12434 auto needsInitializer = [](ParseNode* propdef) {
12435 return NeedsFieldInitializer(propdef, false) ||
12436 NeedsAccessorInitializer(propdef, false);
12437 };
12438
12439 // As an optimization omit the |.initializers| binding when no instance
12440 // fields or private methods are present.
12441 bool needsInitializers =
12442 std::any_of(classMembers->contents().begin(),
12443 classMembers->contents().end(), needsInitializer);
12444 if (needsInitializers) {
12445#ifndef ENABLE_DECORATORS
12446 lse.emplace(this);
12447 if (!lse->emitScope(ScopeKind::Lexical,
12448 constructorScope->scopeBindings())) {
12449 return false;
12450 }
12451#endif
12452 // Any class with field initializers will have a constructor
12453 if (!emitCreateMemberInitializers(ce, classMembers,
12454 FieldPlacement::Instance
12455#ifdef ENABLE_DECORATORS
12456 ,
12457 isDerived
12458#endif
12459 )) {
12460 return false;
12461 }
12462 }
12463
12464 ctor = &constructorScope->scopeBody()->as<ClassMethod>().method();
12465 } else {
12466 // The |.initializers| binding is never emitted when in self-hosting mode.
12467 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", 12467)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode == BytecodeEmitter::SelfHosting"
")"); do { MOZ_CrashSequence(__null, 12467); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12468 ctor = &constructor->as<ClassMethod>().method();
12469 }
12470
12471 bool needsHomeObject = ctor->funbox()->needsHomeObject();
12472 // HERITAGE is consumed inside emitFunction.
12473 if (nameKind == ClassNameKind::InferredName) {
12474 setFunName(ctor->funbox(), nameForAnonymousClass);
12475 }
12476 if (!emitFunction(ctor, isDerived)) {
12477 // [stack] HOMEOBJ CTOR
12478 return false;
12479 }
12480 if (lse.isSome()) {
12481 if (!lse->emitEnd()) {
12482 return false;
12483 }
12484 lse.reset();
12485 }
12486 if (!ce.emitInitConstructor(needsHomeObject)) {
12487 // [stack] CTOR HOMEOBJ
12488 return false;
12489 }
12490
12491 if (!emitCreateFieldKeys(classMembers, FieldPlacement::Instance)) {
12492 return false;
12493 }
12494
12495#ifdef ENABLE_DECORATORS
12496 // TODO: See Bug 1868220 for support for static extra initializers.
12497 if (!emit1(JSOp::Undefined)) {
12498 // [stack] ADDINIT? CTOR HOMEOBJ UNDEFINED
12499 return false;
12500 }
12501 if (!emitUnpickN(2)) {
12502 // [stack] ADDINIT? UNDEFINED CTOR HOMEOBJ
12503 return false;
12504 }
12505#endif
12506
12507 if (!emitCreateMemberInitializers(ce, classMembers, FieldPlacement::Static
12508#ifdef ENABLE_DECORATORS
12509 ,
12510 false
12511#endif
12512 )) {
12513 return false;
12514 }
12515
12516#ifdef ENABLE_DECORATORS
12517 if (!emitPickN(2)) {
12518 // [stack] ADDINIT? CTOR HOMEOBJ UNDEFINED
12519 return false;
12520 }
12521 if (!emitPopN(1)) {
12522 // [stack] ADDINIT? CTOR HOMEOBJ
12523 return false;
12524 }
12525#endif
12526
12527 if (!emitCreateFieldKeys(classMembers, FieldPlacement::Static)) {
12528 return false;
12529 }
12530
12531 if (!emitPropertyList(classMembers, ce, ClassBody)) {
12532 // [stack] CTOR HOMEOBJ
12533 return false;
12534 }
12535
12536#ifdef ENABLE_DECORATORS
12537 if (extraInitializersPresent) {
12538 if (!emitPickN(2)) {
12539 // [stack] CTOR HOMEOBJ ADDINIT
12540 return false;
12541 }
12542 if (!emitPopN(1)) {
12543 // [stack] CTOR HOMEOBJ
12544 return false;
12545 }
12546 }
12547#endif
12548
12549 if (!ce.emitBinding()) {
12550 // [stack] CTOR
12551 return false;
12552 }
12553
12554 if (!emitInitializeStaticFields(classMembers)) {
12555 // [stack] CTOR
12556 return false;
12557 }
12558
12559#if ENABLE_DECORATORS
12560 if (!ce.prepareForDecorators()) {
12561 // [stack] CTOR
12562 return false;
12563 }
12564 if (classNode->decorators() != nullptr) {
12565 DecoratorEmitter de(this);
12566 NameNode* className =
12567 classNode->names() ? classNode->names()->innerBinding() : nullptr;
12568 if (!de.emitApplyDecoratorsToClassDefinition(className,
12569 classNode->decorators())) {
12570 // [stack] CTOR
12571 return false;
12572 }
12573 }
12574#endif
12575
12576 if (!ce.emitEnd(kind)) {
12577 // [stack] # class declaration
12578 // [stack]
12579 // [stack] # class expression
12580 // [stack] CTOR
12581 return false;
12582 }
12583
12584 return true;
12585}
12586
12587bool BytecodeEmitter::emitExportDefault(BinaryNode* exportNode) {
12588 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"
, 12588); AnnotateMozCrashReason("MOZ_ASSERT" "(" "exportNode->isKind(ParseNodeKind::ExportDefaultStmt)"
")"); do { MOZ_CrashSequence(__null, 12588); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12589
12590 ParseNode* valueNode = exportNode->left();
12591 if (valueNode->isDirectRHSAnonFunction()) {
12592 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", 12592)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "exportNode->right()"
")"); do { MOZ_CrashSequence(__null, 12592); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12593
12594 if (!emitAnonymousFunctionWithName(
12595 valueNode, TaggedParserAtomIndex::WellKnown::default_())) {
12596 return false;
12597 }
12598 } else {
12599 if (!emitTree(valueNode)) {
12600 return false;
12601 }
12602 }
12603
12604 if (ParseNode* binding = exportNode->right()) {
12605 if (!emitLexicalInitialization(&binding->as<NameNode>())) {
12606 return false;
12607 }
12608
12609 if (!emit1(JSOp::Pop)) {
12610 return false;
12611 }
12612 }
12613
12614 return true;
12615}
12616
12617bool BytecodeEmitter::emitTree(
12618 ParseNode* pn, ValueUsage valueUsage /* = ValueUsage::WantValue */,
12619 EmitLineNumberNote emitLineNote /* = EMIT_LINENOTE */) {
12620 AutoCheckRecursionLimit recursion(fc);
12621 if (!recursion.check(fc)) {
12622 return false;
12623 }
12624
12625 /* Emit notes to tell the current bytecode's source line number.
12626 However, a couple trees require special treatment; see the
12627 relevant emitter functions for details. */
12628 if (emitLineNote == EMIT_LINENOTE &&
12629 !ParseNodeRequiresSpecialLineNumberNotes(pn)) {
12630 if (!updateLineNumberNotes(pn->pn_pos.begin)) {
12631 return false;
12632 }
12633 }
12634
12635 switch (pn->getKind()) {
12636 case ParseNodeKind::Function:
12637 if (!emitFunction(&pn->as<FunctionNode>())) {
12638 return false;
12639 }
12640 break;
12641
12642 case ParseNodeKind::ParamsBody:
12643 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"
, 12644); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "ParamsBody should be handled in emitFunctionScript."
")"); do { MOZ_CrashSequence(__null, 12644); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12644 "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"
, 12644); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "ParamsBody should be handled in emitFunctionScript."
")"); do { MOZ_CrashSequence(__null, 12644); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12645 break;
12646
12647 case ParseNodeKind::IfStmt:
12648 if (!emitIf(&pn->as<TernaryNode>())) {
12649 return false;
12650 }
12651 break;
12652
12653 case ParseNodeKind::SwitchStmt:
12654 if (!emitSwitch(&pn->as<SwitchStatement>())) {
12655 return false;
12656 }
12657 break;
12658
12659 case ParseNodeKind::WhileStmt:
12660 if (!emitWhile(&pn->as<BinaryNode>())) {
12661 return false;
12662 }
12663 break;
12664
12665 case ParseNodeKind::DoWhileStmt:
12666 if (!emitDo(&pn->as<BinaryNode>())) {
12667 return false;
12668 }
12669 break;
12670
12671 case ParseNodeKind::ForStmt:
12672 if (!emitFor(&pn->as<ForNode>())) {
12673 return false;
12674 }
12675 break;
12676
12677 case ParseNodeKind::BreakStmt:
12678 // Ensure that the column of the 'break' is set properly.
12679 if (!updateSourceCoordNotes(pn->pn_pos.begin)) {
12680 return false;
12681 }
12682 if (!markStepBreakpoint()) {
12683 return false;
12684 }
12685
12686 if (!emitBreak(pn->as<BreakStatement>().label())) {
12687 return false;
12688 }
12689 break;
12690
12691 case ParseNodeKind::ContinueStmt:
12692 // Ensure that the column of the 'continue' is set properly.
12693 if (!updateSourceCoordNotes(pn->pn_pos.begin)) {
12694 return false;
12695 }
12696 if (!markStepBreakpoint()) {
12697 return false;
12698 }
12699
12700 if (!emitContinue(pn->as<ContinueStatement>().label())) {
12701 return false;
12702 }
12703 break;
12704
12705 case ParseNodeKind::WithStmt:
12706 if (!emitWith(&pn->as<BinaryNode>())) {
12707 return false;
12708 }
12709 break;
12710
12711 case ParseNodeKind::TryStmt:
12712 if (!emitTry(&pn->as<TryNode>())) {
12713 return false;
12714 }
12715 break;
12716
12717 case ParseNodeKind::Catch:
12718 if (!emitCatch(&pn->as<BinaryNode>())) {
12719 return false;
12720 }
12721 break;
12722
12723 case ParseNodeKind::VarStmt:
12724 if (!emitDeclarationList(&pn->as<ListNode>())) {
12725 return false;
12726 }
12727 break;
12728
12729 case ParseNodeKind::ReturnStmt:
12730 if (!emitReturn(&pn->as<UnaryNode>())) {
12731 return false;
12732 }
12733 break;
12734
12735 case ParseNodeKind::YieldStarExpr:
12736 if (!emitYieldStar(pn->as<UnaryNode>().kid())) {
12737 return false;
12738 }
12739 break;
12740
12741 case ParseNodeKind::Generator:
12742 if (!emit1(JSOp::Generator)) {
12743 return false;
12744 }
12745 break;
12746
12747 case ParseNodeKind::InitialYield:
12748 if (!emitInitialYield(&pn->as<UnaryNode>())) {
12749 return false;
12750 }
12751 break;
12752
12753 case ParseNodeKind::YieldExpr:
12754 if (!emitYield(&pn->as<UnaryNode>())) {
12755 return false;
12756 }
12757 break;
12758
12759 case ParseNodeKind::AwaitExpr:
12760 if (!emitAwaitInInnermostScope(&pn->as<UnaryNode>())) {
12761 return false;
12762 }
12763 break;
12764
12765 case ParseNodeKind::StatementList:
12766 if (!emitStatementList(&pn->as<ListNode>())) {
12767 return false;
12768 }
12769 break;
12770
12771 case ParseNodeKind::EmptyStmt:
12772 break;
12773
12774 case ParseNodeKind::ExpressionStmt:
12775 if (!emitExpressionStatement(&pn->as<UnaryNode>())) {
12776 return false;
12777 }
12778 break;
12779
12780 case ParseNodeKind::LabelStmt:
12781 if (!emitLabeledStatement(&pn->as<LabeledStatement>())) {
12782 return false;
12783 }
12784 break;
12785
12786 case ParseNodeKind::CommaExpr:
12787 if (!emitSequenceExpr(&pn->as<ListNode>(), valueUsage)) {
12788 return false;
12789 }
12790 break;
12791
12792 case ParseNodeKind::InitExpr:
12793 case ParseNodeKind::AssignExpr:
12794 case ParseNodeKind::AddAssignExpr:
12795 case ParseNodeKind::SubAssignExpr:
12796 case ParseNodeKind::BitOrAssignExpr:
12797 case ParseNodeKind::BitXorAssignExpr:
12798 case ParseNodeKind::BitAndAssignExpr:
12799 case ParseNodeKind::LshAssignExpr:
12800 case ParseNodeKind::RshAssignExpr:
12801 case ParseNodeKind::UrshAssignExpr:
12802 case ParseNodeKind::MulAssignExpr:
12803 case ParseNodeKind::DivAssignExpr:
12804 case ParseNodeKind::ModAssignExpr:
12805 case ParseNodeKind::PowAssignExpr: {
12806 BinaryNode* assignNode = &pn->as<BinaryNode>();
12807 if (!emitAssignmentOrInit(assignNode->getKind(), assignNode->left(),
12808 assignNode->right())) {
12809 return false;
12810 }
12811 break;
12812 }
12813
12814 case ParseNodeKind::CoalesceAssignExpr:
12815 case ParseNodeKind::OrAssignExpr:
12816 case ParseNodeKind::AndAssignExpr:
12817 if (!emitShortCircuitAssignment(&pn->as<AssignmentNode>())) {
12818 return false;
12819 }
12820 break;
12821
12822 case ParseNodeKind::ConditionalExpr:
12823 if (!emitConditionalExpression(pn->as<ConditionalExpression>(),
12824 valueUsage)) {
12825 return false;
12826 }
12827 break;
12828
12829 case ParseNodeKind::OrExpr:
12830 case ParseNodeKind::CoalesceExpr:
12831 case ParseNodeKind::AndExpr:
12832 if (!emitShortCircuit(&pn->as<ListNode>(), valueUsage)) {
12833 return false;
12834 }
12835 break;
12836
12837 case ParseNodeKind::StrictEqExpr:
12838 case ParseNodeKind::EqExpr:
12839 case ParseNodeKind::StrictNeExpr:
12840 case ParseNodeKind::NeExpr:
12841 case ParseNodeKind::LtExpr:
12842 case ParseNodeKind::GtExpr: {
12843 bool emitted;
12844 if (!tryEmitTypeofEq(&pn->as<ListNode>(), &emitted)) {
12845 return false;
12846 }
12847 if (emitted) {
12848 return true;
12849 }
12850 }
12851 [[fallthrough]];
12852
12853 case ParseNodeKind::AddExpr:
12854 case ParseNodeKind::SubExpr:
12855 case ParseNodeKind::BitOrExpr:
12856 case ParseNodeKind::BitXorExpr:
12857 case ParseNodeKind::BitAndExpr:
12858 case ParseNodeKind::LeExpr:
12859 case ParseNodeKind::GeExpr:
12860 case ParseNodeKind::InExpr:
12861 case ParseNodeKind::InstanceOfExpr:
12862 case ParseNodeKind::LshExpr:
12863 case ParseNodeKind::RshExpr:
12864 case ParseNodeKind::UrshExpr:
12865 case ParseNodeKind::MulExpr:
12866 case ParseNodeKind::DivExpr:
12867 case ParseNodeKind::ModExpr:
12868 if (!emitLeftAssociative(&pn->as<ListNode>())) {
12869 return false;
12870 }
12871 break;
12872
12873 case ParseNodeKind::PrivateInExpr:
12874 if (!emitPrivateInExpr(&pn->as<ListNode>())) {
12875 return false;
12876 }
12877 break;
12878
12879 case ParseNodeKind::PowExpr:
12880 if (!emitRightAssociative(&pn->as<ListNode>())) {
12881 return false;
12882 }
12883 break;
12884
12885 case ParseNodeKind::TypeOfNameExpr:
12886 if (!emitTypeof(&pn->as<UnaryNode>(), JSOp::Typeof)) {
12887 return false;
12888 }
12889 break;
12890
12891 case ParseNodeKind::TypeOfExpr:
12892 if (!emitTypeof(&pn->as<UnaryNode>(), JSOp::TypeofExpr)) {
12893 return false;
12894 }
12895 break;
12896
12897 case ParseNodeKind::ThrowStmt:
12898 if (!updateSourceCoordNotes(pn->pn_pos.begin)) {
12899 return false;
12900 }
12901 if (!markStepBreakpoint()) {
12902 return false;
12903 }
12904 [[fallthrough]];
12905 case ParseNodeKind::VoidExpr:
12906 case ParseNodeKind::NotExpr:
12907 case ParseNodeKind::BitNotExpr:
12908 case ParseNodeKind::PosExpr:
12909 case ParseNodeKind::NegExpr:
12910 if (!emitUnary(&pn->as<UnaryNode>())) {
12911 return false;
12912 }
12913 break;
12914
12915 case ParseNodeKind::PreIncrementExpr:
12916 case ParseNodeKind::PreDecrementExpr:
12917 case ParseNodeKind::PostIncrementExpr:
12918 case ParseNodeKind::PostDecrementExpr:
12919 if (!emitIncOrDec(&pn->as<UnaryNode>(), valueUsage)) {
12920 return false;
12921 }
12922 break;
12923
12924 case ParseNodeKind::DeleteNameExpr:
12925 if (!emitDeleteName(&pn->as<UnaryNode>())) {
12926 return false;
12927 }
12928 break;
12929
12930 case ParseNodeKind::DeletePropExpr:
12931 if (!emitDeleteProperty(&pn->as<UnaryNode>())) {
12932 return false;
12933 }
12934 break;
12935
12936 case ParseNodeKind::DeleteElemExpr:
12937 if (!emitDeleteElement(&pn->as<UnaryNode>())) {
12938 return false;
12939 }
12940 break;
12941
12942 case ParseNodeKind::DeleteExpr:
12943 if (!emitDeleteExpression(&pn->as<UnaryNode>())) {
12944 return false;
12945 }
12946 break;
12947
12948 case ParseNodeKind::DeleteOptionalChainExpr:
12949 if (!emitDeleteOptionalChain(&pn->as<UnaryNode>())) {
12950 return false;
12951 }
12952 break;
12953
12954 case ParseNodeKind::OptionalChain:
12955 if (!emitOptionalChain(&pn->as<UnaryNode>(), valueUsage)) {
12956 return false;
12957 }
12958 break;
12959
12960 case ParseNodeKind::DotExpr: {
12961 PropertyAccess* prop = &pn->as<PropertyAccess>();
12962 bool isSuper = prop->isSuper();
12963 PropOpEmitter poe(this, PropOpEmitter::Kind::Get,
12964 isSuper ? PropOpEmitter::ObjKind::Super
12965 : PropOpEmitter::ObjKind::Other);
12966 if (!poe.prepareForObj()) {
12967 return false;
12968 }
12969 if (isSuper) {
12970 UnaryNode* base = &prop->expression().as<UnaryNode>();
12971 if (!emitGetThisForSuperBase(base)) {
12972 // [stack] THIS
12973 return false;
12974 }
12975 } else {
12976 if (!emitPropLHS(prop)) {
12977 // [stack] OBJ
12978 return false;
12979 }
12980 }
12981 if (!poe.emitGet(prop->key().atom())) {
12982 // [stack] PROP
12983 return false;
12984 }
12985 break;
12986 }
12987
12988 case ParseNodeKind::ArgumentsLength: {
12989 if (!emitArgumentsLength()) {
12990 return false;
12991 }
12992 break;
12993 }
12994
12995 case ParseNodeKind::ElemExpr: {
12996 PropertyByValue* elem = &pn->as<PropertyByValue>();
12997 bool isSuper = elem->isSuper();
12998 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", 12998)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)"
")"); do { MOZ_CrashSequence(__null, 12998); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12999 ElemOpEmitter eoe(this, ElemOpEmitter::Kind::Get,
13000 isSuper ? ElemOpEmitter::ObjKind::Super
13001 : ElemOpEmitter::ObjKind::Other);
13002 if (!emitElemObjAndKey(elem, eoe)) {
13003 // [stack] # if Super
13004 // [stack] THIS KEY
13005 // [stack] # otherwise
13006 // [stack] OBJ KEY
13007 return false;
13008 }
13009 if (!eoe.emitGet()) {
13010 // [stack] ELEM
13011 return false;
13012 }
13013
13014 break;
13015 }
13016
13017 case ParseNodeKind::PrivateMemberExpr: {
13018 PrivateMemberAccess* privateExpr = &pn->as<PrivateMemberAccess>();
13019 PrivateOpEmitter xoe(this, PrivateOpEmitter::Kind::Get,
13020 privateExpr->privateName().name());
13021 if (!emitTree(&privateExpr->expression())) {
13022 // [stack] OBJ
13023 return false;
13024 }
13025 if (!xoe.emitReference()) {
13026 // [stack] OBJ NAME
13027 return false;
13028 }
13029 if (!xoe.emitGet()) {
13030 // [stack] VALUE
13031 return false;
13032 }
13033
13034 break;
13035 }
13036
13037 case ParseNodeKind::NewExpr:
13038 case ParseNodeKind::TaggedTemplateExpr:
13039 case ParseNodeKind::CallExpr:
13040 case ParseNodeKind::SuperCallExpr:
13041 if (!emitCallOrNew(&pn->as<CallNode>(), valueUsage)) {
13042 return false;
13043 }
13044 break;
13045
13046 case ParseNodeKind::LexicalScope:
13047 if (!emitLexicalScope(&pn->as<LexicalScopeNode>())) {
13048 return false;
13049 }
13050 break;
13051
13052 case ParseNodeKind::ConstDecl:
13053 case ParseNodeKind::LetDecl:
13054 if (!emitDeclarationList(&pn->as<ListNode>())) {
13055 return false;
13056 }
13057 break;
13058 case ParseNodeKind::AwaitUsingDecl:
13059 case ParseNodeKind::UsingDecl:
13060 if (!emitDeclarationList(&pn->as<ListNode>())) {
13061 return false;
13062 }
13063 break;
13064
13065 case ParseNodeKind::ImportDecl:
13066 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", 13066)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isModuleContext()"
")"); do { MOZ_CrashSequence(__null, 13066); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13067 break;
13068
13069 case ParseNodeKind::ExportStmt: {
13070 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", 13070)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isModuleContext()"
")"); do { MOZ_CrashSequence(__null, 13070); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13071 UnaryNode* node = &pn->as<UnaryNode>();
13072 ParseNode* decl = node->kid();
13073 if (decl->getKind() != ParseNodeKind::ExportSpecList) {
13074 if (!emitTree(decl)) {
13075 return false;
13076 }
13077 }
13078 break;
13079 }
13080
13081 case ParseNodeKind::ExportDefaultStmt:
13082 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", 13082)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isModuleContext()"
")"); do { MOZ_CrashSequence(__null, 13082); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13083 if (!emitExportDefault(&pn->as<BinaryNode>())) {
13084 return false;
13085 }
13086 break;
13087
13088 case ParseNodeKind::ExportFromStmt:
13089 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", 13089)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isModuleContext()"
")"); do { MOZ_CrashSequence(__null, 13089); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13090 break;
13091
13092 case ParseNodeKind::CallSiteObj:
13093 if (!emitCallSiteObject(&pn->as<CallSiteNode>())) {
13094 return false;
13095 }
13096 break;
13097
13098 case ParseNodeKind::ArrayExpr:
13099 if (!emitArrayLiteral(&pn->as<ListNode>())) {
13100 return false;
13101 }
13102 break;
13103
13104 case ParseNodeKind::ObjectExpr:
13105 if (!emitObject(&pn->as<ListNode>())) {
13106 return false;
13107 }
13108 break;
13109
13110 case ParseNodeKind::Name:
13111 if (!emitGetName(&pn->as<NameNode>())) {
13112 return false;
13113 }
13114 break;
13115
13116 case ParseNodeKind::PrivateName:
13117 if (!emitGetPrivateName(&pn->as<NameNode>())) {
13118 return false;
13119 }
13120 break;
13121
13122 case ParseNodeKind::TemplateStringListExpr:
13123 if (!emitTemplateString(&pn->as<ListNode>())) {
13124 return false;
13125 }
13126 break;
13127
13128 case ParseNodeKind::TemplateStringExpr:
13129 case ParseNodeKind::StringExpr:
13130 if (!emitStringOp(JSOp::String, pn->as<NameNode>().atom())) {
13131 return false;
13132 }
13133 break;
13134
13135 case ParseNodeKind::NumberExpr:
13136 if (!emitNumberOp(pn->as<NumericLiteral>().value())) {
13137 return false;
13138 }
13139 break;
13140
13141 case ParseNodeKind::BigIntExpr:
13142 if (!emitBigIntOp(&pn->as<BigIntLiteral>())) {
13143 return false;
13144 }
13145 break;
13146
13147 case ParseNodeKind::RegExpExpr: {
13148 GCThingIndex index;
13149 if (!perScriptData().gcThingList().append(&pn->as<RegExpLiteral>(),
13150 &index)) {
13151 return false;
13152 }
13153 if (!emitRegExp(index)) {
13154 return false;
13155 }
13156 break;
13157 }
13158
13159 case ParseNodeKind::TrueExpr:
13160 if (!emit1(JSOp::True)) {
13161 return false;
13162 }
13163 break;
13164 case ParseNodeKind::FalseExpr:
13165 if (!emit1(JSOp::False)) {
13166 return false;
13167 }
13168 break;
13169 case ParseNodeKind::NullExpr:
13170 if (!emit1(JSOp::Null)) {
13171 return false;
13172 }
13173 break;
13174 case ParseNodeKind::RawUndefinedExpr:
13175 if (!emit1(JSOp::Undefined)) {
13176 return false;
13177 }
13178 break;
13179
13180 case ParseNodeKind::ThisExpr:
13181 if (!emitThisLiteral(&pn->as<ThisLiteral>())) {
13182 return false;
13183 }
13184 break;
13185
13186 case ParseNodeKind::DebuggerStmt:
13187 if (!updateSourceCoordNotes(pn->pn_pos.begin)) {
13188 return false;
13189 }
13190 if (!markStepBreakpoint()) {
13191 return false;
13192 }
13193 if (!emit1(JSOp::Debugger)) {
13194 return false;
13195 }
13196 break;
13197
13198 case ParseNodeKind::ClassDecl:
13199 if (!emitClass(&pn->as<ClassNode>())) {
13200 return false;
13201 }
13202 break;
13203
13204 case ParseNodeKind::NewTargetExpr:
13205 if (!emitNewTarget(&pn->as<NewTargetNode>())) {
13206 return false;
13207 }
13208 break;
13209
13210 case ParseNodeKind::ImportMetaExpr:
13211 if (!emit1(JSOp::ImportMeta)) {
13212 return false;
13213 }
13214 break;
13215
13216 case ParseNodeKind::CallImportExpr: {
13217 CallImportNode* callImport = &pn->as<CallImportNode>();
13218 BinaryNode* spec = &callImport->right()->as<BinaryNode>();
13219
13220 if (!emitTree(spec->left())) {
13221 // [stack] specifier
13222 return false;
13223 }
13224
13225 // import.source does not have an options parameter, so its spec always
13226 // carries a PosHolder in place of the options argument.
13227 if (!spec->right()->isKind(ParseNodeKind::PosHolder)) {
13228 // [stack] specifier options
13229 if (!emitTree(spec->right())) {
13230 return false;
13231 }
13232 } else {
13233 // [stack] specifier undefined
13234 if (!emit1(JSOp::Undefined)) {
13235 return false;
13236 }
13237 }
13238
13239 if (!emit2(JSOp::DynamicImport, uint8_t(callImport->phase()))) {
13240 return false;
13241 }
13242
13243 break;
13244 }
13245
13246 case ParseNodeKind::SetThis:
13247 if (!emitSetThis(&pn->as<BinaryNode>())) {
13248 return false;
13249 }
13250 break;
13251
13252 case ParseNodeKind::PropertyNameExpr:
13253 case ParseNodeKind::PosHolder:
13254 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", 13255)
; AnnotateMozCrashReason("MOZ_CRASH(" "MOZ_FALLTHROUGH_ASSERT: "
"Should never try to emit ParseNodeKind::PosHolder or ::Property"
")"); do { MOZ_CrashSequence(__null, 13255); __attribute__((
nomerge)) ::abort(); } while (false); } while (false)
13255 "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", 13255)
; AnnotateMozCrashReason("MOZ_CRASH(" "MOZ_FALLTHROUGH_ASSERT: "
"Should never try to emit ParseNodeKind::PosHolder or ::Property"
")"); do { MOZ_CrashSequence(__null, 13255); __attribute__((
nomerge)) ::abort(); } while (false); } while (false)
;
13256
13257 default:
13258 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", 13258
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0" ")"); do { MOZ_CrashSequence
(__null, 13258); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
13259 }
13260
13261 return true;
13262}
13263
13264static bool AllocSrcNote(FrontendContext* fc, SrcNotesVector& notes,
13265 unsigned size, unsigned* index) {
13266 size_t oldLength = notes.length();
13267
13268 if (MOZ_UNLIKELY(oldLength + size > MaxSrcNotesLength)(__builtin_expect(!!(oldLength + size > MaxSrcNotesLength)
, 0))
) {
13269 ReportAllocationOverflow(fc);
13270 return false;
13271 }
13272
13273 if (!notes.growByUninitialized(size)) {
13274 return false;
13275 }
13276
13277 *index = oldLength;
13278 return true;
13279}
13280
13281bool BytecodeEmitter::addTryNote(TryNoteKind kind, uint32_t stackDepth,
13282 BytecodeOffset start, BytecodeOffset end) {
13283 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", 13283);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inPrologue()" ")")
; do { MOZ_CrashSequence(__null, 13283); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
13284 return bytecodeSection().tryNoteList().append(kind, stackDepth, start, end);
13285}
13286
13287bool BytecodeEmitter::newSrcNote(SrcNoteType type, unsigned* indexp) {
13288 SrcNotesVector& notes = bytecodeSection().notes();
13289 unsigned index;
13290
13291 /*
13292 * Compute delta from the last annotated bytecode's offset. If it's too
13293 * big to fit in sn, allocate one or more xdelta notes and reset sn.
13294 */
13295 BytecodeOffset offset = bytecodeSection().offset();
13296 ptrdiff_t delta = (offset - bytecodeSection().lastNoteOffset()).value();
13297 bytecodeSection().setLastNoteOffset(offset);
13298
13299 auto allocator = [&](unsigned size) -> SrcNote* {
13300 if (!AllocSrcNote(fc, notes, size, &index)) {
13301 return nullptr;
13302 }
13303 return &notes[index];
13304 };
13305
13306 if (!SrcNoteWriter::writeNote(type, delta, allocator)) {
13307 return false;
13308 }
13309
13310 if (indexp) {
13311 *indexp = index;
13312 }
13313
13314 if (type == SrcNoteType::NewLine || type == SrcNoteType::SetLine) {
13315 lastLineOnlySrcNoteIndex = index;
13316 } else {
13317 lastLineOnlySrcNoteIndex = LastSrcNoteIsNotLineOnly;
13318 }
13319
13320 return true;
13321}
13322
13323bool BytecodeEmitter::newSrcNote2(SrcNoteType type, ptrdiff_t offset,
13324 unsigned* indexp) {
13325 unsigned index;
13326 if (!newSrcNote(type, &index)) {
13327 return false;
13328 }
13329 if (!newSrcNoteOperand(offset)) {
13330 return false;
13331 }
13332 if (indexp) {
13333 *indexp = index;
13334 }
13335 return true;
13336}
13337
13338bool BytecodeEmitter::convertLastNewLineToNewLineColumn(
13339 JS::LimitedColumnNumberOneOrigin column) {
13340 SrcNotesVector& notes = bytecodeSection().notes();
13341 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", 13341)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "lastLineOnlySrcNoteIndex == notes.length() - 1"
")"); do { MOZ_CrashSequence(__null, 13341); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13342 SrcNote* sn = &notes[lastLineOnlySrcNoteIndex];
13343 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", 13343)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "sn->type() == SrcNoteType::NewLine"
")"); do { MOZ_CrashSequence(__null, 13343); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13344
13345 SrcNoteWriter::convertNote(sn, SrcNoteType::NewLineColumn);
13346 if (!newSrcNoteOperand(SrcNote::NewLineColumn::toOperand(column))) {
13347 return false;
13348 }
13349
13350 lastLineOnlySrcNoteIndex = LastSrcNoteIsNotLineOnly;
13351 return true;
13352}
13353
13354bool BytecodeEmitter::convertLastSetLineToSetLineColumn(
13355 JS::LimitedColumnNumberOneOrigin column) {
13356 SrcNotesVector& notes = bytecodeSection().notes();
13357 // The Line operand is either 1 byte or 4 bytes.
13358 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", 13359)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "lastLineOnlySrcNoteIndex == notes.length() - 1 - 1 || lastLineOnlySrcNoteIndex == notes.length() - 1 - 4"
")"); do { MOZ_CrashSequence(__null, 13359); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
13359 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", 13359)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "lastLineOnlySrcNoteIndex == notes.length() - 1 - 1 || lastLineOnlySrcNoteIndex == notes.length() - 1 - 4"
")"); do { MOZ_CrashSequence(__null, 13359); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13360 SrcNote* sn = &notes[lastLineOnlySrcNoteIndex];
13361 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", 13361)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "sn->type() == SrcNoteType::SetLine"
")"); do { MOZ_CrashSequence(__null, 13361); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13362
13363 SrcNoteWriter::convertNote(sn, SrcNoteType::SetLineColumn);
13364 if (!newSrcNoteOperand(SrcNote::SetLineColumn::columnToOperand(column))) {
13365 return false;
13366 }
13367
13368 lastLineOnlySrcNoteIndex = LastSrcNoteIsNotLineOnly;
13369 return true;
13370}
13371
13372bool BytecodeEmitter::newSrcNoteOperand(ptrdiff_t operand) {
13373 if (!SrcNote::isRepresentableOperand(operand)) {
13374 reportError(nullptr, JSMSG_NEED_DIET, "script");
13375 return false;
13376 }
13377
13378 SrcNotesVector& notes = bytecodeSection().notes();
13379
13380 auto allocator = [&](unsigned size) -> SrcNote* {
13381 unsigned index;
13382 if (!AllocSrcNote(fc, notes, size, &index)) {
13383 return nullptr;
13384 }
13385 return &notes[index];
13386 };
13387
13388 return SrcNoteWriter::writeOperand(operand, allocator);
13389}
13390
13391bool BytecodeEmitter::intoScriptStencil(ScriptIndex scriptIndex) {
13392 js::UniquePtr<ImmutableScriptData> immutableScriptData =
13393 createImmutableScriptData();
13394 if (!immutableScriptData) {
13395 return false;
13396 }
13397
13398 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", 13399)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "outermostScope().hasNonSyntacticScopeOnChain() == sc->hasNonSyntacticScope()"
")"); do { MOZ_CrashSequence(__null, 13399); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
13399 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", 13399)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "outermostScope().hasNonSyntacticScopeOnChain() == sc->hasNonSyntacticScope()"
")"); do { MOZ_CrashSequence(__null, 13399); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13400
13401 auto& things = perScriptData().gcThingList().objects();
13402 if (!compilationState.appendGCThings(fc, scriptIndex, things)) {
13403 return false;
13404 }
13405
13406 // Hand over the ImmutableScriptData instance generated by BCE.
13407 auto* sharedData =
13408 SharedImmutableScriptData::createWith(fc, std::move(immutableScriptData));
13409 if (!sharedData) {
13410 return false;
13411 }
13412
13413 // De-duplicate the bytecode within the runtime.
13414 if (!compilationState.sharedData.addAndShare(fc, scriptIndex, sharedData)) {
13415 return false;
13416 }
13417
13418 ScriptStencil& script = compilationState.scriptData[scriptIndex];
13419 script.setHasSharedData();
13420
13421 // Update flags specific to functions.
13422 if (sc->isFunctionBox()) {
13423 FunctionBox* funbox = sc->asFunctionBox();
13424 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", 13424)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "&script == &funbox->functionStencil()"
")"); do { MOZ_CrashSequence(__null, 13424); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13425 funbox->copyUpdatedImmutableFlags();
13426 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", 13426)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "script.isFunction()"
")"); do { MOZ_CrashSequence(__null, 13426); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13427 } else {
13428 ScriptStencilExtra& scriptExtra = compilationState.scriptExtra[scriptIndex];
13429 sc->copyScriptExtraFields(scriptExtra);
13430 }
13431
13432 return true;
13433}
13434
13435SelfHostedIter BytecodeEmitter::getSelfHostedIterFor(
13436 ParseNode* parseNode) const {
13437 if (emitterMode == BytecodeEmitter::SelfHosting &&
13438 parseNode->isKind(ParseNodeKind::CallExpr)) {
13439 auto* callee = parseNode->as<CallNode>().callee();
13440 if (callee->isName(TaggedParserAtomIndex::WellKnown::allowContentIter())) {
13441 return SelfHostedIter::AllowContent;
13442 }
13443 if (callee->isName(
13444 TaggedParserAtomIndex::WellKnown::allowContentIterWith())) {
13445 return SelfHostedIter::AllowContentWith;
13446 }
13447 if (callee->isName(
13448 TaggedParserAtomIndex::WellKnown::allowContentIterWithNext())) {
13449 return SelfHostedIter::AllowContentWithNext;
13450 }
13451 }
13452
13453 return SelfHostedIter::Deny;
13454}
13455
13456#if defined(DEBUG1) || defined(JS_JITSPEW1)
13457void BytecodeEmitter::dumpAtom(TaggedParserAtomIndex index) const {
13458 parserAtoms().dump(index);
13459}
13460#endif