Bug Summary

File:var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp
Warning:line 821, 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 -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=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/js/src/frontend -fcoverage-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/js/src/frontend -resource-dir /usr/lib/llvm-19/lib/clang/19 -include /var/lib/jenkins/workspace/firefox-scan-build/config/gcc_hidden.h -include /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -I /var/lib/jenkins/workspace/firefox-scan-build/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 /var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/js/src/frontend -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/js/src -I /var/lib/jenkins/workspace/firefox-scan-build/js/src -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/backward -internal-isystem /usr/lib/llvm-19/lib/clang/19/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -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-deprecated-this-capture -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 -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 -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2024-09-22-115206-3586786-1 -x c++ Unified_cpp_js_src_frontend0.cpp
1/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=8 sts=2 et sw=2 tw=80:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7/*
8 * JS bytecode generation.
9 */
10
11#include "frontend/BytecodeEmitter.h"
12
13#include "mozilla/Casting.h" // mozilla::AssertedCast
14#include "mozilla/DebugOnly.h" // mozilla::DebugOnly
15#include "mozilla/FloatingPoint.h" // mozilla::NumberEqualsInt32, mozilla::NumberIsInt32
16#include "mozilla/HashTable.h" // mozilla::HashSet
17#include "mozilla/Maybe.h" // mozilla::{Maybe,Nothing,Some}
18#include "mozilla/Saturate.h"
19#include "mozilla/Variant.h" // mozilla::AsVariant
20
21#include <algorithm>
22#include <iterator>
23#include <string.h>
24
25#include "jstypes.h" // JS_BIT
26
27#include "frontend/AbstractScopePtr.h" // ScopeIndex
28#include "frontend/BytecodeControlStructures.h" // NestableControl, BreakableControl, LabelControl, LoopControl, TryFinallyControl
29#include "frontend/CallOrNewEmitter.h" // CallOrNewEmitter
30#include "frontend/CForEmitter.h" // CForEmitter
31#include "frontend/DecoratorEmitter.h" // DecoratorEmitter
32#include "frontend/DefaultEmitter.h" // DefaultEmitter
33#include "frontend/DoWhileEmitter.h" // DoWhileEmitter
34#include "frontend/ElemOpEmitter.h" // ElemOpEmitter
35#include "frontend/EmitterScope.h" // EmitterScope
36#include "frontend/ExpressionStatementEmitter.h" // ExpressionStatementEmitter
37#include "frontend/ForInEmitter.h" // ForInEmitter
38#include "frontend/ForOfEmitter.h" // ForOfEmitter
39#include "frontend/FunctionEmitter.h" // FunctionEmitter, FunctionScriptEmitter, FunctionParamsEmitter
40#include "frontend/IfEmitter.h" // IfEmitter, InternalIfEmitter, CondEmitter
41#include "frontend/LabelEmitter.h" // LabelEmitter
42#include "frontend/LexicalScopeEmitter.h" // LexicalScopeEmitter
43#include "frontend/ModuleSharedContext.h" // ModuleSharedContext
44#include "frontend/NameAnalysisTypes.h" // PrivateNameKind
45#include "frontend/NameFunctions.h" // NameFunctions
46#include "frontend/NameOpEmitter.h" // NameOpEmitter
47#include "frontend/ObjectEmitter.h" // PropertyEmitter, ObjectEmitter, ClassEmitter
48#include "frontend/OptionalEmitter.h" // OptionalEmitter
49#include "frontend/ParseContext.h" // ParseContext::Scope
50#include "frontend/ParseNode.h" // ParseNodeKind, ParseNode and subclasses
51#include "frontend/Parser.h" // Parser
52#include "frontend/ParserAtom.h" // ParserAtomsTable, ParserAtom
53#include "frontend/PrivateOpEmitter.h" // PrivateOpEmitter
54#include "frontend/PropOpEmitter.h" // PropOpEmitter
55#include "frontend/SourceNotes.h" // SrcNote, SrcNoteType, SrcNoteWriter
56#include "frontend/SwitchEmitter.h" // SwitchEmitter
57#include "frontend/TaggedParserAtomIndexHasher.h" // TaggedParserAtomIndexHasher
58#include "frontend/TDZCheckCache.h" // TDZCheckCache
59#include "frontend/TryEmitter.h" // TryEmitter
60#include "frontend/UsingEmitter.h" // UsingEmitter
61#include "frontend/WhileEmitter.h" // WhileEmitter
62#include "js/ColumnNumber.h" // JS::LimitedColumnNumberOneOrigin, JS::ColumnNumberOffset
63#include "js/friend/ErrorMessages.h" // JSMSG_*
64#include "js/friend/StackLimits.h" // AutoCheckRecursionLimit
65#include "util/StringBuilder.h" // StringBuilder
66#include "vm/BytecodeUtil.h" // JOF_*, IsArgOp, IsLocalOp, SET_UINT24, SET_ICINDEX, BytecodeFallsThrough, BytecodeIsJumpTarget
67#include "vm/CompletionKind.h" // CompletionKind
68#include "vm/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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 151); AnnotateMozCrashReason("MOZ_ASSERT" "(" "fc == parent->fc"
")"); do { *((volatile int*)__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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 295); AnnotateMozCrashReason("MOZ_ASSERT" "(" "checkStrictOrSloppy(op)"
")"); do { *((volatile int*)__null) = 295; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
296
297 BytecodeOffset offset;
298 if (!emitCheck(op, 1, &offset)) {
299 return false;
300 }
301
302 jsbytecode* code = bytecodeSection().code(offset);
303 code[0] = jsbytecode(op);
304 bytecodeSection().updateDepth(op, offset);
305 return true;
306}
307
308bool BytecodeEmitter::emit2(JSOp op, uint8_t op1) {
309 MOZ_ASSERT(checkStrictOrSloppy(op))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(checkStrictOrSloppy(op))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(checkStrictOrSloppy(op)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("checkStrictOrSloppy(op)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 309); AnnotateMozCrashReason("MOZ_ASSERT" "(" "checkStrictOrSloppy(op)"
")"); do { *((volatile int*)__null) = 309; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
310
311 BytecodeOffset offset;
312 if (!emitCheck(op, 2, &offset)) {
313 return false;
314 }
315
316 jsbytecode* code = bytecodeSection().code(offset);
317 code[0] = jsbytecode(op);
318 code[1] = jsbytecode(op1);
319 bytecodeSection().updateDepth(op, offset);
320 return true;
321}
322
323bool BytecodeEmitter::emit3(JSOp op, jsbytecode op1, jsbytecode op2) {
324 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 324); AnnotateMozCrashReason("MOZ_ASSERT" "(" "checkStrictOrSloppy(op)"
")"); do { *((volatile int*)__null) = 324; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
325
326 /* These should filter through emitVarOp. */
327 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)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 327); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsArgOp(op)"
")"); do { *((volatile int*)__null) = 327; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
328 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 328); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsLocalOp(op)"
")"); do { *((volatile int*)__null) = 328; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
329
330 BytecodeOffset offset;
331 if (!emitCheck(op, 3, &offset)) {
332 return false;
333 }
334
335 jsbytecode* code = bytecodeSection().code(offset);
336 code[0] = jsbytecode(op);
337 code[1] = op1;
338 code[2] = op2;
339 bytecodeSection().updateDepth(op, offset);
340 return true;
341}
342
343bool BytecodeEmitter::emitN(JSOp op, size_t extra, BytecodeOffset* offset) {
344 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 344); AnnotateMozCrashReason("MOZ_ASSERT" "(" "checkStrictOrSloppy(op)"
")"); do { *((volatile int*)__null) = 344; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
345 ptrdiff_t length = 1 + ptrdiff_t(extra);
346
347 BytecodeOffset off;
348 if (!emitCheck(op, length, &off)) {
349 return false;
350 }
351
352 jsbytecode* code = bytecodeSection().code(off);
353 code[0] = jsbytecode(op);
354 /* The remaining |extra| bytes are set by the caller */
355
356 /*
357 * Don't updateDepth if op's use-count comes from the immediate
358 * operand yet to be stored in the extra bytes after op.
359 */
360 if (CodeSpec(op).nuses >= 0) {
361 bytecodeSection().updateDepth(op, off);
362 }
363
364 if (offset) {
365 *offset = off;
366 }
367 return true;
368}
369
370bool BytecodeEmitter::emitJumpTargetOp(JSOp op, BytecodeOffset* off) {
371 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 371); AnnotateMozCrashReason("MOZ_ASSERT" "(" "BytecodeIsJumpTarget(op)"
")"); do { *((volatile int*)__null) = 371; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
372
373 // Record the current IC-entry index at start of this op.
374 uint32_t numEntries = bytecodeSection().numICEntries();
375
376 size_t n = GetOpLength(op) - 1;
377 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 377); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetOpLength(op) >= 1 + ICINDEX_LEN"
")"); do { *((volatile int*)__null) = 377; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
378
379 if (!emitN(op, n, off)) {
380 return false;
381 }
382
383 SET_ICINDEX(bytecodeSection().code(*off), numEntries);
384 return true;
385}
386
387bool BytecodeEmitter::emitJumpTarget(JumpTarget* target) {
388 BytecodeOffset off = bytecodeSection().offset();
389
390 // Alias consecutive jump targets.
391 if (bytecodeSection().lastTargetOffset().valid() &&
392 off == bytecodeSection().lastTargetOffset() +
393 BytecodeOffsetDiff(JSOpLength_JumpTarget)) {
394 target->offset = bytecodeSection().lastTargetOffset();
395 return true;
396 }
397
398 target->offset = off;
399 bytecodeSection().setLastTargetOffset(off);
400
401 BytecodeOffset opOff;
402 return emitJumpTargetOp(JSOp::JumpTarget, &opOff);
403}
404
405bool BytecodeEmitter::emitJumpNoFallthrough(JSOp op, JumpList* jump) {
406 BytecodeOffset offset;
407 if (!emitCheck(op, 5, &offset)) {
408 return false;
409 }
410
411 jsbytecode* code = bytecodeSection().code(offset);
412 code[0] = jsbytecode(op);
413 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 414); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!jump->offset.valid() || (0 <= jump->offset.value() && jump->offset < offset)"
")"); do { *((volatile int*)__null) = 414; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
414 (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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 414); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!jump->offset.valid() || (0 <= jump->offset.value() && jump->offset < offset)"
")"); do { *((volatile int*)__null) = 414; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
415 jump->push(bytecodeSection().code(BytecodeOffset(0)), offset);
416 bytecodeSection().updateDepth(op, offset);
417 return true;
418}
419
420bool BytecodeEmitter::emitJump(JSOp op, JumpList* jump) {
421 if (!emitJumpNoFallthrough(op, jump)) {
422 return false;
423 }
424 if (BytecodeFallsThrough(op)) {
425 JumpTarget fallthrough;
426 if (!emitJumpTarget(&fallthrough)) {
427 return false;
428 }
429 }
430 return true;
431}
432
433void BytecodeEmitter::patchJumpsToTarget(JumpList jump, JumpTarget target) {
434 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())"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 436); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset())"
")"); do { *((volatile int*)__null) = 436; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
435 !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())"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 436); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset())"
")"); do { *((volatile int*)__null) = 436; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
436 (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())"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 436); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset())"
")"); do { *((volatile int*)__null) = 436; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
437 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 438); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0 <= target.offset.value() && target.offset <= bytecodeSection().offset()"
")"); do { *((volatile int*)__null) = 438; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
438 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 438); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0 <= target.offset.value() && target.offset <= bytecodeSection().offset()"
")"); do { *((volatile int*)__null) = 438; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
439 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)))"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 442); AnnotateMozCrashReason("MOZ_ASSERT" "(" "BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))"
")"); do { *((volatile int*)__null) = 442; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
440 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)))"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 442); AnnotateMozCrashReason("MOZ_ASSERT" "(" "BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))"
")"); do { *((volatile int*)__null) = 442; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
441 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)))"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 442); AnnotateMozCrashReason("MOZ_ASSERT" "(" "BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))"
")"); do { *((volatile int*)__null) = 442; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
442 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)))"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 442); AnnotateMozCrashReason("MOZ_ASSERT" "(" "BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))"
")"); do { *((volatile int*)__null) = 442; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
443 jump.patchAll(bytecodeSection().code(BytecodeOffset(0)), target);
444}
445
446bool BytecodeEmitter::emitJumpTargetAndPatch(JumpList jump) {
447 if (!jump.offset.valid()) {
448 return true;
449 }
450 JumpTarget target;
451 if (!emitJumpTarget(&target)) {
452 return false;
453 }
454 patchJumpsToTarget(jump, target);
455 return true;
456}
457
458bool BytecodeEmitter::emitCall(JSOp op, uint16_t argc,
459 const Maybe<uint32_t>& sourceCoordOffset) {
460 if (sourceCoordOffset.isSome()) {
461 if (!updateSourceCoordNotes(*sourceCoordOffset)) {
462 return false;
463 }
464 }
465 return emit3(op, ARGC_LO(argc), ARGC_HI(argc));
466}
467
468bool BytecodeEmitter::emitCall(JSOp op, uint16_t argc, ParseNode* pn) {
469 return emitCall(op, argc, pn ? Some(pn->pn_pos.begin) : Nothing());
470}
471
472bool BytecodeEmitter::emitDupAt(unsigned slotFromTop, unsigned count) {
473 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())",
"/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 473); AnnotateMozCrashReason("MOZ_ASSERT" "(" "slotFromTop < unsigned(bytecodeSection().stackDepth())"
")"); do { *((volatile int*)__null) = 473; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
474 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 474); AnnotateMozCrashReason("MOZ_ASSERT" "(" "slotFromTop + 1 >= count"
")"); do { *((volatile int*)__null) = 474; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
475
476 if (slotFromTop == 0 && count == 1) {
477 return emit1(JSOp::Dup);
478 }
479
480 if (slotFromTop == 1 && count == 2) {
481 return emit1(JSOp::Dup2);
482 }
483
484 if (slotFromTop >= Bit(24)) {
485 reportError(nullptr, JSMSG_TOO_MANY_LOCALS);
486 return false;
487 }
488
489 for (unsigned i = 0; i < count; i++) {
490 BytecodeOffset off;
491 if (!emitN(JSOp::DupAt, 3, &off)) {
492 return false;
493 }
494
495 jsbytecode* pc = bytecodeSection().code(off);
496 SET_UINT24(pc, slotFromTop);
497 }
498
499 return true;
500}
501
502bool BytecodeEmitter::emitPopN(unsigned n) {
503 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 503); AnnotateMozCrashReason("MOZ_ASSERT" "(" "n != 0" ")")
; do { *((volatile int*)__null) = 503; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
504
505 if (n == 1) {
506 return emit1(JSOp::Pop);
507 }
508
509 // 2 JSOp::Pop instructions (2 bytes) are shorter than JSOp::PopN (3 bytes).
510 if (n == 2) {
511 return emit1(JSOp::Pop) && emit1(JSOp::Pop);
512 }
513
514 return emitUint16Operand(JSOp::PopN, n);
515}
516
517bool BytecodeEmitter::emitPickN(uint8_t n) {
518 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 518); AnnotateMozCrashReason("MOZ_ASSERT" "(" "n != 0" ")")
; do { *((volatile int*)__null) = 518; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
519
520 if (n == 1) {
521 return emit1(JSOp::Swap);
522 }
523
524 return emit2(JSOp::Pick, n);
525}
526
527bool BytecodeEmitter::emitUnpickN(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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 528); AnnotateMozCrashReason("MOZ_ASSERT" "(" "n != 0" ")")
; do { *((volatile int*)__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::Unpick, n);
535}
536
537bool BytecodeEmitter::emitCheckIsObj(CheckIsObjectKind kind) {
538 return emit2(JSOp::CheckIsObj, uint8_t(kind));
539}
540
541bool BytecodeEmitter::emitBuiltinObject(BuiltinObjectKind kind) {
542 return emit2(JSOp::BuiltinObject, uint8_t(kind));
543}
544
545/* Updates line number notes, not column notes. */
546bool BytecodeEmitter::updateLineNumberNotes(uint32_t offset) {
547 if (skipLocationSrcNotes()) {
548 return true;
549 }
550
551 const ErrorReporter& er = errorReporter();
552 std::optional<bool> onThisLineStatus =
553 er.isOnThisLine(offset, bytecodeSection().currentLine());
554 if (!onThisLineStatus.has_value()) {
555 er.errorNoOffset(JSMSG_OUT_OF_MEMORY);
556 return false;
557 }
558
559 bool onThisLine = *onThisLineStatus;
560
561 if (!onThisLine) {
562 unsigned line = er.lineAt(offset);
563 unsigned delta = line - bytecodeSection().currentLine();
564
565 // If we use a `SetLine` note below, we want it to be relative to the
566 // scripts initial line number for better chance of sharing.
567 unsigned initialLine = sc->extent().lineno;
568 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 568); AnnotateMozCrashReason("MOZ_ASSERT" "(" "line >= initialLine"
")"); do { *((volatile int*)__null) = 568; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
569
570 /*
571 * Encode any change in the current source line number by using
572 * either several SrcNoteType::NewLine notes or just one
573 * SrcNoteType::SetLine note, whichever consumes less space.
574 *
575 * NB: We handle backward line number deltas (possible with for
576 * loops where the update part is emitted after the body, but its
577 * line number is <= any line number in the body) here by letting
578 * unsigned delta_ wrap to a very large number, which triggers a
579 * SrcNoteType::SetLine.
580 */
581 bytecodeSection().setCurrentLine(line, offset);
582 if (delta >= SrcNote::SetLine::lengthFor(line, initialLine)) {
583 if (!newSrcNote2(SrcNoteType::SetLine,
584 SrcNote::SetLine::toOperand(line, initialLine))) {
585 return false;
586 }
587 } else {
588 do {
589 if (!newSrcNote(SrcNoteType::NewLine)) {
590 return false;
591 }
592 } while (--delta != 0);
593 }
594
595 bytecodeSection().updateSeparatorPositionIfPresent();
596 }
597 return true;
598}
599
600/* Updates the line number and column number information in the source notes. */
601bool BytecodeEmitter::updateSourceCoordNotes(uint32_t offset) {
602 if (skipLocationSrcNotes()) {
603 return true;
604 }
605
606 if (!updateLineNumberNotes(offset)) {
607 return false;
608 }
609
610 JS::LimitedColumnNumberOneOrigin columnIndex =
611 errorReporter().columnAt(offset);
612
613 // Assert colspan is always representable.
614 static_assert((0 - ptrdiff_t(JS::LimitedColumnNumberOneOrigin::Limit)) >=
615 SrcNote::ColSpan::MinColSpan);
616 static_assert((ptrdiff_t(JS::LimitedColumnNumberOneOrigin::Limit) - 0) <=
617 SrcNote::ColSpan::MaxColSpan);
618
619 JS::ColumnNumberOffset colspan = columnIndex - bytecodeSection().lastColumn();
620
621 if (colspan != JS::ColumnNumberOffset::zero()) {
622 if (lastLineOnlySrcNoteIndex != LastSrcNoteIsNotLineOnly) {
623 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 624); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().lastColumn() == JS::LimitedColumnNumberOneOrigin()"
")"); do { *((volatile int*)__null) = 624; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
624 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 624); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().lastColumn() == JS::LimitedColumnNumberOneOrigin()"
")"); do { *((volatile int*)__null) = 624; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
625
626 const SrcNotesVector& notes = bytecodeSection().notes();
627 SrcNoteType type = notes[lastLineOnlySrcNoteIndex].type();
628 if (type == SrcNoteType::NewLine) {
629 if (!convertLastNewLineToNewLineColumn(columnIndex)) {
630 return false;
631 }
632 } else {
633 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 633); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == SrcNoteType::SetLine"
")"); do { *((volatile int*)__null) = 633; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
634 if (!convertLastSetLineToSetLineColumn(columnIndex)) {
635 return false;
636 }
637 }
638 } else {
639 if (!newSrcNote2(SrcNoteType::ColSpan,
640 SrcNote::ColSpan::toOperand(colspan))) {
641 return false;
642 }
643 }
644 bytecodeSection().setLastColumn(columnIndex, offset);
645 bytecodeSection().updateSeparatorPositionIfPresent();
646 }
647 return true;
648}
649
650bool BytecodeEmitter::updateSourceCoordNotesIfNonLiteral(ParseNode* node) {
651 if (node->isLiteral()) {
652 return true;
653 }
654 return updateSourceCoordNotes(node->pn_pos.begin);
655}
656
657uint32_t BytecodeEmitter::getOffsetForLoop(ParseNode* nextpn) const {
658 // Try to give the JSOp::LoopHead the same line number as the next
659 // instruction. nextpn is often a block, in which case the next instruction
660 // typically comes from the first statement inside.
661 if (nextpn->is<LexicalScopeNode>()) {
662 nextpn = nextpn->as<LexicalScopeNode>().scopeBody();
663 }
664 if (nextpn->isKind(ParseNodeKind::StatementList)) {
665 if (ParseNode* firstStatement = nextpn->as<ListNode>().head()) {
666 nextpn = firstStatement;
667 }
668 }
669
670 return nextpn->pn_pos.begin;
671}
672
673bool BytecodeEmitter::emitUint16Operand(JSOp op, uint32_t operand) {
674 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 674); AnnotateMozCrashReason("MOZ_ASSERT" "(" "operand <= (65535)"
")"); do { *((volatile int*)__null) = 674; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
675 if (!emit3(op, UINT16_LO(operand), UINT16_HI(operand))) {
676 return false;
677 }
678 return true;
679}
680
681bool BytecodeEmitter::emitUint32Operand(JSOp op, uint32_t operand) {
682 BytecodeOffset off;
683 if (!emitN(op, 4, &off)) {
684 return false;
685 }
686 SET_UINT32(bytecodeSection().code(off), operand);
687 return true;
688}
689
690bool BytecodeEmitter::emitGoto(NestableControl* target, GotoKind kind) {
691 NonLocalExitControl nle(this, kind == GotoKind::Continue
692 ? NonLocalExitKind::Continue
693 : NonLocalExitKind::Break);
694 return nle.emitNonLocalJump(target);
695}
696
697AbstractScopePtr BytecodeEmitter::innermostScope() const {
698 return innermostEmitterScope()->scope(this);
699}
700
701ScopeIndex BytecodeEmitter::innermostScopeIndex() const {
702 return *innermostEmitterScope()->scopeIndex(this);
703}
704
705bool BytecodeEmitter::emitGCIndexOp(JSOp op, GCThingIndex index) {
706 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 706); AnnotateMozCrashReason("MOZ_ASSERT" "(" "checkStrictOrSloppy(op)"
")"); do { *((volatile int*)__null) = 706; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
707
708 constexpr size_t OpLength = 1 + GCTHING_INDEX_LEN;
709 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 709); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetOpLength(op) == OpLength"
")"); do { *((volatile int*)__null) = 709; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
710
711 BytecodeOffset offset;
712 if (!emitCheck(op, OpLength, &offset)) {
713 return false;
714 }
715
716 jsbytecode* code = bytecodeSection().code(offset);
717 code[0] = jsbytecode(op);
718 SET_GCTHING_INDEX(code, index);
719 bytecodeSection().updateDepth(op, offset);
720 return true;
721}
722
723bool BytecodeEmitter::emitAtomOp(JSOp op, TaggedParserAtomIndex atom) {
724 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 724); AnnotateMozCrashReason("MOZ_ASSERT" "(" "atom" ")"); do
{ *((volatile int*)__null) = 724; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
725
726 // .generator lookups should be emitted as JSOp::GetAliasedVar instead of
727 // JSOp::GetName etc, to bypass |with| objects on the scope chain.
728 // It's safe to emit .this lookups though because |with| objects skip
729 // those.
730 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_()",
"/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 731); AnnotateMozCrashReason("MOZ_ASSERT" "(" "atom != TaggedParserAtomIndex::WellKnown::dot_generator_()"
")"); do { *((volatile int*)__null) = 731; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
731 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_()",
"/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 731); AnnotateMozCrashReason("MOZ_ASSERT" "(" "atom != TaggedParserAtomIndex::WellKnown::dot_generator_()"
")"); do { *((volatile int*)__null) = 731; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
732
733 GCThingIndex index;
734 if (!makeAtomIndex(atom, ParserAtom::Atomize::Yes, &index)) {
735 return false;
736 }
737
738 return emitAtomOp(op, index);
739}
740
741bool BytecodeEmitter::emitAtomOp(JSOp op, GCThingIndex atomIndex) {
742 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 742); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JOF_OPTYPE(op) == JOF_ATOM"
")"); do { *((volatile int*)__null) = 742; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
743#ifdef DEBUG1
744 auto atom = perScriptData().gcThingList().getAtom(atomIndex);
745 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)",
"/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 745); AnnotateMozCrashReason("MOZ_ASSERT" "(" "compilationState.parserAtoms.isInstantiatedAsJSAtom(atom)"
")"); do { *((volatile int*)__null) = 745; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
746#endif
747 return emitGCIndexOp(op, atomIndex);
748}
749
750bool BytecodeEmitter::emitStringOp(JSOp op, TaggedParserAtomIndex atom) {
751 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 751); AnnotateMozCrashReason("MOZ_ASSERT" "(" "atom" ")"); do
{ *((volatile int*)__null) = 751; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
752 GCThingIndex index;
753 if (!makeAtomIndex(atom, ParserAtom::Atomize::No, &index)) {
754 return false;
755 }
756
757 return emitStringOp(op, index);
758}
759
760bool BytecodeEmitter::emitStringOp(JSOp op, GCThingIndex atomIndex) {
761 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 761); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JOF_OPTYPE(op) == JOF_STRING"
")"); do { *((volatile int*)__null) = 761; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
762 return emitGCIndexOp(op, atomIndex);
763}
764
765bool BytecodeEmitter::emitInternedScopeOp(GCThingIndex index, JSOp op) {
766 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 766); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JOF_OPTYPE(op) == JOF_SCOPE"
")"); do { *((volatile int*)__null) = 766; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
767 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 767); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index < perScriptData().gcThingList().length()"
")"); do { *((volatile int*)__null) = 767; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
768 return emitGCIndexOp(op, index);
769}
770
771bool BytecodeEmitter::emitInternedObjectOp(GCThingIndex index, JSOp op) {
772 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 772); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JOF_OPTYPE(op) == JOF_OBJECT"
")"); do { *((volatile int*)__null) = 772; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
773 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 773); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index < perScriptData().gcThingList().length()"
")"); do { *((volatile int*)__null) = 773; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
774 return emitGCIndexOp(op, index);
775}
776
777bool BytecodeEmitter::emitRegExp(GCThingIndex index) {
778 return emitGCIndexOp(JSOp::RegExp, index);
779}
780
781bool BytecodeEmitter::emitLocalOp(JSOp op, uint32_t slot) {
782 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 782); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JOF_OPTYPE(op) != JOF_ENVCOORD"
")"); do { *((volatile int*)__null) = 782; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
783 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)",
"/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 783); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsLocalOp(op)"
")"); do { *((volatile int*)__null) = 783; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
784
785 BytecodeOffset off;
786 if (!emitN(op, LOCALNO_LEN, &off)) {
787 return false;
788 }
789
790 SET_LOCALNO(bytecodeSection().code(off), slot);
791 return true;
792}
793
794bool BytecodeEmitter::emitArgOp(JSOp op, uint16_t slot) {
795 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)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 795); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsArgOp(op)"
")"); do { *((volatile int*)__null) = 795; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
796 BytecodeOffset off;
797 if (!emitN(op, ARGNO_LEN, &off)) {
798 return false;
799 }
800
801 SET_ARGNO(bytecodeSection().code(off), slot);
802 return true;
803}
804
805bool BytecodeEmitter::emitEnvCoordOp(JSOp op, EnvironmentCoordinate ec) {
806 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 807); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JOF_OPTYPE(op) == JOF_ENVCOORD || JOF_OPTYPE(op) == JOF_DEBUGCOORD"
")"); do { *((volatile int*)__null) = 807; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
807 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 807); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JOF_OPTYPE(op) == JOF_ENVCOORD || JOF_OPTYPE(op) == JOF_DEBUGCOORD"
")"); do { *((volatile int*)__null) = 807; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
808
809 constexpr size_t N = ENVCOORD_HOPS_LEN + ENVCOORD_SLOT_LEN;
810 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 810); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetOpLength(op) == 1 + N"
")"); do { *((volatile int*)__null) = 810; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
811
812 BytecodeOffset off;
813 if (!emitN(op, N, &off)) {
814 return false;
815 }
816
817 jsbytecode* pc = bytecodeSection().code(off);
818 SET_ENVCOORD_HOPS(pc, ec.hops());
819 pc += ENVCOORD_HOPS_LEN;
820 SET_ENVCOORD_SLOT(pc, ec.slot());
821 pc += ENVCOORD_SLOT_LEN;
Value stored to 'pc' is never read
822 return true;
823}
824
825bool BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer) const {
826 AutoCheckRecursionLimit recursion(fc);
827 if (!recursion.check(fc)) {
828 return false;
829 }
830
831restart:
832
833 switch (pn->getKind()) {
834 // Trivial cases with no side effects.
835 case ParseNodeKind::EmptyStmt:
836 case ParseNodeKind::TrueExpr:
837 case ParseNodeKind::FalseExpr:
838 case ParseNodeKind::NullExpr:
839 case ParseNodeKind::RawUndefinedExpr:
840 case ParseNodeKind::Elision:
841 case ParseNodeKind::Generator:
842 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>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 842); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<NullaryNode>()"
")"); do { *((volatile int*)__null) = 842; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
843 *answer = false;
844 return true;
845
846 case ParseNodeKind::ObjectPropertyName:
847 case ParseNodeKind::PrivateName: // no side effects, unlike
848 // ParseNodeKind::Name
849 case ParseNodeKind::StringExpr:
850 case ParseNodeKind::TemplateStringExpr:
851 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>()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 851); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<NameNode>()"
")"); do { *((volatile int*)__null) = 851; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
852 *answer = false;
853 return true;
854
855 case ParseNodeKind::RegExpExpr:
856 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>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 856); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<RegExpLiteral>()"
")"); do { *((volatile int*)__null) = 856; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
857 *answer = false;
858 return true;
859
860 case ParseNodeKind::NumberExpr:
861 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>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 861); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<NumericLiteral>()"
")"); do { *((volatile int*)__null) = 861; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
862 *answer = false;
863 return true;
864
865 case ParseNodeKind::BigIntExpr:
866 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>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 866); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BigIntLiteral>()"
")"); do { *((volatile int*)__null) = 866; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
867 *answer = false;
868 return true;
869
870 // |this| can throw in derived class constructors, including nested arrow
871 // functions or eval.
872 case ParseNodeKind::ThisExpr:
873 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>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 873); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { *((volatile int*)__null) = 873; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
874 *answer = sc->needsThisTDZChecks();
875 return true;
876
877 // |new.target| doesn't have any side-effects.
878 case ParseNodeKind::NewTargetExpr: {
879 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>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 879); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<NewTargetNode>()"
")"); do { *((volatile int*)__null) = 879; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
880 *answer = false;
881 return true;
882 }
883
884 // Trivial binary nodes with more token pos holders.
885 case ParseNodeKind::ImportMetaExpr: {
886 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 886); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->as<BinaryNode>().left()->isKind(ParseNodeKind::PosHolder)"
")"); do { *((volatile int*)__null) = 886; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
887 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 888); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->as<BinaryNode>().right()->isKind(ParseNodeKind::PosHolder)"
")"); do { *((volatile int*)__null) = 888; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
888 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 888); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->as<BinaryNode>().right()->isKind(ParseNodeKind::PosHolder)"
")"); do { *((volatile int*)__null) = 888; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
889 *answer = false;
890 return true;
891 }
892
893 case ParseNodeKind::BreakStmt:
894 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>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 894); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BreakStatement>()"
")"); do { *((volatile int*)__null) = 894; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
895 *answer = true;
896 return true;
897
898 case ParseNodeKind::ContinueStmt:
899 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>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 899); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<ContinueStatement>()"
")"); do { *((volatile int*)__null) = 899; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
900 *answer = true;
901 return true;
902
903 case ParseNodeKind::DebuggerStmt:
904 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>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 904); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<DebuggerStatement>()"
")"); do { *((volatile int*)__null) = 904; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
905 *answer = true;
906 return true;
907
908 // Watch out for getters!
909 case ParseNodeKind::OptionalDotExpr:
910 case ParseNodeKind::DotExpr:
911 case ParseNodeKind::ArgumentsLength:
912 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>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 912); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { *((volatile int*)__null) = 912; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
913 *answer = true;
914 return true;
915
916 // Unary cases with side effects only if the child has them.
917 case ParseNodeKind::TypeOfExpr:
918 case ParseNodeKind::VoidExpr:
919 case ParseNodeKind::NotExpr:
920 return checkSideEffects(pn->as<UnaryNode>().kid(), answer);
921
922 // Even if the name expression is effect-free, performing ToPropertyKey on
923 // it might not be effect-free:
924 //
925 // RegExp.prototype.toString = () => { throw 42; };
926 // ({ [/regex/]: 0 }); // ToPropertyKey(/regex/) throws 42
927 //
928 // function Q() {
929 // ({ [new.target]: 0 });
930 // }
931 // Q.toString = () => { throw 17; };
932 // new Q; // new.target will be Q, ToPropertyKey(Q) throws 17
933 case ParseNodeKind::ComputedName:
934 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>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 934); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { *((volatile int*)__null) = 934; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
935 *answer = true;
936 return true;
937
938 // Looking up or evaluating the associated name could throw.
939 case ParseNodeKind::TypeOfNameExpr:
940 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>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 940); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { *((volatile int*)__null) = 940; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
941 *answer = true;
942 return true;
943
944 // This unary case has side effects on the enclosing object, sure. But
945 // that's not the question this function answers: it's whether the
946 // operation may have a side effect on something *other* than the result
947 // of the overall operation in which it's embedded. The answer to that
948 // is no, because an object literal having a mutated prototype only
949 // produces a value, without affecting anything else.
950 case ParseNodeKind::MutateProto:
951 return checkSideEffects(pn->as<UnaryNode>().kid(), answer);
952
953 // Unary cases with obvious side effects.
954 case ParseNodeKind::PreIncrementExpr:
955 case ParseNodeKind::PostIncrementExpr:
956 case ParseNodeKind::PreDecrementExpr:
957 case ParseNodeKind::PostDecrementExpr:
958 case ParseNodeKind::ThrowStmt:
959 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>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 959); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { *((volatile int*)__null) = 959; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
960 *answer = true;
961 return true;
962
963 // These might invoke valueOf/toString, even with a subexpression without
964 // side effects! Consider |+{ valueOf: null, toString: null }|.
965 case ParseNodeKind::BitNotExpr:
966 case ParseNodeKind::PosExpr:
967 case ParseNodeKind::NegExpr:
968 MOZ_ASSERT(pn->is<UnaryNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<UnaryNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<UnaryNode>()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"pn->is<UnaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 968); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { *((volatile int*)__null) = 968; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
969 *answer = true;
970 return true;
971
972 // This invokes the (user-controllable) iterator protocol.
973 case ParseNodeKind::Spread:
974 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>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 974); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { *((volatile int*)__null) = 974; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
975 *answer = true;
976 return true;
977
978 case ParseNodeKind::InitialYield:
979 case ParseNodeKind::YieldStarExpr:
980 case ParseNodeKind::YieldExpr:
981 case ParseNodeKind::AwaitExpr:
982 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>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 982); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { *((volatile int*)__null) = 982; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
983 *answer = true;
984 return true;
985
986 // Deletion generally has side effects, even if isolated cases have none.
987 case ParseNodeKind::DeleteNameExpr:
988 case ParseNodeKind::DeletePropExpr:
989 case ParseNodeKind::DeleteElemExpr:
990 case ParseNodeKind::DeleteOptionalChainExpr:
991 MOZ_ASSERT(pn->is<UnaryNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<UnaryNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<UnaryNode>()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"pn->is<UnaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 991); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { *((volatile int*)__null) = 991; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
992 *answer = true;
993 return true;
994
995 // Deletion of a non-Reference expression has side effects only through
996 // evaluating the expression.
997 case ParseNodeKind::DeleteExpr: {
998 ParseNode* expr = pn->as<UnaryNode>().kid();
999 return checkSideEffects(expr, answer);
1000 }
1001
1002 case ParseNodeKind::ExpressionStmt:
1003 return checkSideEffects(pn->as<UnaryNode>().kid(), answer);
1004
1005 // Binary cases with obvious side effects.
1006 case ParseNodeKind::InitExpr:
1007 *answer = true;
1008 return true;
1009
1010 case ParseNodeKind::AssignExpr:
1011 case ParseNodeKind::AddAssignExpr:
1012 case ParseNodeKind::SubAssignExpr:
1013 case ParseNodeKind::CoalesceAssignExpr:
1014 case ParseNodeKind::OrAssignExpr:
1015 case ParseNodeKind::AndAssignExpr:
1016 case ParseNodeKind::BitOrAssignExpr:
1017 case ParseNodeKind::BitXorAssignExpr:
1018 case ParseNodeKind::BitAndAssignExpr:
1019 case ParseNodeKind::LshAssignExpr:
1020 case ParseNodeKind::RshAssignExpr:
1021 case ParseNodeKind::UrshAssignExpr:
1022 case ParseNodeKind::MulAssignExpr:
1023 case ParseNodeKind::DivAssignExpr:
1024 case ParseNodeKind::ModAssignExpr:
1025 case ParseNodeKind::PowAssignExpr:
1026 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>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1026); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<AssignmentNode>()"
")"); do { *((volatile int*)__null) = 1026; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1027 *answer = true;
1028 return true;
1029
1030 case ParseNodeKind::SetThis:
1031 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>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1031); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { *((volatile int*)__null) = 1031; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1032 *answer = true;
1033 return true;
1034
1035 case ParseNodeKind::StatementList:
1036 // Strict equality operations and short circuit operators are well-behaved
1037 // and perform no conversions.
1038 case ParseNodeKind::CoalesceExpr:
1039 case ParseNodeKind::OrExpr:
1040 case ParseNodeKind::AndExpr:
1041 case ParseNodeKind::StrictEqExpr:
1042 case ParseNodeKind::StrictNeExpr:
1043 // Any subexpression of a comma expression could be effectful.
1044 case ParseNodeKind::CommaExpr:
1045 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()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1045); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!pn->as<ListNode>().empty()"
")"); do { *((volatile int*)__null) = 1045; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1046 [[fallthrough]];
1047 // Subcomponents of a literal may be effectful.
1048 case ParseNodeKind::ArrayExpr:
1049 case ParseNodeKind::ObjectExpr:
1050 for (ParseNode* item : pn->as<ListNode>().contents()) {
1051 if (!checkSideEffects(item, answer)) {
1052 return false;
1053 }
1054 if (*answer) {
1055 return true;
1056 }
1057 }
1058 return true;
1059
1060#ifdef ENABLE_RECORD_TUPLE
1061 case ParseNodeKind::RecordExpr:
1062 case ParseNodeKind::TupleExpr:
1063 MOZ_CRASH("Record and Tuple are not supported yet")do { do { } while (false); MOZ_ReportCrash("" "Record and Tuple are not supported yet"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1063); AnnotateMozCrashReason("MOZ_CRASH(" "Record and Tuple are not supported yet"
")"); do { *((volatile int*)__null) = 1063; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
1064#endif
1065
1066#ifdef ENABLE_DECORATORS
1067 case ParseNodeKind::DecoratorList:
1068 MOZ_CRASH("Decorators are not supported yet")do { do { } while (false); MOZ_ReportCrash("" "Decorators are not supported yet"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1068); AnnotateMozCrashReason("MOZ_CRASH(" "Decorators are not supported yet"
")"); do { *((volatile int*)__null) = 1068; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
1069#endif
1070
1071#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
1072 case ParseNodeKind::UsingDecl:
1073 case ParseNodeKind::AwaitUsingDecl:
1074 MOZ_CRASH("Using declarations are not supported yet")do { do { } while (false); MOZ_ReportCrash("" "Using declarations are not supported yet"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1074); AnnotateMozCrashReason("MOZ_CRASH(" "Using declarations are not supported yet"
")"); do { *((volatile int*)__null) = 1074; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
1075#endif
1076
1077 // Most other binary operations (parsed as lists in SpiderMonkey) may
1078 // perform conversions triggering side effects. Math operations perform
1079 // ToNumber and may fail invoking invalid user-defined toString/valueOf:
1080 // |5 < { toString: null }|. |instanceof| throws if provided a
1081 // non-object constructor: |null instanceof null|. |in| throws if given
1082 // a non-object RHS: |5 in null|.
1083 case ParseNodeKind::BitOrExpr:
1084 case ParseNodeKind::BitXorExpr:
1085 case ParseNodeKind::BitAndExpr:
1086 case ParseNodeKind::EqExpr:
1087 case ParseNodeKind::NeExpr:
1088 case ParseNodeKind::LtExpr:
1089 case ParseNodeKind::LeExpr:
1090 case ParseNodeKind::GtExpr:
1091 case ParseNodeKind::GeExpr:
1092 case ParseNodeKind::InstanceOfExpr:
1093 case ParseNodeKind::InExpr:
1094 case ParseNodeKind::PrivateInExpr:
1095 case ParseNodeKind::LshExpr:
1096 case ParseNodeKind::RshExpr:
1097 case ParseNodeKind::UrshExpr:
1098 case ParseNodeKind::AddExpr:
1099 case ParseNodeKind::SubExpr:
1100 case ParseNodeKind::MulExpr:
1101 case ParseNodeKind::DivExpr:
1102 case ParseNodeKind::ModExpr:
1103 case ParseNodeKind::PowExpr:
1104 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1104); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->as<ListNode>().count() >= 2"
")"); do { *((volatile int*)__null) = 1104; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1105 *answer = true;
1106 return true;
1107
1108 case ParseNodeKind::PropertyDefinition:
1109 case ParseNodeKind::Case: {
1110 BinaryNode* node = &pn->as<BinaryNode>();
1111 if (!checkSideEffects(node->left(), answer)) {
1112 return false;
1113 }
1114 if (*answer) {
1115 return true;
1116 }
1117 return checkSideEffects(node->right(), answer);
1118 }
1119
1120 // More getters.
1121 case ParseNodeKind::ElemExpr:
1122 case ParseNodeKind::OptionalElemExpr:
1123 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>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1123); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { *((volatile int*)__null) = 1123; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1124 *answer = true;
1125 return true;
1126
1127 // Throws if the operand is not of the right class. Can also call a private
1128 // getter.
1129 case ParseNodeKind::PrivateMemberExpr:
1130 case ParseNodeKind::OptionalPrivateMemberExpr:
1131 *answer = true;
1132 return true;
1133
1134 // These affect visible names in this code, or in other code.
1135 case ParseNodeKind::ImportDecl:
1136 case ParseNodeKind::ExportFromStmt:
1137 case ParseNodeKind::ExportDefaultStmt:
1138 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>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1138); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { *((volatile int*)__null) = 1138; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1139 *answer = true;
1140 return true;
1141
1142 // Likewise.
1143 case ParseNodeKind::ExportStmt:
1144 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>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1144); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { *((volatile int*)__null) = 1144; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1145 *answer = true;
1146 return true;
1147
1148 case ParseNodeKind::CallImportExpr:
1149 case ParseNodeKind::CallImportSpec:
1150 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>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1150); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { *((volatile int*)__null) = 1150; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1151 *answer = true;
1152 return true;
1153
1154 // Every part of a loop might be effect-free, but looping infinitely *is*
1155 // an effect. (Language lawyer trivia: C++ says threads can be assumed
1156 // to exit or have side effects, C++14 [intro.multithread]p27, so a C++
1157 // implementation's equivalent of the below could set |*answer = false;|
1158 // if all loop sub-nodes set |*answer = false|!)
1159 case ParseNodeKind::DoWhileStmt:
1160 case ParseNodeKind::WhileStmt:
1161 case ParseNodeKind::ForStmt:
1162 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>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1162); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { *((volatile int*)__null) = 1162; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1163 *answer = true;
1164 return true;
1165
1166 // Declarations affect the name set of the relevant scope.
1167 case ParseNodeKind::VarStmt:
1168 case ParseNodeKind::ConstDecl:
1169 case ParseNodeKind::LetDecl:
1170 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>()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1170); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<ListNode>()"
")"); do { *((volatile int*)__null) = 1170; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1171 *answer = true;
1172 return true;
1173
1174 case ParseNodeKind::IfStmt:
1175 case ParseNodeKind::ConditionalExpr: {
1176 TernaryNode* node = &pn->as<TernaryNode>();
1177 if (!checkSideEffects(node->kid1(), answer)) {
1178 return false;
1179 }
1180 if (*answer) {
1181 return true;
1182 }
1183 if (!checkSideEffects(node->kid2(), answer)) {
1184 return false;
1185 }
1186 if (*answer) {
1187 return true;
1188 }
1189 if ((pn = node->kid3())) {
1190 goto restart;
1191 }
1192 return true;
1193 }
1194
1195 // Function calls can invoke non-local code.
1196 case ParseNodeKind::NewExpr:
1197 case ParseNodeKind::CallExpr:
1198 case ParseNodeKind::OptionalCallExpr:
1199 case ParseNodeKind::TaggedTemplateExpr:
1200 case ParseNodeKind::SuperCallExpr:
1201 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>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1201); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { *((volatile int*)__null) = 1201; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1202 *answer = true;
1203 return true;
1204
1205 // Function arg lists can contain arbitrary expressions. Technically
1206 // this only causes side-effects if one of the arguments does, but since
1207 // the call being made will always trigger side-effects, it isn't needed.
1208 case ParseNodeKind::Arguments:
1209 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>()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1209); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<ListNode>()"
")"); do { *((volatile int*)__null) = 1209; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1210 *answer = true;
1211 return true;
1212
1213 case ParseNodeKind::OptionalChain:
1214 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>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1214); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { *((volatile int*)__null) = 1214; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1215 *answer = true;
1216 return true;
1217
1218 // Classes typically introduce names. Even if no name is introduced,
1219 // the heritage and/or class body (through computed property names)
1220 // usually have effects.
1221 case ParseNodeKind::ClassDecl:
1222 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>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1222); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<ClassNode>()"
")"); do { *((volatile int*)__null) = 1222; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1223 *answer = true;
1224 return true;
1225
1226 // |with| calls |ToObject| on its expression and so throws if that value
1227 // is null/undefined.
1228 case ParseNodeKind::WithStmt:
1229 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>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1229); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { *((volatile int*)__null) = 1229; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1230 *answer = true;
1231 return true;
1232
1233 case ParseNodeKind::ReturnStmt:
1234 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>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1234); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { *((volatile int*)__null) = 1234; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1235 *answer = true;
1236 return true;
1237
1238 case ParseNodeKind::Name:
1239 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>()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1239); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<NameNode>()"
")"); do { *((volatile int*)__null) = 1239; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1240 *answer = true;
1241 return true;
1242
1243 // Shorthands could trigger getters: the |x| in the object literal in
1244 // |with ({ get x() { throw 42; } }) ({ x });|, for example, triggers
1245 // one. (Of course, it isn't necessary to use |with| for a shorthand to
1246 // trigger a getter.)
1247 case ParseNodeKind::Shorthand:
1248 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>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1248); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { *((volatile int*)__null) = 1248; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1249 *answer = true;
1250 return true;
1251
1252 case ParseNodeKind::Function:
1253 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>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1253); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<FunctionNode>()"
")"); do { *((volatile int*)__null) = 1253; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1254 /*
1255 * A named function, contrary to ES3, is no longer effectful, because
1256 * we bind its name lexically (using JSOp::Callee) instead of creating
1257 * an Object instance and binding a readonly, permanent property in it
1258 * (the object and binding can be detected and hijacked or captured).
1259 * This is a bug fix to ES3; it is fixed in ES3.1 drafts.
1260 */
1261 *answer = false;
1262 return true;
1263
1264 case ParseNodeKind::Module:
1265 *answer = false;
1266 return true;
1267
1268 case ParseNodeKind::TryStmt: {
1269 TryNode* tryNode = &pn->as<TryNode>();
1270 if (!checkSideEffects(tryNode->body(), answer)) {
1271 return false;
1272 }
1273 if (*answer) {
1274 return true;
1275 }
1276 if (LexicalScopeNode* catchScope = tryNode->catchScope()) {
1277 if (!checkSideEffects(catchScope, answer)) {
1278 return false;
1279 }
1280 if (*answer) {
1281 return true;
1282 }
1283 }
1284 if (ParseNode* finallyBlock = tryNode->finallyBlock()) {
1285 if (!checkSideEffects(finallyBlock, answer)) {
1286 return false;
1287 }
1288 }
1289 return true;
1290 }
1291
1292 case ParseNodeKind::Catch: {
1293 BinaryNode* catchClause = &pn->as<BinaryNode>();
1294 if (ParseNode* name = catchClause->left()) {
1295 if (!checkSideEffects(name, answer)) {
1296 return false;
1297 }
1298 if (*answer) {
1299 return true;
1300 }
1301 }
1302 return checkSideEffects(catchClause->right(), answer);
1303 }
1304
1305 case ParseNodeKind::SwitchStmt: {
1306 SwitchStatement* switchStmt = &pn->as<SwitchStatement>();
1307 if (!checkSideEffects(&switchStmt->discriminant(), answer)) {
1308 return false;
1309 }
1310 return *answer ||
1311 checkSideEffects(&switchStmt->lexicalForCaseList(), answer);
1312 }
1313
1314 case ParseNodeKind::LabelStmt:
1315 return checkSideEffects(pn->as<LabeledStatement>().statement(), answer);
1316
1317 case ParseNodeKind::LexicalScope:
1318 return checkSideEffects(pn->as<LexicalScopeNode>().scopeBody(), answer);
1319
1320 // We could methodically check every interpolated expression, but it's
1321 // probably not worth the trouble. Treat template strings as effect-free
1322 // only if they don't contain any substitutions.
1323 case ParseNodeKind::TemplateStringListExpr: {
1324 ListNode* list = &pn->as<ListNode>();
1325 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1325); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!list->empty()"
")"); do { *((volatile int*)__null) = 1325; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1326 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1328); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(list->count() % 2) == 1"
") (" "template strings must alternate template and substitution "
"parts" ")"); do { *((volatile int*)__null) = 1328; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
1327 "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1328); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(list->count() % 2) == 1"
") (" "template strings must alternate template and substitution "
"parts" ")"); do { *((volatile int*)__null) = 1328; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
1328 "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1328); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(list->count() % 2) == 1"
") (" "template strings must alternate template and substitution "
"parts" ")"); do { *((volatile int*)__null) = 1328; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
1329 *answer = list->count() > 1;
1330 return true;
1331 }
1332
1333 // This should be unreachable but is left as-is for now.
1334 case ParseNodeKind::ParamsBody:
1335 *answer = true;
1336 return true;
1337
1338 case ParseNodeKind::ForIn: // by ParseNodeKind::For
1339 case ParseNodeKind::ForOf: // by ParseNodeKind::For
1340 case ParseNodeKind::ForHead: // by ParseNodeKind::For
1341 case ParseNodeKind::DefaultConstructor: // by ParseNodeKind::ClassDecl
1342 case ParseNodeKind::ClassBodyScope: // by ParseNodeKind::ClassDecl
1343 case ParseNodeKind::ClassMethod: // by ParseNodeKind::ClassDecl
1344 case ParseNodeKind::ClassField: // by ParseNodeKind::ClassDecl
1345 case ParseNodeKind::ClassNames: // by ParseNodeKind::ClassDecl
1346 case ParseNodeKind::StaticClassBlock: // by ParseNodeKind::ClassDecl
1347 case ParseNodeKind::ClassMemberList: // by ParseNodeKind::ClassDecl
1348 case ParseNodeKind::ImportSpecList: // by ParseNodeKind::Import
1349 case ParseNodeKind::ImportSpec: // by ParseNodeKind::Import
1350 case ParseNodeKind::ImportNamespaceSpec: // by ParseNodeKind::Import
1351 case ParseNodeKind::ImportAttribute: // by ParseNodeKind::Import
1352 case ParseNodeKind::ImportAttributeList: // by ParseNodeKind::Import
1353 case ParseNodeKind::ImportModuleRequest: // by ParseNodeKind::Import
1354 case ParseNodeKind::ExportBatchSpecStmt: // by ParseNodeKind::Export
1355 case ParseNodeKind::ExportSpecList: // by ParseNodeKind::Export
1356 case ParseNodeKind::ExportSpec: // by ParseNodeKind::Export
1357 case ParseNodeKind::ExportNamespaceSpec: // by ParseNodeKind::Export
1358 case ParseNodeKind::CallSiteObj: // by ParseNodeKind::TaggedTemplate
1359 case ParseNodeKind::PosHolder: // by ParseNodeKind::NewTarget
1360 case ParseNodeKind::SuperBase: // by ParseNodeKind::Elem and others
1361 case ParseNodeKind::PropertyNameExpr: // by ParseNodeKind::Dot
1362 MOZ_CRASH("handled by parent nodes")do { do { } while (false); MOZ_ReportCrash("" "handled by parent nodes"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1362); AnnotateMozCrashReason("MOZ_CRASH(" "handled by parent nodes"
")"); do { *((volatile int*)__null) = 1362; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
1363
1364 case ParseNodeKind::LastUnused:
1365 case ParseNodeKind::Limit:
1366 MOZ_CRASH("invalid node kind")do { do { } while (false); MOZ_ReportCrash("" "invalid node kind"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1366); AnnotateMozCrashReason("MOZ_CRASH(" "invalid node kind"
")"); do { *((volatile int*)__null) = 1366; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
1367 }
1368
1369 MOZ_CRASH(do { do { } while (false); MOZ_ReportCrash("" "invalid, unenumerated ParseNodeKind value encountered in "
"BytecodeEmitter::checkSideEffects", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1371); AnnotateMozCrashReason("MOZ_CRASH(" "invalid, unenumerated ParseNodeKind value encountered in "
"BytecodeEmitter::checkSideEffects" ")"); do { *((volatile int
*)__null) = 1371; __attribute__((nomerge)) ::abort(); } while
(false); } while (false)
1370 "invalid, unenumerated ParseNodeKind value encountered in "do { do { } while (false); MOZ_ReportCrash("" "invalid, unenumerated ParseNodeKind value encountered in "
"BytecodeEmitter::checkSideEffects", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1371); AnnotateMozCrashReason("MOZ_CRASH(" "invalid, unenumerated ParseNodeKind value encountered in "
"BytecodeEmitter::checkSideEffects" ")"); do { *((volatile int
*)__null) = 1371; __attribute__((nomerge)) ::abort(); } while
(false); } while (false)
1371 "BytecodeEmitter::checkSideEffects")do { do { } while (false); MOZ_ReportCrash("" "invalid, unenumerated ParseNodeKind value encountered in "
"BytecodeEmitter::checkSideEffects", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1371); AnnotateMozCrashReason("MOZ_CRASH(" "invalid, unenumerated ParseNodeKind value encountered in "
"BytecodeEmitter::checkSideEffects" ")"); do { *((volatile int
*)__null) = 1371; __attribute__((nomerge)) ::abort(); } while
(false); } while (false)
;
1372}
1373
1374bool BytecodeEmitter::isInLoop() const {
1375 return findInnermostNestableControl<LoopControl>();
1376}
1377
1378bool BytecodeEmitter::checkSingletonContext() const {
1379 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1379); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isTopLevelContext()"
")"); do { *((volatile int*)__null) = 1379; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
1380 return sc->treatAsRunOnce() && !isInLoop();
1381}
1382
1383bool BytecodeEmitter::needsImplicitThis() const {
1384 // Short-circuit if there is an enclosing 'with' scope.
1385 if (sc->inWith()) {
1386 return true;
1387 }
1388
1389 // Otherwise see if the current point is under a 'with'.
1390 for (EmitterScope* es = innermostEmitterScope(); es;
1391 es = es->enclosingInFrame()) {
1392 if (es->scope(this).kind() == ScopeKind::With) {
1393 return true;
1394 }
1395 }
1396
1397 return false;
1398}
1399
1400size_t BytecodeEmitter::countThisEnvironmentHops() const {
1401 unsigned numHops = 0;
1402
1403 for (const auto* current = this; current; current = current->parent) {
1404 for (EmitterScope* es = current->innermostEmitterScope(); es;
1405 es = es->enclosingInFrame()) {
1406 if (es->scope(current).is<FunctionScope>()) {
1407 if (!es->scope(current).isArrow()) {
1408 // The Parser is responsible for marking the environment as either
1409 // closed-over or used-by-eval which ensure that is must exist.
1410 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1410); AnnotateMozCrashReason("MOZ_ASSERT" "(" "es->scope(current).hasEnvironment()"
")"); do { *((volatile int*)__null) = 1410; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1411 return numHops;
1412 }
1413 }
1414 if (es->scope(current).hasEnvironment()) {
1415 numHops++;
1416 }
1417 }
1418 }
1419
1420 // The "this" environment exists outside of the compilation, but the
1421 // `ScopeContext` recorded the number of additional hops needed, so add
1422 // those in now.
1423 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1423); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->allowSuperProperty()"
")"); do { *((volatile int*)__null) = 1423; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1424 numHops += compilationState.scopeContext.enclosingThisEnvironmentHops;
1425 return numHops;
1426}
1427
1428bool BytecodeEmitter::emitThisEnvironmentCallee() {
1429 // Get the innermost enclosing function that has a |this| binding.
1430
1431 // Directly load callee from the frame if possible.
1432 if (sc->isFunctionBox() && !sc->asFunctionBox()->isArrow()) {
1433 return emit1(JSOp::Callee);
1434 }
1435
1436 // We have to load the callee from the environment chain.
1437 size_t numHops = countThisEnvironmentHops();
1438
1439 static_assert(
1440 ENVCOORD_HOPS_LIMIT - 1 <= UINT8_MAX(255),
1441 "JSOp::EnvCallee operand size should match ENVCOORD_HOPS_LIMIT");
1442
1443 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1443); AnnotateMozCrashReason("MOZ_ASSERT" "(" "numHops < ENVCOORD_HOPS_LIMIT - 1"
")"); do { *((volatile int*)__null) = 1443; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1444
1445 return emit2(JSOp::EnvCallee, numHops);
1446}
1447
1448bool BytecodeEmitter::emitSuperBase() {
1449 if (!emitThisEnvironmentCallee()) {
1450 return false;
1451 }
1452
1453 return emit1(JSOp::SuperBase);
1454}
1455
1456void BytecodeEmitter::reportError(ParseNode* pn, unsigned errorNumber,
1457 ...) const {
1458 uint32_t offset = pn ? pn->pn_pos.begin : *scriptStartOffset;
1459
1460 va_list args;
1461 va_start(args, errorNumber)__builtin_va_start(args, errorNumber);
1462
1463 errorReporter().errorWithNotesAtVA(nullptr, AsVariant(offset), errorNumber,
1464 &args);
1465
1466 va_end(args)__builtin_va_end(args);
1467}
1468
1469void BytecodeEmitter::reportError(uint32_t offset, unsigned errorNumber,
1470 ...) const {
1471 va_list args;
1472 va_start(args, errorNumber)__builtin_va_start(args, errorNumber);
1473
1474 errorReporter().errorWithNotesAtVA(nullptr, AsVariant(offset), errorNumber,
1475 &args);
1476
1477 va_end(args)__builtin_va_end(args);
1478}
1479
1480bool BytecodeEmitter::addObjLiteralData(ObjLiteralWriter& writer,
1481 GCThingIndex* outIndex) {
1482 if (!writer.checkForDuplicatedNames(fc)) {
1483 return false;
1484 }
1485
1486 size_t len = writer.getCode().size();
1487 auto* code = compilationState.alloc.newArrayUninitialized<uint8_t>(len);
1488 if (!code) {
1489 js::ReportOutOfMemory(fc);
1490 return false;
1491 }
1492 memcpy(code, writer.getCode().data(), len);
1493
1494 ObjLiteralIndex objIndex(compilationState.objLiteralData.length());
1495 if (uint32_t(objIndex) >= TaggedScriptThingIndex::IndexLimit) {
1496 ReportAllocationOverflow(fc);
1497 return false;
1498 }
1499 if (!compilationState.objLiteralData.emplaceBack(code, len, writer.getKind(),
1500 writer.getFlags(),
1501 writer.getPropertyCount())) {
1502 js::ReportOutOfMemory(fc);
1503 return false;
1504 }
1505
1506 return perScriptData().gcThingList().append(objIndex, outIndex);
1507}
1508
1509bool BytecodeEmitter::emitPrepareIteratorResult() {
1510 constexpr JSOp op = JSOp::NewObject;
1511
1512 ObjLiteralWriter writer;
1513 writer.beginShape(op);
1514
1515 writer.setPropNameNoDuplicateCheck(parserAtoms(),
1516 TaggedParserAtomIndex::WellKnown::value());
1517 if (!writer.propWithUndefinedValue(fc)) {
1518 return false;
1519 }
1520 writer.setPropNameNoDuplicateCheck(parserAtoms(),
1521 TaggedParserAtomIndex::WellKnown::done());
1522 if (!writer.propWithUndefinedValue(fc)) {
1523 return false;
1524 }
1525
1526 GCThingIndex shape;
1527 if (!addObjLiteralData(writer, &shape)) {
1528 return false;
1529 }
1530
1531 return emitGCIndexOp(op, shape);
1532}
1533
1534bool BytecodeEmitter::emitFinishIteratorResult(bool done) {
1535 if (!emitAtomOp(JSOp::InitProp, TaggedParserAtomIndex::WellKnown::value())) {
1536 return false;
1537 }
1538 if (!emit1(done ? JSOp::True : JSOp::False)) {
1539 return false;
1540 }
1541 if (!emitAtomOp(JSOp::InitProp, TaggedParserAtomIndex::WellKnown::done())) {
1542 return false;
1543 }
1544 return true;
1545}
1546
1547bool BytecodeEmitter::emitGetNameAtLocation(TaggedParserAtomIndex name,
1548 const NameLocation& loc) {
1549 NameOpEmitter noe(this, name, loc, NameOpEmitter::Kind::Get);
1550 if (!noe.emitGet()) {
1551 return false;
1552 }
1553
1554 return true;
1555}
1556
1557bool BytecodeEmitter::emitGetName(NameNode* name) {
1558 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)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1558); AnnotateMozCrashReason("MOZ_ASSERT" "(" "name->isKind(ParseNodeKind::Name)"
")"); do { *((volatile int*)__null) = 1558; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1559
1560 return emitGetName(name->name());
1561}
1562
1563bool BytecodeEmitter::emitGetPrivateName(NameNode* name) {
1564 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1564); AnnotateMozCrashReason("MOZ_ASSERT" "(" "name->isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 1564; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1565 return emitGetPrivateName(name->name());
1566}
1567
1568bool BytecodeEmitter::emitGetPrivateName(TaggedParserAtomIndex nameAtom) {
1569 // The parser ensures the private name is present on the environment chain,
1570 // but its location can be Dynamic or Global when emitting debugger
1571 // eval-in-frame code.
1572 NameLocation location = lookupName(nameAtom);
1573 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1576); AnnotateMozCrashReason("MOZ_ASSERT" "(" "location.kind() == NameLocation::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate || location.kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation::Kind::Global"
")"); do { *((volatile int*)__null) = 1576; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1574 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1576); AnnotateMozCrashReason("MOZ_ASSERT" "(" "location.kind() == NameLocation::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate || location.kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation::Kind::Global"
")"); do { *((volatile int*)__null) = 1576; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1575 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1576); AnnotateMozCrashReason("MOZ_ASSERT" "(" "location.kind() == NameLocation::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate || location.kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation::Kind::Global"
")"); do { *((volatile int*)__null) = 1576; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1576 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1576); AnnotateMozCrashReason("MOZ_ASSERT" "(" "location.kind() == NameLocation::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate || location.kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation::Kind::Global"
")"); do { *((volatile int*)__null) = 1576; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1577
1578 return emitGetNameAtLocation(nameAtom, location);
1579}
1580
1581bool BytecodeEmitter::emitTDZCheckIfNeeded(TaggedParserAtomIndex name,
1582 const NameLocation& loc,
1583 ValueIsOnStack isOnStack) {
1584 // Dynamic accesses have TDZ checks built into their VM code and should
1585 // never emit explicit TDZ checks.
1586 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1586); AnnotateMozCrashReason("MOZ_ASSERT" "(" "loc.hasKnownSlot()"
")"); do { *((volatile int*)__null) = 1586; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1587 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1587); AnnotateMozCrashReason("MOZ_ASSERT" "(" "loc.isLexical() || loc.isPrivateMethod() || loc.isSynthetic()"
")"); do { *((volatile int*)__null) = 1587; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1588
1589 // Private names are implemented as lexical bindings, but it's just an
1590 // implementation detail. Per spec there's no TDZ check when using them.
1591 if (parserAtoms().isPrivateName(name)) {
1592 return true;
1593 }
1594
1595 Maybe<MaybeCheckTDZ> check =
1596 innermostTDZCheckCache->needsTDZCheck(this, name);
1597 if (!check) {
1598 return false;
1599 }
1600
1601 // We've already emitted a check in this basic block.
1602 if (*check == DontCheckTDZ) {
1603 return true;
1604 }
1605
1606 // If the value is not on the stack, we have to load it first.
1607 if (isOnStack == ValueIsOnStack::No) {
1608 if (loc.kind() == NameLocation::Kind::FrameSlot) {
1609 if (!emitLocalOp(JSOp::GetLocal, loc.frameSlot())) {
1610 return false;
1611 }
1612 } else {
1613 if (!emitEnvCoordOp(JSOp::GetAliasedVar, loc.environmentCoordinate())) {
1614 return false;
1615 }
1616 }
1617 }
1618
1619 // Emit the lexical check.
1620 if (loc.kind() == NameLocation::Kind::FrameSlot) {
1621 if (!emitLocalOp(JSOp::CheckLexical, loc.frameSlot())) {
1622 return false;
1623 }
1624 } else {
1625 if (!emitEnvCoordOp(JSOp::CheckAliasedLexical,
1626 loc.environmentCoordinate())) {
1627 return false;
1628 }
1629 }
1630
1631 // Pop the value if needed.
1632 if (isOnStack == ValueIsOnStack::No) {
1633 if (!emit1(JSOp::Pop)) {
1634 return false;
1635 }
1636 }
1637
1638 return innermostTDZCheckCache->noteTDZCheck(this, name, DontCheckTDZ);
1639}
1640
1641bool BytecodeEmitter::emitPropLHS(PropertyAccess* prop) {
1642 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1642); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!prop->isSuper()"
")"); do { *((volatile int*)__null) = 1642; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1643
1644 ParseNode* expr = &prop->expression();
1645
1646 if (!expr->is<PropertyAccess>() || expr->as<PropertyAccess>().isSuper()) {
1647 // The non-optimized case.
1648 return emitTree(expr);
1649 }
1650
1651 // If the object operand is also a dotted property reference, reverse the
1652 // list linked via expression() temporarily so we can iterate over it from
1653 // the bottom up (reversing again as we go), to avoid excessive recursion.
1654 PropertyAccess* pndot = &expr->as<PropertyAccess>();
1655 ParseNode* pnup = nullptr;
1656 ParseNode* pndown;
1657 for (;;) {
1658 // Reverse pndot->expression() to point up, not down.
1659 pndown = &pndot->expression();
1660 pndot->setExpression(pnup);
1661 if (!pndown->is<PropertyAccess>() ||
1662 pndown->as<PropertyAccess>().isSuper()) {
1663 break;
1664 }
1665 pnup = pndot;
1666 pndot = &pndown->as<PropertyAccess>();
1667 }
1668
1669 // pndown is a primary expression, not a dotted property reference.
1670 if (!emitTree(pndown)) {
1671 return false;
1672 }
1673
1674 while (true) {
1675 // Walk back up the list, emitting annotated name ops.
1676 if (!emitAtomOp(JSOp::GetProp, pndot->key().atom())) {
1677 return false;
1678 }
1679
1680 // Reverse the pndot->expression() link again.
1681 pnup = pndot->maybeExpression();
1682 pndot->setExpression(pndown);
1683 pndown = pndot;
1684 if (!pnup) {
1685 break;
1686 }
1687 pndot = &pnup->as<PropertyAccess>();
1688 }
1689 return true;
1690}
1691
1692bool BytecodeEmitter::emitPropIncDec(UnaryNode* incDec, ValueUsage valueUsage) {
1693 PropertyAccess* prop = &incDec->kid()->as<PropertyAccess>();
1694 bool isSuper = prop->isSuper();
1695 ParseNodeKind kind = incDec->getKind();
1696 PropOpEmitter poe(
1697 this,
1698 kind == ParseNodeKind::PostIncrementExpr
1699 ? PropOpEmitter::Kind::PostIncrement
1700 : kind == ParseNodeKind::PreIncrementExpr
1701 ? PropOpEmitter::Kind::PreIncrement
1702 : kind == ParseNodeKind::PostDecrementExpr
1703 ? PropOpEmitter::Kind::PostDecrement
1704 : PropOpEmitter::Kind::PreDecrement,
1705 isSuper ? PropOpEmitter::ObjKind::Super : PropOpEmitter::ObjKind::Other);
1706 if (!poe.prepareForObj()) {
1707 return false;
1708 }
1709 if (isSuper) {
1710 UnaryNode* base = &prop->expression().as<UnaryNode>();
1711 if (!emitGetThisForSuperBase(base)) {
1712 // [stack] THIS
1713 return false;
1714 }
1715 } else {
1716 if (!emitPropLHS(prop)) {
1717 // [stack] OBJ
1718 return false;
1719 }
1720 }
1721 if (!poe.emitIncDec(prop->key().atom(), valueUsage)) {
1722 // [stack] RESULT
1723 return false;
1724 }
1725
1726 return true;
1727}
1728
1729bool BytecodeEmitter::emitNameIncDec(UnaryNode* incDec, ValueUsage valueUsage) {
1730 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1730); AnnotateMozCrashReason("MOZ_ASSERT" "(" "incDec->kid()->isKind(ParseNodeKind::Name)"
")"); do { *((volatile int*)__null) = 1730; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1731
1732 ParseNodeKind kind = incDec->getKind();
1733 NameNode* name = &incDec->kid()->as<NameNode>();
1734 NameOpEmitter noe(this, name->atom(),
1735 kind == ParseNodeKind::PostIncrementExpr
1736 ? NameOpEmitter::Kind::PostIncrement
1737 : kind == ParseNodeKind::PreIncrementExpr
1738 ? NameOpEmitter::Kind::PreIncrement
1739 : kind == ParseNodeKind::PostDecrementExpr
1740 ? NameOpEmitter::Kind::PostDecrement
1741 : NameOpEmitter::Kind::PreDecrement);
1742 if (!noe.emitIncDec(valueUsage)) {
1743 return false;
1744 }
1745
1746 return true;
1747}
1748
1749bool BytecodeEmitter::emitElemObjAndKey(PropertyByValue* elem,
1750 ElemOpEmitter& eoe) {
1751 ParseNode* exprOrSuper = &elem->expression();
1752 ParseNode* key = &elem->key();
1753
1754 if (!eoe.prepareForObj()) {
1755 // [stack]
1756 return false;
1757 }
1758
1759 if (elem->isSuper()) {
1760 auto* base = &exprOrSuper->as<UnaryNode>();
1761 if (!emitGetThisForSuperBase(base)) {
1762 // [stack] THIS
1763 return false;
1764 }
1765 } else {
1766 if (!emitTree(exprOrSuper)) {
1767 // [stack] OBJ
1768 return false;
1769 }
1770 }
1771
1772 if (!eoe.prepareForKey()) {
1773 // [stack] # if Super
1774 // [stack] THIS? THIS
1775 // [stack] # otherwise
1776 // [stack] OBJ? OBJ
1777 return false;
1778 }
1779
1780 if (!emitTree(key)) {
1781 // [stack] # if Super
1782 // [stack] THIS? THIS KEY
1783 // [stack] # otherwise
1784 // [stack] OBJ? OBJ KEY
1785 return false;
1786 }
1787
1788 return true;
1789}
1790
1791bool BytecodeEmitter::emitElemOpBase(JSOp op) {
1792 if (!emit1(op)) {
1793 return false;
1794 }
1795
1796 return true;
1797}
1798
1799static ElemOpEmitter::Kind ConvertIncDecKind(ParseNodeKind kind) {
1800 switch (kind) {
1801 case ParseNodeKind::PostIncrementExpr:
1802 return ElemOpEmitter::Kind::PostIncrement;
1803 case ParseNodeKind::PreIncrementExpr:
1804 return ElemOpEmitter::Kind::PreIncrement;
1805 case ParseNodeKind::PostDecrementExpr:
1806 return ElemOpEmitter::Kind::PostDecrement;
1807 case ParseNodeKind::PreDecrementExpr:
1808 return ElemOpEmitter::Kind::PreDecrement;
1809 default:
1810 MOZ_CRASH("unexpected inc/dec node kind")do { do { } while (false); MOZ_ReportCrash("" "unexpected inc/dec node kind"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1810); AnnotateMozCrashReason("MOZ_CRASH(" "unexpected inc/dec node kind"
")"); do { *((volatile int*)__null) = 1810; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
1811 }
1812}
1813
1814static PrivateOpEmitter::Kind PrivateConvertIncDecKind(ParseNodeKind kind) {
1815 switch (kind) {
1816 case ParseNodeKind::PostIncrementExpr:
1817 return PrivateOpEmitter::Kind::PostIncrement;
1818 case ParseNodeKind::PreIncrementExpr:
1819 return PrivateOpEmitter::Kind::PreIncrement;
1820 case ParseNodeKind::PostDecrementExpr:
1821 return PrivateOpEmitter::Kind::PostDecrement;
1822 case ParseNodeKind::PreDecrementExpr:
1823 return PrivateOpEmitter::Kind::PreDecrement;
1824 default:
1825 MOZ_CRASH("unexpected inc/dec node kind")do { do { } while (false); MOZ_ReportCrash("" "unexpected inc/dec node kind"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1825); AnnotateMozCrashReason("MOZ_CRASH(" "unexpected inc/dec node kind"
")"); do { *((volatile int*)__null) = 1825; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
1826 }
1827}
1828
1829bool BytecodeEmitter::emitElemIncDec(UnaryNode* incDec, ValueUsage valueUsage) {
1830 PropertyByValue* elemExpr = &incDec->kid()->as<PropertyByValue>();
1831 bool isSuper = elemExpr->isSuper();
1832 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)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1832); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elemExpr->key().isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 1832; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1833 ParseNodeKind kind = incDec->getKind();
1834 ElemOpEmitter eoe(
1835 this, ConvertIncDecKind(kind),
1836 isSuper ? ElemOpEmitter::ObjKind::Super : ElemOpEmitter::ObjKind::Other);
1837 if (!emitElemObjAndKey(elemExpr, eoe)) {
1838 // [stack] # if Super
1839 // [stack] THIS KEY
1840 // [stack] # otherwise
1841 // [stack] OBJ KEY
1842 return false;
1843 }
1844 if (!eoe.emitIncDec(valueUsage)) {
1845 // [stack] RESULT
1846 return false;
1847 }
1848
1849 return true;
1850}
1851
1852bool BytecodeEmitter::emitCallIncDec(UnaryNode* incDec) {
1853 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1856); AnnotateMozCrashReason("MOZ_ASSERT" "(" "incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind(ParseNodeKind::PostDecrementExpr)"
")"); do { *((volatile int*)__null) = 1856; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1854 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1856); AnnotateMozCrashReason("MOZ_ASSERT" "(" "incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind(ParseNodeKind::PostDecrementExpr)"
")"); do { *((volatile int*)__null) = 1856; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1855 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1856); AnnotateMozCrashReason("MOZ_ASSERT" "(" "incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind(ParseNodeKind::PostDecrementExpr)"
")"); do { *((volatile int*)__null) = 1856; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1856 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1856); AnnotateMozCrashReason("MOZ_ASSERT" "(" "incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind(ParseNodeKind::PostDecrementExpr)"
")"); do { *((volatile int*)__null) = 1856; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1857
1858 ParseNode* call = incDec->kid();
1859 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1859); AnnotateMozCrashReason("MOZ_ASSERT" "(" "call->isKind(ParseNodeKind::CallExpr)"
")"); do { *((volatile int*)__null) = 1859; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1860 if (!emitTree(call)) {
1861 // [stack] CALLRESULT
1862 return false;
1863 }
1864 if (!emit1(JSOp::ToNumeric)) {
1865 // [stack] N
1866 return false;
1867 }
1868
1869 // The increment/decrement has no side effects, so proceed to throw for
1870 // invalid assignment target.
1871 return emit2(JSOp::ThrowMsg, uint8_t(ThrowMsgKind::AssignToCall));
1872}
1873
1874bool BytecodeEmitter::emitPrivateIncDec(UnaryNode* incDec,
1875 ValueUsage valueUsage) {
1876 PrivateMemberAccess* privateExpr = &incDec->kid()->as<PrivateMemberAccess>();
1877 ParseNodeKind kind = incDec->getKind();
1878 PrivateOpEmitter xoe(this, PrivateConvertIncDecKind(kind),
1879 privateExpr->privateName().name());
1880 if (!emitTree(&privateExpr->expression())) {
1881 // [stack] OBJ
1882 return false;
1883 }
1884 if (!xoe.emitReference()) {
1885 // [stack] OBJ NAME
1886 return false;
1887 }
1888 if (!xoe.emitIncDec(valueUsage)) {
1889 // [stack] RESULT
1890 return false;
1891 }
1892
1893 return true;
1894}
1895
1896bool BytecodeEmitter::emitDouble(double d) {
1897 BytecodeOffset offset;
1898 if (!emitCheck(JSOp::Double, 9, &offset)) {
1899 return false;
1900 }
1901
1902 jsbytecode* code = bytecodeSection().code(offset);
1903 code[0] = jsbytecode(JSOp::Double);
1904 SET_INLINE_VALUE(code, DoubleValue(d));
1905 bytecodeSection().updateDepth(JSOp::Double, offset);
1906 return true;
1907}
1908
1909bool BytecodeEmitter::emitNumberOp(double dval) {
1910 int32_t ival;
1911 if (NumberIsInt32(dval, &ival)) {
1912 if (ival == 0) {
1913 return emit1(JSOp::Zero);
1914 }
1915 if (ival == 1) {
1916 return emit1(JSOp::One);
1917 }
1918 if ((int)(int8_t)ival == ival) {
1919 return emit2(JSOp::Int8, uint8_t(int8_t(ival)));
1920 }
1921
1922 uint32_t u = uint32_t(ival);
1923 if (u < Bit(16)) {
1924 if (!emitUint16Operand(JSOp::Uint16, u)) {
1925 return false;
1926 }
1927 } else if (u < Bit(24)) {
1928 BytecodeOffset off;
1929 if (!emitN(JSOp::Uint24, 3, &off)) {
1930 return false;
1931 }
1932 SET_UINT24(bytecodeSection().code(off), u);
1933 } else {
1934 BytecodeOffset off;
1935 if (!emitN(JSOp::Int32, 4, &off)) {
1936 return false;
1937 }
1938 SET_INT32(bytecodeSection().code(off), ival);
1939 }
1940 return true;
1941 }
1942
1943 return emitDouble(dval);
1944}
1945
1946/*
1947 * Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047.
1948 * LLVM is deciding to inline this function which uses a lot of stack space
1949 * into emitTree which is recursive and uses relatively little stack space.
1950 */
1951MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitSwitch(SwitchStatement* switchStmt) {
1952 LexicalScopeNode& lexical = switchStmt->lexicalForCaseList();
1953 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1953); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lexical.isKind(ParseNodeKind::LexicalScope)"
")"); do { *((volatile int*)__null) = 1953; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1954 ListNode* cases = &lexical.scopeBody()->as<ListNode>();
1955 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1955); AnnotateMozCrashReason("MOZ_ASSERT" "(" "cases->isKind(ParseNodeKind::StatementList)"
")"); do { *((volatile int*)__null) = 1955; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1956
1957 SwitchEmitter se(this);
1958 if (!se.emitDiscriminant(switchStmt->discriminant().pn_pos.begin)) {
1959 return false;
1960 }
1961
1962 if (!markStepBreakpoint()) {
1963 return false;
1964 }
1965 if (!emitTree(&switchStmt->discriminant())) {
1966 return false;
1967 }
1968
1969 // Enter the scope before pushing the switch BreakableControl since all
1970 // breaks are under this scope.
1971
1972 if (!lexical.isEmptyScope()) {
1973 if (!se.emitLexical(lexical.scopeBindings())) {
1974 return false;
1975 }
1976
1977 // A switch statement may contain hoisted functions inside its
1978 // cases. The hasTopLevelFunctionDeclarations flag is propagated from the
1979 // StatementList bodies of the cases to the case list.
1980 if (cases->hasTopLevelFunctionDeclarations()) {
1981 for (ParseNode* item : cases->contents()) {
1982 CaseClause* caseClause = &item->as<CaseClause>();
1983 ListNode* statements = caseClause->statementList();
1984 if (statements->hasTopLevelFunctionDeclarations()) {
1985 if (!emitHoistedFunctionsInList(statements)) {
1986 return false;
1987 }
1988 }
1989 }
1990 }
1991 } else {
1992 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1992); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!cases->hasTopLevelFunctionDeclarations()"
")"); do { *((volatile int*)__null) = 1992; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1993 }
1994
1995 SwitchEmitter::TableGenerator tableGen(this);
1996 uint32_t caseCount = cases->count() - (switchStmt->hasDefault() ? 1 : 0);
1997 if (caseCount == 0) {
1998 tableGen.finish(0);
1999 } else {
2000 for (ParseNode* item : cases->contents()) {
2001 CaseClause* caseClause = &item->as<CaseClause>();
2002 if (caseClause->isDefault()) {
2003 continue;
2004 }
2005
2006 ParseNode* caseValue = caseClause->caseExpression();
2007
2008 if (caseValue->getKind() != ParseNodeKind::NumberExpr) {
2009 tableGen.setInvalid();
2010 break;
2011 }
2012
2013 int32_t i;
2014 if (!NumberEqualsInt32(caseValue->as<NumericLiteral>().value(), &i)) {
2015 tableGen.setInvalid();
2016 break;
2017 }
2018
2019 if (!tableGen.addNumber(i)) {
2020 return false;
2021 }
2022 }
2023
2024 tableGen.finish(caseCount);
2025 }
2026
2027 if (!se.validateCaseCount(caseCount)) {
2028 return false;
2029 }
2030
2031 bool isTableSwitch = tableGen.isValid();
2032 if (isTableSwitch) {
2033 if (!se.emitTable(tableGen)) {
2034 return false;
2035 }
2036 } else {
2037 if (!se.emitCond()) {
2038 return false;
2039 }
2040
2041 // Emit code for evaluating cases and jumping to case statements.
2042 for (ParseNode* item : cases->contents()) {
2043 CaseClause* caseClause = &item->as<CaseClause>();
2044 if (caseClause->isDefault()) {
2045 continue;
2046 }
2047
2048 if (!se.prepareForCaseValue()) {
2049 return false;
2050 }
2051
2052 ParseNode* caseValue = caseClause->caseExpression();
2053 // If the expression is a literal, suppress line number emission so
2054 // that debugging works more naturally.
2055 if (!emitTree(
2056 caseValue, ValueUsage::WantValue,
2057 caseValue->isLiteral() ? SUPPRESS_LINENOTE : EMIT_LINENOTE)) {
2058 return false;
2059 }
2060
2061 if (!se.emitCaseJump()) {
2062 return false;
2063 }
2064 }
2065 }
2066
2067 // Emit code for each case's statements.
2068 for (ParseNode* item : cases->contents()) {
2069 CaseClause* caseClause = &item->as<CaseClause>();
2070 if (caseClause->isDefault()) {
2071 if (!se.emitDefaultBody()) {
2072 return false;
2073 }
2074 } else {
2075 if (isTableSwitch) {
2076 ParseNode* caseValue = caseClause->caseExpression();
2077 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2077); AnnotateMozCrashReason("MOZ_ASSERT" "(" "caseValue->isKind(ParseNodeKind::NumberExpr)"
")"); do { *((volatile int*)__null) = 2077; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2078
2079 NumericLiteral* literal = &caseValue->as<NumericLiteral>();
2080#ifdef DEBUG1
2081 // Use NumberEqualsInt32 here because switches compare using
2082 // strict equality, which will equate -0 and +0. In contrast
2083 // NumberIsInt32 would return false for -0.
2084 int32_t v;
2085 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)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2085); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mozilla::NumberEqualsInt32(literal->value(), &v)"
")"); do { *((volatile int*)__null) = 2085; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2086#endif
2087 int32_t i = int32_t(literal->value());
2088
2089 if (!se.emitCaseBody(i, tableGen)) {
2090 return false;
2091 }
2092 } else {
2093 if (!se.emitCaseBody()) {
2094 return false;
2095 }
2096 }
2097 }
2098
2099 if (!emitTree(caseClause->statementList())) {
2100 return false;
2101 }
2102 }
2103
2104 if (!se.emitEnd()) {
2105 return false;
2106 }
2107
2108 return true;
2109}
2110
2111bool BytecodeEmitter::allocateResumeIndex(BytecodeOffset offset,
2112 uint32_t* resumeIndex) {
2113 static constexpr uint32_t MaxResumeIndex = BitMask(24);
2114
2115 static_assert(
2116 MaxResumeIndex < uint32_t(AbstractGeneratorObject::RESUME_INDEX_RUNNING),
2117 "resumeIndex should not include magic AbstractGeneratorObject "
2118 "resumeIndex values");
2119 static_assert(
2120 MaxResumeIndex <= INT32_MAX(2147483647) / sizeof(uintptr_t),
2121 "resumeIndex * sizeof(uintptr_t) must fit in an int32. JIT code relies "
2122 "on this when loading resume entries from BaselineScript");
2123
2124 *resumeIndex = bytecodeSection().resumeOffsetList().length();
2125 if (*resumeIndex > MaxResumeIndex) {
2126 reportError(nullptr, JSMSG_TOO_MANY_RESUME_INDEXES);
2127 return false;
2128 }
2129
2130 return bytecodeSection().resumeOffsetList().append(offset.value());
2131}
2132
2133bool BytecodeEmitter::allocateResumeIndexRange(
2134 mozilla::Span<BytecodeOffset> offsets, uint32_t* firstResumeIndex) {
2135 *firstResumeIndex = 0;
2136
2137 for (size_t i = 0, len = offsets.size(); i < len; i++) {
2138 uint32_t resumeIndex;
2139 if (!allocateResumeIndex(offsets[i], &resumeIndex)) {
2140 return false;
2141 }
2142 if (i == 0) {
2143 *firstResumeIndex = resumeIndex;
2144 }
2145 }
2146
2147 return true;
2148}
2149
2150bool BytecodeEmitter::emitYieldOp(JSOp op) {
2151 // ParseContext::Scope::setOwnStackSlotCount should check the fixed slot
2152 // for the following, and it should prevent using fixed slot if there are
2153 // too many bindings:
2154 // * generator or asyn function
2155 // * module code after top-level await
2156 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2157); AnnotateMozCrashReason("MOZ_ASSERT" "(" "innermostEmitterScopeNoCheck()->frameSlotEnd() <= ParseContext::Scope::FixedSlotLimit"
")"); do { *((volatile int*)__null) = 2157; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2157 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2157); AnnotateMozCrashReason("MOZ_ASSERT" "(" "innermostEmitterScopeNoCheck()->frameSlotEnd() <= ParseContext::Scope::FixedSlotLimit"
")"); do { *((volatile int*)__null) = 2157; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2158
2159 if (op == JSOp::FinalYieldRval) {
2160 return emit1(JSOp::FinalYieldRval);
2161 }
2162
2163 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2164); AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::InitialYield || op == JSOp::Yield || op == JSOp::Await"
")"); do { *((volatile int*)__null) = 2164; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2164 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2164); AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::InitialYield || op == JSOp::Yield || op == JSOp::Await"
")"); do { *((volatile int*)__null) = 2164; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2165
2166 BytecodeOffset off;
2167 if (!emitN(op, 3, &off)) {
2168 return false;
2169 }
2170
2171 if (op == JSOp::InitialYield || op == JSOp::Yield) {
2172 bytecodeSection().addNumYields();
2173 }
2174
2175 uint32_t resumeIndex;
2176 if (!allocateResumeIndex(bytecodeSection().offset(), &resumeIndex)) {
2177 return false;
2178 }
2179
2180 SET_RESUMEINDEX(bytecodeSection().code(off), resumeIndex);
2181
2182 BytecodeOffset unusedOffset;
2183 return emitJumpTargetOp(JSOp::AfterYield, &unusedOffset);
2184}
2185
2186bool BytecodeEmitter::emitPushResumeKind(GeneratorResumeKind kind) {
2187 return emit2(JSOp::ResumeKind, uint8_t(kind));
2188}
2189
2190bool BytecodeEmitter::emitSetThis(BinaryNode* setThisNode) {
2191 // ParseNodeKind::SetThis is used to update |this| after a super() call
2192 // in a derived class constructor.
2193
2194 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2194); AnnotateMozCrashReason("MOZ_ASSERT" "(" "setThisNode->isKind(ParseNodeKind::SetThis)"
")"); do { *((volatile int*)__null) = 2194; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2195 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)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2195); AnnotateMozCrashReason("MOZ_ASSERT" "(" "setThisNode->left()->isKind(ParseNodeKind::Name)"
")"); do { *((volatile int*)__null) = 2195; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2196
2197 auto name = setThisNode->left()->as<NameNode>().name();
2198
2199 // The 'this' binding is not lexical, but due to super() semantics this
2200 // initialization needs to be treated as a lexical one.
2201 NameLocation loc = lookupName(name);
2202 NameLocation lexicalLoc;
2203 if (loc.kind() == NameLocation::Kind::FrameSlot) {
2204 lexicalLoc = NameLocation::FrameSlot(BindingKind::Let, loc.frameSlot());
2205 } else if (loc.kind() == NameLocation::Kind::EnvironmentCoordinate) {
2206 EnvironmentCoordinate coord = loc.environmentCoordinate();
2207 uint8_t hops = AssertedCast<uint8_t>(coord.hops());
2208 lexicalLoc = NameLocation::EnvironmentCoordinate(BindingKind::Let, hops,
2209 coord.slot());
2210 } else {
2211 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2211); AnnotateMozCrashReason("MOZ_ASSERT" "(" "loc.kind() == NameLocation::Kind::Dynamic"
")"); do { *((volatile int*)__null) = 2211; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2212 lexicalLoc = loc;
2213 }
2214
2215 NameOpEmitter noe(this, name, lexicalLoc, NameOpEmitter::Kind::Initialize);
2216 if (!noe.prepareForRhs()) {
2217 // [stack]
2218 return false;
2219 }
2220
2221 // Emit the new |this| value.
2222 if (!emitTree(setThisNode->right())) {
2223 // [stack] NEWTHIS
2224 return false;
2225 }
2226
2227 // Get the original |this| and throw if we already initialized
2228 // it. Do *not* use the NameLocation argument, as that's the special
2229 // lexical location below to deal with super() semantics.
2230 if (!emitGetName(name)) {
2231 // [stack] NEWTHIS THIS
2232 return false;
2233 }
2234 if (!emit1(JSOp::CheckThisReinit)) {
2235 // [stack] NEWTHIS THIS
2236 return false;
2237 }
2238 if (!emit1(JSOp::Pop)) {
2239 // [stack] NEWTHIS
2240 return false;
2241 }
2242 if (!noe.emitAssignment()) {
2243 // [stack] NEWTHIS
2244 return false;
2245 }
2246
2247 if (!emitInitializeInstanceMembers(true)) {
2248 return false;
2249 }
2250
2251 return true;
2252}
2253
2254bool BytecodeEmitter::defineHoistedTopLevelFunctions(ParseNode* body) {
2255 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()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2255); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inPrologue()"
")"); do { *((volatile int*)__null) = 2255; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2256 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())"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2256); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isGlobalContext() || (sc->isEvalContext() && !sc->strict())"
")"); do { *((volatile int*)__null) = 2256; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2257 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>()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2257); AnnotateMozCrashReason("MOZ_ASSERT" "(" "body->is<LexicalScopeNode>() || body->is<ListNode>()"
")"); do { *((volatile int*)__null) = 2257; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2258
2259 if (body->is<LexicalScopeNode>()) {
2260 body = body->as<LexicalScopeNode>().scopeBody();
2261 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>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2261); AnnotateMozCrashReason("MOZ_ASSERT" "(" "body->is<ListNode>()"
")"); do { *((volatile int*)__null) = 2261; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2262 }
2263
2264 if (!body->as<ListNode>().hasTopLevelFunctionDeclarations()) {
2265 return true;
2266 }
2267
2268 return emitHoistedFunctionsInList(&body->as<ListNode>());
2269}
2270
2271// For Global and sloppy-Eval scripts, this performs most of the steps of the
2272// spec's [GlobalDeclarationInstantiation] and [EvalDeclarationInstantiation]
2273// operations.
2274//
2275// Note that while strict-Eval is handled in the same part of the spec, it never
2276// fails for global-redeclaration checks so those scripts initialize directly in
2277// their bytecode.
2278bool BytecodeEmitter::emitDeclarationInstantiation(ParseNode* body) {
2279 if (sc->isModuleContext()) {
2280 // ES Modules have dedicated variable and lexial environments and therefore
2281 // do not have to perform redeclaration checks. We initialize their bindings
2282 // elsewhere in bytecode.
2283 return true;
2284 }
2285
2286 if (sc->isEvalContext() && sc->strict()) {
2287 // Strict Eval has a dedicated variables (and lexical) environment and
2288 // therefore does not have to perform redeclaration checks. We initialize
2289 // their bindings elsewhere in the bytecode.
2290 return true;
2291 }
2292
2293 // If we have no variables bindings, then we are done!
2294 if (sc->isGlobalContext()) {
2295 if (!sc->asGlobalContext()->bindings) {
2296 return true;
2297 }
2298 } else {
2299 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2299); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isEvalContext()"
")"); do { *((volatile int*)__null) = 2299; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2300
2301 if (!sc->asEvalContext()->bindings) {
2302 return true;
2303 }
2304 }
2305
2306#if DEBUG1
2307 // There should be no emitted functions yet.
2308 for (const auto& thing : perScriptData().gcThingList().objects()) {
2309 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2309); AnnotateMozCrashReason("MOZ_ASSERT" "(" "thing.isEmptyGlobalScope() || thing.isScope()"
")"); do { *((volatile int*)__null) = 2309; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2310 }
2311#endif
2312
2313 // Emit the hoisted functions to gc-things list. There is no bytecode
2314 // generated yet to bind them.
2315 if (!defineHoistedTopLevelFunctions(body)) {
2316 return false;
2317 }
2318
2319 // Save the last GCThingIndex emitted. The hoisted functions are contained in
2320 // the gc-things list up until this point. This set of gc-things also contain
2321 // initial scopes (of which there must be at least one).
2322 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2322); AnnotateMozCrashReason("MOZ_ASSERT" "(" "perScriptData().gcThingList().length() > 0"
")"); do { *((volatile int*)__null) = 2322; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2323 GCThingIndex lastFun =
2324 GCThingIndex(perScriptData().gcThingList().length() - 1);
2325
2326#if DEBUG1
2327 for (const auto& thing : perScriptData().gcThingList().objects()) {
2328 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2329); AnnotateMozCrashReason("MOZ_ASSERT" "(" "thing.isEmptyGlobalScope() || thing.isScope() || thing.isFunction()"
")"); do { *((volatile int*)__null) = 2329; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2329 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2329); AnnotateMozCrashReason("MOZ_ASSERT" "(" "thing.isEmptyGlobalScope() || thing.isScope() || thing.isFunction()"
")"); do { *((volatile int*)__null) = 2329; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2330 }
2331#endif
2332
2333 // Check for declaration conflicts and initialize the bindings.
2334 // NOTE: The self-hosting top-level script should not populate the builtins
2335 // directly on the GlobalObject (and instead uses JSOp::GetIntrinsic for
2336 // lookups).
2337 if (emitterMode == BytecodeEmitter::EmitterMode::Normal) {
2338 if (!emitGCIndexOp(JSOp::GlobalOrEvalDeclInstantiation, lastFun)) {
2339 return false;
2340 }
2341 }
2342
2343 return true;
2344}
2345
2346bool BytecodeEmitter::emitScript(ParseNode* body) {
2347 setScriptStartOffsetIfUnset(body->pn_pos.begin);
2348
2349 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()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2349); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inPrologue()"
")"); do { *((volatile int*)__null) = 2349; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2350
2351 TDZCheckCache tdzCache(this);
2352 EmitterScope emitterScope(this);
2353 Maybe<AsyncEmitter> topLevelAwait;
2354 if (sc->isGlobalContext()) {
2355 if (!emitterScope.enterGlobal(this, sc->asGlobalContext())) {
2356 return false;
2357 }
2358 } else if (sc->isEvalContext()) {
2359 if (!emitterScope.enterEval(this, sc->asEvalContext())) {
2360 return false;
2361 }
2362 } else {
2363 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2363); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isModuleContext()"
")"); do { *((volatile int*)__null) = 2363; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2364 if (!emitterScope.enterModule(this, sc->asModuleContext())) {
2365 return false;
2366 }
2367 if (sc->asModuleContext()->isAsync()) {
2368 topLevelAwait.emplace(this);
2369 }
2370 }
2371
2372 setFunctionBodyEndPos(body->pn_pos.end);
2373
2374 bool isSloppyEval = sc->isEvalContext() && !sc->strict();
2375 if (isSloppyEval && body->is<LexicalScopeNode>() &&
2376 !body->as<LexicalScopeNode>().isEmptyScope()) {
2377 // Sloppy eval scripts may emit hoisted functions bindings with a
2378 // `JSOp::GlobalOrEvalDeclInstantiation` opcode below. If this eval needs a
2379 // top-level lexical environment, we must ensure that environment is created
2380 // before those functions are created and bound.
2381 //
2382 // This differs from the global-script case below because the global-lexical
2383 // environment exists outside the script itself. In the case of strict eval
2384 // scripts, the `emitterScope` above is already sufficient.
2385 EmitterScope lexicalEmitterScope(this);
2386 LexicalScopeNode* scope = &body->as<LexicalScopeNode>();
2387
2388 if (!lexicalEmitterScope.enterLexical(this, ScopeKind::Lexical,
2389 scope->scopeBindings())) {
2390 return false;
2391 }
2392
2393 if (!emitDeclarationInstantiation(scope->scopeBody())) {
2394 return false;
2395 }
2396
2397 switchToMain();
2398
2399 ParseNode* scopeBody = scope->scopeBody();
2400 if (!emitLexicalScopeBody(scopeBody)) {
2401 return false;
2402 }
2403
2404 if (!updateSourceCoordNotes(scopeBody->pn_pos.end)) {
2405 return false;
2406 }
2407
2408 if (!lexicalEmitterScope.leave(this)) {
2409 return false;
2410 }
2411 } else {
2412 if (!emitDeclarationInstantiation(body)) {
2413 return false;
2414 }
2415 if (topLevelAwait) {
2416 if (!topLevelAwait->prepareForModule()) {
2417 return false;
2418 }
2419 }
2420
2421 switchToMain();
2422
2423#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
2424 if (!emitterScope.prepareForModuleDisposableScopeBody(this)) {
2425 return false;
2426 }
2427#endif
2428
2429 if (topLevelAwait) {
2430 if (!topLevelAwait->prepareForBody()) {
2431 return false;
2432 }
2433 }
2434
2435 if (!emitTree(body)) {
2436 // [stack]
2437 return false;
2438 }
2439
2440 if (!updateSourceCoordNotes(body->pn_pos.end)) {
2441 return false;
2442 }
2443 }
2444
2445#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
2446 if (!emitterScope.emitModuleDisposableScopeBodyEnd(this)) {
2447 return false;
2448 }
2449#endif
2450
2451 if (topLevelAwait) {
2452 if (!topLevelAwait->emitEndModule()) {
2453 return false;
2454 }
2455 }
2456
2457 if (!markSimpleBreakpoint()) {
2458 return false;
2459 }
2460
2461 if (!emitReturnRval()) {
2462 return false;
2463 }
2464
2465 if (!emitterScope.leave(this)) {
2466 return false;
2467 }
2468
2469 if (!NameFunctions(fc, parserAtoms(), body)) {
2470 return false;
2471 }
2472
2473 // Create a Stencil and convert it into a JSScript.
2474 return intoScriptStencil(CompilationStencil::TopLevelIndex);
2475}
2476
2477js::UniquePtr<ImmutableScriptData>
2478BytecodeEmitter::createImmutableScriptData() {
2479 uint32_t nslots;
2480 if (!getNslots(&nslots)) {
2481 return nullptr;
2482 }
2483
2484 bool isFunction = sc->isFunctionBox();
2485 uint16_t funLength = isFunction ? sc->asFunctionBox()->length() : 0;
2486
2487 mozilla::SaturateUint8 propertyCountEstimate = propertyAdditionEstimate;
2488
2489 // Add fields to the property count estimate.
2490 if (isFunction && sc->asFunctionBox()->useMemberInitializers()) {
2491 propertyCountEstimate +=
2492 sc->asFunctionBox()->memberInitializers().numMemberInitializers;
2493 }
2494
2495 return ImmutableScriptData::new_(
2496 fc, mainOffset(), maxFixedSlots, nslots, bodyScopeIndex,
2497 bytecodeSection().numICEntries(), isFunction, funLength,
2498 propertyCountEstimate.value(), bytecodeSection().code(),
2499 bytecodeSection().notes(), bytecodeSection().resumeOffsetList().span(),
2500 bytecodeSection().scopeNoteList().span(),
2501 bytecodeSection().tryNoteList().span());
2502}
2503
2504#if defined(ENABLE_DECORATORS) || defined(ENABLE_EXPLICIT_RESOURCE_MANAGEMENT)
2505bool BytecodeEmitter::emitCheckIsCallable() {
2506 // This emits code to check if the value at the top of the stack is
2507 // callable. The value is left on the stack.
2508 // [stack] VAL
2509 if (!emitAtomOp(JSOp::GetIntrinsic,
2510 TaggedParserAtomIndex::WellKnown::IsCallable())) {
2511 // [stack] VAL ISCALLABLE
2512 return false;
2513 }
2514 if (!emit1(JSOp::Undefined)) {
2515 // [stack] VAL ISCALLABLE UNDEFINED
2516 return false;
2517 }
2518 if (!emitDupAt(2)) {
2519 // [stack] VAL ISCALLABLE UNDEFINED VAL
2520 return false;
2521 }
2522 return emitCall(JSOp::Call, 1);
2523 // [stack] VAL ISCALLABLE_RESULT
2524}
2525#endif
2526
2527bool BytecodeEmitter::getNslots(uint32_t* nslots) const {
2528 uint64_t nslots64 =
2529 maxFixedSlots + static_cast<uint64_t>(bytecodeSection().maxStackDepth());
2530 if (nslots64 > UINT32_MAX(4294967295U)) {
2531 reportError(nullptr, JSMSG_NEED_DIET, "script");
2532 return false;
2533 }
2534 *nslots = nslots64;
2535 return true;
2536}
2537
2538bool BytecodeEmitter::emitFunctionScript(FunctionNode* funNode) {
2539 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()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2539); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inPrologue()"
")"); do { *((volatile int*)__null) = 2539; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2540 ParamsBodyNode* paramsBody = funNode->body();
2541 FunctionBox* funbox = sc->asFunctionBox();
2542
2543 setScriptStartOffsetIfUnset(paramsBody->pn_pos.begin);
2544
2545 // [stack]
2546
2547 FunctionScriptEmitter fse(this, funbox, Some(paramsBody->pn_pos.begin),
2548 Some(paramsBody->pn_pos.end));
2549 if (!fse.prepareForParameters()) {
2550 // [stack]
2551 return false;
2552 }
2553
2554 if (!emitFunctionFormalParameters(paramsBody)) {
2555 // [stack]
2556 return false;
2557 }
2558
2559 if (!fse.prepareForBody()) {
2560 // [stack]
2561 return false;
2562 }
2563
2564 if (!emitTree(paramsBody->body())) {
2565 // [stack]
2566 return false;
2567 }
2568
2569 if (!fse.emitEndBody()) {
2570 // [stack]
2571 return false;
2572 }
2573
2574 if (funbox->index() == CompilationStencil::TopLevelIndex) {
2575 if (!NameFunctions(fc, parserAtoms(), funNode)) {
2576 return false;
2577 }
2578 }
2579
2580 return fse.intoStencil();
2581}
2582
2583class js::frontend::DestructuringLHSRef {
2584 struct None {
2585 size_t numReferenceSlots() const { return 0; }
2586 };
2587
2588 mozilla::Variant<None, NameOpEmitter, PropOpEmitter, ElemOpEmitter,
2589 PrivateOpEmitter>
2590 emitter_ = AsVariant(None{});
2591
2592 public:
2593 template <typename T>
2594 void from(T&& emitter) {
2595 emitter_.emplace<T>(std::forward<T>(emitter));
2596 }
2597
2598 template <typename T>
2599 T& emitter() {
2600 return emitter_.as<T>();
2601 }
2602
2603 /**
2604 * Return the number of values pushed onto the stack.
2605 */
2606 size_t numReferenceSlots() const {
2607 return emitter_.match([](auto& e) { return e.numReferenceSlots(); });
2608 }
2609};
2610
2611bool BytecodeEmitter::emitDestructuringLHSRef(ParseNode* target,
2612 DestructuringFlavor flav,
2613 DestructuringLHSRef& lref) {
2614#ifdef DEBUG1
2615 int depth = bytecodeSection().stackDepth();
2616#endif
2617
2618 switch (target->getKind()) {
2619 case ParseNodeKind::ArrayExpr:
2620 case ParseNodeKind::ObjectExpr:
2621 // No need to recurse into ParseNodeKind::Array and ParseNodeKind::Object
2622 // subpatterns here, since emitSetOrInitializeDestructuring does the
2623 // recursion when setting or initializing the value.
2624 break;
2625
2626 case ParseNodeKind::Name: {
2627 auto* name = &target->as<NameNode>();
2628 NameOpEmitter noe(this, name->atom(),
2629 flav == DestructuringFlavor::Assignment
2630 ? NameOpEmitter::Kind::SimpleAssignment
2631 : NameOpEmitter::Kind::Initialize);
2632 if (!noe.prepareForRhs()) {
2633 return false;
2634 }
2635
2636 lref.from(std::move(noe));
2637 return true;
2638 }
2639
2640 case ParseNodeKind::ArgumentsLength:
2641 case ParseNodeKind::DotExpr: {
2642 PropertyAccess* prop = &target->as<PropertyAccess>();
2643 bool isSuper = prop->isSuper();
2644 PropOpEmitter poe(this, PropOpEmitter::Kind::SimpleAssignment,
2645 isSuper ? PropOpEmitter::ObjKind::Super
2646 : PropOpEmitter::ObjKind::Other);
2647 if (!poe.prepareForObj()) {
2648 return false;
2649 }
2650 if (isSuper) {
2651 UnaryNode* base = &prop->expression().as<UnaryNode>();
2652 if (!emitGetThisForSuperBase(base)) {
2653 // [stack] THIS SUPERBASE
2654 return false;
2655 }
2656 } else {
2657 if (!emitTree(&prop->expression())) {
2658 // [stack] OBJ
2659 return false;
2660 }
2661 }
2662 if (!poe.prepareForRhs()) {
2663 // [stack] # if Super
2664 // [stack] THIS SUPERBASE
2665 // [stack] # otherwise
2666 // [stack] OBJ
2667 return false;
2668 }
2669
2670 lref.from(std::move(poe));
2671 break;
2672 }
2673
2674 case ParseNodeKind::ElemExpr: {
2675 PropertyByValue* elem = &target->as<PropertyByValue>();
2676 bool isSuper = elem->isSuper();
2677 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2677); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 2677; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2678 ElemOpEmitter eoe(this, ElemOpEmitter::Kind::SimpleAssignment,
2679 isSuper ? ElemOpEmitter::ObjKind::Super
2680 : ElemOpEmitter::ObjKind::Other);
2681 if (!emitElemObjAndKey(elem, eoe)) {
2682 // [stack] # if Super
2683 // [stack] THIS KEY
2684 // [stack] # otherwise
2685 // [stack] OBJ KEY
2686 return false;
2687 }
2688 if (!eoe.prepareForRhs()) {
2689 // [stack] # if Super
2690 // [stack] THIS KEY SUPERBASE
2691 // [stack] # otherwise
2692 // [stack] OBJ KEY
2693 return false;
2694 }
2695
2696 lref.from(std::move(eoe));
2697 break;
2698 }
2699
2700 case ParseNodeKind::PrivateMemberExpr: {
2701 PrivateMemberAccess* privateExpr = &target->as<PrivateMemberAccess>();
2702 PrivateOpEmitter xoe(this, PrivateOpEmitter::Kind::SimpleAssignment,
2703 privateExpr->privateName().name());
2704 if (!emitTree(&privateExpr->expression())) {
2705 // [stack] OBJ
2706 return false;
2707 }
2708 if (!xoe.emitReference()) {
2709 // [stack] OBJ NAME
2710 return false;
2711 }
2712
2713 lref.from(std::move(xoe));
2714 break;
2715 }
2716
2717 case ParseNodeKind::CallExpr:
2718 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2721); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget "
"rejects function calls as assignment " "targets in destructuring assignments"
")"); do { *((volatile int*)__null) = 2721; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2719 "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2721); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget "
"rejects function calls as assignment " "targets in destructuring assignments"
")"); do { *((volatile int*)__null) = 2721; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2720 "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2721); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget "
"rejects function calls as assignment " "targets in destructuring assignments"
")"); do { *((volatile int*)__null) = 2721; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2721 "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2721); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget "
"rejects function calls as assignment " "targets in destructuring assignments"
")"); do { *((volatile int*)__null) = 2721; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2722 break;
2723
2724 default:
2725 MOZ_CRASH("emitDestructuringLHSRef: bad lhs kind")do { do { } while (false); MOZ_ReportCrash("" "emitDestructuringLHSRef: bad lhs kind"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2725); AnnotateMozCrashReason("MOZ_CRASH(" "emitDestructuringLHSRef: bad lhs kind"
")"); do { *((volatile int*)__null) = 2725; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
2726 }
2727
2728 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())"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2729); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == depth + int(lref.numReferenceSlots())"
")"); do { *((volatile int*)__null) = 2729; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2729 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())"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2729); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == depth + int(lref.numReferenceSlots())"
")"); do { *((volatile int*)__null) = 2729; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2730
2731 return true;
2732}
2733
2734bool BytecodeEmitter::emitSetOrInitializeDestructuring(
2735 ParseNode* target, DestructuringFlavor flav, DestructuringLHSRef& lref) {
2736 // Now emit the lvalue opcode sequence. If the lvalue is a nested
2737 // destructuring initialiser-form, call ourselves to handle it, then pop
2738 // the matched value. Otherwise emit an lvalue bytecode sequence followed
2739 // by an assignment op.
2740
2741 switch (target->getKind()) {
2742 case ParseNodeKind::ArrayExpr:
2743 case ParseNodeKind::ObjectExpr:
2744 if (!emitDestructuringOps(&target->as<ListNode>(), flav)) {
2745 return false;
2746 }
2747 // emitDestructuringOps leaves the assigned (to-be-destructured) value on
2748 // top of the stack.
2749 break;
2750
2751 case ParseNodeKind::Name: {
2752 // The environment is already pushed by emitDestructuringLHSRef.
2753 // [stack] ENV? VAL
2754 auto& noe = lref.emitter<NameOpEmitter>();
2755
2756 if (!noe.emitAssignment()) {
2757 // [stack] VAL
2758 return false;
2759 }
2760 break;
2761 }
2762
2763 case ParseNodeKind::ArgumentsLength:
2764 case ParseNodeKind::DotExpr: {
2765 // The reference is already pushed by emitDestructuringLHSRef.
2766 // [stack] # if Super
2767 // [stack] THIS SUPERBASE VAL
2768 // [stack] # otherwise
2769 // [stack] OBJ VAL
2770 auto& poe = lref.emitter<PropOpEmitter>();
2771 auto* prop = &target->as<PropertyAccess>();
2772
2773 if (!poe.emitAssignment(prop->key().atom())) {
2774 // [stack] # VAL
2775 return false;
2776 }
2777 break;
2778 }
2779
2780 case ParseNodeKind::ElemExpr: {
2781 // The reference is already pushed by emitDestructuringLHSRef.
2782 // [stack] # if Super
2783 // [stack] THIS KEY SUPERBASE VAL
2784 // [stack] # otherwise
2785 // [stack] OBJ KEY VAL
2786 auto& eoe = lref.emitter<ElemOpEmitter>();
2787
2788 if (!eoe.emitAssignment()) {
2789 // [stack] VAL
2790 return false;
2791 }
2792 break;
2793 }
2794
2795 case ParseNodeKind::PrivateMemberExpr: {
2796 // The reference is already pushed by emitDestructuringLHSRef.
2797 // [stack] OBJ NAME VAL
2798 auto& xoe = lref.emitter<PrivateOpEmitter>();
2799
2800 if (!xoe.emitAssignment()) {
2801 // [stack] VAL
2802 return false;
2803 }
2804 break;
2805 }
2806
2807 case ParseNodeKind::CallExpr:
2808 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2811); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget "
"rejects function calls as assignment " "targets in destructuring assignments"
")"); do { *((volatile int*)__null) = 2811; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2809 "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2811); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget "
"rejects function calls as assignment " "targets in destructuring assignments"
")"); do { *((volatile int*)__null) = 2811; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2810 "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2811); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget "
"rejects function calls as assignment " "targets in destructuring assignments"
")"); do { *((volatile int*)__null) = 2811; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2811 "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2811); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget "
"rejects function calls as assignment " "targets in destructuring assignments"
")"); do { *((volatile int*)__null) = 2811; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2812 break;
2813
2814 default:
2815 MOZ_CRASH("emitSetOrInitializeDestructuring: bad lhs kind")do { do { } while (false); MOZ_ReportCrash("" "emitSetOrInitializeDestructuring: bad lhs kind"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2815); AnnotateMozCrashReason("MOZ_CRASH(" "emitSetOrInitializeDestructuring: bad lhs kind"
")"); do { *((volatile int*)__null) = 2815; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
2816 }
2817
2818 // Pop the assigned value.
2819 if (!emit1(JSOp::Pop)) {
2820 // [stack] # empty
2821 return false;
2822 }
2823
2824 return true;
2825}
2826
2827JSOp BytecodeEmitter::getIterCallOp(JSOp callOp,
2828 SelfHostedIter selfHostedIter) const {
2829 if (emitterMode == BytecodeEmitter::SelfHosting) {
2830 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2830); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny"
")"); do { *((volatile int*)__null) = 2830; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2831
2832 switch (callOp) {
2833 case JSOp::Call:
2834 return JSOp::CallContent;
2835 case JSOp::CallIter:
2836 return JSOp::CallContentIter;
2837 default:
2838 MOZ_CRASH("Unknown iterator call op")do { do { } while (false); MOZ_ReportCrash("" "Unknown iterator call op"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2838); AnnotateMozCrashReason("MOZ_CRASH(" "Unknown iterator call op"
")"); do { *((volatile int*)__null) = 2838; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
2839 }
2840 }
2841
2842 return callOp;
2843}
2844
2845bool BytecodeEmitter::emitIteratorNext(
2846 const Maybe<uint32_t>& callSourceCoordOffset,
2847 IteratorKind iterKind /* = IteratorKind::Sync */,
2848 SelfHostedIter selfHostedIter /* = SelfHostedIter::Deny */) {
2849 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2852); 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 { *((volatile
int*)__null) = 2852; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
2850 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2852); 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 { *((volatile
int*)__null) = 2852; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
2851 ".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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2852); 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 { *((volatile
int*)__null) = 2852; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
2852 "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2852); 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 { *((volatile
int*)__null) = 2852; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
2853
2854 // [stack] ... NEXT ITER
2855 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2855); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() >= 2"
")"); do { *((volatile int*)__null) = 2855; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2856
2857 if (!emitCall(getIterCallOp(JSOp::Call, selfHostedIter), 0,
2858 callSourceCoordOffset)) {
2859 // [stack] ... RESULT
2860 return false;
2861 }
2862
2863 if (iterKind == IteratorKind::Async) {
2864 if (!emitAwaitInInnermostScope()) {
2865 // [stack] ... RESULT
2866 return false;
2867 }
2868 }
2869
2870 if (!emitCheckIsObj(CheckIsObjectKind::IteratorNext)) {
2871 // [stack] ... RESULT
2872 return false;
2873 }
2874 return true;
2875}
2876
2877bool BytecodeEmitter::emitIteratorCloseInScope(
2878 EmitterScope& currentScope,
2879 IteratorKind iterKind /* = IteratorKind::Sync */,
2880 CompletionKind completionKind /* = CompletionKind::Normal */,
2881 SelfHostedIter selfHostedIter /* = SelfHostedIter::Deny */) {
2882 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2885); 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 { *((volatile
int*)__null) = 2885; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
2883 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2885); 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 { *((volatile
int*)__null) = 2885; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
2884 ".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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2885); 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 { *((volatile
int*)__null) = 2885; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
2885 "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2885); 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 { *((volatile
int*)__null) = 2885; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
2886
2887 if (iterKind == IteratorKind::Sync) {
2888 return emit2(JSOp::CloseIter, uint8_t(completionKind));
2889 }
2890
2891 // Generate inline logic corresponding to IteratorClose (ES2021 7.4.6) and
2892 // AsyncIteratorClose (ES2021 7.4.7). Steps numbers apply to both operations.
2893 //
2894 // Callers need to ensure that the iterator object is at the top of the
2895 // stack.
2896
2897 // For non-Throw completions, we emit the equivalent of:
2898 //
2899 // var returnMethod = GetMethod(iterator, "return");
2900 // if (returnMethod !== undefined) {
2901 // var innerResult = [Await] Call(returnMethod, iterator);
2902 // CheckIsObj(innerResult);
2903 // }
2904 //
2905 // Whereas for Throw completions, we emit:
2906 //
2907 // try {
2908 // var returnMethod = GetMethod(iterator, "return");
2909 // if (returnMethod !== undefined) {
2910 // [Await] Call(returnMethod, iterator);
2911 // }
2912 // } catch {}
2913
2914 Maybe<TryEmitter> tryCatch;
2915
2916 if (completionKind == CompletionKind::Throw) {
2917 tryCatch.emplace(this, TryEmitter::Kind::TryCatch,
2918 TryEmitter::ControlKind::NonSyntactic);
2919
2920 if (!tryCatch->emitTry()) {
2921 // [stack] ... ITER
2922 return false;
2923 }
2924 }
2925
2926 if (!emit1(JSOp::Dup)) {
2927 // [stack] ... ITER ITER
2928 return false;
2929 }
2930
2931 // Steps 1-2 are assertions, step 3 is implicit.
2932
2933 // Step 4.
2934 //
2935 // Get the "return" method.
2936 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::return_())) {
2937 // [stack] ... ITER RET
2938 return false;
2939 }
2940
2941 // Step 5.
2942 //
2943 // Do nothing if "return" is undefined or null.
2944 InternalIfEmitter ifReturnMethodIsDefined(this);
2945 if (!emit1(JSOp::IsNullOrUndefined)) {
2946 // [stack] ... ITER RET NULL-OR-UNDEF
2947 return false;
2948 }
2949
2950 if (!ifReturnMethodIsDefined.emitThenElse(
2951 IfEmitter::ConditionKind::Negative)) {
2952 // [stack] ... ITER RET
2953 return false;
2954 }
2955
2956 // Steps 5.c, 7.
2957 //
2958 // Call the "return" method.
2959 if (!emit1(JSOp::Swap)) {
2960 // [stack] ... RET ITER
2961 return false;
2962 }
2963
2964 if (!emitCall(getIterCallOp(JSOp::Call, selfHostedIter), 0)) {
2965 // [stack] ... RESULT
2966 return false;
2967 }
2968
2969 // 7.4.7 AsyncIteratorClose, step 5.d.
2970 if (iterKind == IteratorKind::Async) {
2971 if (completionKind != CompletionKind::Throw) {
2972 // Await clobbers rval, so save the current rval.
2973 if (!emit1(JSOp::GetRval)) {
2974 // [stack] ... RESULT RVAL
2975 return false;
2976 }
2977 if (!emit1(JSOp::Swap)) {
2978 // [stack] ... RVAL RESULT
2979 return false;
2980 }
2981 }
2982
2983 if (!emitAwaitInScope(currentScope)) {
2984 // [stack] ... RVAL? RESULT
2985 return false;
2986 }
2987
2988 if (completionKind != CompletionKind::Throw) {
2989 if (!emit1(JSOp::Swap)) {
2990 // [stack] ... RESULT RVAL
2991 return false;
2992 }
2993 if (!emit1(JSOp::SetRval)) {
2994 // [stack] ... RESULT
2995 return false;
2996 }
2997 }
2998 }
2999
3000 // Step 6 (Handled in caller).
3001
3002 // Step 8.
3003 if (completionKind != CompletionKind::Throw) {
3004 // Check that the "return" result is an object.
3005 if (!emitCheckIsObj(CheckIsObjectKind::IteratorReturn)) {
3006 // [stack] ... RESULT
3007 return false;
3008 }
3009 }
3010
3011 if (!ifReturnMethodIsDefined.emitElse()) {
3012 // [stack] ... ITER RET
3013 return false;
3014 }
3015
3016 if (!emit1(JSOp::Pop)) {
3017 // [stack] ... ITER
3018 return false;
3019 }
3020
3021 if (!ifReturnMethodIsDefined.emitEnd()) {
3022 return false;
3023 }
3024
3025 if (completionKind == CompletionKind::Throw) {
3026 if (!tryCatch->emitCatch()) {
3027 // [stack] ... ITER EXC
3028 return false;
3029 }
3030
3031 // Just ignore the exception thrown by call and await.
3032 if (!emit1(JSOp::Pop)) {
3033 // [stack] ... ITER
3034 return false;
3035 }
3036
3037 if (!tryCatch->emitEnd()) {
3038 // [stack] ... ITER
3039 return false;
3040 }
3041 }
3042
3043 // Step 9 (Handled in caller).
3044
3045 return emit1(JSOp::Pop);
3046 // [stack] ...
3047}
3048
3049template <typename InnerEmitter>
3050bool BytecodeEmitter::wrapWithDestructuringTryNote(int32_t iterDepth,
3051 InnerEmitter emitter) {
3052 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3052); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() >= iterDepth"
")"); do { *((volatile int*)__null) = 3052; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3053
3054 // Pad a nop at the beginning of the bytecode covered by the trynote so
3055 // that when unwinding environments, we may unwind to the scope
3056 // corresponding to the pc *before* the start, in case the first bytecode
3057 // emitted by |emitter| is the start of an inner scope. See comment above
3058 // UnwindEnvironmentToTryPc.
3059 if (!emit1(JSOp::TryDestructuring)) {
3060 return false;
3061 }
3062
3063 BytecodeOffset start = bytecodeSection().offset();
3064 if (!emitter(this)) {
3065 return false;
3066 }
3067 BytecodeOffset end = bytecodeSection().offset();
3068 if (start != end) {
3069 return addTryNote(TryNoteKind::Destructuring, iterDepth, start, end);
3070 }
3071 return true;
3072}
3073
3074bool BytecodeEmitter::emitDefault(ParseNode* defaultExpr, ParseNode* pattern) {
3075 // [stack] VALUE
3076
3077 DefaultEmitter de(this);
3078 if (!de.prepareForDefault()) {
3079 // [stack]
3080 return false;
3081 }
3082 if (!emitInitializer(defaultExpr, pattern)) {
3083 // [stack] DEFAULTVALUE
3084 return false;
3085 }
3086 if (!de.emitEnd()) {
3087 // [stack] VALUE/DEFAULTVALUE
3088 return false;
3089 }
3090 return true;
3091}
3092
3093bool BytecodeEmitter::emitAnonymousFunctionWithName(
3094 ParseNode* node, TaggedParserAtomIndex name) {
3095 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()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3095); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isDirectRHSAnonFunction()"
")"); do { *((volatile int*)__null) = 3095; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3096
3097 if (node->is<FunctionNode>()) {
3098 // Function doesn't have 'name' property at this point.
3099 // Set function's name at compile time.
3100 setFunName(node->as<FunctionNode>().funbox(), name);
3101
3102 return emitTree(node);
3103 }
3104
3105 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>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3105); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->is<ClassNode>()"
")"); do { *((volatile int*)__null) = 3105; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3106
3107 return emitClass(&node->as<ClassNode>(), ClassNameKind::InferredName, name);
3108}
3109
3110bool BytecodeEmitter::emitAnonymousFunctionWithComputedName(
3111 ParseNode* node, FunctionPrefixKind prefixKind) {
3112 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()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3112); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isDirectRHSAnonFunction()"
")"); do { *((volatile int*)__null) = 3112; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3113
3114 if (node->is<FunctionNode>()) {
3115 if (!emitTree(node)) {
3116 // [stack] NAME FUN
3117 return false;
3118 }
3119 if (!emitDupAt(1)) {
3120 // [stack] NAME FUN NAME
3121 return false;
3122 }
3123 if (!emit2(JSOp::SetFunName, uint8_t(prefixKind))) {
3124 // [stack] NAME FUN
3125 return false;
3126 }
3127 return true;
3128 }
3129
3130 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>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3130); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->is<ClassNode>()"
")"); do { *((volatile int*)__null) = 3130; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3131 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3131); AnnotateMozCrashReason("MOZ_ASSERT" "(" "prefixKind == FunctionPrefixKind::None"
")"); do { *((volatile int*)__null) = 3131; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3132
3133 return emitClass(&node->as<ClassNode>(), ClassNameKind::ComputedName);
3134}
3135
3136void BytecodeEmitter::setFunName(FunctionBox* funbox,
3137 TaggedParserAtomIndex name) const {
3138 // The inferred name may already be set if this function is an interpreted
3139 // lazy function and we OOM'ed after we set the inferred name the first
3140 // time.
3141 if (funbox->hasInferredName()) {
3142 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3142); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!funbox->emitBytecode"
")"); do { *((volatile int*)__null) = 3142; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3143 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3143); AnnotateMozCrashReason("MOZ_ASSERT" "(" "funbox->displayAtom() == name"
")"); do { *((volatile int*)__null) = 3143; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3144 } else {
3145 funbox->setInferredName(name);
3146 }
3147}
3148
3149bool BytecodeEmitter::emitInitializer(ParseNode* initializer,
3150 ParseNode* pattern) {
3151 if (initializer->isDirectRHSAnonFunction()) {
3152 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3152); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!pattern->isInParens()"
")"); do { *((volatile int*)__null) = 3152; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3153 auto name = pattern->as<NameNode>().name();
3154 if (!emitAnonymousFunctionWithName(initializer, name)) {
3155 return false;
3156 }
3157 } else {
3158 if (!emitTree(initializer)) {
3159 return false;
3160 }
3161 }
3162
3163 return true;
3164}
3165
3166bool BytecodeEmitter::emitDestructuringOpsArray(ListNode* pattern,
3167 DestructuringFlavor flav) {
3168 MOZ_ASSERT(getSelfHostedIterFor(pattern) == SelfHostedIter::Deny,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(getSelfHostedIterFor(pattern) == SelfHostedIter::Deny
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(getSelfHostedIterFor(pattern) == SelfHostedIter::Deny
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"getSelfHostedIterFor(pattern) == SelfHostedIter::Deny" " (" "array destructuring is prohibited in self-hosted code because it"
"can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3170); AnnotateMozCrashReason("MOZ_ASSERT" "(" "getSelfHostedIterFor(pattern) == SelfHostedIter::Deny"
") (" "array destructuring is prohibited in self-hosted code because it"
"can run user-modifiable iteration code" ")"); do { *((volatile
int*)__null) = 3170; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
3169 "array destructuring is prohibited in self-hosted code because it"do { static_assert( mozilla::detail::AssertionConditionType<
decltype(getSelfHostedIterFor(pattern) == SelfHostedIter::Deny
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(getSelfHostedIterFor(pattern) == SelfHostedIter::Deny
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"getSelfHostedIterFor(pattern) == SelfHostedIter::Deny" " (" "array destructuring is prohibited in self-hosted code because it"
"can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3170); AnnotateMozCrashReason("MOZ_ASSERT" "(" "getSelfHostedIterFor(pattern) == SelfHostedIter::Deny"
") (" "array destructuring is prohibited in self-hosted code because it"
"can run user-modifiable iteration code" ")"); do { *((volatile
int*)__null) = 3170; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
3170 "can run user-modifiable iteration code")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(getSelfHostedIterFor(pattern) == SelfHostedIter::Deny
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(getSelfHostedIterFor(pattern) == SelfHostedIter::Deny
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"getSelfHostedIterFor(pattern) == SelfHostedIter::Deny" " (" "array destructuring is prohibited in self-hosted code because it"
"can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3170); AnnotateMozCrashReason("MOZ_ASSERT" "(" "getSelfHostedIterFor(pattern) == SelfHostedIter::Deny"
") (" "array destructuring is prohibited in self-hosted code because it"
"can run user-modifiable iteration code" ")"); do { *((volatile
int*)__null) = 3170; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
3171 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3171); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pattern->isKind(ParseNodeKind::ArrayExpr)"
")"); do { *((volatile int*)__null) = 3171; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3172 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3172); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() != 0"
")"); do { *((volatile int*)__null) = 3172; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3173
3174 // Here's pseudo code for |let [a, b, , c=y, ...d] = x;|
3175 //
3176 // Lines that are annotated "covered by trynote" mean that upon throwing
3177 // an exception, IteratorClose is called on iter only if done is false.
3178 //
3179 // let x, y;
3180 // let a, b, c, d;
3181 // let iter, next, lref, result, done, value; // stack values
3182 //
3183 // // NOTE: the fast path for this example is not applicable, because of
3184 // // the spread and the assignment |c=y|, but it is documented here for a
3185 // // simpler example, |let [a,b] = x;|
3186 // //
3187 // // if (IsOptimizableArray(x)) {
3188 // // a = x[0];
3189 // // b = x[1];
3190 // // goto end: // (skip everything below)
3191 // // }
3192 //
3193 // iter = x[Symbol.iterator]();
3194 // next = iter.next;
3195 //
3196 // // ==== emitted by loop for a ====
3197 // lref = GetReference(a); // covered by trynote
3198 //
3199 // result = Call(next, iter);
3200 // done = result.done;
3201 //
3202 // if (done)
3203 // value = undefined;
3204 // else
3205 // value = result.value;
3206 //
3207 // SetOrInitialize(lref, value); // covered by trynote
3208 //
3209 // // ==== emitted by loop for b ====
3210 // lref = GetReference(b); // covered by trynote
3211 //
3212 // if (done) {
3213 // value = undefined;
3214 // } else {
3215 // result = Call(next, iter);
3216 // done = result.done;
3217 // if (done)
3218 // value = undefined;
3219 // else
3220 // value = result.value;
3221 // }
3222 //
3223 // SetOrInitialize(lref, value); // covered by trynote
3224 //
3225 // // ==== emitted by loop for elision ====
3226 // if (done) {
3227 // value = undefined;
3228 // } else {
3229 // result = Call(next, iter);
3230 // done = result.done;
3231 // if (done)
3232 // value = undefined;
3233 // else
3234 // value = result.value;
3235 // }
3236 //
3237 // // ==== emitted by loop for c ====
3238 // lref = GetReference(c); // covered by trynote
3239 //
3240 // if (done) {
3241 // value = undefined;
3242 // } else {
3243 // result = Call(next, iter);
3244 // done = result.done;
3245 // if (done)
3246 // value = undefined;
3247 // else
3248 // value = result.value;
3249 // }
3250 //
3251 // if (value === undefined)
3252 // value = y; // covered by trynote
3253 //
3254 // SetOrInitialize(lref, value); // covered by trynote
3255 //
3256 // // ==== emitted by loop for d ====
3257 // lref = GetReference(d); // covered by trynote
3258 //
3259 // if (done)
3260 // value = [];
3261 // else
3262 // value = [...iter];
3263 //
3264 // SetOrInitialize(lref, value); // covered by trynote
3265 //
3266 // // === emitted after loop ===
3267 // if (!done)
3268 // IteratorClose(iter);
3269 //
3270 // end:
3271
3272 bool isEligibleForArrayOptimizations = true;
3273 for (ParseNode* member : pattern->contents()) {
3274 switch (member->getKind()) {
3275 case ParseNodeKind::Elision:
3276 break;
3277 case ParseNodeKind::Name: {
3278 auto name = member->as<NameNode>().name();
3279 NameLocation loc = lookupName(name);
3280 if (loc.kind() != NameLocation::Kind::ArgumentSlot &&
3281 loc.kind() != NameLocation::Kind::FrameSlot &&
3282 loc.kind() != NameLocation::Kind::EnvironmentCoordinate) {
3283 isEligibleForArrayOptimizations = false;
3284 }
3285 break;
3286 }
3287 default:
3288 // Unfortunately we can't handle any recursive destructuring,
3289 // because we can't guarantee that the recursed-into parts
3290 // won't run code which invalidates our constraints. We also
3291 // cannot handle ParseNodeKind::AssignExpr for similar reasons.
3292 isEligibleForArrayOptimizations = false;
3293 break;
3294 }
3295 if (!isEligibleForArrayOptimizations) {
3296 break;
3297 }
3298 }
3299
3300 // Use an iterator to destructure the RHS, instead of index lookup. We
3301 // must leave the *original* value on the stack.
3302 if (!emit1(JSOp::Dup)) {
3303 // [stack] ... OBJ OBJ
3304 return false;
3305 }
3306
3307 Maybe<InternalIfEmitter> ifArrayOptimizable;
3308
3309 if (isEligibleForArrayOptimizations) {
3310 ifArrayOptimizable.emplace(
3311 this, BranchEmitterBase::LexicalKind::MayContainLexicalAccessInBranch);
3312
3313 if (!emit1(JSOp::Dup)) {
3314 // [stack] OBJ OBJ
3315 return false;
3316 }
3317
3318 if (!emit1(JSOp::OptimizeGetIterator)) {
3319 // [stack] OBJ OBJ IS_OPTIMIZABLE
3320 return false;
3321 }
3322
3323 if (!ifArrayOptimizable->emitThenElse()) {
3324 // [stack] OBJ OBJ
3325 return false;
3326 }
3327
3328 if (!emitAtomOp(JSOp::GetProp,
3329 TaggedParserAtomIndex::WellKnown::length())) {
3330 // [stack] OBJ LENGTH
3331 return false;
3332 }
3333
3334 if (!emit1(JSOp::Swap)) {
3335 // [stack] LENGTH OBJ
3336 return false;
3337 }
3338
3339 uint32_t idx = 0;
3340 for (ParseNode* member : pattern->contents()) {
3341 if (member->isKind(ParseNodeKind::Elision)) {
3342 idx += 1;
3343 continue;
3344 }
3345 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3345); AnnotateMozCrashReason("MOZ_ASSERT" "(" "member->isKind(ParseNodeKind::Name)"
")"); do { *((volatile int*)__null) = 3345; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3346
3347 if (!emit1(JSOp::Dup)) {
3348 // [stack] LENGTH OBJ OBJ
3349 return false;
3350 }
3351
3352 if (!emitNumberOp(idx)) {
3353 // [stack] LENGTH OBJ OBJ IDX
3354 return false;
3355 }
3356
3357 if (!emit1(JSOp::Dup)) {
3358 // [stack] LENGTH OBJ OBJ IDX IDX
3359 return false;
3360 }
3361
3362 if (!emitDupAt(4)) {
3363 // [stack] LENGTH OBJ OBJ IDX IDX LENGTH
3364 return false;
3365 }
3366
3367 if (!emit1(JSOp::Lt)) {
3368 // [stack] LENGTH OBJ OBJ IDX IS_IN_DENSE_BOUNDS
3369 return false;
3370 }
3371
3372 InternalIfEmitter isInDenseBounds(this);
3373 if (!isInDenseBounds.emitThenElse()) {
3374 // [stack] LENGTH OBJ OBJ IDX
3375 return false;
3376 }
3377
3378 if (!emit1(JSOp::GetElem)) {
3379 // [stack] LENGTH OBJ VALUE
3380 return false;
3381 }
3382
3383 if (!isInDenseBounds.emitElse()) {
3384 // [stack] LENGTH OBJ OBJ IDX
3385 return false;
3386 }
3387
3388 if (!emitPopN(2)) {
3389 // [stack] LENGTH OBJ
3390 return false;
3391 }
3392
3393 if (!emit1(JSOp::Undefined)) {
3394 // [stack] LENGTH OBJ UNDEFINED
3395 return false;
3396 }
3397
3398 if (!isInDenseBounds.emitEnd()) {
3399 // [stack] LENGTH OBJ VALUE|UNDEFINED
3400 return false;
3401 }
3402
3403 DestructuringLHSRef lref;
3404 if (!emitDestructuringLHSRef(member, flav, lref)) {
3405 // [stack] LENGTH OBJ
3406 return false;
3407 }
3408
3409 if (!emitSetOrInitializeDestructuring(member, flav, lref)) {
3410 // [stack] LENGTH OBJ
3411 return false;
3412 }
3413
3414 idx += 1;
3415 }
3416
3417 if (!emit1(JSOp::Swap)) {
3418 // [stack] OBJ LENGTH
3419 return false;
3420 }
3421
3422 if (!emit1(JSOp::Pop)) {
3423 // [stack] OBJ
3424 return false;
3425 }
3426
3427 if (!ifArrayOptimizable->emitElse()) {
3428 // [stack] OBJ OBJ
3429 return false;
3430 }
3431 }
3432
3433 if (!emitIterator(SelfHostedIter::Deny)) {
3434 // [stack] ... OBJ NEXT ITER
3435 return false;
3436 }
3437
3438 // For an empty pattern [], call IteratorClose unconditionally. Nothing
3439 // else needs to be done.
3440 if (!pattern->head()) {
3441 if (!emit1(JSOp::Swap)) {
3442 // [stack] ... OBJ ITER NEXT
3443 return false;
3444 }
3445 if (!emit1(JSOp::Pop)) {
3446 // [stack] ... OBJ ITER
3447 return false;
3448 }
3449
3450 if (!emitIteratorCloseInInnermostScope()) {
3451 // [stack] ... OBJ
3452 return false;
3453 }
3454
3455 if (ifArrayOptimizable.isSome()) {
3456 if (!ifArrayOptimizable->emitEnd()) {
3457 // [stack] OBJ
3458 return false;
3459 }
3460 }
3461
3462 return true;
3463 }
3464
3465 // Push an initial FALSE value for DONE.
3466 if (!emit1(JSOp::False)) {
3467 // [stack] ... OBJ NEXT ITER FALSE
3468 return false;
3469 }
3470
3471 // TryNoteKind::Destructuring expects the iterator and the done value
3472 // to be the second to top and the top of the stack, respectively.
3473 // IteratorClose is called upon exception only if done is false.
3474 int32_t tryNoteDepth = bytecodeSection().stackDepth();
3475
3476 for (ParseNode* member : pattern->contents()) {
3477 bool isFirst = member == pattern->head();
3478 DebugOnly<bool> hasNext = !!member->pn_next;
3479
3480 ParseNode* subpattern;
3481 if (member->isKind(ParseNodeKind::Spread)) {
3482 subpattern = member->as<UnaryNode>().kid();
3483
3484 MOZ_ASSERT(!subpattern->isKind(ParseNodeKind::AssignExpr))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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3484); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!subpattern->isKind(ParseNodeKind::AssignExpr)"
")"); do { *((volatile int*)__null) = 3484; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3485 } else {
3486 subpattern = member;
3487 }
3488
3489 ParseNode* lhsPattern = subpattern;
3490 ParseNode* pndefault = nullptr;
3491 if (subpattern->isKind(ParseNodeKind::AssignExpr)) {
3492 lhsPattern = subpattern->as<AssignmentNode>().left();
3493 pndefault = subpattern->as<AssignmentNode>().right();
3494 }
3495
3496 // Spec requires LHS reference to be evaluated first.
3497 DestructuringLHSRef lref;
3498 bool isElision = lhsPattern->isKind(ParseNodeKind::Elision);
3499 if (!isElision) {
3500 auto emitLHSRef = [lhsPattern, flav, &lref](BytecodeEmitter* bce) {
3501 return bce->emitDestructuringLHSRef(lhsPattern, flav, lref);
3502 // [stack] ... OBJ NEXT ITER DONE LREF*
3503 };
3504 if (!wrapWithDestructuringTryNote(tryNoteDepth, emitLHSRef)) {
3505 return false;
3506 }
3507 }
3508
3509 // Number of stack slots emitted for the LHS reference.
3510 size_t emitted = lref.numReferenceSlots();
3511
3512 // Pick the DONE value to the top of the stack.
3513 if (emitted) {
3514 if (!emitPickN(emitted)) {
3515 // [stack] ... OBJ NEXT ITER LREF* DONE
3516 return false;
3517 }
3518 }
3519
3520 if (isFirst) {
3521 // If this element is the first, DONE is always FALSE, so pop it.
3522 //
3523 // Non-first elements should emit if-else depending on the
3524 // member pattern, below.
3525 if (!emit1(JSOp::Pop)) {
3526 // [stack] ... OBJ NEXT ITER LREF*
3527 return false;
3528 }
3529 }
3530
3531 if (member->isKind(ParseNodeKind::Spread)) {
3532 InternalIfEmitter ifThenElse(this);
3533 if (!isFirst) {
3534 // If spread is not the first element of the pattern,
3535 // iterator can already be completed.
3536 // [stack] ... OBJ NEXT ITER LREF* DONE
3537
3538 if (!ifThenElse.emitThenElse()) {
3539 // [stack] ... OBJ NEXT ITER LREF*
3540 return false;
3541 }
3542
3543 if (!emitUint32Operand(JSOp::NewArray, 0)) {
3544 // [stack] ... OBJ NEXT ITER LREF* ARRAY
3545 return false;
3546 }
3547 if (!ifThenElse.emitElse()) {
3548 // [stack] ... OBJ NEXT ITER LREF*
3549 return false;
3550 }
3551 }
3552
3553 // If iterator is not completed, create a new array with the rest
3554 // of the iterator.
3555 if (!emitDupAt(emitted + 1, 2)) {
3556 // [stack] ... OBJ NEXT ITER LREF* NEXT ITER
3557 return false;
3558 }
3559 if (!emitUint32Operand(JSOp::NewArray, 0)) {
3560 // [stack] ... OBJ NEXT ITER LREF* NEXT ITER ARRAY
3561 return false;
3562 }
3563 if (!emitNumberOp(0)) {
3564 // [stack] ... OBJ NEXT ITER LREF* NEXT ITER ARRAY INDEX
3565 return false;
3566 }
3567 if (!emitSpread(SelfHostedIter::Deny)) {
3568 // [stack] ... OBJ NEXT ITER LREF* ARRAY INDEX
3569 return false;
3570 }
3571 if (!emit1(JSOp::Pop)) {
3572 // [stack] ... OBJ NEXT ITER LREF* ARRAY
3573 return false;
3574 }
3575
3576 if (!isFirst) {
3577 if (!ifThenElse.emitEnd()) {
3578 return false;
3579 }
3580 MOZ_ASSERT(ifThenElse.pushed() == 1)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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3580); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ifThenElse.pushed() == 1"
")"); do { *((volatile int*)__null) = 3580; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3581 }
3582
3583 // At this point the iterator is done. Unpick a TRUE value for DONE above
3584 // ITER.
3585 if (!emit1(JSOp::True)) {
3586 // [stack] ... OBJ NEXT ITER LREF* ARRAY TRUE
3587 return false;
3588 }
3589 if (!emitUnpickN(emitted + 1)) {
3590 // [stack] ... OBJ NEXT ITER TRUE LREF* ARRAY
3591 return false;
3592 }
3593
3594 auto emitAssignment = [lhsPattern, flav, &lref](BytecodeEmitter* bce) {
3595 return bce->emitSetOrInitializeDestructuring(lhsPattern, flav, lref);
3596 // [stack] ... OBJ NEXT ITER TRUE
3597 };
3598 if (!wrapWithDestructuringTryNote(tryNoteDepth, emitAssignment)) {
3599 return false;
3600 }
3601
3602 MOZ_ASSERT(!hasNext)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!hasNext)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!hasNext))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!hasNext", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3602); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!hasNext" ")"
); do { *((volatile int*)__null) = 3602; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3603 break;
3604 }
3605
3606 InternalIfEmitter ifAlreadyDone(this);
3607 if (!isFirst) {
3608 // [stack] ... OBJ NEXT ITER LREF* DONE
3609
3610 if (!ifAlreadyDone.emitThenElse()) {
3611 // [stack] ... OBJ NEXT ITER LREF*
3612 return false;
3613 }
3614
3615 if (!emit1(JSOp::Undefined)) {
3616 // [stack] ... OBJ NEXT ITER LREF* UNDEF
3617 return false;
3618 }
3619 if (!emit1(JSOp::NopDestructuring)) {
3620 // [stack] ... OBJ NEXT ITER LREF* UNDEF
3621 return false;
3622 }
3623
3624 // The iterator is done. Unpick a TRUE value for DONE above ITER.
3625 if (!emit1(JSOp::True)) {
3626 // [stack] ... OBJ NEXT ITER LREF* UNDEF TRUE
3627 return false;
3628 }
3629 if (!emitUnpickN(emitted + 1)) {
3630 // [stack] ... OBJ NEXT ITER TRUE LREF* UNDEF
3631 return false;
3632 }
3633
3634 if (!ifAlreadyDone.emitElse()) {
3635 // [stack] ... OBJ NEXT ITER LREF*
3636 return false;
3637 }
3638 }
3639
3640 if (!emitDupAt(emitted + 1, 2)) {
3641 // [stack] ... OBJ NEXT ITER LREF* NEXT
3642 return false;
3643 }
3644 if (!emitIteratorNext(Some(pattern->pn_pos.begin))) {
3645 // [stack] ... OBJ NEXT ITER LREF* RESULT
3646 return false;
3647 }
3648 if (!emit1(JSOp::Dup)) {
3649 // [stack] ... OBJ NEXT ITER LREF* RESULT RESULT
3650 return false;
3651 }
3652 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::done())) {
3653 // [stack] ... OBJ NEXT ITER LREF* RESULT DONE
3654 return false;
3655 }
3656
3657 if (!emit1(JSOp::Dup)) {
3658 // [stack] ... OBJ NEXT ITER LREF* RESULT DONE DONE
3659 return false;
3660 }
3661 if (!emitUnpickN(emitted + 2)) {
3662 // [stack] ... OBJ NEXT ITER DONE LREF* RESULT DONE
3663 return false;
3664 }
3665
3666 InternalIfEmitter ifDone(this);
3667 if (!ifDone.emitThenElse()) {
3668 // [stack] ... OBJ NEXT ITER DONE LREF* RESULT
3669 return false;
3670 }
3671
3672 if (!emit1(JSOp::Pop)) {
3673 // [stack] ... OBJ NEXT ITER DONE LREF*
3674 return false;
3675 }
3676 if (!emit1(JSOp::Undefined)) {
3677 // [stack] ... OBJ NEXT ITER DONE LREF* UNDEF
3678 return false;
3679 }
3680 if (!emit1(JSOp::NopDestructuring)) {
3681 // [stack] ... OBJ NEXT ITER DONE LREF* UNDEF
3682 return false;
3683 }
3684
3685 if (!ifDone.emitElse()) {
3686 // [stack] ... OBJ NEXT ITER DONE LREF* RESULT
3687 return false;
3688 }
3689
3690 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::value())) {
3691 // [stack] ... OBJ NEXT ITER DONE LREF* VALUE
3692 return false;
3693 }
3694
3695 if (!ifDone.emitEnd()) {
3696 return false;
3697 }
3698 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3698); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ifDone.pushed() == 0"
")"); do { *((volatile int*)__null) = 3698; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3699
3700 if (!isFirst) {
3701 if (!ifAlreadyDone.emitEnd()) {
3702 return false;
3703 }
3704 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3704); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ifAlreadyDone.pushed() == 2"
")"); do { *((volatile int*)__null) = 3704; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3705 }
3706
3707 if (pndefault) {
3708 auto emitDefault = [pndefault, lhsPattern](BytecodeEmitter* bce) {
3709 return bce->emitDefault(pndefault, lhsPattern);
3710 // [stack] ... OBJ NEXT ITER DONE LREF* VALUE
3711 };
3712
3713 if (!wrapWithDestructuringTryNote(tryNoteDepth, emitDefault)) {
3714 return false;
3715 }
3716 }
3717
3718 if (!isElision) {
3719 auto emitAssignment = [lhsPattern, flav, &lref](BytecodeEmitter* bce) {
3720 return bce->emitSetOrInitializeDestructuring(lhsPattern, flav, lref);
3721 // [stack] ... OBJ NEXT ITER DONE
3722 };
3723
3724 if (!wrapWithDestructuringTryNote(tryNoteDepth, emitAssignment)) {
3725 return false;
3726 }
3727 } else {
3728 if (!emit1(JSOp::Pop)) {
3729 // [stack] ... OBJ NEXT ITER DONE
3730 return false;
3731 }
3732 }
3733 }
3734
3735 // The last DONE value is on top of the stack. If not DONE, call
3736 // IteratorClose.
3737 // [stack] ... OBJ NEXT ITER DONE
3738
3739 InternalIfEmitter ifDone(this);
3740 if (!ifDone.emitThenElse()) {
3741 // [stack] ... OBJ NEXT ITER
3742 return false;
3743 }
3744 if (!emitPopN(2)) {
3745 // [stack] ... OBJ
3746 return false;
3747 }
3748 if (!ifDone.emitElse()) {
3749 // [stack] ... OBJ NEXT ITER
3750 return false;
3751 }
3752 if (!emit1(JSOp::Swap)) {
3753 // [stack] ... OBJ ITER NEXT
3754 return false;
3755 }
3756 if (!emit1(JSOp::Pop)) {
3757 // [stack] ... OBJ ITER
3758 return false;
3759 }
3760 if (!emitIteratorCloseInInnermostScope()) {
3761 // [stack] ... OBJ
3762 return false;
3763 }
3764 if (!ifDone.emitEnd()) {
3765 return false;
3766 }
3767
3768 if (ifArrayOptimizable.isSome()) {
3769 if (!ifArrayOptimizable->emitEnd()) {
3770 // [stack] OBJ
3771 return false;
3772 }
3773 }
3774
3775 return true;
3776}
3777
3778bool BytecodeEmitter::emitComputedPropertyName(UnaryNode* computedPropName) {
3779 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)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3779); AnnotateMozCrashReason("MOZ_ASSERT" "(" "computedPropName->isKind(ParseNodeKind::ComputedName)"
")"); do { *((volatile int*)__null) = 3779; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3780 return emitTree(computedPropName->kid()) && emit1(JSOp::ToPropertyKey);
3781}
3782
3783bool BytecodeEmitter::emitDestructuringOpsObject(ListNode* pattern,
3784 DestructuringFlavor flav) {
3785 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3785); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pattern->isKind(ParseNodeKind::ObjectExpr)"
")"); do { *((volatile int*)__null) = 3785; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3786
3787 // [stack] ... RHS
3788 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3788); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() > 0"
")"); do { *((volatile int*)__null) = 3788; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3789
3790 if (!emit1(JSOp::CheckObjCoercible)) {
3791 // [stack] ... RHS
3792 return false;
3793 }
3794
3795 bool needsRestPropertyExcludedSet =
3796 pattern->count() > 1 && pattern->last()->isKind(ParseNodeKind::Spread);
3797 if (needsRestPropertyExcludedSet) {
3798 if (!emitDestructuringObjRestExclusionSet(pattern)) {
3799 // [stack] ... RHS SET
3800 return false;
3801 }
3802
3803 if (!emit1(JSOp::Swap)) {
3804 // [stack] ... SET RHS
3805 return false;
3806 }
3807 }
3808
3809 for (ParseNode* member : pattern->contents()) {
3810 ParseNode* subpattern;
3811 bool hasKeyOnStack = false;
3812 if (member->isKind(ParseNodeKind::MutateProto) ||
3813 member->isKind(ParseNodeKind::Spread)) {
3814 subpattern = member->as<UnaryNode>().kid();
3815
3816 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)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3817); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!subpattern->isKind(ParseNodeKind::AssignExpr)"
")"); do { *((volatile int*)__null) = 3817; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3817 !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)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3817); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!subpattern->isKind(ParseNodeKind::AssignExpr)"
")"); do { *((volatile int*)__null) = 3817; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
3818 } else {
3819 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3820); AnnotateMozCrashReason("MOZ_ASSERT" "(" "member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)"
")"); do { *((volatile int*)__null) = 3820; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3820 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3820); AnnotateMozCrashReason("MOZ_ASSERT" "(" "member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)"
")"); do { *((volatile int*)__null) = 3820; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3821 subpattern = member->as<BinaryNode>().right();
3822
3823 // Computed property names are evaluated before the subpattern.
3824 ParseNode* key = member->as<BinaryNode>().left();
3825 if (key->isKind(ParseNodeKind::ComputedName)) {
3826 if (!emitComputedPropertyName(&key->as<UnaryNode>())) {
3827 // [stack] ... SET? RHS KEY
3828 return false;
3829 }
3830 hasKeyOnStack = true;
3831 }
3832 }
3833
3834 ParseNode* lhs = subpattern;
3835 ParseNode* pndefault = nullptr;
3836 if (subpattern->isKind(ParseNodeKind::AssignExpr)) {
3837 lhs = subpattern->as<AssignmentNode>().left();
3838 pndefault = subpattern->as<AssignmentNode>().right();
3839 }
3840
3841 // Spec requires LHS reference to be evaluated first.
3842 DestructuringLHSRef lref;
3843 if (!emitDestructuringLHSRef(lhs, flav, lref)) {
3844 // [stack] ... SET? RHS KEY? LREF*
3845 return false;
3846 }
3847
3848 // Number of stack slots emitted for the LHS reference.
3849 size_t emitted = lref.numReferenceSlots();
3850
3851 // Duplicate the value being destructured to use as a reference base.
3852 if (!emitDupAt(emitted + hasKeyOnStack)) {
3853 // [stack] ... SET? RHS KEY? LREF* RHS
3854 return false;
3855 }
3856
3857 if (member->isKind(ParseNodeKind::Spread)) {
3858 if (!updateSourceCoordNotes(member->pn_pos.begin)) {
3859 return false;
3860 }
3861
3862 if (!emit1(JSOp::NewInit)) {
3863 // [stack] ... SET? RHS LREF* RHS TARGET
3864 return false;
3865 }
3866 if (!emit1(JSOp::Dup)) {
3867 // [stack] ... SET? RHS LREF* RHS TARGET TARGET
3868 return false;
3869 }
3870 if (!emit2(JSOp::Pick, 2)) {
3871 // [stack] ... SET? RHS LREF* TARGET TARGET RHS
3872 return false;
3873 }
3874
3875 if (needsRestPropertyExcludedSet) {
3876 if (!emit2(JSOp::Pick, emitted + 4)) {
3877 // [stack] ... RHS LREF* TARGET TARGET RHS SET
3878 return false;
3879 }
3880 }
3881
3882 CopyOption option = needsRestPropertyExcludedSet ? CopyOption::Filtered
3883 : CopyOption::Unfiltered;
3884 if (!emitCopyDataProperties(option)) {
3885 // [stack] ... RHS LREF* TARGET
3886 return false;
3887 }
3888
3889 // Destructure TARGET per this member's lhs.
3890 if (!emitSetOrInitializeDestructuring(lhs, flav, lref)) {
3891 // [stack] ... RHS
3892 return false;
3893 }
3894
3895 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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3895); AnnotateMozCrashReason("MOZ_ASSERT" "(" "member == pattern->last()"
") (" "Rest property is always last" ")"); do { *((volatile int
*)__null) = 3895; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
3896 break;
3897 }
3898
3899 // Now push the property value currently being matched, which is the value
3900 // of the current property name "label" on the left of a colon in the object
3901 // initialiser.
3902 if (member->isKind(ParseNodeKind::MutateProto)) {
3903 if (!emitAtomOp(JSOp::GetProp,
3904 TaggedParserAtomIndex::WellKnown::proto_())) {
3905 // [stack] ... SET? RHS LREF* PROP
3906 return false;
3907 }
3908 } else {
3909 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3910); AnnotateMozCrashReason("MOZ_ASSERT" "(" "member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)"
")"); do { *((volatile int*)__null) = 3910; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3910 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3910); AnnotateMozCrashReason("MOZ_ASSERT" "(" "member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)"
")"); do { *((volatile int*)__null) = 3910; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3911
3912 ParseNode* key = member->as<BinaryNode>().left();
3913 if (key->isKind(ParseNodeKind::ObjectPropertyName) ||
3914 key->isKind(ParseNodeKind::StringExpr)) {
3915 if (!emitAtomOp(JSOp::GetProp, key->as<NameNode>().atom())) {
3916 // [stack] ... SET? RHS LREF* PROP
3917 return false;
3918 }
3919 } else {
3920 if (key->isKind(ParseNodeKind::NumberExpr)) {
3921 if (!emitNumberOp(key->as<NumericLiteral>().value())) {
3922 // [stack]... SET? RHS LREF* RHS KEY
3923 return false;
3924 }
3925 } else {
3926 // Otherwise this is a computed property name. BigInt keys are parsed
3927 // as (synthetic) computed property names, too.
3928 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3928); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::ComputedName)"
")"); do { *((volatile int*)__null) = 3928; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3929 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",
"/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3929); AnnotateMozCrashReason("MOZ_ASSERT" "(" "hasKeyOnStack"
")"); do { *((volatile int*)__null) = 3929; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3930
3931 if (!emit2(JSOp::Pick, emitted + 1)) {
3932 // [stack] ... SET? RHS LREF* RHS KEY
3933 return false;
3934 }
3935
3936 // Add the computed property key to the exclusion set.
3937 if (needsRestPropertyExcludedSet) {
3938 if (!emitDupAt(emitted + 3)) {
3939 // [stack] ... SET RHS LREF* RHS KEY SET
3940 return false;
3941 }
3942 if (!emitDupAt(1)) {
3943 // [stack] ... SET RHS LREF* RHS KEY SET KEY
3944 return false;
3945 }
3946 if (!emit1(JSOp::Undefined)) {
3947 // [stack] ... SET RHS LREF* RHS KEY SET KEY UNDEFINED
3948 return false;
3949 }
3950 if (!emit1(JSOp::InitElem)) {
3951 // [stack] ... SET RHS LREF* RHS KEY SET
3952 return false;
3953 }
3954 if (!emit1(JSOp::Pop)) {
3955 // [stack] ... SET RHS LREF* RHS KEY
3956 return false;
3957 }
3958 }
3959 }
3960
3961 // Get the property value.
3962 if (!emitElemOpBase(JSOp::GetElem)) {
3963 // [stack] ... SET? RHS LREF* PROP
3964 return false;
3965 }
3966 }
3967 }
3968
3969 if (pndefault) {
3970 if (!emitDefault(pndefault, lhs)) {
3971 // [stack] ... SET? RHS LREF* VALUE
3972 return false;
3973 }
3974 }
3975
3976 // Destructure PROP per this member's lhs.
3977 if (!emitSetOrInitializeDestructuring(lhs, flav, lref)) {
3978 // [stack] ... SET? RHS
3979 return false;
3980 }
3981 }
3982
3983 return true;
3984}
3985
3986static bool IsDestructuringRestExclusionSetObjLiteralCompatible(
3987 ListNode* pattern) {
3988 uint32_t propCount = 0;
3989 for (ParseNode* member : pattern->contents()) {
3990 if (member->isKind(ParseNodeKind::Spread)) {
3991 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3991); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!member->pn_next"
") (" "unexpected trailing element after spread" ")"); do { *
((volatile int*)__null) = 3991; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
3992 break;
3993 }
3994
3995 propCount++;
3996
3997 if (member->isKind(ParseNodeKind::MutateProto)) {
3998 continue;
3999 }
4000
4001 ParseNode* key = member->as<BinaryNode>().left();
4002 if (key->isKind(ParseNodeKind::ObjectPropertyName) ||
4003 key->isKind(ParseNodeKind::StringExpr)) {
4004 continue;
4005 }
4006
4007 // Number and BigInt keys aren't yet supported. Computed property names need
4008 // to be added dynamically.
4009 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4011); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr) || key->isKind(ParseNodeKind::ComputedName)"
")"); do { *((volatile int*)__null) = 4011; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4010 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4011); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr) || key->isKind(ParseNodeKind::ComputedName)"
")"); do { *((volatile int*)__null) = 4011; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4011 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4011); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr) || key->isKind(ParseNodeKind::ComputedName)"
")"); do { *((volatile int*)__null) = 4011; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4012 return false;
4013 }
4014
4015 if (propCount > SharedPropMap::MaxPropsForNonDictionary) {
4016 // JSOp::NewObject cannot accept dictionary-mode objects.
4017 return false;
4018 }
4019
4020 return true;
4021}
4022
4023bool BytecodeEmitter::emitDestructuringObjRestExclusionSet(ListNode* pattern) {
4024 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4024); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pattern->isKind(ParseNodeKind::ObjectExpr)"
")"); do { *((volatile int*)__null) = 4024; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4025 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)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4025); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pattern->last()->isKind(ParseNodeKind::Spread)"
")"); do { *((volatile int*)__null) = 4025; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4026
4027 // See if we can use ObjLiteral to construct the exclusion set object.
4028 if (IsDestructuringRestExclusionSetObjLiteralCompatible(pattern)) {
4029 if (!emitDestructuringRestExclusionSetObjLiteral(pattern)) {
4030 // [stack] OBJ
4031 return false;
4032 }
4033 } else {
4034 // Take the slow but sure way and start off with a blank object.
4035 if (!emit1(JSOp::NewInit)) {
4036 // [stack] OBJ
4037 return false;
4038 }
4039 }
4040
4041 for (ParseNode* member : pattern->contents()) {
4042 if (member->isKind(ParseNodeKind::Spread)) {
4043 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4043); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!member->pn_next"
") (" "unexpected trailing element after spread" ")"); do { *
((volatile int*)__null) = 4043; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
4044 break;
4045 }
4046
4047 TaggedParserAtomIndex pnatom;
4048 if (member->isKind(ParseNodeKind::MutateProto)) {
4049 pnatom = TaggedParserAtomIndex::WellKnown::proto_();
4050 } else {
4051 ParseNode* key = member->as<BinaryNode>().left();
4052 if (key->isKind(ParseNodeKind::ObjectPropertyName) ||
4053 key->isKind(ParseNodeKind::StringExpr)) {
4054 pnatom = key->as<NameNode>().atom();
4055 } else if (key->isKind(ParseNodeKind::NumberExpr)) {
4056 if (!emitNumberOp(key->as<NumericLiteral>().value())) {
4057 return false;
4058 }
4059 } else {
4060 // Otherwise this is a computed property name which needs to be added
4061 // dynamically. BigInt keys are parsed as (synthetic) computed property
4062 // names, too.
4063 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4063); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::ComputedName)"
")"); do { *((volatile int*)__null) = 4063; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4064 continue;
4065 }
4066 }
4067
4068 // Initialize elements with |undefined|.
4069 if (!emit1(JSOp::Undefined)) {
4070 return false;
4071 }
4072
4073 if (!pnatom) {
4074 if (!emit1(JSOp::InitElem)) {
4075 return false;
4076 }
4077 } else {
4078 if (!emitAtomOp(JSOp::InitProp, pnatom)) {
4079 return false;
4080 }
4081 }
4082 }
4083
4084 return true;
4085}
4086
4087bool BytecodeEmitter::emitDestructuringOps(ListNode* pattern,
4088 DestructuringFlavor flav) {
4089 if (pattern->isKind(ParseNodeKind::ArrayExpr)) {
4090 return emitDestructuringOpsArray(pattern, flav);
4091 }
4092 return emitDestructuringOpsObject(pattern, flav);
4093}
4094
4095bool BytecodeEmitter::emitTemplateString(ListNode* templateString) {
4096 bool pushedString = false;
4097
4098 for (ParseNode* item : templateString->contents()) {
4099 bool isString = (item->getKind() == ParseNodeKind::StringExpr ||
4100 item->getKind() == ParseNodeKind::TemplateStringExpr);
4101
4102 // Skip empty strings. These are very common: a template string like
4103 // `${a}${b}` has three empty strings and without this optimization
4104 // we'd emit four JSOp::Add operations instead of just one.
4105 if (isString && item->as<NameNode>().atom() ==
4106 TaggedParserAtomIndex::WellKnown::empty()) {
4107 continue;
4108 }
4109
4110 if (!isString) {
4111 // We update source notes before emitting the expression
4112 if (!updateSourceCoordNotes(item->pn_pos.begin)) {
4113 return false;
4114 }
4115 }
4116
4117 if (!emitTree(item)) {
4118 return false;
4119 }
4120
4121 if (!isString) {
4122 // We need to convert the expression to a string
4123 if (!emit1(JSOp::ToString)) {
4124 return false;
4125 }
4126 }
4127
4128 if (pushedString) {
4129 // We've pushed two strings onto the stack. Add them together, leaving
4130 // just one.
4131 if (!emit1(JSOp::Add)) {
4132 return false;
4133 }
4134 } else {
4135 pushedString = true;
4136 }
4137 }
4138
4139 if (!pushedString) {
4140 // All strings were empty, this can happen for something like `${""}`.
4141 // Just push an empty string.
4142 if (!emitStringOp(JSOp::String,
4143 TaggedParserAtomIndex::WellKnown::empty())) {
4144 return false;
4145 }
4146 }
4147
4148 return true;
4149}
4150
4151bool BytecodeEmitter::emitDeclarationList(ListNode* declList) {
4152 for (ParseNode* decl : declList->contents()) {
4153 ParseNode* pattern;
4154 ParseNode* initializer;
4155 if (decl->isKind(ParseNodeKind::Name)) {
4156 pattern = decl;
4157 initializer = nullptr;
4158 } else {
4159 AssignmentNode* assignNode = &decl->as<AssignmentNode>();
4160 pattern = assignNode->left();
4161 initializer = assignNode->right();
4162 }
4163
4164 if (pattern->isKind(ParseNodeKind::Name)) {
4165 // initializer can be null here.
4166 if (!emitSingleDeclaration(declList, &pattern->as<NameNode>(),
4167 initializer)) {
4168 return false;
4169 }
4170 } else {
4171 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4172); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pattern->isKind(ParseNodeKind::ArrayExpr) || pattern->isKind(ParseNodeKind::ObjectExpr)"
")"); do { *((volatile int*)__null) = 4172; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4172 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4172); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pattern->isKind(ParseNodeKind::ArrayExpr) || pattern->isKind(ParseNodeKind::ObjectExpr)"
")"); do { *((volatile int*)__null) = 4172; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4173 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4173); AnnotateMozCrashReason("MOZ_ASSERT" "(" "initializer != nullptr"
")"); do { *((volatile int*)__null) = 4173; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4174
4175 if (!updateSourceCoordNotes(initializer->pn_pos.begin)) {
4176 return false;
4177 }
4178 if (!markStepBreakpoint()) {
4179 return false;
4180 }
4181 if (!emitTree(initializer)) {
4182 return false;
4183 }
4184
4185 if (!emitDestructuringOps(&pattern->as<ListNode>(),
4186 DestructuringFlavor::Declaration)) {
4187 return false;
4188 }
4189
4190 if (!emit1(JSOp::Pop)) {
4191 return false;
4192 }
4193 }
4194 }
4195 return true;
4196}
4197
4198bool BytecodeEmitter::emitSingleDeclaration(ListNode* declList, NameNode* decl,
4199 ParseNode* initializer) {
4200 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)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4200); AnnotateMozCrashReason("MOZ_ASSERT" "(" "decl->isKind(ParseNodeKind::Name)"
")"); do { *((volatile int*)__null) = 4200; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4201
4202 // Nothing to do for initializer-less 'var' declarations, as there's no TDZ.
4203 if (!initializer && declList->isKind(ParseNodeKind::VarStmt)) {
4204 return true;
4205 }
4206
4207 auto nameAtom = decl->name();
4208 NameOpEmitter noe(this, nameAtom, NameOpEmitter::Kind::Initialize);
4209 if (!noe.prepareForRhs()) {
4210 // [stack] ENV?
4211 return false;
4212 }
4213 if (!initializer) {
4214 // Lexical declarations are initialized to undefined without an
4215 // initializer.
4216 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4218); AnnotateMozCrashReason("MOZ_ASSERT" "(" "declList->isKind(ParseNodeKind::LetDecl)"
") (" "var declarations without initializers handled above, "
"and const declarations must have initializers" ")"); do { *
((volatile int*)__null) = 4218; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
4217 "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4218); AnnotateMozCrashReason("MOZ_ASSERT" "(" "declList->isKind(ParseNodeKind::LetDecl)"
") (" "var declarations without initializers handled above, "
"and const declarations must have initializers" ")"); do { *
((volatile int*)__null) = 4218; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
4218 "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4218); AnnotateMozCrashReason("MOZ_ASSERT" "(" "declList->isKind(ParseNodeKind::LetDecl)"
") (" "var declarations without initializers handled above, "
"and const declarations must have initializers" ")"); do { *
((volatile int*)__null) = 4218; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
4219 if (!emit1(JSOp::Undefined)) {
4220 // [stack] ENV? UNDEF
4221 return false;
4222 }
4223 } else {
4224 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4224); AnnotateMozCrashReason("MOZ_ASSERT" "(" "initializer"
")"); do { *((volatile int*)__null) = 4224; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4225
4226 if (!updateSourceCoordNotes(initializer->pn_pos.begin)) {
4227 return false;
4228 }
4229 if (!markStepBreakpoint()) {
4230 return false;
4231 }
4232 if (!emitInitializer(initializer, decl)) {
4233 // [stack] ENV? V
4234 return false;
4235 }
4236 }
4237
4238#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
4239 if (declList->isKind(ParseNodeKind::UsingDecl)) {
4240 if (!innermostEmitterScope()->prepareForDisposableAssignment(
4241 UsingHint::Sync)) {
4242 // [stack] ENV? V
4243 return false;
4244 }
4245 } else if (declList->isKind(ParseNodeKind::AwaitUsingDecl)) {
4246 if (!innermostEmitterScope()->prepareForDisposableAssignment(
4247 UsingHint::Async)) {
4248 // [stack] ENV? V
4249 return false;
4250 }
4251 }
4252#endif
4253
4254 if (!noe.emitAssignment()) {
4255 // [stack] V
4256 return false;
4257 }
4258
4259 if (!emit1(JSOp::Pop)) {
4260 // [stack]
4261 return false;
4262 }
4263
4264 return true;
4265}
4266
4267bool BytecodeEmitter::emitAssignmentRhs(
4268 ParseNode* rhs, TaggedParserAtomIndex anonFunctionName) {
4269 if (rhs->isDirectRHSAnonFunction()) {
4270 if (anonFunctionName) {
4271 return emitAnonymousFunctionWithName(rhs, anonFunctionName);
4272 }
4273 return emitAnonymousFunctionWithComputedName(rhs, FunctionPrefixKind::None);
4274 }
4275 return emitTree(rhs);
4276}
4277
4278// The RHS value to assign is already on the stack, i.e., the next enumeration
4279// value in a for-in or for-of loop. Offset is the location in the stack of the
4280// already-emitted rhs. If we emitted a JSOp::BindUnqualifiedName or
4281// JSOp::BindUnqualifiedGName, then the scope is on the top of the stack and we
4282// need to dig one deeper to get the right RHS value.
4283bool BytecodeEmitter::emitAssignmentRhs(uint8_t offset) {
4284 if (offset != 1) {
4285 return emitPickN(offset - 1);
4286 }
4287
4288 return true;
4289}
4290
4291static inline JSOp CompoundAssignmentParseNodeKindToJSOp(ParseNodeKind pnk) {
4292 switch (pnk) {
4293 case ParseNodeKind::InitExpr:
4294 return JSOp::Nop;
4295 case ParseNodeKind::AssignExpr:
4296 return JSOp::Nop;
4297 case ParseNodeKind::AddAssignExpr:
4298 return JSOp::Add;
4299 case ParseNodeKind::SubAssignExpr:
4300 return JSOp::Sub;
4301 case ParseNodeKind::BitOrAssignExpr:
4302 return JSOp::BitOr;
4303 case ParseNodeKind::BitXorAssignExpr:
4304 return JSOp::BitXor;
4305 case ParseNodeKind::BitAndAssignExpr:
4306 return JSOp::BitAnd;
4307 case ParseNodeKind::LshAssignExpr:
4308 return JSOp::Lsh;
4309 case ParseNodeKind::RshAssignExpr:
4310 return JSOp::Rsh;
4311 case ParseNodeKind::UrshAssignExpr:
4312 return JSOp::Ursh;
4313 case ParseNodeKind::MulAssignExpr:
4314 return JSOp::Mul;
4315 case ParseNodeKind::DivAssignExpr:
4316 return JSOp::Div;
4317 case ParseNodeKind::ModAssignExpr:
4318 return JSOp::Mod;
4319 case ParseNodeKind::PowAssignExpr:
4320 return JSOp::Pow;
4321 case ParseNodeKind::CoalesceAssignExpr:
4322 case ParseNodeKind::OrAssignExpr:
4323 case ParseNodeKind::AndAssignExpr:
4324 // Short-circuit assignment operators are handled elsewhere.
4325 [[fallthrough]];
4326 default:
4327 MOZ_CRASH("unexpected compound assignment op")do { do { } while (false); MOZ_ReportCrash("" "unexpected compound assignment op"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4327); AnnotateMozCrashReason("MOZ_CRASH(" "unexpected compound assignment op"
")"); do { *((volatile int*)__null) = 4327; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
4328 }
4329}
4330
4331bool BytecodeEmitter::emitAssignmentOrInit(ParseNodeKind kind, ParseNode* lhs,
4332 ParseNode* rhs) {
4333 JSOp compoundOp = CompoundAssignmentParseNodeKindToJSOp(kind);
4334 bool isCompound = compoundOp != JSOp::Nop;
4335 bool isInit = kind == ParseNodeKind::InitExpr;
4336
4337 // We estimate the number of properties this could create
4338 // if used as constructor merely by counting this.foo = assignment
4339 // or init expressions;
4340 //
4341 // This currently doesn't handle this[x] = foo;
4342 if (isInit || kind == ParseNodeKind::AssignExpr) {
4343 if (lhs->isKind(ParseNodeKind::DotExpr)) {
4344 if (lhs->as<PropertyAccess>().expression().isKind(
4345 ParseNodeKind::ThisExpr)) {
4346 propertyAdditionEstimate++;
4347 }
4348 }
4349 }
4350
4351 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4353); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lhs->isKind(ParseNodeKind::DotExpr) || lhs->isKind(ParseNodeKind::ElemExpr) || lhs->isKind(ParseNodeKind::PrivateMemberExpr)"
")"); do { *((volatile int*)__null) = 4353; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4352 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4353); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lhs->isKind(ParseNodeKind::DotExpr) || lhs->isKind(ParseNodeKind::ElemExpr) || lhs->isKind(ParseNodeKind::PrivateMemberExpr)"
")"); do { *((volatile int*)__null) = 4353; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4353 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4353); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lhs->isKind(ParseNodeKind::DotExpr) || lhs->isKind(ParseNodeKind::ElemExpr) || lhs->isKind(ParseNodeKind::PrivateMemberExpr)"
")"); do { *((volatile int*)__null) = 4353; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4354
4355 // |name| is used within NameOpEmitter, so its lifetime must surpass |noe|.
4356 TaggedParserAtomIndex name;
4357
4358 Maybe<NameOpEmitter> noe;
4359 Maybe<PropOpEmitter> poe;
4360 Maybe<ElemOpEmitter> eoe;
4361 Maybe<PrivateOpEmitter> xoe;
4362
4363 // Deal with non-name assignments.
4364 uint8_t offset = 1;
4365
4366 // Purpose of anonFunctionName:
4367 //
4368 // In normal name assignments (`f = function(){}`), an anonymous function gets
4369 // an inferred name based on the left-hand side name node.
4370 //
4371 // In normal property assignments (`obj.x = function(){}`), the anonymous
4372 // function does not have a computed name, and rhs->isDirectRHSAnonFunction()
4373 // will be false (and anonFunctionName will not be used). However, in field
4374 // initializers (`class C { x = function(){} }`), field initialization is
4375 // implemented via a property or elem assignment (where we are now), and
4376 // rhs->isDirectRHSAnonFunction() is set - so we'll assign the name of the
4377 // function.
4378 TaggedParserAtomIndex anonFunctionName;
4379
4380 switch (lhs->getKind()) {
4381 case ParseNodeKind::Name: {
4382 name = lhs->as<NameNode>().name();
4383 anonFunctionName = name;
4384 noe.emplace(this, name,
4385 isCompound ? NameOpEmitter::Kind::CompoundAssignment
4386 : NameOpEmitter::Kind::SimpleAssignment);
4387 break;
4388 }
4389 case ParseNodeKind::ArgumentsLength:
4390 case ParseNodeKind::DotExpr: {
4391 PropertyAccess* prop = &lhs->as<PropertyAccess>();
4392 bool isSuper = prop->isSuper();
4393 poe.emplace(this,
4394 isCompound ? PropOpEmitter::Kind::CompoundAssignment
4395 : isInit ? PropOpEmitter::Kind::PropInit
4396 : PropOpEmitter::Kind::SimpleAssignment,
4397 isSuper ? PropOpEmitter::ObjKind::Super
4398 : PropOpEmitter::ObjKind::Other);
4399 if (!poe->prepareForObj()) {
4400 return false;
4401 }
4402 anonFunctionName = prop->name();
4403 if (isSuper) {
4404 UnaryNode* base = &prop->expression().as<UnaryNode>();
4405 if (!emitGetThisForSuperBase(base)) {
4406 // [stack] THIS SUPERBASE
4407 return false;
4408 }
4409 // SUPERBASE is pushed onto THIS later in poe->emitGet below.
4410 offset += 2;
4411 } else {
4412 if (!emitTree(&prop->expression())) {
4413 // [stack] OBJ
4414 return false;
4415 }
4416 offset += 1;
4417 }
4418 break;
4419 }
4420 case ParseNodeKind::ElemExpr: {
4421 PropertyByValue* elem = &lhs->as<PropertyByValue>();
4422 bool isSuper = elem->isSuper();
4423 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4423); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 4423; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4424 eoe.emplace(this,
4425 isCompound ? ElemOpEmitter::Kind::CompoundAssignment
4426 : isInit ? ElemOpEmitter::Kind::PropInit
4427 : ElemOpEmitter::Kind::SimpleAssignment,
4428 isSuper ? ElemOpEmitter::ObjKind::Super
4429 : ElemOpEmitter::ObjKind::Other);
4430 if (!emitElemObjAndKey(elem, *eoe)) {
4431 // [stack] # if Super
4432 // [stack] THIS KEY
4433 // [stack] # otherwise
4434 // [stack] OBJ KEY
4435 return false;
4436 }
4437 if (isSuper) {
4438 // SUPERBASE is pushed onto KEY in eoe->emitGet below.
4439 offset += 3;
4440 } else {
4441 offset += 2;
4442 }
4443 break;
4444 }
4445 case ParseNodeKind::PrivateMemberExpr: {
4446 PrivateMemberAccess* privateExpr = &lhs->as<PrivateMemberAccess>();
4447 xoe.emplace(this,
4448 isCompound ? PrivateOpEmitter::Kind::CompoundAssignment
4449 : isInit ? PrivateOpEmitter::Kind::PropInit
4450 : PrivateOpEmitter::Kind::SimpleAssignment,
4451 privateExpr->privateName().name());
4452 if (!emitTree(&privateExpr->expression())) {
4453 // [stack] OBJ
4454 return false;
4455 }
4456 if (!xoe->emitReference()) {
4457 // [stack] OBJ KEY
4458 return false;
4459 }
4460 offset += xoe->numReferenceSlots();
4461 break;
4462 }
4463 case ParseNodeKind::ArrayExpr:
4464 case ParseNodeKind::ObjectExpr:
4465 break;
4466 case ParseNodeKind::CallExpr:
4467 if (!emitTree(lhs)) {
4468 return false;
4469 }
4470
4471 // Assignment to function calls is forbidden, but we have to make the
4472 // call first. Now we can throw.
4473 if (!emit2(JSOp::ThrowMsg, uint8_t(ThrowMsgKind::AssignToCall))) {
4474 return false;
4475 }
4476
4477 // Rebalance the stack to placate stack-depth assertions.
4478 if (!emit1(JSOp::Pop)) {
4479 return false;
4480 }
4481 break;
4482 default:
4483 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4483); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0" ")"); do
{ *((volatile int*)__null) = 4483; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
4484 }
4485
4486 if (isCompound) {
4487 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4487); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rhs" ")"); do
{ *((volatile int*)__null) = 4487; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
4488 switch (lhs->getKind()) {
4489 case ParseNodeKind::ArgumentsLength:
4490 case ParseNodeKind::DotExpr: {
4491 PropertyAccess* prop = &lhs->as<PropertyAccess>();
4492 if (!poe->emitGet(prop->key().atom())) {
4493 // [stack] # if Super
4494 // [stack] THIS SUPERBASE PROP
4495 // [stack] # otherwise
4496 // [stack] OBJ PROP
4497 return false;
4498 }
4499 break;
4500 }
4501 case ParseNodeKind::ElemExpr: {
4502 if (!eoe->emitGet()) {
4503 // [stack] KEY THIS OBJ ELEM
4504 return false;
4505 }
4506 break;
4507 }
4508 case ParseNodeKind::PrivateMemberExpr: {
4509 if (!xoe->emitGet()) {
4510 // [stack] OBJ KEY VALUE
4511 return false;
4512 }
4513 break;
4514 }
4515 case ParseNodeKind::CallExpr:
4516 // We just emitted a JSOp::ThrowMsg and popped the call's return
4517 // value. Push a random value to make sure the stack depth is
4518 // correct.
4519 if (!emit1(JSOp::Null)) {
4520 // [stack] NULL
4521 return false;
4522 }
4523 break;
4524 default:;
4525 }
4526 }
4527
4528 switch (lhs->getKind()) {
4529 case ParseNodeKind::Name:
4530 if (!noe->prepareForRhs()) {
4531 // [stack] ENV? VAL?
4532 return false;
4533 }
4534 offset += noe->emittedBindOp();
4535 break;
4536 case ParseNodeKind::ArgumentsLength:
4537 case ParseNodeKind::DotExpr:
4538 if (!poe->prepareForRhs()) {
4539 // [stack] # if Simple Assignment with Super
4540 // [stack] THIS SUPERBASE
4541 // [stack] # if Simple Assignment with other
4542 // [stack] OBJ
4543 // [stack] # if Compound Assignment with Super
4544 // [stack] THIS SUPERBASE PROP
4545 // [stack] # if Compound Assignment with other
4546 // [stack] OBJ PROP
4547 return false;
4548 }
4549 break;
4550 case ParseNodeKind::ElemExpr:
4551 if (!eoe->prepareForRhs()) {
4552 // [stack] # if Simple Assignment with Super
4553 // [stack] THIS KEY SUPERBASE
4554 // [stack] # if Simple Assignment with other
4555 // [stack] OBJ KEY
4556 // [stack] # if Compound Assignment with Super
4557 // [stack] THIS KEY SUPERBASE ELEM
4558 // [stack] # if Compound Assignment with other
4559 // [stack] OBJ KEY ELEM
4560 return false;
4561 }
4562 break;
4563 case ParseNodeKind::PrivateMemberExpr:
4564 // no stack adjustment needed
4565 break;
4566 default:
4567 break;
4568 }
4569
4570 if (rhs) {
4571 if (!emitAssignmentRhs(rhs, anonFunctionName)) {
4572 // [stack] ... VAL? RHS
4573 return false;
4574 }
4575 } else {
4576 // Assumption: Things with pre-emitted RHS values never need to be named.
4577 if (!emitAssignmentRhs(offset)) {
4578 // [stack] ... VAL? RHS
4579 return false;
4580 }
4581 }
4582
4583 /* If += etc., emit the binary operator with a hint for the decompiler. */
4584 if (isCompound) {
4585 if (!emit1(compoundOp)) {
4586 // [stack] ... VAL
4587 return false;
4588 }
4589 if (!emit1(JSOp::NopIsAssignOp)) {
4590 // [stack] ... VAL
4591 return false;
4592 }
4593 }
4594
4595 /* Finally, emit the specialized assignment bytecode. */
4596 switch (lhs->getKind()) {
4597 case ParseNodeKind::Name: {
4598 if (!noe->emitAssignment()) {
4599 // [stack] VAL
4600 return false;
4601 }
4602 break;
4603 }
4604 case ParseNodeKind::ArgumentsLength:
4605 case ParseNodeKind::DotExpr: {
4606 PropertyAccess* prop = &lhs->as<PropertyAccess>();
4607 if (!poe->emitAssignment(prop->key().atom())) {
4608 // [stack] VAL
4609 return false;
4610 }
4611 break;
4612 }
4613 case ParseNodeKind::CallExpr:
4614 // We threw above, so nothing to do here.
4615 break;
4616 case ParseNodeKind::ElemExpr: {
4617 if (!eoe->emitAssignment()) {
4618 // [stack] VAL
4619 return false;
4620 }
4621 break;
4622 }
4623 case ParseNodeKind::PrivateMemberExpr:
4624 if (!xoe->emitAssignment()) {
4625 // [stack] VAL
4626 return false;
4627 }
4628 break;
4629 case ParseNodeKind::ArrayExpr:
4630 case ParseNodeKind::ObjectExpr:
4631 if (!emitDestructuringOps(&lhs->as<ListNode>(),
4632 DestructuringFlavor::Assignment)) {
4633 return false;
4634 }
4635 break;
4636 default:
4637 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4637); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0" ")"); do
{ *((volatile int*)__null) = 4637; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
4638 }
4639 return true;
4640}
4641
4642bool BytecodeEmitter::emitShortCircuitAssignment(AssignmentNode* node) {
4643 TDZCheckCache tdzCache(this);
4644
4645 JSOp op;
4646 switch (node->getKind()) {
4647 case ParseNodeKind::CoalesceAssignExpr:
4648 op = JSOp::Coalesce;
4649 break;
4650 case ParseNodeKind::OrAssignExpr:
4651 op = JSOp::Or;
4652 break;
4653 case ParseNodeKind::AndAssignExpr:
4654 op = JSOp::And;
4655 break;
4656 default:
4657 MOZ_CRASH("Unexpected ParseNodeKind")do { do { } while (false); MOZ_ReportCrash("" "Unexpected ParseNodeKind"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4657); AnnotateMozCrashReason("MOZ_CRASH(" "Unexpected ParseNodeKind"
")"); do { *((volatile int*)__null) = 4657; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
4658 }
4659
4660 ParseNode* lhs = node->left();
4661 ParseNode* rhs = node->right();
4662
4663 // |name| is used within NameOpEmitter, so its lifetime must surpass |noe|.
4664 TaggedParserAtomIndex name;
4665
4666 // Select the appropriate emitter based on the left-hand side.
4667 Maybe<NameOpEmitter> noe;
4668 Maybe<PropOpEmitter> poe;
4669 Maybe<ElemOpEmitter> eoe;
4670 Maybe<PrivateOpEmitter> xoe;
4671
4672 int32_t depth = bytecodeSection().stackDepth();
4673
4674 // Number of values pushed onto the stack in addition to the lhs value.
4675 int32_t numPushed;
4676
4677 // Evaluate the left-hand side expression and compute any stack values needed
4678 // for the assignment.
4679 switch (lhs->getKind()) {
4680 case ParseNodeKind::Name: {
4681 name = lhs->as<NameNode>().name();
4682 noe.emplace(this, name, NameOpEmitter::Kind::CompoundAssignment);
4683
4684 if (!noe->prepareForRhs()) {
4685 // [stack] ENV? LHS
4686 return false;
4687 }
4688
4689 numPushed = noe->emittedBindOp();
4690 break;
4691 }
4692 case ParseNodeKind::ArgumentsLength:
4693 case ParseNodeKind::DotExpr: {
4694 PropertyAccess* prop = &lhs->as<PropertyAccess>();
4695 bool isSuper = prop->isSuper();
4696
4697 poe.emplace(this, PropOpEmitter::Kind::CompoundAssignment,
4698 isSuper ? PropOpEmitter::ObjKind::Super
4699 : PropOpEmitter::ObjKind::Other);
4700
4701 if (!poe->prepareForObj()) {
4702 return false;
4703 }
4704
4705 if (isSuper) {
4706 UnaryNode* base = &prop->expression().as<UnaryNode>();
4707 if (!emitGetThisForSuperBase(base)) {
4708 // [stack] THIS SUPERBASE
4709 return false;
4710 }
4711 } else {
4712 if (!emitTree(&prop->expression())) {
4713 // [stack] OBJ
4714 return false;
4715 }
4716 }
4717
4718 if (!poe->emitGet(prop->key().atom())) {
4719 // [stack] # if Super
4720 // [stack] THIS SUPERBASE LHS
4721 // [stack] # otherwise
4722 // [stack] OBJ LHS
4723 return false;
4724 }
4725
4726 if (!poe->prepareForRhs()) {
4727 // [stack] # if Super
4728 // [stack] THIS SUPERBASE LHS
4729 // [stack] # otherwise
4730 // [stack] OBJ LHS
4731 return false;
4732 }
4733
4734 numPushed = 1 + isSuper;
4735 break;
4736 }
4737
4738 case ParseNodeKind::ElemExpr: {
4739 PropertyByValue* elem = &lhs->as<PropertyByValue>();
4740 bool isSuper = elem->isSuper();
4741 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4741); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 4741; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4742 eoe.emplace(this, ElemOpEmitter::Kind::CompoundAssignment,
4743 isSuper ? ElemOpEmitter::ObjKind::Super
4744 : ElemOpEmitter::ObjKind::Other);
4745
4746 if (!emitElemObjAndKey(elem, *eoe)) {
4747 // [stack] # if Super
4748 // [stack] THIS KEY
4749 // [stack] # otherwise
4750 // [stack] OBJ KEY
4751 return false;
4752 }
4753
4754 if (!eoe->emitGet()) {
4755 // [stack] # if Super
4756 // [stack] THIS KEY SUPERBASE LHS
4757 // [stack] # otherwise
4758 // [stack] OBJ KEY LHS
4759 return false;
4760 }
4761
4762 if (!eoe->prepareForRhs()) {
4763 // [stack] # if Super
4764 // [stack] THIS KEY SUPERBASE LHS
4765 // [stack] # otherwise
4766 // [stack] OBJ KEY LHS
4767 return false;
4768 }
4769
4770 numPushed = 2 + isSuper;
4771 break;
4772 }
4773
4774 case ParseNodeKind::PrivateMemberExpr: {
4775 PrivateMemberAccess* privateExpr = &lhs->as<PrivateMemberAccess>();
4776 xoe.emplace(this, PrivateOpEmitter::Kind::CompoundAssignment,
4777 privateExpr->privateName().name());
4778 if (!emitTree(&privateExpr->expression())) {
4779 // [stack] OBJ
4780 return false;
4781 }
4782 if (!xoe->emitReference()) {
4783 // [stack] OBJ NAME
4784 return false;
4785 }
4786 if (!xoe->emitGet()) {
4787 // [stack] OBJ NAME LHS
4788 return false;
4789 }
4790 numPushed = xoe->numReferenceSlots();
4791 break;
4792 }
4793
4794 default:
4795 MOZ_CRASH()do { do { } while (false); MOZ_ReportCrash("" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4795); AnnotateMozCrashReason("MOZ_CRASH(" ")"); do { *((volatile
int*)__null) = 4795; __attribute__((nomerge)) ::abort(); } while
(false); } while (false)
;
4796 }
4797
4798 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4798); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == depth + numPushed + 1"
")"); do { *((volatile int*)__null) = 4798; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4799
4800 // Test for the short-circuit condition.
4801 JumpList jump;
4802 if (!emitJump(op, &jump)) {
4803 // [stack] ... LHS
4804 return false;
4805 }
4806
4807 // The short-circuit condition wasn't fulfilled, pop the left-hand side value
4808 // which was kept on the stack.
4809 if (!emit1(JSOp::Pop)) {
4810 // [stack] ...
4811 return false;
4812 }
4813
4814 if (!emitAssignmentRhs(rhs, name)) {
4815 // [stack] ... RHS
4816 return false;
4817 }
4818
4819 // Perform the actual assignment.
4820 switch (lhs->getKind()) {
4821 case ParseNodeKind::Name: {
4822 if (!noe->emitAssignment()) {
4823 // [stack] RHS
4824 return false;
4825 }
4826 break;
4827 }
4828 case ParseNodeKind::ArgumentsLength:
4829 case ParseNodeKind::DotExpr: {
4830 PropertyAccess* prop = &lhs->as<PropertyAccess>();
4831
4832 if (!poe->emitAssignment(prop->key().atom())) {
4833 // [stack] RHS
4834 return false;
4835 }
4836 break;
4837 }
4838
4839 case ParseNodeKind::ElemExpr: {
4840 if (!eoe->emitAssignment()) {
4841 // [stack] RHS
4842 return false;
4843 }
4844 break;
4845 }
4846
4847 case ParseNodeKind::PrivateMemberExpr:
4848 if (!xoe->emitAssignment()) {
4849 // [stack] RHS
4850 return false;
4851 }
4852 break;
4853
4854 default:
4855 MOZ_CRASH()do { do { } while (false); MOZ_ReportCrash("" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4855); AnnotateMozCrashReason("MOZ_CRASH(" ")"); do { *((volatile
int*)__null) = 4855; __attribute__((nomerge)) ::abort(); } while
(false); } while (false)
;
4856 }
4857
4858 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4858); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == depth + 1"
")"); do { *((volatile int*)__null) = 4858; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4859
4860 // Join with the short-circuit jump and pop anything left on the stack.
4861 if (numPushed > 0) {
4862 JumpList jumpAroundPop;
4863 if (!emitJump(JSOp::Goto, &jumpAroundPop)) {
4864 // [stack] RHS
4865 return false;
4866 }
4867
4868 if (!emitJumpTargetAndPatch(jump)) {
4869 // [stack] ... LHS
4870 return false;
4871 }
4872
4873 // Reconstruct the stack depth after the jump.
4874 bytecodeSection().setStackDepth(depth + 1 + numPushed);
4875
4876 // Move the left-hand side value to the bottom and pop the rest.
4877 if (!emitUnpickN(numPushed)) {
4878 // [stack] LHS ...
4879 return false;
4880 }
4881 if (!emitPopN(numPushed)) {
4882 // [stack] LHS
4883 return false;
4884 }
4885
4886 if (!emitJumpTargetAndPatch(jumpAroundPop)) {
4887 // [stack] LHS | RHS
4888 return false;
4889 }
4890 } else {
4891 if (!emitJumpTargetAndPatch(jump)) {
4892 // [stack] LHS | RHS
4893 return false;
4894 }
4895 }
4896
4897 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4897); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == depth + 1"
")"); do { *((volatile int*)__null) = 4897; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4898
4899 return true;
4900}
4901
4902bool BytecodeEmitter::emitCallSiteObjectArray(ObjLiteralWriter& writer,
4903 ListNode* cookedOrRaw,
4904 ParseNode* head, uint32_t count) {
4905 DebugOnly<size_t> idx = 0;
4906 for (ParseNode* pn : cookedOrRaw->contentsFrom(head)) {
4907 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4908); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->isKind(ParseNodeKind::TemplateStringExpr) || pn->isKind(ParseNodeKind::RawUndefinedExpr)"
")"); do { *((volatile int*)__null) = 4908; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4908 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4908); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->isKind(ParseNodeKind::TemplateStringExpr) || pn->isKind(ParseNodeKind::RawUndefinedExpr)"
")"); do { *((volatile int*)__null) = 4908; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4909
4910 if (!emitObjLiteralValue(writer, pn)) {
4911 return false;
4912 }
4913 idx++;
4914 }
4915 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4915); AnnotateMozCrashReason("MOZ_ASSERT" "(" "idx == count"
")"); do { *((volatile int*)__null) = 4915; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4916
4917 return true;
4918}
4919
4920bool BytecodeEmitter::emitCallSiteObject(CallSiteNode* callSiteObj) {
4921 constexpr JSOp op = JSOp::CallSiteObj;
4922
4923 // The first element of a call-site node is the raw-values list. Skip over it.
4924 ListNode* raw = callSiteObj->rawNodes();
4925 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4925); AnnotateMozCrashReason("MOZ_ASSERT" "(" "raw->isKind(ParseNodeKind::ArrayExpr)"
")"); do { *((volatile int*)__null) = 4925; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4926 ParseNode* head = callSiteObj->head()->pn_next;
4927
4928 uint32_t count = callSiteObj->count() - 1;
4929 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4929); AnnotateMozCrashReason("MOZ_ASSERT" "(" "count == raw->count()"
")"); do { *((volatile int*)__null) = 4929; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4930
4931 ObjLiteralWriter writer;
4932 writer.beginCallSiteObj(op);
4933 writer.beginDenseArrayElements();
4934
4935 // Write elements of the two arrays: the 'cooked' values followed by the
4936 // 'raw' values.
4937 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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4938); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "count < (4294967295U) / 2"
") (" "Number of elements for both arrays must fit in uint32_t"
")"); do { *((volatile int*)__null) = 4938; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4938 "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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4938); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "count < (4294967295U) / 2"
") (" "Number of elements for both arrays must fit in uint32_t"
")"); do { *((volatile int*)__null) = 4938; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4939 if (!emitCallSiteObjectArray(writer, callSiteObj, head, count)) {
4940 return false;
4941 }
4942 if (!emitCallSiteObjectArray(writer, raw, raw->head(), count)) {
4943 return false;
4944 }
4945
4946 GCThingIndex cookedIndex;
4947 if (!addObjLiteralData(writer, &cookedIndex)) {
4948 return false;
4949 }
4950
4951 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4951); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->hasCallSiteObj()"
")"); do { *((volatile int*)__null) = 4951; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4952
4953 return emitInternedObjectOp(cookedIndex, op);
4954}
4955
4956bool BytecodeEmitter::emitCatch(BinaryNode* catchClause) {
4957 // We must be nested under a try-finally statement.
4958 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>()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4958); AnnotateMozCrashReason("MOZ_ASSERT" "(" "innermostNestableControl->is<TryFinallyControl>()"
")"); do { *((volatile int*)__null) = 4958; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4959
4960 ParseNode* param = catchClause->left();
4961 if (!param) {
4962 // Catch parameter was omitted; just discard the exception.
4963 if (!emit1(JSOp::Pop)) {
4964 return false;
4965 }
4966 } else {
4967 switch (param->getKind()) {
4968 case ParseNodeKind::ArrayExpr:
4969 case ParseNodeKind::ObjectExpr:
4970 if (!emitDestructuringOps(&param->as<ListNode>(),
4971 DestructuringFlavor::Declaration)) {
4972 return false;
4973 }
4974 if (!emit1(JSOp::Pop)) {
4975 return false;
4976 }
4977 break;
4978
4979 case ParseNodeKind::Name:
4980 if (!emitLexicalInitialization(&param->as<NameNode>())) {
4981 return false;
4982 }
4983 if (!emit1(JSOp::Pop)) {
4984 return false;
4985 }
4986 break;
4987
4988 default:
4989 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4989); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0" ")"); do
{ *((volatile int*)__null) = 4989; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
4990 }
4991 }
4992
4993 /* Emit the catch body. */
4994 return emitTree(catchClause->right());
4995}
4996
4997// Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See the
4998// comment on EmitSwitch.
4999MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitTry(TryNode* tryNode) {
5000 LexicalScopeNode* catchScope = tryNode->catchScope();
5001 ParseNode* finallyNode = tryNode->finallyBlock();
5002
5003 TryEmitter::Kind kind;
5004 if (catchScope) {
5005 if (finallyNode) {
5006 kind = TryEmitter::Kind::TryCatchFinally;
5007 } else {
5008 kind = TryEmitter::Kind::TryCatch;
5009 }
5010 } else {
5011 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5011); AnnotateMozCrashReason("MOZ_ASSERT" "(" "finallyNode"
")"); do { *((volatile int*)__null) = 5011; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5012 kind = TryEmitter::Kind::TryFinally;
5013 }
5014 TryEmitter tryCatch(this, kind, TryEmitter::ControlKind::Syntactic);
5015
5016 if (!tryCatch.emitTry()) {
5017 return false;
5018 }
5019
5020 if (!emitTree(tryNode->body())) {
5021 return false;
5022 }
5023
5024 // If this try has a catch block, emit it.
5025 if (catchScope) {
5026 // The emitted code for a catch block looks like:
5027 //
5028 // [pushlexicalenv] only if any local aliased
5029 // exception
5030 // setlocal 0; pop assign or possibly destructure exception
5031 // < catch block contents >
5032 // debugleaveblock
5033 // [poplexicalenv] only if any local aliased
5034 // if there is a finally block:
5035 // goto <finally>
5036 // [jump target for returning from finally]
5037 // goto <after finally>
5038 if (!tryCatch.emitCatch()) {
5039 return false;
5040 }
5041
5042 // Emit the lexical scope and catch body.
5043 if (!emitTree(catchScope)) {
5044 return false;
5045 }
5046 }
5047
5048 // Emit the finally handler, if there is one.
5049 if (finallyNode) {
5050 if (!tryCatch.emitFinally(Some(finallyNode->pn_pos.begin))) {
5051 return false;
5052 }
5053
5054 if (!emitTree(finallyNode)) {
5055 return false;
5056 }
5057 }
5058
5059 if (!tryCatch.emitEnd()) {
5060 return false;
5061 }
5062
5063 return true;
5064}
5065
5066[[nodiscard]] bool BytecodeEmitter::emitJumpToFinally(JumpList* jump,
5067 uint32_t idx) {
5068 // Push the continuation index.
5069 if (!emitNumberOp(idx)) {
5070 return false;
5071 }
5072
5073 // Push |exception_stack|.
5074 if (!emit1(JSOp::Null)) {
5075 return false;
5076 }
5077
5078 // Push |throwing|.
5079 if (!emit1(JSOp::False)) {
5080 return false;
5081 }
5082
5083 // Jump to the finally block.
5084 if (!emitJumpNoFallthrough(JSOp::Goto, jump)) {
5085 return false;
5086 }
5087
5088 return true;
5089}
5090
5091bool BytecodeEmitter::emitIf(TernaryNode* ifNode) {
5092 IfEmitter ifThenElse(this);
5093
5094 if (!ifThenElse.emitIf(Some(ifNode->kid1()->pn_pos.begin))) {
5095 return false;
5096 }
5097
5098if_again:
5099 ParseNode* testNode = ifNode->kid1();
5100 auto conditionKind = IfEmitter::ConditionKind::Positive;
5101 if (testNode->isKind(ParseNodeKind::NotExpr)) {
5102 testNode = testNode->as<UnaryNode>().kid();
5103 conditionKind = IfEmitter::ConditionKind::Negative;
5104 }
5105
5106 if (!markStepBreakpoint()) {
5107 return false;
5108 }
5109
5110 // Emit code for the condition before pushing stmtInfo.
5111 // NOTE: NotExpr of testNode may be unwrapped, and in that case the negation
5112 // is handled by conditionKind.
5113 if (!emitTree(testNode)) {
5114 return false;
5115 }
5116
5117 ParseNode* elseNode = ifNode->kid3();
5118 if (elseNode) {
5119 if (!ifThenElse.emitThenElse(conditionKind)) {
5120 return false;
5121 }
5122 } else {
5123 if (!ifThenElse.emitThen(conditionKind)) {
5124 return false;
5125 }
5126 }
5127
5128 /* Emit code for the then part. */
5129 if (!emitTree(ifNode->kid2())) {
5130 return false;
5131 }
5132
5133 if (elseNode) {
5134 if (elseNode->isKind(ParseNodeKind::IfStmt)) {
5135 ifNode = &elseNode->as<TernaryNode>();
5136
5137 if (!ifThenElse.emitElseIf(Some(ifNode->kid1()->pn_pos.begin))) {
5138 return false;
5139 }
5140
5141 goto if_again;
5142 }
5143
5144 if (!ifThenElse.emitElse()) {
5145 return false;
5146 }
5147
5148 /* Emit code for the else part. */
5149 if (!emitTree(elseNode)) {
5150 return false;
5151 }
5152 }
5153
5154 if (!ifThenElse.emitEnd()) {
5155 return false;
5156 }
5157
5158 return true;
5159}
5160
5161bool BytecodeEmitter::emitHoistedFunctionsInList(ListNode* stmtList) {
5162 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5162); AnnotateMozCrashReason("MOZ_ASSERT" "(" "stmtList->hasTopLevelFunctionDeclarations()"
")"); do { *((volatile int*)__null) = 5162; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5163
5164 // We can call this multiple times for sloppy eval scopes.
5165 if (stmtList->emittedTopLevelFunctionDeclarations()) {
5166 return true;
5167 }
5168
5169 stmtList->setEmittedTopLevelFunctionDeclarations();
5170
5171 for (ParseNode* stmt : stmtList->contents()) {
5172 ParseNode* maybeFun = stmt;
5173
5174 if (!sc->strict()) {
5175 while (maybeFun->isKind(ParseNodeKind::LabelStmt)) {
5176 maybeFun = maybeFun->as<LabeledStatement>().statement();
5177 }
5178 }
5179
5180 if (maybeFun->is<FunctionNode>() &&
5181 maybeFun->as<FunctionNode>().functionIsHoisted()) {
5182 if (!emitTree(maybeFun)) {
5183 return false;
5184 }
5185 }
5186 }
5187
5188 return true;
5189}
5190
5191bool BytecodeEmitter::emitLexicalScopeBody(
5192 ParseNode* body, EmitLineNumberNote emitLineNote /* = EMIT_LINENOTE */) {
5193 if (body->isKind(ParseNodeKind::StatementList) &&
5194 body->as<ListNode>().hasTopLevelFunctionDeclarations()) {
5195 // This block contains function statements whose definitions are
5196 // hoisted to the top of the block. Emit these as a separate pass
5197 // before the rest of the block.
5198 if (!emitHoistedFunctionsInList(&body->as<ListNode>())) {
5199 return false;
5200 }
5201 }
5202
5203 // Line notes were updated by emitLexicalScope or emitScript.
5204 return emitTree(body, ValueUsage::WantValue, emitLineNote);
5205}
5206
5207// Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See
5208// the comment on emitSwitch.
5209MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitLexicalScope(
5210 LexicalScopeNode* lexicalScope) {
5211 LexicalScopeEmitter lse(this);
5212
5213 ParseNode* body = lexicalScope->scopeBody();
5214 if (lexicalScope->isEmptyScope()) {
5215 if (!lse.emitEmptyScope()) {
5216 return false;
5217 }
5218
5219 if (!emitLexicalScopeBody(body)) {
5220 return false;
5221 }
5222
5223 if (!lse.emitEnd()) {
5224 return false;
5225 }
5226
5227 return true;
5228 }
5229
5230 // We are about to emit some bytecode for what the spec calls "declaration
5231 // instantiation". Assign these instructions to the opening `{` of the
5232 // block. (Using the location of each declaration we're instantiating is
5233 // too weird when stepping in the debugger.)
5234 if (!ParseNodeRequiresSpecialLineNumberNotes(body)) {
5235 if (!updateSourceCoordNotes(lexicalScope->pn_pos.begin)) {
5236 return false;
5237 }
5238 }
5239
5240 ScopeKind kind;
5241 if (body->isKind(ParseNodeKind::Catch)) {
5242 BinaryNode* catchNode = &body->as<BinaryNode>();
5243 kind =
5244 (!catchNode->left() || catchNode->left()->isKind(ParseNodeKind::Name))
5245 ? ScopeKind::SimpleCatch
5246 : ScopeKind::Catch;
5247 } else {
5248 kind = lexicalScope->kind();
5249 }
5250
5251 if (!lse.emitScope(kind, lexicalScope->scopeBindings())) {
5252 return false;
5253 }
5254
5255 if (body->isKind(ParseNodeKind::ForStmt)) {
5256 // for loops need to emit JSOp::FreshenLexicalEnv/JSOp::RecreateLexicalEnv
5257 // if there are lexical declarations in the head. Signal this by passing a
5258 // non-nullptr lexical scope.
5259 if (!emitFor(&body->as<ForNode>(), &lse.emitterScope())) {
5260 return false;
5261 }
5262 } else {
5263 if (!emitLexicalScopeBody(body, SUPPRESS_LINENOTE)) {
5264 return false;
5265 }
5266 }
5267
5268 if (!lse.emitEnd()) {
5269 return false;
5270 }
5271 return true;
5272}
5273
5274bool BytecodeEmitter::emitWith(BinaryNode* withNode) {
5275 // Ensure that the column of the 'with' is set properly.
5276 if (!updateSourceCoordNotes(withNode->left()->pn_pos.begin)) {
5277 return false;
5278 }
5279
5280 if (!markStepBreakpoint()) {
5281 return false;
5282 }
5283
5284 if (!emitTree(withNode->left())) {
5285 return false;
5286 }
5287
5288 EmitterScope emitterScope(this);
5289 if (!emitterScope.enterWith(this)) {
5290 return false;
5291 }
5292
5293 if (!emitTree(withNode->right())) {
5294 return false;
5295 }
5296
5297 return emitterScope.leave(this);
5298}
5299
5300bool BytecodeEmitter::emitCopyDataProperties(CopyOption option) {
5301 DebugOnly<int32_t> depth = bytecodeSection().stackDepth();
5302
5303 uint32_t argc;
5304 if (option == CopyOption::Filtered) {
5305 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5305); AnnotateMozCrashReason("MOZ_ASSERT" "(" "depth > 2"
")"); do { *((volatile int*)__null) = 5305; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5306 // [stack] TARGET SOURCE SET
5307 argc = 3;
5308
5309 if (!emitAtomOp(JSOp::GetIntrinsic,
5310 TaggedParserAtomIndex::WellKnown::CopyDataProperties())) {
5311 // [stack] TARGET SOURCE SET COPYDATAPROPERTIES
5312 return false;
5313 }
5314 } else {
5315 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5315); AnnotateMozCrashReason("MOZ_ASSERT" "(" "depth > 1"
")"); do { *((volatile int*)__null) = 5315; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5316 // [stack] TARGET SOURCE
5317 argc = 2;
5318
5319 if (!emitAtomOp(
5320 JSOp::GetIntrinsic,
5321 TaggedParserAtomIndex::WellKnown::CopyDataPropertiesUnfiltered())) {
5322 // [stack] TARGET SOURCE COPYDATAPROPERTIES
5323 return false;
5324 }
5325 }
5326
5327 if (!emit1(JSOp::Undefined)) {
5328 // [stack] TARGET SOURCE SET? COPYDATAPROPERTIES
5329 // UNDEFINED
5330 return false;
5331 }
5332 if (!emit2(JSOp::Pick, argc + 1)) {
5333 // [stack] SOURCE SET? COPYDATAPROPERTIES UNDEFINED
5334 // TARGET
5335 return false;
5336 }
5337 if (!emit2(JSOp::Pick, argc + 1)) {
5338 // [stack] SET? COPYDATAPROPERTIES UNDEFINED TARGET
5339 // SOURCE
5340 return false;
5341 }
5342 if (option == CopyOption::Filtered) {
5343 if (!emit2(JSOp::Pick, argc + 1)) {
5344 // [stack] COPYDATAPROPERTIES UNDEFINED TARGET SOURCE SET
5345 return false;
5346 }
5347 }
5348 // Callee is always self-hosted instrinsic, and cannot be content function.
5349 if (!emitCall(JSOp::CallIgnoresRv, argc)) {
5350 // [stack] IGNORED
5351 return false;
5352 }
5353
5354 if (!emit1(JSOp::Pop)) {
5355 // [stack]
5356 return false;
5357 }
5358
5359 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5359); AnnotateMozCrashReason("MOZ_ASSERT" "(" "depth - int(argc) == bytecodeSection().stackDepth()"
")"); do { *((volatile int*)__null) = 5359; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5360 return true;
5361}
5362
5363bool BytecodeEmitter::emitBigIntOp(BigIntLiteral* bigint) {
5364 GCThingIndex index;
5365 if (!perScriptData().gcThingList().append(bigint, &index)) {
5366 return false;
5367 }
5368 return emitGCIndexOp(JSOp::BigInt, index);
5369}
5370
5371bool BytecodeEmitter::emitIterable(ParseNode* value,
5372 SelfHostedIter selfHostedIter,
5373 IteratorKind iterKind) {
5374 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5374); AnnotateMozCrashReason("MOZ_ASSERT" "(" "getSelfHostedIterFor(value) == selfHostedIter"
")"); do { *((volatile int*)__null) = 5374; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5375
5376 if (!emitTree(value)) {
5377 // [stack] ITERABLE
5378 return false;
5379 }
5380
5381 switch (selfHostedIter) {
5382 case SelfHostedIter::Deny:
5383 case SelfHostedIter::AllowContent:
5384 // [stack] ITERABLE
5385 return true;
5386
5387 case SelfHostedIter::AllowContentWith: {
5388 // This is the following case:
5389 //
5390 // for (const nextValue of allowContentIterWith(items, usingIterator)) {
5391 //
5392 // `items` is emitted by `emitTree(value)` above, and the result is on the
5393 // stack as ITERABLE.
5394 // `usingIterator` is the value of `items[Symbol.iterator]`, that's
5395 // already retrieved.
5396 ListNode* argsList = value->as<CallNode>().args();
5397 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5397); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2"
")"); do { *((volatile int*)__null) = 5397; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
5398 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5398); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 3"
")"); do { *((volatile int*)__null) = 5398; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
5399
5400 if (!emitTree(argsList->head()->pn_next)) {
5401 // [stack] ITERABLE ITERFN
5402 return false;
5403 }
5404
5405 // Async iterator has two possible iterators: An async iterator and a sync
5406 // iterator.
5407 if (iterKind == IteratorKind::Async) {
5408 if (!emitTree(argsList->head()->pn_next->pn_next)) {
5409 // [stack] ITERABLE ASYNC_ITERFN SYNC_ITERFN
5410 return false;
5411 }
5412 }
5413
5414 // [stack] ITERABLE ASYNC_ITERFN? SYNC_ITERFN
5415 return true;
5416 }
5417
5418 case SelfHostedIter::AllowContentWithNext: {
5419 // This is the following case:
5420 //
5421 // for (const nextValue of allowContentIterWithNext(iterator, next)) {
5422 //
5423 // `iterator` is emitted by `emitTree(value)` above, and the result is on
5424 // the stack as ITER.
5425 // `next` is the value of `iterator.next`, that's already retrieved.
5426 ListNode* argsList = value->as<CallNode>().args();
5427 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5427); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2"
")"); do { *((volatile int*)__null) = 5427; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5428
5429 if (!emitTree(argsList->head()->pn_next)) {
5430 // [stack] ITER NEXT
5431 return false;
5432 }
5433
5434 if (!emit1(JSOp::Swap)) {
5435 // [stack] NEXT ITER
5436 return false;
5437 }
5438
5439 // [stack] NEXT ITER
5440 return true;
5441 }
5442 }
5443
5444 MOZ_CRASH("invalid self-hosted iteration kind")do { do { } while (false); MOZ_ReportCrash("" "invalid self-hosted iteration kind"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5444); AnnotateMozCrashReason("MOZ_CRASH(" "invalid self-hosted iteration kind"
")"); do { *((volatile int*)__null) = 5444; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
5445}
5446
5447bool BytecodeEmitter::emitIterator(SelfHostedIter selfHostedIter) {
5448 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5451); 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
{ *((volatile int*)__null) = 5451; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
5449 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5451); 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
{ *((volatile int*)__null) = 5451; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
5450 "[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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5451); 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
{ *((volatile int*)__null) = 5451; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
5451 "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5451); 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
{ *((volatile int*)__null) = 5451; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
5452
5453 if (selfHostedIter == SelfHostedIter::AllowContentWithNext) {
5454 // [stack] NEXT ITER
5455
5456 // Nothing to do, stack already contains the iterator and its `next` method.
5457 return true;
5458 }
5459
5460 if (selfHostedIter != SelfHostedIter::AllowContentWith) {
5461 // [stack] OBJ
5462
5463 // Convert iterable to iterator.
5464 if (!emit1(JSOp::Dup)) {
5465 // [stack] OBJ OBJ
5466 return false;
5467 }
5468 if (!emit2(JSOp::Symbol, uint8_t(JS::SymbolCode::iterator))) {
5469 // [stack] OBJ OBJ @@ITERATOR
5470 return false;
5471 }
5472 if (!emitElemOpBase(JSOp::GetElem)) {
5473 // [stack] OBJ ITERFN
5474 return false;
5475 }
5476 }
5477
5478 if (!emit1(JSOp::Swap)) {
5479 // [stack] ITERFN OBJ
5480 return false;
5481 }
5482 if (!emitCall(getIterCallOp(JSOp::CallIter, selfHostedIter), 0)) {
5483 // [stack] ITER
5484 return false;
5485 }
5486 if (!emitCheckIsObj(CheckIsObjectKind::GetIterator)) {
5487 // [stack] ITER
5488 return false;
5489 }
5490 if (!emit1(JSOp::Dup)) {
5491 // [stack] ITER ITER
5492 return false;
5493 }
5494 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::next())) {
5495 // [stack] ITER NEXT
5496 return false;
5497 }
5498 if (!emit1(JSOp::Swap)) {
5499 // [stack] NEXT ITER
5500 return false;
5501 }
5502 return true;
5503}
5504
5505bool BytecodeEmitter::emitAsyncIterator(SelfHostedIter selfHostedIter) {
5506 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5506); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::AllowContentWithNext"
")"); do { *((volatile int*)__null) = 5506; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5507 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5510); 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
{ *((volatile int*)__null) = 5510; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
5508 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5510); 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
{ *((volatile int*)__null) = 5510; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
5509 "[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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5510); 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
{ *((volatile int*)__null) = 5510; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
5510 "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5510); 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
{ *((volatile int*)__null) = 5510; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
5511
5512 if (selfHostedIter != SelfHostedIter::AllowContentWith) {
5513 // [stack] OBJ
5514
5515 // Convert iterable to iterator.
5516 if (!emit1(JSOp::Dup)) {
5517 // [stack] OBJ OBJ
5518 return false;
5519 }
5520 if (!emit2(JSOp::Symbol, uint8_t(JS::SymbolCode::asyncIterator))) {
5521 // [stack] OBJ OBJ @@ASYNCITERATOR
5522 return false;
5523 }
5524 if (!emitElemOpBase(JSOp::GetElem)) {
5525 // [stack] OBJ ASYNC_ITERFN
5526 return false;
5527 }
5528 } else {
5529 // [stack] OBJ ASYNC_ITERFN SYNC_ITERFN
5530
5531 if (!emitElemOpBase(JSOp::Swap)) {
5532 // [stack] OBJ SYNC_ITERFN ASYNC_ITERFN
5533 return false;
5534 }
5535 }
5536
5537 InternalIfEmitter ifAsyncIterIsUndefined(this);
5538 if (!emit1(JSOp::IsNullOrUndefined)) {
5539 // [stack] OBJ SYNC_ITERFN? ASYNC_ITERFN NULL-OR-UNDEF
5540 return false;
5541 }
5542 if (!ifAsyncIterIsUndefined.emitThenElse()) {
5543 // [stack] OBJ SYNC_ITERFN? ASYNC_ITERFN
5544 return false;
5545 }
5546
5547 if (!emit1(JSOp::Pop)) {
5548 // [stack] OBJ SYNC_ITERFN?
5549 return false;
5550 }
5551
5552 if (selfHostedIter != SelfHostedIter::AllowContentWith) {
5553 if (!emit1(JSOp::Dup)) {
5554 // [stack] OBJ OBJ
5555 return false;
5556 }
5557 if (!emit2(JSOp::Symbol, uint8_t(JS::SymbolCode::iterator))) {
5558 // [stack] OBJ OBJ @@ITERATOR
5559 return false;
5560 }
5561 if (!emitElemOpBase(JSOp::GetElem)) {
5562 // [stack] OBJ SYNC_ITERFN
5563 return false;
5564 }
5565 } else {
5566 // [stack] OBJ SYNC_ITERFN
5567 }
5568
5569 if (!emit1(JSOp::Swap)) {
5570 // [stack] SYNC_ITERFN OBJ
5571 return false;
5572 }
5573 if (!emitCall(getIterCallOp(JSOp::CallIter, selfHostedIter), 0)) {
5574 // [stack] ITER
5575 return false;
5576 }
5577 if (!emitCheckIsObj(CheckIsObjectKind::GetIterator)) {
5578 // [stack] ITER
5579 return false;
5580 }
5581
5582 if (!emit1(JSOp::Dup)) {
5583 // [stack] ITER ITER
5584 return false;
5585 }
5586 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::next())) {
5587 // [stack] ITER SYNCNEXT
5588 return false;
5589 }
5590
5591 if (!emit1(JSOp::ToAsyncIter)) {
5592 // [stack] ITER
5593 return false;
5594 }
5595
5596 if (!ifAsyncIterIsUndefined.emitElse()) {
5597 // [stack] OBJ SYNC_ITERFN? ASYNC_ITERFN
5598 return false;
5599 }
5600
5601 if (selfHostedIter == SelfHostedIter::AllowContentWith) {
5602 if (!emit1(JSOp::Swap)) {
5603 // [stack] OBJ ASYNC_ITERFN SYNC_ITERFN
5604 return false;
5605 }
5606 if (!emit1(JSOp::Pop)) {
5607 // [stack] OBJ ASYNC_ITERFN
5608 return false;
5609 }
5610 }
5611
5612 if (!emit1(JSOp::Swap)) {
5613 // [stack] ASYNC_ITERFN OBJ
5614 return false;
5615 }
5616 if (!emitCall(getIterCallOp(JSOp::CallIter, selfHostedIter), 0)) {
5617 // [stack] ITER
5618 return false;
5619 }
5620 if (!emitCheckIsObj(CheckIsObjectKind::GetAsyncIterator)) {
5621 // [stack] ITER
5622 return false;
5623 }
5624
5625 if (!ifAsyncIterIsUndefined.emitEnd()) {
5626 // [stack] ITER
5627 return false;
5628 }
5629
5630 if (!emit1(JSOp::Dup)) {
5631 // [stack] ITER ITER
5632 return false;
5633 }
5634 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::next())) {
5635 // [stack] ITER NEXT
5636 return false;
5637 }
5638 if (!emit1(JSOp::Swap)) {
5639 // [stack] NEXT ITER
5640 return false;
5641 }
5642
5643 return true;
5644}
5645
5646bool BytecodeEmitter::emitSpread(SelfHostedIter selfHostedIter) {
5647 // [stack] NEXT ITER ARR I
5648 return emitSpread(selfHostedIter, 2, JSOp::InitElemInc);
5649 // [stack] ARR FINAL_INDEX
5650}
5651
5652bool BytecodeEmitter::emitSpread(SelfHostedIter selfHostedIter,
5653 int spreadeeStackItems, JSOp storeElementOp) {
5654 LoopControl loopInfo(this, StatementKind::Spread);
5655 // In the [stack] annotations, (spreadee) can be "ARR I" (when spreading
5656 // into an array or into call parameters, or "TUPLE" (when spreading into a
5657 // tuple)
5658
5659 if (!loopInfo.emitLoopHead(this, Nothing())) {
5660 // [stack] NEXT ITER (spreadee)
5661 return false;
5662 }
5663
5664 {
5665#ifdef DEBUG1
5666 auto loopDepth = bytecodeSection().stackDepth();
5667#endif
5668
5669 // Spread operations can't contain |continue|, so don't bother setting loop
5670 // and enclosing "update" offsets, as we do with for-loops.
5671
5672 if (!emitDupAt(spreadeeStackItems + 1, 2)) {
5673 // [stack] NEXT ITER (spreadee) NEXT ITER
5674 return false;
5675 }
5676 if (!emitIteratorNext(Nothing(), IteratorKind::Sync, selfHostedIter)) {
5677 // [stack] NEXT ITER (spreadee) RESULT
5678 return false;
5679 }
5680 if (!emit1(JSOp::Dup)) {
5681 // [stack] NEXT ITER (spreadee) RESULT RESULT
5682 return false;
5683 }
5684 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::done())) {
5685 // [stack] NEXT ITER (spreadee) RESULT DONE
5686 return false;
5687 }
5688 if (!emitJump(JSOp::JumpIfTrue, &loopInfo.breaks)) {
5689 // [stack] NEXT ITER (spreadee) RESULT
5690 return false;
5691 }
5692
5693 // Emit code to assign result.value to the iteration variable.
5694 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::value())) {
5695 // [stack] NEXT ITER (spreadee) VALUE
5696 return false;
5697 }
5698 if (!emit1(storeElementOp)) {
5699 // [stack] NEXT ITER (spreadee)
5700 return false;
5701 }
5702
5703 if (!loopInfo.emitLoopEnd(this, JSOp::Goto, TryNoteKind::ForOf)) {
5704 // [stack] NEXT ITER (spreadee)
5705 return false;
5706 }
5707
5708 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5708); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == loopDepth"
")"); do { *((volatile int*)__null) = 5708; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5709 }
5710
5711 // When we leave the loop body and jump to this point, the result value is
5712 // still on the stack. Account for that by updating the stack depth
5713 // manually.
5714 bytecodeSection().setStackDepth(bytecodeSection().stackDepth() + 1);
5715
5716 // No continues should occur in spreads.
5717 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()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5717); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!loopInfo.continues.offset.valid()"
")"); do { *((volatile int*)__null) = 5717; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5718
5719 if (!emit2(JSOp::Pick, spreadeeStackItems + 2)) {
5720 // [stack] ITER (spreadee) RESULT NEXT
5721 return false;
5722 }
5723 if (!emit2(JSOp::Pick, spreadeeStackItems + 2)) {
5724 // [stack] (spreadee) RESULT NEXT ITER
5725 return false;
5726 }
5727
5728 return emitPopN(3);
5729 // [stack] (spreadee)
5730}
5731
5732bool BytecodeEmitter::emitInitializeForInOrOfTarget(TernaryNode* forHead) {
5733 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5734); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forHead->isKind(ParseNodeKind::ForIn) || forHead->isKind(ParseNodeKind::ForOf)"
")"); do { *((volatile int*)__null) = 5734; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5734 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5734); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forHead->isKind(ParseNodeKind::ForIn) || forHead->isKind(ParseNodeKind::ForOf)"
")"); do { *((volatile int*)__null) = 5734; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5735
5736 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" ")",
"/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5737); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() >= 1"
") (" "must have a per-iteration value for initializing" ")"
); do { *((volatile int*)__null) = 5737; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5737 "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" ")",
"/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5737); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() >= 1"
") (" "must have a per-iteration value for initializing" ")"
); do { *((volatile int*)__null) = 5737; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5738
5739 ParseNode* target = forHead->kid1();
5740 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5740); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!forHead->kid2()"
")"); do { *((volatile int*)__null) = 5740; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5741
5742 // If the for-in/of loop didn't have a variable declaration, per-loop
5743 // initialization is just assigning the iteration value to a target
5744 // expression.
5745 if (!target->is<DeclarationListNode>()) {
5746 return emitAssignmentOrInit(ParseNodeKind::AssignExpr, target, nullptr);
5747 // [stack] ... ITERVAL
5748 }
5749
5750 // Otherwise, per-loop initialization is (possibly) declaration
5751 // initialization. If the declaration is a lexical declaration, it must be
5752 // initialized. If the declaration is a variable declaration, an
5753 // assignment to that name (which does *not* necessarily assign to the
5754 // variable!) must be generated.
5755
5756 auto* declarationList = &target->as<DeclarationListNode>();
5757 if (!updateSourceCoordNotes(declarationList->pn_pos.begin)) {
5758 return false;
5759 }
5760
5761 target = declarationList->singleBinding();
5762
5763 NameNode* nameNode = nullptr;
5764 if (target->isKind(ParseNodeKind::Name)) {
5765 nameNode = &target->as<NameNode>();
5766 } else if (target->isKind(ParseNodeKind::AssignExpr)) {
5767 BinaryNode* assignNode = &target->as<BinaryNode>();
5768 if (assignNode->left()->is<NameNode>()) {
5769 nameNode = &assignNode->left()->as<NameNode>();
5770 }
5771 }
5772
5773 if (nameNode) {
5774 auto nameAtom = nameNode->name();
5775 NameOpEmitter noe(this, nameAtom, NameOpEmitter::Kind::Initialize);
5776 if (!noe.prepareForRhs()) {
5777 return false;
5778 }
5779 if (noe.emittedBindOp()) {
5780 // Per-iteration initialization in for-in/of loops computes the
5781 // iteration value *before* initializing. Thus the initializing
5782 // value may be buried under a bind-specific value on the stack.
5783 // Swap it to the top of the stack.
5784 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5784); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() >= 2"
")"); do { *((volatile int*)__null) = 5784; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5785 if (!emit1(JSOp::Swap)) {
5786 return false;
5787 }
5788 } else {
5789 // In cases of emitting a frame slot or environment slot,
5790 // nothing needs be done.
5791 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5791); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() >= 1"
")"); do { *((volatile int*)__null) = 5791; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5792 }
5793
5794#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
5795 if (declarationList->isKind(ParseNodeKind::UsingDecl)) {
5796 if (!innermostEmitterScope()->prepareForDisposableAssignment(
5797 UsingHint::Sync)) {
5798 // [stack] ENV? V
5799 return false;
5800 }
5801 } else if (declarationList->isKind(ParseNodeKind::AwaitUsingDecl)) {
5802 if (!innermostEmitterScope()->prepareForDisposableAssignment(
5803 UsingHint::Async)) {
5804 // [stack] ENV? V
5805 return false;
5806 }
5807 }
5808#endif
5809
5810 if (!noe.emitAssignment()) {
5811 return false;
5812 }
5813
5814 // The caller handles removing the iteration value from the stack.
5815 return true;
5816 }
5817
5818 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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5820); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!target->isKind(ParseNodeKind::AssignExpr)"
") (" "for-in/of loop destructuring declarations can't have initializers"
")"); do { *((volatile int*)__null) = 5820; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5819 !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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5820); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!target->isKind(ParseNodeKind::AssignExpr)"
") (" "for-in/of loop destructuring declarations can't have initializers"
")"); do { *((volatile int*)__null) = 5820; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5820 "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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5820); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!target->isKind(ParseNodeKind::AssignExpr)"
") (" "for-in/of loop destructuring declarations can't have initializers"
")"); do { *((volatile int*)__null) = 5820; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5821
5822 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5823); AnnotateMozCrashReason("MOZ_ASSERT" "(" "target->isKind(ParseNodeKind::ArrayExpr) || target->isKind(ParseNodeKind::ObjectExpr)"
")"); do { *((volatile int*)__null) = 5823; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5823 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5823); AnnotateMozCrashReason("MOZ_ASSERT" "(" "target->isKind(ParseNodeKind::ArrayExpr) || target->isKind(ParseNodeKind::ObjectExpr)"
")"); do { *((volatile int*)__null) = 5823; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5824 return emitDestructuringOps(&target->as<ListNode>(),
5825 DestructuringFlavor::Declaration);
5826}
5827
5828bool BytecodeEmitter::emitForOf(ForNode* forOfLoop,
5829 const EmitterScope* headLexicalEmitterScope) {
5830 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5830); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfLoop->isKind(ParseNodeKind::ForStmt)"
")"); do { *((volatile int*)__null) = 5830; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5831
5832 TernaryNode* forOfHead = forOfLoop->head();
5833 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5833); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfHead->isKind(ParseNodeKind::ForOf)"
")"); do { *((volatile int*)__null) = 5833; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5834
5835 unsigned iflags = forOfLoop->iflags();
5836 IteratorKind iterKind =
5837 (iflags & JSITER_FORAWAITOF0x80) ? IteratorKind::Async : IteratorKind::Sync;
5838 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()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5838); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isSuspendableContext()"
")"); do { *((volatile int*)__null) = 5838; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
5839 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()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5840); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->asSuspendableContext()->isAsync()"
")"); do { *((volatile int*)__null) = 5840; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
5840 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()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5840); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->asSuspendableContext()->isAsync()"
")"); do { *((volatile int*)__null) = 5840; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
5841
5842 ParseNode* forHeadExpr = forOfHead->kid3();
5843
5844 // Certain builtins (e.g. Array.from) are implemented in self-hosting
5845 // as for-of loops.
5846 auto selfHostedIter = getSelfHostedIterFor(forHeadExpr);
5847 ForOfEmitter forOf(
5848 this, headLexicalEmitterScope, selfHostedIter, iterKind
5849#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
5850 ,
5851 forOfHead->kid1()->isKind(ParseNodeKind::UsingDecl) ||
5852 forOfHead->kid1()->isKind(ParseNodeKind::AwaitUsingDecl)
5853 ? ForOfEmitter::HasUsingDeclarationInHead::Yes
5854 : ForOfEmitter::HasUsingDeclarationInHead::No
5855#endif
5856 );
5857
5858 if (!forOf.emitIterated()) {
5859 // [stack]
5860 return false;
5861 }
5862
5863 if (!updateSourceCoordNotes(forHeadExpr->pn_pos.begin)) {
5864 return false;
5865 }
5866 if (!markStepBreakpoint()) {
5867 return false;
5868 }
5869 if (!emitIterable(forHeadExpr, selfHostedIter, iterKind)) {
5870 // [stack] ITERABLE
5871 return false;
5872 }
5873
5874 if (headLexicalEmitterScope) {
5875 DebugOnly<ParseNode*> forOfTarget = forOfHead->kid1();
5876 MOZ_ASSERT(forOfTarget->isKind(ParseNodeKind::LetDecl) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget
->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
|| forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget
->isKind(ParseNodeKind::AwaitUsingDecl)endif)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget
->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
|| forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget
->isKind(ParseNodeKind::AwaitUsingDecl)endif))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)endif"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5882); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)endif"
")"); do { *((volatile int*)__null) = 5882; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5877 forOfTarget->isKind(ParseNodeKind::ConstDecl)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget
->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
|| forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget
->isKind(ParseNodeKind::AwaitUsingDecl)endif)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget
->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
|| forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget
->isKind(ParseNodeKind::AwaitUsingDecl)endif))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)endif"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5882); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)endif"
")"); do { *((volatile int*)__null) = 5882; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5878#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENTdo { static_assert( mozilla::detail::AssertionConditionType<
decltype(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget
->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
|| forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget
->isKind(ParseNodeKind::AwaitUsingDecl)endif)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget
->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
|| forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget
->isKind(ParseNodeKind::AwaitUsingDecl)endif))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)endif"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5882); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)endif"
")"); do { *((volatile int*)__null) = 5882; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5879 || forOfTarget->isKind(ParseNodeKind::UsingDecl) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget
->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
|| forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget
->isKind(ParseNodeKind::AwaitUsingDecl)endif)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget
->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
|| forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget
->isKind(ParseNodeKind::AwaitUsingDecl)endif))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)endif"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5882); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)endif"
")"); do { *((volatile int*)__null) = 5882; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5880 forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget
->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
|| forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget
->isKind(ParseNodeKind::AwaitUsingDecl)endif)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget
->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
|| forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget
->isKind(ParseNodeKind::AwaitUsingDecl)endif))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)endif"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5882); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)endif"
")"); do { *((volatile int*)__null) = 5882; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5881#endifdo { static_assert( mozilla::detail::AssertionConditionType<
decltype(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget
->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
|| forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget
->isKind(ParseNodeKind::AwaitUsingDecl)endif)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget
->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
|| forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget
->isKind(ParseNodeKind::AwaitUsingDecl)endif))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)endif"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5882); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)endif"
")"); do { *((volatile int*)__null) = 5882; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5882 )do { static_assert( mozilla::detail::AssertionConditionType<
decltype(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget
->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
|| forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget
->isKind(ParseNodeKind::AwaitUsingDecl)endif)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget
->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
|| forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget
->isKind(ParseNodeKind::AwaitUsingDecl)endif))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)endif"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5882); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)endif"
")"); do { *((volatile int*)__null) = 5882; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5883 }
5884
5885 if (!forOf.emitInitialize(forOfHead->pn_pos.begin)) {
5886 // [stack] NEXT ITER VALUE
5887 return false;
5888 }
5889
5890 if (!emitInitializeForInOrOfTarget(forOfHead)) {
5891 // [stack] NEXT ITER VALUE
5892 return false;
5893 }
5894
5895 if (!forOf.emitBody()) {
5896 // [stack] NEXT ITER UNDEF
5897 return false;
5898 }
5899
5900 // Perform the loop body.
5901 ParseNode* forBody = forOfLoop->body();
5902 if (!emitTree(forBody)) {
5903 // [stack] NEXT ITER UNDEF
5904 return false;
5905 }
5906
5907 if (!forOf.emitEnd(forHeadExpr->pn_pos.begin)) {
5908 // [stack]
5909 return false;
5910 }
5911
5912 return true;
5913}
5914
5915bool BytecodeEmitter::emitForIn(ForNode* forInLoop,
5916 const EmitterScope* headLexicalEmitterScope) {
5917 TernaryNode* forInHead = forInLoop->head();
5918 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5918); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInHead->isKind(ParseNodeKind::ForIn)"
")"); do { *((volatile int*)__null) = 5918; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5919
5920 ForInEmitter forIn(this, headLexicalEmitterScope);
5921
5922 // Annex B: Evaluate the var-initializer expression if present.
5923 // |for (var i = initializer in expr) { ... }|
5924 ParseNode* forInTarget = forInHead->kid1();
5925 if (forInTarget->is<DeclarationListNode>()) {
5926 auto* declarationList = &forInTarget->as<DeclarationListNode>();
5927
5928 ParseNode* decl = declarationList->singleBinding();
5929 if (decl->isKind(ParseNodeKind::AssignExpr)) {
5930 BinaryNode* assignNode = &decl->as<BinaryNode>();
5931 if (assignNode->left()->is<NameNode>()) {
5932 NameNode* nameNode = &assignNode->left()->as<NameNode>();
5933 ParseNode* initializer = assignNode->right();
5934 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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5936); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInTarget->isKind(ParseNodeKind::VarStmt)"
") (" "for-in initializers are only permitted for |var| declarations"
")"); do { *((volatile int*)__null) = 5936; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5935 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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5936); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInTarget->isKind(ParseNodeKind::VarStmt)"
") (" "for-in initializers are only permitted for |var| declarations"
")"); do { *((volatile int*)__null) = 5936; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5936 "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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5936); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInTarget->isKind(ParseNodeKind::VarStmt)"
") (" "for-in initializers are only permitted for |var| declarations"
")"); do { *((volatile int*)__null) = 5936; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5937
5938 if (!updateSourceCoordNotes(decl->pn_pos.begin)) {
5939 return false;
5940 }
5941
5942 auto nameAtom = nameNode->name();
5943 NameOpEmitter noe(this, nameAtom, NameOpEmitter::Kind::Initialize);
5944 if (!noe.prepareForRhs()) {
5945 return false;
5946 }
5947 if (!emitInitializer(initializer, nameNode)) {
5948 return false;
5949 }
5950 if (!noe.emitAssignment()) {
5951 return false;
5952 }
5953
5954 // Pop the initializer.
5955 if (!emit1(JSOp::Pop)) {
5956 return false;
5957 }
5958 }
5959 }
5960 }
5961
5962 if (!forIn.emitIterated()) {
5963 // [stack]
5964 return false;
5965 }
5966
5967 // Evaluate the expression being iterated.
5968 ParseNode* expr = forInHead->kid3();
5969
5970 if (!updateSourceCoordNotes(expr->pn_pos.begin)) {
5971 return false;
5972 }
5973 if (!markStepBreakpoint()) {
5974 return false;
5975 }
5976 if (!emitTree(expr)) {
5977 // [stack] EXPR
5978 return false;
5979 }
5980
5981 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5981); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInLoop->iflags() == 0"
")"); do { *((volatile int*)__null) = 5981; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5982
5983 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5985); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInTarget->isKind(ParseNodeKind::LetDecl) || forInTarget->isKind(ParseNodeKind::ConstDecl)"
")"); do { *((volatile int*)__null) = 5985; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
5984 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5985); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInTarget->isKind(ParseNodeKind::LetDecl) || forInTarget->isKind(ParseNodeKind::ConstDecl)"
")"); do { *((volatile int*)__null) = 5985; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
5985 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5985); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInTarget->isKind(ParseNodeKind::LetDecl) || forInTarget->isKind(ParseNodeKind::ConstDecl)"
")"); do { *((volatile int*)__null) = 5985; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
5986
5987 if (!forIn.emitInitialize()) {
5988 // [stack] ITER ITERVAL
5989 return false;
5990 }
5991
5992 if (!emitInitializeForInOrOfTarget(forInHead)) {
5993 // [stack] ITER ITERVAL
5994 return false;
5995 }
5996
5997 if (!forIn.emitBody()) {
5998 // [stack] ITER ITERVAL
5999 return false;
6000 }
6001
6002 // Perform the loop body.
6003 ParseNode* forBody = forInLoop->body();
6004 if (!emitTree(forBody)) {
6005 // [stack] ITER ITERVAL
6006 return false;
6007 }
6008
6009 if (!forIn.emitEnd(forInHead->pn_pos.begin)) {
6010 // [stack]
6011 return false;
6012 }
6013
6014 return true;
6015}
6016
6017/* C-style `for (init; cond; update) ...` loop. */
6018bool BytecodeEmitter::emitCStyleFor(
6019 ForNode* forNode, const EmitterScope* headLexicalEmitterScope) {
6020 TernaryNode* forHead = forNode->head();
6021 ParseNode* forBody = forNode->body();
6022 ParseNode* init = forHead->kid1();
6023 ParseNode* cond = forHead->kid2();
6024 ParseNode* update = forHead->kid3();
6025 bool isLet = init && init->isKind(ParseNodeKind::LetDecl);
6026
6027 CForEmitter cfor(this, isLet ? headLexicalEmitterScope : nullptr);
6028
6029 if (!cfor.emitInit(init ? Some(init->pn_pos.begin) : Nothing())) {
6030 // [stack]
6031 return false;
6032 }
6033
6034 // If the head of this for-loop declared any lexical variables, the parser
6035 // wrapped this ParseNodeKind::For node in a ParseNodeKind::LexicalScope
6036 // representing the implicit scope of those variables. By the time we get
6037 // here, we have already entered that scope. So far, so good.
6038 if (init) {
6039 // Emit the `init` clause, whether it's an expression or a variable
6040 // declaration. (The loop variables were hoisted into an enclosing
6041 // scope, but we still need to emit code for the initializers.)
6042 if (init->is<DeclarationListNode>()) {
6043 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6043); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!init->as<DeclarationListNode>().empty()"
")"); do { *((volatile int*)__null) = 6043; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6044
6045 if (!emitTree(init)) {
6046 // [stack]
6047 return false;
6048 }
6049 } else {
6050 if (!updateSourceCoordNotes(init->pn_pos.begin)) {
6051 return false;
6052 }
6053 if (!markStepBreakpoint()) {
6054 return false;
6055 }
6056
6057 // 'init' is an expression, not a declaration. emitTree left its
6058 // value on the stack.
6059 if (!emitTree(init, ValueUsage::IgnoreValue)) {
6060 // [stack] VAL
6061 return false;
6062 }
6063 if (!emit1(JSOp::Pop)) {
6064 // [stack]
6065 return false;
6066 }
6067 }
6068 }
6069
6070 if (!cfor.emitCond(cond ? Some(cond->pn_pos.begin) : Nothing())) {
6071 // [stack]
6072 return false;
6073 }
6074
6075 if (cond) {
6076 if (!updateSourceCoordNotes(cond->pn_pos.begin)) {
6077 return false;
6078 }
6079 if (!markStepBreakpoint()) {
6080 return false;
6081 }
6082 if (!emitTree(cond)) {
6083 // [stack] VAL
6084 return false;
6085 }
6086 }
6087
6088 if (!cfor.emitBody(cond ? CForEmitter::Cond::Present
6089 : CForEmitter::Cond::Missing)) {
6090 // [stack]
6091 return false;
6092 }
6093
6094 if (!emitTree(forBody)) {
6095 // [stack]
6096 return false;
6097 }
6098
6099 if (!cfor.emitUpdate(
6100 update ? CForEmitter::Update::Present : CForEmitter::Update::Missing,
6101 update ? Some(update->pn_pos.begin) : Nothing())) {
6102 // [stack]
6103 return false;
6104 }
6105
6106 // Check for update code to do before the condition (if any).
6107 if (update) {
6108 if (!updateSourceCoordNotes(update->pn_pos.begin)) {
6109 return false;
6110 }
6111 if (!markStepBreakpoint()) {
6112 return false;
6113 }
6114 if (!emitTree(update, ValueUsage::IgnoreValue)) {
6115 // [stack] VAL
6116 return false;
6117 }
6118 }
6119
6120 if (!cfor.emitEnd(forNode->pn_pos.begin)) {
6121 // [stack]
6122 return false;
6123 }
6124
6125 return true;
6126}
6127
6128bool BytecodeEmitter::emitFor(ForNode* forNode,
6129 const EmitterScope* headLexicalEmitterScope) {
6130 if (forNode->head()->isKind(ParseNodeKind::ForHead)) {
6131 return emitCStyleFor(forNode, headLexicalEmitterScope);
6132 }
6133
6134 if (!updateLineNumberNotes(forNode->pn_pos.begin)) {
6135 return false;
6136 }
6137
6138 if (forNode->head()->isKind(ParseNodeKind::ForIn)) {
6139 return emitForIn(forNode, headLexicalEmitterScope);
6140 }
6141
6142 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6142); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forNode->head()->isKind(ParseNodeKind::ForOf)"
")"); do { *((volatile int*)__null) = 6142; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6143 return emitForOf(forNode, headLexicalEmitterScope);
6144}
6145
6146MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitFunction(
6147 FunctionNode* funNode, bool needsProto /* = false */) {
6148 FunctionBox* funbox = funNode->funbox();
6149
6150 // [stack]
6151
6152 FunctionEmitter fe(this, funbox, funNode->syntaxKind(),
6153 funNode->functionIsHoisted()
6154 ? FunctionEmitter::IsHoisted::Yes
6155 : FunctionEmitter::IsHoisted::No);
6156
6157 // |wasEmittedByEnclosingScript| flag is set to true once the function has
6158 // been emitted. Function definitions that need hoisting to the top of the
6159 // function will be seen by emitFunction in two places.
6160 if (funbox->wasEmittedByEnclosingScript()) {
6161 if (!fe.emitAgain()) {
6162 // [stack]
6163 return false;
6164 }
6165 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()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6165); AnnotateMozCrashReason("MOZ_ASSERT" "(" "funNode->functionIsHoisted()"
")"); do { *((volatile int*)__null) = 6165; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6166 } else if (funbox->isInterpreted()) {
6167 if (!funbox->emitBytecode) {
6168 return fe.emitLazy();
6169 // [stack] FUN?
6170 }
6171
6172 if (!fe.prepareForNonLazy()) {
6173 // [stack]
6174 return false;
6175 }
6176
6177 BytecodeEmitter bce2(this, funbox);
6178 if (!bce2.init(funNode->pn_pos)) {
6179 return false;
6180 }
6181
6182 /* We measured the max scope depth when we parsed the function. */
6183 if (!bce2.emitFunctionScript(funNode)) {
6184 return false;
6185 }
6186
6187 if (!fe.emitNonLazyEnd()) {
6188 // [stack] FUN?
6189 return false;
6190 }
6191 } else {
6192 if (!fe.emitAsmJSModule()) {
6193 // [stack]
6194 return false;
6195 }
6196 }
6197
6198 // Track the last emitted top-level self-hosted function, so that intrinsics
6199 // can adjust attributes at parse time.
6200 //
6201 // NOTE: We also disallow lambda functions in the top-level body. This is done
6202 // to simplify handling of the self-hosted stencil. Within normal function
6203 // declarations there are no such restrictions.
6204 if (emitterMode == EmitterMode::SelfHosting) {
6205 if (sc->isTopLevelContext()) {
6206 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6206); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!funbox->isLambda()"
")"); do { *((volatile int*)__null) = 6206; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6207 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6207); AnnotateMozCrashReason("MOZ_ASSERT" "(" "funbox->explicitName()"
")"); do { *((volatile int*)__null) = 6207; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6208 prevSelfHostedTopLevelFunction = funbox;
6209 }
6210 }
6211
6212 return true;
6213}
6214
6215bool BytecodeEmitter::emitDo(BinaryNode* doNode) {
6216 ParseNode* bodyNode = doNode->left();
6217
6218 DoWhileEmitter doWhile(this);
6219 if (!doWhile.emitBody(doNode->pn_pos.begin, getOffsetForLoop(bodyNode))) {
6220 return false;
6221 }
6222
6223 if (!emitTree(bodyNode)) {
6224 return false;
6225 }
6226
6227 if (!doWhile.emitCond()) {
6228 return false;
6229 }
6230
6231 ParseNode* condNode = doNode->right();
6232 if (!updateSourceCoordNotes(condNode->pn_pos.begin)) {
6233 return false;
6234 }
6235 if (!markStepBreakpoint()) {
6236 return false;
6237 }
6238 if (!emitTree(condNode)) {
6239 return false;
6240 }
6241
6242 if (!doWhile.emitEnd()) {
6243 return false;
6244 }
6245
6246 return true;
6247}
6248
6249bool BytecodeEmitter::emitWhile(BinaryNode* whileNode) {
6250 ParseNode* bodyNode = whileNode->right();
6251
6252 WhileEmitter wh(this);
6253
6254 ParseNode* condNode = whileNode->left();
6255 if (!wh.emitCond(whileNode->pn_pos.begin, getOffsetForLoop(condNode),
6256 whileNode->pn_pos.end)) {
6257 return false;
6258 }
6259
6260 if (!updateSourceCoordNotes(condNode->pn_pos.begin)) {
6261 return false;
6262 }
6263 if (!markStepBreakpoint()) {
6264 return false;
6265 }
6266 if (!emitTree(condNode)) {
6267 return false;
6268 }
6269
6270 if (!wh.emitBody()) {
6271 return false;
6272 }
6273 if (!emitTree(bodyNode)) {
6274 return false;
6275 }
6276
6277 if (!wh.emitEnd()) {
6278 return false;
6279 }
6280
6281 return true;
6282}
6283
6284bool BytecodeEmitter::emitBreak(TaggedParserAtomIndex label) {
6285 BreakableControl* target;
6286 if (label) {
6287 // Any statement with the matching label may be the break target.
6288 auto hasSameLabel = [label](LabelControl* labelControl) {
6289 return labelControl->label() == label;
6290 };
6291 target = findInnermostNestableControl<LabelControl>(hasSameLabel);
6292 } else {
6293 auto isNotLabel = [](BreakableControl* control) {
6294 return !control->is<LabelControl>();
6295 };
6296 target = findInnermostNestableControl<BreakableControl>(isNotLabel);
6297 }
6298
6299 return emitGoto(target, GotoKind::Break);
6300}
6301
6302bool BytecodeEmitter::emitContinue(TaggedParserAtomIndex label) {
6303 LoopControl* target = nullptr;
6304 if (label) {
6305 // Find the loop statement enclosed by the matching label.
6306 NestableControl* control = innermostNestableControl;
6307 while (!control->is<LabelControl>() ||
6308 control->as<LabelControl>().label() != label) {
6309 if (control->is<LoopControl>()) {
6310 target = &control->as<LoopControl>();
6311 }
6312 control = control->enclosing();
6313 }
6314 } else {
6315 target = findInnermostNestableControl<LoopControl>();
6316 }
6317 return emitGoto(target, GotoKind::Continue);
6318}
6319
6320bool BytecodeEmitter::emitGetFunctionThis(NameNode* thisName) {
6321 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()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6321); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->hasFunctionThisBinding()"
")"); do { *((volatile int*)__null) = 6321; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6322 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_())"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6322); AnnotateMozCrashReason("MOZ_ASSERT" "(" "thisName->isName(TaggedParserAtomIndex::WellKnown::dot_this_())"
")"); do { *((volatile int*)__null) = 6322; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6323
6324 if (!updateLineNumberNotes(thisName->pn_pos.begin)) {
6325 return false;
6326 }
6327
6328 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_this_())) {
6329 // [stack] THIS
6330 return false;
6331 }
6332 if (sc->needsThisTDZChecks()) {
6333 if (!emit1(JSOp::CheckThis)) {
6334 // [stack] THIS
6335 return false;
6336 }
6337 }
6338
6339 return true;
6340}
6341
6342bool BytecodeEmitter::emitGetThisForSuperBase(UnaryNode* superBase) {
6343 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6343); AnnotateMozCrashReason("MOZ_ASSERT" "(" "superBase->isKind(ParseNodeKind::SuperBase)"
")"); do { *((volatile int*)__null) = 6343; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6344 NameNode* nameNode = &superBase->kid()->as<NameNode>();
6345 return emitGetFunctionThis(nameNode);
6346 // [stack] THIS
6347}
6348
6349bool BytecodeEmitter::emitThisLiteral(ThisLiteral* pn) {
6350 if (ParseNode* kid = pn->kid()) {
6351 NameNode* thisName = &kid->as<NameNode>();
6352 return emitGetFunctionThis(thisName);
6353 // [stack] THIS
6354 }
6355
6356 if (sc->thisBinding() == ThisBinding::Module) {
6357 return emit1(JSOp::Undefined);
6358 // [stack] UNDEF
6359 }
6360
6361 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6361); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->thisBinding() == ThisBinding::Global"
")"); do { *((volatile int*)__null) = 6361; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6362
6363 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6364); AnnotateMozCrashReason("MOZ_ASSERT" "(" "outermostScope().hasNonSyntacticScopeOnChain() == sc->hasNonSyntacticScope()"
")"); do { *((volatile int*)__null) = 6364; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6364 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6364); AnnotateMozCrashReason("MOZ_ASSERT" "(" "outermostScope().hasNonSyntacticScopeOnChain() == sc->hasNonSyntacticScope()"
")"); do { *((volatile int*)__null) = 6364; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6365 if (sc->hasNonSyntacticScope()) {
6366 return emit1(JSOp::NonSyntacticGlobalThis);
6367 // [stack] THIS
6368 }
6369
6370 return emit1(JSOp::GlobalThis);
6371 // [stack] THIS
6372}
6373
6374bool BytecodeEmitter::emitCheckDerivedClassConstructorReturn() {
6375 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6376); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lookupName(TaggedParserAtomIndex::WellKnown::dot_this_()).hasKnownSlot()"
")"); do { *((volatile int*)__null) = 6376; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6376 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6376); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lookupName(TaggedParserAtomIndex::WellKnown::dot_this_()).hasKnownSlot()"
")"); do { *((volatile int*)__null) = 6376; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6377 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_this_())) {
6378 return false;
6379 }
6380 if (!emit1(JSOp::CheckReturn)) {
6381 return false;
6382 }
6383 if (!emit1(JSOp::SetRval)) {
6384 return false;
6385 }
6386 return true;
6387}
6388
6389bool BytecodeEmitter::emitNewTarget() {
6390 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6390); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->allowNewTarget()"
")"); do { *((volatile int*)__null) = 6390; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6391
6392 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_newTarget_())) {
6393 // [stack] NEW.TARGET
6394 return false;
6395 }
6396 return true;
6397}
6398
6399bool BytecodeEmitter::emitNewTarget(NewTargetNode* pn) {
6400 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_())"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6401); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->newTargetName()->isName( TaggedParserAtomIndex::WellKnown::dot_newTarget_())"
")"); do { *((volatile int*)__null) = 6401; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6401 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_())"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6401); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->newTargetName()->isName( TaggedParserAtomIndex::WellKnown::dot_newTarget_())"
")"); do { *((volatile int*)__null) = 6401; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6402
6403 return emitNewTarget();
6404}
6405
6406bool BytecodeEmitter::emitNewTarget(CallNode* pn) {
6407 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6408); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->callOp() == JSOp::SuperCall || pn->callOp() == JSOp::SpreadSuperCall"
")"); do { *((volatile int*)__null) = 6408; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6408 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6408); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->callOp() == JSOp::SuperCall || pn->callOp() == JSOp::SpreadSuperCall"
")"); do { *((volatile int*)__null) = 6408; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6409
6410 // The parser is responsible for marking the "new.target" binding as being
6411 // implicitly used in super() calls.
6412 return emitNewTarget();
6413}
6414
6415bool BytecodeEmitter::emitReturn(UnaryNode* returnNode) {
6416 if (!updateSourceCoordNotes(returnNode->pn_pos.begin)) {
6417 return false;
6418 }
6419
6420 if (!markStepBreakpoint()) {
6421 return false;
6422 }
6423
6424 /* Push a return value */
6425 if (ParseNode* expr = returnNode->kid()) {
6426 if (!emitTree(expr)) {
6427 return false;
6428 }
6429
6430 if (sc->asSuspendableContext()->isAsync() &&
6431 sc->asSuspendableContext()->isGenerator()) {
6432 if (!emitAwaitInInnermostScope()) {
6433 return false;
6434 }
6435 }
6436 } else {
6437 /* No explicit return value provided */
6438 if (!emit1(JSOp::Undefined)) {
6439 return false;
6440 }
6441 }
6442
6443 // We know functionBodyEndPos is set because "return" is only
6444 // valid in a function, and so we've passed through
6445 // emitFunctionScript.
6446 if (!updateSourceCoordNotes(*functionBodyEndPos)) {
6447 return false;
6448 }
6449
6450 /*
6451 * The return value is currently on the stack. We would like to
6452 * generate JSOp::Return, but if we have work to do before returning,
6453 * we will instead generate JSOp::SetRval / JSOp::RetRval.
6454 *
6455 * We don't know whether we will need fixup code until after calling
6456 * prepareForNonLocalJumpToOutermost, so we start by generating
6457 * JSOp::SetRval, then mutate it to JSOp::Return in finishReturn if it
6458 * wasn't needed.
6459 */
6460 BytecodeOffset setRvalOffset = bytecodeSection().offset();
6461 if (!emit1(JSOp::SetRval)) {
6462 return false;
6463 }
6464
6465 NonLocalExitControl nle(this, NonLocalExitKind::Return);
6466 return nle.emitReturn(setRvalOffset);
6467}
6468
6469bool BytecodeEmitter::finishReturn(BytecodeOffset setRvalOffset) {
6470 // The return value is currently in rval. Depending on the current function,
6471 // we may have to do additional work before returning:
6472 // - Derived class constructors must check if the return value is an object.
6473 // - Generators and async functions must do a final yield.
6474 // - Non-async generators must return the value as an iterator result:
6475 // { value: <rval>, done: true }
6476 // - Non-generator async functions must resolve the function's result promise
6477 // with the value.
6478 //
6479 // If we have not generated any code since the SetRval that stored the return
6480 // value, we can also optimize the bytecode by rewriting that SetRval as a
6481 // JSOp::Return. See |emitReturn| above.
6482
6483 bool isDerivedClassConstructor =
6484 sc->isFunctionBox() && sc->asFunctionBox()->isDerivedClassConstructor();
6485 bool needsFinalYield =
6486 sc->isFunctionBox() && sc->asFunctionBox()->needsFinalYield();
6487 bool isSimpleReturn =
6488 setRvalOffset.valid() &&
6489 setRvalOffset + BytecodeOffsetDiff(JSOpLength_SetRval) ==
6490 bytecodeSection().offset();
6491
6492 if (isDerivedClassConstructor) {
6493 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6493); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!needsFinalYield"
")"); do { *((volatile int*)__null) = 6493; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6494 if (!emitJump(JSOp::Goto, &endOfDerivedClassConstructorBody)) {
6495 return false;
6496 }
6497 return true;
6498 }
6499
6500 if (needsFinalYield) {
6501 if (!emitJump(JSOp::Goto, &finalYields)) {
6502 return false;
6503 }
6504 return true;
6505 }
6506
6507 if (isSimpleReturn) {
6508 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6509); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JSOp(bytecodeSection().code()[setRvalOffset.value()]) == JSOp::SetRval"
")"); do { *((volatile int*)__null) = 6509; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6509 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6509); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JSOp(bytecodeSection().code()[setRvalOffset.value()]) == JSOp::SetRval"
")"); do { *((volatile int*)__null) = 6509; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6510 bytecodeSection().code()[setRvalOffset.value()] = jsbytecode(JSOp::Return);
6511 return true;
6512 }
6513
6514 // Nothing special needs to be done.
6515 return emitReturnRval();
6516}
6517
6518bool BytecodeEmitter::emitGetDotGeneratorInScope(EmitterScope& currentScope) {
6519 if (!sc->isFunction() && sc->isModuleContext() &&
6520 sc->asModuleContext()->isAsync()) {
6521 NameLocation loc = *locationOfNameBoundInScopeType<ModuleScope>(
6522 TaggedParserAtomIndex::WellKnown::dot_generator_(), &currentScope);
6523 return emitGetNameAtLocation(
6524 TaggedParserAtomIndex::WellKnown::dot_generator_(), loc);
6525 }
6526 NameLocation loc = *locationOfNameBoundInScopeType<FunctionScope>(
6527 TaggedParserAtomIndex::WellKnown::dot_generator_(), &currentScope);
6528 return emitGetNameAtLocation(
6529 TaggedParserAtomIndex::WellKnown::dot_generator_(), loc);
6530}
6531
6532bool BytecodeEmitter::emitInitialYield(UnaryNode* yieldNode) {
6533 if (!emitTree(yieldNode->kid())) {
6534 return false;
6535 }
6536
6537 if (!emitYieldOp(JSOp::InitialYield)) {
6538 // [stack] RVAL GENERATOR RESUMEKIND
6539 return false;
6540 }
6541 if (!emit1(JSOp::CheckResumeKind)) {
6542 // [stack] RVAL
6543 return false;
6544 }
6545 if (!emit1(JSOp::Pop)) {
6546 // [stack]
6547 return false;
6548 }
6549
6550 return true;
6551}
6552
6553bool BytecodeEmitter::emitYield(UnaryNode* yieldNode) {
6554 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6554); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isFunctionBox()"
")"); do { *((volatile int*)__null) = 6554; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6555 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6555); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->asFunctionBox()->isGenerator()"
")"); do { *((volatile int*)__null) = 6555; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6556 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6556); AnnotateMozCrashReason("MOZ_ASSERT" "(" "yieldNode->isKind(ParseNodeKind::YieldExpr)"
")"); do { *((volatile int*)__null) = 6556; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6557
6558 bool needsIteratorResult = sc->asFunctionBox()->needsIteratorResult();
6559 if (needsIteratorResult) {
6560 if (!emitPrepareIteratorResult()) {
6561 // [stack] ITEROBJ
6562 return false;
6563 }
6564 }
6565 if (ParseNode* expr = yieldNode->kid()) {
6566 if (!emitTree(expr)) {
6567 // [stack] ITEROBJ? VAL
6568 return false;
6569 }
6570 } else {
6571 if (!emit1(JSOp::Undefined)) {
6572 // [stack] ITEROBJ? UNDEFINED
6573 return false;
6574 }
6575 }
6576
6577 if (sc->asSuspendableContext()->isAsync()) {
6578 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6578); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!needsIteratorResult"
")"); do { *((volatile int*)__null) = 6578; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6579 if (!emitAwaitInInnermostScope()) {
6580 // [stack] RESULT
6581 return false;
6582 }
6583 }
6584
6585 if (needsIteratorResult) {
6586 if (!emitFinishIteratorResult(false)) {
6587 // [stack] ITEROBJ
6588 return false;
6589 }
6590 }
6591
6592 if (!emitGetDotGeneratorInInnermostScope()) {
6593 // [stack] # if needsIteratorResult
6594 // [stack] ITEROBJ .GENERATOR
6595 // [stack] # else
6596 // [stack] RESULT .GENERATOR
6597 return false;
6598 }
6599
6600 if (!emitYieldOp(JSOp::Yield)) {
6601 // [stack] YIELDRESULT GENERATOR RESUMEKIND
6602 return false;
6603 }
6604
6605 if (!emit1(JSOp::CheckResumeKind)) {
6606 // [stack] YIELDRESULT
6607 return false;
6608 }
6609
6610 return true;
6611}
6612
6613bool BytecodeEmitter::emitAwaitInInnermostScope(UnaryNode* awaitNode) {
6614 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()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6614); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isSuspendableContext()"
")"); do { *((volatile int*)__null) = 6614; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6615 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6615); AnnotateMozCrashReason("MOZ_ASSERT" "(" "awaitNode->isKind(ParseNodeKind::AwaitExpr)"
")"); do { *((volatile int*)__null) = 6615; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6616
6617 if (!emitTree(awaitNode->kid())) {
6618 return false;
6619 }
6620 return emitAwaitInInnermostScope();
6621}
6622
6623bool BytecodeEmitter::emitAwaitInScope(EmitterScope& currentScope) {
6624 if (!emit1(JSOp::CanSkipAwait)) {
6625 // [stack] VALUE CANSKIP
6626 return false;
6627 }
6628
6629 if (!emit1(JSOp::MaybeExtractAwaitValue)) {
6630 // [stack] VALUE_OR_RESOLVED CANSKIP
6631 return false;
6632 }
6633
6634 InternalIfEmitter ifCanSkip(this);
6635 if (!ifCanSkip.emitThen(IfEmitter::ConditionKind::Negative)) {
6636 // [stack] VALUE_OR_RESOLVED
6637 return false;
6638 }
6639
6640 if (sc->asSuspendableContext()->needsPromiseResult()) {
6641 if (!emitGetDotGeneratorInScope(currentScope)) {
6642 // [stack] VALUE GENERATOR
6643 return false;
6644 }
6645 if (!emit1(JSOp::AsyncAwait)) {
6646 // [stack] PROMISE
6647 return false;
6648 }
6649 }
6650
6651 if (!emitGetDotGeneratorInScope(currentScope)) {
6652 // [stack] VALUE|PROMISE GENERATOR
6653 return false;
6654 }
6655 if (!emitYieldOp(JSOp::Await)) {
6656 // [stack] RESOLVED GENERATOR RESUMEKIND
6657 return false;
6658 }
6659 if (!emit1(JSOp::CheckResumeKind)) {
6660 // [stack] RESOLVED
6661 return false;
6662 }
6663
6664 if (!ifCanSkip.emitEnd()) {
6665 return false;
6666 }
6667
6668 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6668); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ifCanSkip.popped() == 0"
")"); do { *((volatile int*)__null) = 6668; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6669
6670 return true;
6671}
6672
6673// ES2019 draft rev 49b781ec80117b60f73327ef3054703a3111e40c
6674// 14.4.14 Runtime Semantics: Evaluation
6675// YieldExpression : yield* AssignmentExpression
6676bool BytecodeEmitter::emitYieldStar(ParseNode* iter) {
6677 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6679); AnnotateMozCrashReason("MOZ_ASSERT" "(" "getSelfHostedIterFor(iter) == SelfHostedIter::Deny"
") (" "yield* is prohibited in self-hosted code because it can run "
"user-modifiable iteration code" ")"); do { *((volatile int*
)__null) = 6679; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
6678 "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6679); AnnotateMozCrashReason("MOZ_ASSERT" "(" "getSelfHostedIterFor(iter) == SelfHostedIter::Deny"
") (" "yield* is prohibited in self-hosted code because it can run "
"user-modifiable iteration code" ")"); do { *((volatile int*
)__null) = 6679; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
6679 "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6679); AnnotateMozCrashReason("MOZ_ASSERT" "(" "getSelfHostedIterFor(iter) == SelfHostedIter::Deny"
") (" "yield* is prohibited in self-hosted code because it can run "
"user-modifiable iteration code" ")"); do { *((volatile int*
)__null) = 6679; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6680
6681 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()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6681); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isSuspendableContext()"
")"); do { *((volatile int*)__null) = 6681; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6682 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6682); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->asSuspendableContext()->isGenerator()"
")"); do { *((volatile int*)__null) = 6682; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6683
6684 // Step 1.
6685 IteratorKind iterKind = sc->asSuspendableContext()->isAsync()
6686 ? IteratorKind::Async
6687 : IteratorKind::Sync;
6688 bool needsIteratorResult = sc->asSuspendableContext()->needsIteratorResult();
6689
6690 // Steps 2-5.
6691 if (!emitTree(iter)) {
6692 // [stack] ITERABLE
6693 return false;
6694 }
6695 if (iterKind == IteratorKind::Async) {
6696 if (!emitAsyncIterator(SelfHostedIter::Deny)) {
6697 // [stack] NEXT ITER
6698 return false;
6699 }
6700 } else {
6701 if (!emitIterator(SelfHostedIter::Deny)) {
6702 // [stack] NEXT ITER
6703 return false;
6704 }
6705 }
6706
6707 // Step 6.
6708 // Start with NormalCompletion(undefined).
6709 if (!emit1(JSOp::Undefined)) {
6710 // [stack] NEXT ITER RECEIVED
6711 return false;
6712 }
6713 if (!emitPushResumeKind(GeneratorResumeKind::Next)) {
6714 // [stack] NEXT ITER RECEIVED RESUMEKIND
6715 return false;
6716 }
6717
6718 const int32_t startDepth = bytecodeSection().stackDepth();
6719 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6719); AnnotateMozCrashReason("MOZ_ASSERT" "(" "startDepth >= 4"
")"); do { *((volatile int*)__null) = 6719; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6720
6721 // Step 7 is a loop.
6722 LoopControl loopInfo(this, StatementKind::YieldStar);
6723 if (!loopInfo.emitLoopHead(this, Nothing())) {
6724 // [stack] NEXT ITER RECEIVED RESUMEKIND
6725 return false;
6726 }
6727
6728 // Step 7.a. Check for Normal completion.
6729 if (!emit1(JSOp::Dup)) {
6730 // [stack] NEXT ITER RECEIVED RESUMEKIND RESUMEKIND
6731 return false;
6732 }
6733 if (!emitPushResumeKind(GeneratorResumeKind::Next)) {
6734 // [stack] NEXT ITER RECEIVED RESUMEKIND RESUMEKIND NORMAL
6735 return false;
6736 }
6737 if (!emit1(JSOp::StrictEq)) {
6738 // [stack] NEXT ITER RECEIVED RESUMEKIND IS_NORMAL
6739 return false;
6740 }
6741
6742 InternalIfEmitter ifKind(this);
6743 if (!ifKind.emitThenElse()) {
6744 // [stack] NEXT ITER RECEIVED RESUMEKIND
6745 return false;
6746 }
6747 {
6748 if (!emit1(JSOp::Pop)) {
6749 // [stack] NEXT ITER RECEIVED
6750 return false;
6751 }
6752
6753 // Step 7.a.i.
6754 // result = iter.next(received)
6755 if (!emit2(JSOp::Unpick, 2)) {
6756 // [stack] RECEIVED NEXT ITER
6757 return false;
6758 }
6759 if (!emit1(JSOp::Dup2)) {
6760 // [stack] RECEIVED NEXT ITER NEXT ITER
6761 return false;
6762 }
6763 if (!emit2(JSOp::Pick, 4)) {
6764 // [stack] NEXT ITER NEXT ITER RECEIVED
6765 return false;
6766 }
6767 if (!emitCall(JSOp::Call, 1, iter)) {
6768 // [stack] NEXT ITER RESULT
6769 return false;
6770 }
6771
6772 // Step 7.a.ii.
6773 if (iterKind == IteratorKind::Async) {
6774 if (!emitAwaitInInnermostScope()) {
6775 // [stack] NEXT ITER RESULT
6776 return false;
6777 }
6778 }
6779
6780 // Step 7.a.iii.
6781 if (!emitCheckIsObj(CheckIsObjectKind::IteratorNext)) {
6782 // [stack] NEXT ITER RESULT
6783 return false;
6784 }
6785
6786 // Bytecode for steps 7.a.iv-vii is emitted after the ifKind if-else because
6787 // it's shared with other branches.
6788 }
6789
6790 // Step 7.b. Check for Throw completion.
6791 if (!ifKind.emitElseIf(Nothing())) {
6792 // [stack] NEXT ITER RECEIVED RESUMEKIND
6793 return false;
6794 }
6795 if (!emit1(JSOp::Dup)) {
6796 // [stack] NEXT ITER RECEIVED RESUMEKIND RESUMEKIND
6797 return false;
6798 }
6799 if (!emitPushResumeKind(GeneratorResumeKind::Throw)) {
6800 // [stack] NEXT ITER RECEIVED RESUMEKIND RESUMEKIND THROW
6801 return false;
6802 }
6803 if (!emit1(JSOp::StrictEq)) {
6804 // [stack] NEXT ITER RECEIVED RESUMEKIND IS_THROW
6805 return false;
6806 }
6807 if (!ifKind.emitThenElse()) {
6808 // [stack] NEXT ITER RECEIVED RESUMEKIND
6809 return false;
6810 }
6811 {
6812 if (!emit1(JSOp::Pop)) {
6813 // [stack] NEXT ITER RECEIVED
6814 return false;
6815 }
6816 // Step 7.b.i.
6817 if (!emitDupAt(1)) {
6818 // [stack] NEXT ITER RECEIVED ITER
6819 return false;
6820 }
6821 if (!emit1(JSOp::Dup)) {
6822 // [stack] NEXT ITER RECEIVED ITER ITER
6823 return false;
6824 }
6825 if (!emitAtomOp(JSOp::GetProp,
6826 TaggedParserAtomIndex::WellKnown::throw_())) {
6827 // [stack] NEXT ITER RECEIVED ITER THROW
6828 return false;
6829 }
6830
6831 // Step 7.b.ii.
6832 InternalIfEmitter ifThrowMethodIsNotDefined(this);
6833 if (!emit1(JSOp::IsNullOrUndefined)) {
6834 // [stack] NEXT ITER RECEIVED ITER THROW NULL-OR-UNDEF
6835 return false;
6836 }
6837
6838 if (!ifThrowMethodIsNotDefined.emitThenElse(
6839 IfEmitter::ConditionKind::Negative)) {
6840 // [stack] NEXT ITER RECEIVED ITER THROW
6841 return false;
6842 }
6843
6844 // Step 7.b.ii.1.
6845 // RESULT = ITER.throw(EXCEPTION)
6846 if (!emit1(JSOp::Swap)) {
6847 // [stack] NEXT ITER RECEIVED THROW ITER
6848 return false;
6849 }
6850 if (!emit2(JSOp::Pick, 2)) {
6851 // [stack] NEXT ITER THROW ITER RECEIVED
6852 return false;
6853 }
6854 if (!emitCall(JSOp::Call, 1, iter)) {
6855 // [stack] NEXT ITER RESULT
6856 return false;
6857 }
6858
6859 // Step 7.b.ii.2.
6860 if (iterKind == IteratorKind::Async) {
6861 if (!emitAwaitInInnermostScope()) {
6862 // [stack] NEXT ITER RESULT
6863 return false;
6864 }
6865 }
6866
6867 // Step 7.b.ii.4.
6868 if (!emitCheckIsObj(CheckIsObjectKind::IteratorThrow)) {
6869 // [stack] NEXT ITER RESULT
6870 return false;
6871 }
6872
6873 // Bytecode for steps 7.b.ii.5-8 is emitted after the ifKind if-else because
6874 // it's shared with other branches.
6875
6876 // Step 7.b.iii.
6877 if (!ifThrowMethodIsNotDefined.emitElse()) {
6878 // [stack] NEXT ITER RECEIVED ITER THROW
6879 return false;
6880 }
6881 if (!emit1(JSOp::Pop)) {
6882 // [stack] NEXT ITER RECEIVED ITER
6883 return false;
6884 }
6885
6886 // Steps 7.b.iii.1-4.
6887 //
6888 // If the iterator does not have a "throw" method, it calls IteratorClose
6889 // and then throws a TypeError.
6890 if (!emitIteratorCloseInInnermostScope(iterKind, CompletionKind::Normal)) {
6891 // [stack] NEXT ITER RECEIVED ITER
6892 return false;
6893 }
6894 // Steps 7.b.iii.5-6.
6895 if (!emit2(JSOp::ThrowMsg, uint8_t(ThrowMsgKind::IteratorNoThrow))) {
6896 // [stack] NEXT ITER RECEIVED ITER
6897 // [stack] # throw
6898 return false;
6899 }
6900
6901 if (!ifThrowMethodIsNotDefined.emitEnd()) {
6902 return false;
6903 }
6904 }
6905
6906 // Step 7.c. It must be a Return completion.
6907 if (!ifKind.emitElse()) {
6908 // [stack] NEXT ITER RECEIVED RESUMEKIND
6909 return false;
6910 }
6911 {
6912 if (!emit1(JSOp::Pop)) {
6913 // [stack] NEXT ITER RECEIVED
6914 return false;
6915 }
6916
6917 // Step 7.c.i.
6918 //
6919 // Call iterator.return() for receiving a "forced return" completion from
6920 // the generator.
6921
6922 // Step 7.c.ii.
6923 //
6924 // Get the "return" method.
6925 if (!emitDupAt(1)) {
6926 // [stack] NEXT ITER RECEIVED ITER
6927 return false;
6928 }
6929 if (!emit1(JSOp::Dup)) {
6930 // [stack] NEXT ITER RECEIVED ITER ITER
6931 return false;
6932 }
6933 if (!emitAtomOp(JSOp::GetProp,
6934 TaggedParserAtomIndex::WellKnown::return_())) {
6935 // [stack] NEXT ITER RECEIVED ITER RET
6936 return false;
6937 }
6938
6939 // Step 7.c.iii.
6940 //
6941 // Do nothing if "return" is undefined or null.
6942 InternalIfEmitter ifReturnMethodIsDefined(this);
6943 if (!emit1(JSOp::IsNullOrUndefined)) {
6944 // [stack] NEXT ITER RECEIVED ITER RET NULL-OR-UNDEF
6945 return false;
6946 }
6947
6948 // Step 7.c.iv.
6949 //
6950 // Call "return" with the argument passed to Generator.prototype.return.
6951 if (!ifReturnMethodIsDefined.emitThenElse(
6952 IfEmitter::ConditionKind::Negative)) {
6953 // [stack] NEXT ITER RECEIVED ITER RET
6954 return false;
6955 }
6956 if (!emit1(JSOp::Swap)) {
6957 // [stack] NEXT ITER RECEIVED RET ITER
6958 return false;
6959 }
6960 if (!emit2(JSOp::Pick, 2)) {
6961 // [stack] NEXT ITER RET ITER RECEIVED
6962 return false;
6963 }
6964 if (needsIteratorResult) {
6965 if (!emitAtomOp(JSOp::GetProp,
6966 TaggedParserAtomIndex::WellKnown::value())) {
6967 // [stack] NEXT ITER RET ITER VAL
6968 return false;
6969 }
6970 }
6971 if (!emitCall(JSOp::Call, 1)) {
6972 // [stack] NEXT ITER RESULT
6973 return false;
6974 }
6975
6976 // Step 7.c.v.
6977 if (iterKind == IteratorKind::Async) {
6978 if (!emitAwaitInInnermostScope()) {
6979 // [stack] NEXT ITER RESULT
6980 return false;
6981 }
6982 }
6983
6984 // Step 7.c.vi.
6985 if (!emitCheckIsObj(CheckIsObjectKind::IteratorReturn)) {
6986 // [stack] NEXT ITER RESULT
6987 return false;
6988 }
6989
6990 // Check if the returned object from iterator.return() is done. If not,
6991 // continue yielding.
6992
6993 // Steps 7.c.vii-viii.
6994 InternalIfEmitter ifReturnDone(this);
6995 if (!emit1(JSOp::Dup)) {
6996 // [stack] NEXT ITER RESULT RESULT
6997 return false;
6998 }
6999 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::done())) {
7000 // [stack] NEXT ITER RESULT DONE
7001 return false;
7002 }
7003 if (!ifReturnDone.emitThenElse()) {
7004 // [stack] NEXT ITER RESULT
7005 return false;
7006 }
7007
7008 // Step 7.c.viii.1.
7009 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::value())) {
7010 // [stack] NEXT ITER VALUE
7011 return false;
7012 }
7013 if (needsIteratorResult) {
7014 if (!emitPrepareIteratorResult()) {
7015 // [stack] NEXT ITER VALUE RESULT
7016 return false;
7017 }
7018 if (!emit1(JSOp::Swap)) {
7019 // [stack] NEXT ITER RESULT VALUE
7020 return false;
7021 }
7022 if (!emitFinishIteratorResult(true)) {
7023 // [stack] NEXT ITER RESULT
7024 return false;
7025 }
7026 }
7027
7028 if (!ifReturnDone.emitElse()) {
7029 // [stack] NEXT ITER RESULT
7030 return false;
7031 }
7032
7033 // Jump to continue label for steps 7.c.ix-x.
7034 if (!emitJump(JSOp::Goto, &loopInfo.continues)) {
7035 // [stack] NEXT ITER RESULT
7036 return false;
7037 }
7038
7039 if (!ifReturnDone.emitEnd()) {
7040 // [stack] NEXT ITER RESULT
7041 return false;
7042 }
7043
7044 // Step 7.c.iii.
7045 if (!ifReturnMethodIsDefined.emitElse()) {
7046 // [stack] NEXT ITER RECEIVED ITER RET
7047 return false;
7048 }
7049 if (!emitPopN(2)) {
7050 // [stack] NEXT ITER RECEIVED
7051 return false;
7052 }
7053 if (iterKind == IteratorKind::Async) {
7054 // Step 7.c.iii.1.
7055 if (!emitAwaitInInnermostScope()) {
7056 // [stack] NEXT ITER RECEIVED
7057 return false;
7058 }
7059 }
7060 if (!ifReturnMethodIsDefined.emitEnd()) {
7061 // [stack] NEXT ITER RECEIVED
7062 return false;
7063 }
7064
7065 // Perform a "forced generator return".
7066 //
7067 // Step 7.c.iii.2.
7068 // Step 7.c.viii.2.
7069 if (!emitGetDotGeneratorInInnermostScope()) {
7070 // [stack] NEXT ITER RESULT GENOBJ
7071 return false;
7072 }
7073 if (!emitPushResumeKind(GeneratorResumeKind::Return)) {
7074 // [stack] NEXT ITER RESULT GENOBJ RESUMEKIND
7075 return false;
7076 }
7077 if (!emit1(JSOp::CheckResumeKind)) {
7078 // [stack] NEXT ITER RESULT GENOBJ RESUMEKIND
7079 return false;
7080 }
7081 }
7082
7083 if (!ifKind.emitEnd()) {
7084 // [stack] NEXT ITER RESULT
7085 return false;
7086 }
7087
7088 // Shared tail for Normal/Throw completions.
7089 //
7090 // Steps 7.a.iv-v.
7091 // Steps 7.b.ii.5-6.
7092 //
7093 // [stack] NEXT ITER RESULT
7094
7095 // if (result.done) break;
7096 if (!emit1(JSOp::Dup)) {
7097 // [stack] NEXT ITER RESULT RESULT
7098 return false;
7099 }
7100 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::done())) {
7101 // [stack] NEXT ITER RESULT DONE
7102 return false;
7103 }
7104 if (!emitJump(JSOp::JumpIfTrue, &loopInfo.breaks)) {
7105 // [stack] NEXT ITER RESULT
7106 return false;
7107 }
7108
7109 // Steps 7.a.vi-vii.
7110 // Steps 7.b.ii.7-8.
7111 // Steps 7.c.ix-x.
7112 if (!loopInfo.emitContinueTarget(this)) {
7113 // [stack] NEXT ITER RESULT
7114 return false;
7115 }
7116 if (iterKind == IteratorKind::Async) {
7117 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::value())) {
7118 // [stack] NEXT ITER RESULT
7119 return false;
7120 }
7121 }
7122 if (!emitGetDotGeneratorInInnermostScope()) {
7123 // [stack] NEXT ITER RESULT GENOBJ
7124 return false;
7125 }
7126 if (!emitYieldOp(JSOp::Yield)) {
7127 // [stack] NEXT ITER RVAL GENOBJ RESUMEKIND
7128 return false;
7129 }
7130 if (!emit1(JSOp::Swap)) {
7131 // [stack] NEXT ITER RVAL RESUMEKIND GENOBJ
7132 return false;
7133 }
7134 if (!emit1(JSOp::Pop)) {
7135 // [stack] NEXT ITER RVAL RESUMEKIND
7136 return false;
7137 }
7138 if (!loopInfo.emitLoopEnd(this, JSOp::Goto, TryNoteKind::Loop)) {
7139 // [stack] NEXT ITER RVAL RESUMEKIND
7140 return false;
7141 }
7142
7143 // Jumps to this point have 3 (instead of 4) values on the stack.
7144 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7144); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == startDepth"
")"); do { *((volatile int*)__null) = 7144; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7145 bytecodeSection().setStackDepth(startDepth - 1);
7146
7147 // [stack] NEXT ITER RESULT
7148
7149 // Step 7.a.v.1.
7150 // Step 7.b.ii.6.a.
7151 //
7152 // result.value
7153 if (!emit2(JSOp::Unpick, 2)) {
7154 // [stack] RESULT NEXT ITER
7155 return false;
7156 }
7157 if (!emitPopN(2)) {
7158 // [stack] RESULT
7159 return false;
7160 }
7161 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::value())) {
7162 // [stack] VALUE
7163 return false;
7164 }
7165
7166 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7166); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == startDepth - 3"
")"); do { *((volatile int*)__null) = 7166; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7167
7168 return true;
7169}
7170
7171bool BytecodeEmitter::emitStatementList(ListNode* stmtList) {
7172 for (ParseNode* stmt : stmtList->contents()) {
7173 if (!emitTree(stmt)) {
7174 return false;
7175 }
7176 }
7177 return true;
7178}
7179
7180bool BytecodeEmitter::emitExpressionStatement(UnaryNode* exprStmt) {
7181 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7181); AnnotateMozCrashReason("MOZ_ASSERT" "(" "exprStmt->isKind(ParseNodeKind::ExpressionStmt)"
")"); do { *((volatile int*)__null) = 7181; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7182
7183 /*
7184 * Top-level or called-from-a-native JS_Execute/EvaluateScript,
7185 * debugger, and eval frames may need the value of the ultimate
7186 * expression statement as the script's result, despite the fact
7187 * that it appears useless to the compiler.
7188 *
7189 * API users may also set the ReadOnlyCompileOptions::noScriptRval option when
7190 * calling JS_Compile* to suppress JSOp::SetRval.
7191 */
7192 bool wantval = false;
7193 bool useful = false;
7194 if (sc->isTopLevelContext()) {
7195 useful = wantval = !sc->noScriptRval();
7196 }
7197
7198 /* Don't eliminate expressions with side effects. */
7199 ParseNode* expr = exprStmt->kid();
7200 if (!useful) {
7201 if (!checkSideEffects(expr, &useful)) {
7202 return false;
7203 }
7204
7205 /*
7206 * Don't eliminate apparently useless expressions if they are labeled
7207 * expression statements. The startOffset() test catches the case
7208 * where we are nesting in emitTree for a labeled compound statement.
7209 */
7210 if (innermostNestableControl &&
7211 innermostNestableControl->is<LabelControl>() &&
7212 innermostNestableControl->as<LabelControl>().startOffset() >=
7213 bytecodeSection().offset()) {
7214 useful = true;
7215 }
7216 }
7217
7218 if (useful) {
7219 ValueUsage valueUsage =
7220 wantval ? ValueUsage::WantValue : ValueUsage::IgnoreValue;
7221 ExpressionStatementEmitter ese(this, valueUsage);
7222 if (!ese.prepareForExpr(exprStmt->pn_pos.begin)) {
7223 return false;
7224 }
7225 if (!markStepBreakpoint()) {
7226 return false;
7227 }
7228 if (!emitTree(expr, valueUsage)) {
7229 return false;
7230 }
7231 if (!ese.emitEnd()) {
7232 return false;
7233 }
7234 }
7235
7236 return true;
7237}
7238
7239bool BytecodeEmitter::emitDeleteName(UnaryNode* deleteNode) {
7240 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)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7240); AnnotateMozCrashReason("MOZ_ASSERT" "(" "deleteNode->isKind(ParseNodeKind::DeleteNameExpr)"
")"); do { *((volatile int*)__null) = 7240; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7241
7242 NameNode* nameExpr = &deleteNode->kid()->as<NameNode>();
7243 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7243); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nameExpr->isKind(ParseNodeKind::Name)"
")"); do { *((volatile int*)__null) = 7243; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7244
7245 return emitAtomOp(JSOp::DelName, nameExpr->atom());
7246}
7247
7248bool BytecodeEmitter::emitDeleteProperty(UnaryNode* deleteNode) {
7249 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)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7249); AnnotateMozCrashReason("MOZ_ASSERT" "(" "deleteNode->isKind(ParseNodeKind::DeletePropExpr)"
")"); do { *((volatile int*)__null) = 7249; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7250
7251 PropertyAccess* propExpr = &deleteNode->kid()->as<PropertyAccess>();
7252 PropOpEmitter poe(this, PropOpEmitter::Kind::Delete,
7253 propExpr->as<PropertyAccess>().isSuper()
7254 ? PropOpEmitter::ObjKind::Super
7255 : PropOpEmitter::ObjKind::Other);
7256
7257 if (!poe.prepareForObj()) {
7258 return false;
7259 }
7260
7261 if (propExpr->isSuper()) {
7262 // The expression |delete super.foo;| has to evaluate |super.foo|, which
7263 // could throw if |this| hasn't yet been set by a |super(...)| call.
7264 auto* base = &propExpr->expression().as<UnaryNode>();
7265 if (!emitGetThisForSuperBase(base)) {
7266 // [stack] THIS
7267 return false;
7268 }
7269 } else {
7270 if (!emitPropLHS(propExpr)) {
7271 // [stack] OBJ
7272 return false;
7273 }
7274 }
7275
7276 if (!poe.emitDelete(propExpr->key().atom())) {
7277 // [stack] # if Super
7278 // [stack] THIS
7279 // [stack] # otherwise
7280 // [stack] SUCCEEDED
7281 return false;
7282 }
7283
7284 return true;
7285}
7286
7287bool BytecodeEmitter::emitDeleteElement(UnaryNode* deleteNode) {
7288 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)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7288); AnnotateMozCrashReason("MOZ_ASSERT" "(" "deleteNode->isKind(ParseNodeKind::DeleteElemExpr)"
")"); do { *((volatile int*)__null) = 7288; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7289
7290 auto* elemExpr = &deleteNode->kid()->as<PropertyByValue>();
7291 bool isSuper = elemExpr->isSuper();
7292 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)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7292); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elemExpr->key().isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 7292; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7293 ElemOpEmitter eoe(
7294 this, ElemOpEmitter::Kind::Delete,
7295 isSuper ? ElemOpEmitter::ObjKind::Super : ElemOpEmitter::ObjKind::Other);
7296
7297 if (!emitElemObjAndKey(elemExpr, eoe)) {
7298 // [stack] # if Super
7299 // [stack] THIS KEY
7300 // [stack] # otherwise
7301 // [stack] OBJ KEY
7302 return false;
7303 }
7304
7305 if (!eoe.emitDelete()) {
7306 // [stack] # if Super
7307 // [stack] THIS
7308 // [stack] # otherwise
7309 // [stack] SUCCEEDED
7310 return false;
7311 }
7312
7313 return true;
7314}
7315
7316bool BytecodeEmitter::emitDeleteExpression(UnaryNode* deleteNode) {
7317 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7317); AnnotateMozCrashReason("MOZ_ASSERT" "(" "deleteNode->isKind(ParseNodeKind::DeleteExpr)"
")"); do { *((volatile int*)__null) = 7317; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7318
7319 ParseNode* expression = deleteNode->kid();
7320
7321 // If useless, just emit JSOp::True; otherwise convert |delete <expr>| to
7322 // effectively |<expr>, true|.
7323 bool useful = false;
7324 if (!checkSideEffects(expression, &useful)) {
7325 return false;
7326 }
7327
7328 if (useful) {
7329 if (!emitTree(expression)) {
7330 return false;
7331 }
7332 if (!emit1(JSOp::Pop)) {
7333 return false;
7334 }
7335 }
7336
7337 return emit1(JSOp::True);
7338}
7339
7340bool BytecodeEmitter::emitDeleteOptionalChain(UnaryNode* deleteNode) {
7341 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7341); AnnotateMozCrashReason("MOZ_ASSERT" "(" "deleteNode->isKind(ParseNodeKind::DeleteOptionalChainExpr)"
")"); do { *((volatile int*)__null) = 7341; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7342
7343 OptionalEmitter oe(this, bytecodeSection().stackDepth());
7344
7345 ParseNode* kid = deleteNode->kid();
7346 switch (kid->getKind()) {
7347 case ParseNodeKind::ElemExpr:
7348 case ParseNodeKind::OptionalElemExpr: {
7349 auto* elemExpr = &kid->as<PropertyByValueBase>();
7350 if (!emitDeleteElementInOptChain(elemExpr, oe)) {
7351 // [stack] # If shortcircuit
7352 // [stack] UNDEFINED-OR-NULL
7353 // [stack] # otherwise
7354 // [stack] SUCCEEDED
7355 return false;
7356 }
7357
7358 break;
7359 }
7360 case ParseNodeKind::ArgumentsLength:
7361 case ParseNodeKind::DotExpr:
7362 case ParseNodeKind::OptionalDotExpr: {
7363 auto* propExpr = &kid->as<PropertyAccessBase>();
7364 if (!emitDeletePropertyInOptChain(propExpr, oe)) {
7365 // [stack] # If shortcircuit
7366 // [stack] UNDEFINED-OR-NULL
7367 // [stack] # otherwise
7368 // [stack] SUCCEEDED
7369 return false;
7370 }
7371 break;
7372 }
7373 default:
7374 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7374); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Unrecognized optional delete ParseNodeKind"
")"); do { *((volatile int*)__null) = 7374; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7375 }
7376
7377 if (!oe.emitOptionalJumpTarget(JSOp::True)) {
7378 // [stack] # If shortcircuit
7379 // [stack] TRUE
7380 // [stack] # otherwise
7381 // [stack] SUCCEEDED
7382 return false;
7383 }
7384
7385 return true;
7386}
7387
7388bool BytecodeEmitter::emitDeletePropertyInOptChain(PropertyAccessBase* propExpr,
7389 OptionalEmitter& oe) {
7390 MOZ_ASSERT_IF(propExpr->is<PropertyAccess>(),do { if (propExpr->is<PropertyAccess>()) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(!propExpr
->as<PropertyAccess>().isSuper())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!propExpr->as<PropertyAccess
>().isSuper()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!propExpr->as<PropertyAccess>().isSuper()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7391); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!propExpr->as<PropertyAccess>().isSuper()"
")"); do { *((volatile int*)__null) = 7391; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
7391 !propExpr->as<PropertyAccess>().isSuper())do { if (propExpr->is<PropertyAccess>()) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(!propExpr
->as<PropertyAccess>().isSuper())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!propExpr->as<PropertyAccess
>().isSuper()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!propExpr->as<PropertyAccess>().isSuper()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7391); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!propExpr->as<PropertyAccess>().isSuper()"
")"); do { *((volatile int*)__null) = 7391; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
7392 PropOpEmitter poe(this, PropOpEmitter::Kind::Delete,
7393 PropOpEmitter::ObjKind::Other);
7394
7395 if (!poe.prepareForObj()) {
7396 // [stack]
7397 return false;
7398 }
7399 if (!emitOptionalTree(&propExpr->expression(), oe)) {
7400 // [stack] OBJ
7401 return false;
7402 }
7403 if (propExpr->isKind(ParseNodeKind::OptionalDotExpr)) {
7404 if (!oe.emitJumpShortCircuit()) {
7405 // [stack] # if Jump
7406 // [stack] UNDEFINED-OR-NULL
7407 // [stack] # otherwise
7408 // [stack] OBJ
7409 return false;
7410 }
7411 }
7412
7413 if (!poe.emitDelete(propExpr->key().atom())) {
7414 // [stack] SUCCEEDED
7415 return false;
7416 }
7417
7418 return true;
7419}
7420
7421bool BytecodeEmitter::emitDeleteElementInOptChain(PropertyByValueBase* elemExpr,
7422 OptionalEmitter& oe) {
7423 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()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7424); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elemExpr->as<PropertyByValue>().isSuper()"
")"); do { *((volatile int*)__null) = 7424; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
7424 !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()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7424); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elemExpr->as<PropertyByValue>().isSuper()"
")"); do { *((volatile int*)__null) = 7424; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
7425 ElemOpEmitter eoe(this, ElemOpEmitter::Kind::Delete,
7426 ElemOpEmitter::ObjKind::Other);
7427
7428 if (!eoe.prepareForObj()) {
7429 // [stack]
7430 return false;
7431 }
7432
7433 if (!emitOptionalTree(&elemExpr->expression(), oe)) {
7434 // [stack] OBJ
7435 return false;
7436 }
7437
7438 if (elemExpr->isKind(ParseNodeKind::OptionalElemExpr)) {
7439 if (!oe.emitJumpShortCircuit()) {
7440 // [stack] # if Jump
7441 // [stack] UNDEFINED-OR-NULL
7442 // [stack] # otherwise
7443 // [stack] OBJ
7444 return false;
7445 }
7446 }
7447
7448 if (!eoe.prepareForKey()) {
7449 // [stack] OBJ
7450 return false;
7451 }
7452
7453 if (!emitTree(&elemExpr->key())) {
7454 // [stack] OBJ KEY
7455 return false;
7456 }
7457
7458 if (!eoe.emitDelete()) {
7459 // [stack] SUCCEEDED
7460 return false;
7461 }
7462
7463 return true;
7464}
7465
7466bool BytecodeEmitter::emitDebugCheckSelfHosted() {
7467 // [stack] CALLEE
7468
7469#ifdef DEBUG1
7470 if (!emit1(JSOp::DebugCheckSelfHosted)) {
7471 // [stack] CALLEE
7472 return false;
7473 }
7474#endif
7475
7476 return true;
7477}
7478
7479bool BytecodeEmitter::emitSelfHostedCallFunction(CallNode* callNode, JSOp op) {
7480 // Special-casing of callFunction to emit bytecode that directly
7481 // invokes the callee with the correct |this| object and arguments.
7482 // callFunction(fun, thisArg, arg0, arg1) thus becomes:
7483 // - emit lookup for fun
7484 // - emit lookup for thisArg
7485 // - emit lookups for arg0, arg1
7486 //
7487 // argc is set to the amount of actually emitted args and the
7488 // emitting of args below is disabled by setting emitArgs to false.
7489 NameNode* calleeNode = &callNode->callee()->as<NameNode>();
7490 ListNode* argsList = callNode->args();
7491
7492 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7492); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() >= 2"
")"); do { *((volatile int*)__null) = 7492; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7493
7494 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7494); AnnotateMozCrashReason("MOZ_ASSERT" "(" "callNode->callOp() == JSOp::Call"
")"); do { *((volatile int*)__null) = 7494; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7495
7496 bool constructing =
7497 calleeNode->name() ==
7498 TaggedParserAtomIndex::WellKnown::constructContentFunction();
7499 ParseNode* funNode = argsList->head();
7500
7501 if (!emitTree(funNode)) {
7502 // [stack] CALLEE
7503 return false;
7504 }
7505
7506#ifdef DEBUG1
7507 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7508); AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::Call || op == JSOp::CallContent || op == JSOp::NewContent"
")"); do { *((volatile int*)__null) = 7508; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7508 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7508); AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::Call || op == JSOp::CallContent || op == JSOp::NewContent"
")"); do { *((volatile int*)__null) = 7508; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7509 if (op == JSOp::Call) {
7510 if (!emitDebugCheckSelfHosted()) {
7511 // [stack] CALLEE
7512 return false;
7513 }
7514 }
7515#endif
7516
7517 ParseNode* thisOrNewTarget = funNode->pn_next;
7518 if (constructing) {
7519 // Save off the new.target value, but here emit a proper |this| for a
7520 // constructing call.
7521 if (!emit1(JSOp::IsConstructing)) {
7522 // [stack] CALLEE IS_CONSTRUCTING
7523 return false;
7524 }
7525 } else {
7526 // It's |this|, emit it.
7527 if (!emitTree(thisOrNewTarget)) {
7528 // [stack] CALLEE THIS
7529 return false;
7530 }
7531 }
7532
7533 for (ParseNode* argpn : argsList->contentsFrom(thisOrNewTarget->pn_next)) {
7534 if (!emitTree(argpn)) {
7535 // [stack] CALLEE ... ARGS...
7536 return false;
7537 }
7538 }
7539
7540 if (constructing) {
7541 if (!emitTree(thisOrNewTarget)) {
7542 // [stack] CALLEE IS_CONSTRUCTING ARGS... NEW.TARGET
7543 return false;
7544 }
7545 }
7546
7547 uint32_t argc = argsList->count() - 2;
7548 if (!emitCall(op, argc)) {
7549 // [stack] RVAL
7550 return false;
7551 }
7552
7553 return true;
7554}
7555
7556bool BytecodeEmitter::emitSelfHostedResumeGenerator(CallNode* callNode) {
7557 ListNode* argsList = callNode->args();
7558
7559 // Syntax: resumeGenerator(gen, value, 'next'|'throw'|'return')
7560 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7560); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 3"
")"); do { *((volatile int*)__null) = 7560; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7561
7562 ParseNode* genNode = argsList->head();
7563 if (!emitTree(genNode)) {
7564 // [stack] GENERATOR
7565 return false;
7566 }
7567
7568 ParseNode* valNode = genNode->pn_next;
7569 if (!emitTree(valNode)) {
7570 // [stack] GENERATOR VALUE
7571 return false;
7572 }
7573
7574 ParseNode* kindNode = valNode->pn_next;
7575 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7575); AnnotateMozCrashReason("MOZ_ASSERT" "(" "kindNode->isKind(ParseNodeKind::StringExpr)"
")"); do { *((volatile int*)__null) = 7575; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7576 GeneratorResumeKind kind =
7577 ParserAtomToResumeKind(kindNode->as<NameNode>().atom());
7578 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7578); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!kindNode->pn_next"
")"); do { *((volatile int*)__null) = 7578; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7579
7580 if (!emitPushResumeKind(kind)) {
7581 // [stack] GENERATOR VALUE RESUMEKIND
7582 return false;
7583 }
7584
7585 if (!emit1(JSOp::Resume)) {
7586 // [stack] RVAL
7587 return false;
7588 }
7589
7590 return true;
7591}
7592
7593bool BytecodeEmitter::emitSelfHostedForceInterpreter() {
7594 // JSScript::hasForceInterpreterOp() relies on JSOp::ForceInterpreter being
7595 // the first bytecode op in the script.
7596 MOZ_ASSERT(bytecodeSection().code().empty())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bytecodeSection().code().empty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(bytecodeSection().code().empty
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("bytecodeSection().code().empty()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7596); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().code().empty()"
")"); do { *((volatile int*)__null) = 7596; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7597
7598 if (!emit1(JSOp::ForceInterpreter)) {
7599 return false;
7600 }
7601 if (!emit1(JSOp::Undefined)) {
7602 return false;
7603 }
7604
7605 return true;
7606}
7607
7608bool BytecodeEmitter::emitSelfHostedAllowContentIter(CallNode* callNode) {
7609 ListNode* argsList = callNode->args();
7610
7611 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7611); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1"
")"); do { *((volatile int*)__null) = 7611; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7612
7613 // We're just here as a sentinel. Pass the value through directly.
7614 return emitTree(argsList->head());
7615}
7616
7617bool BytecodeEmitter::emitSelfHostedAllowContentIterWith(CallNode* callNode) {
7618 ListNode* argsList = callNode->args();
7619
7620 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7620); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2 || argsList->count() == 3"
")"); do { *((volatile int*)__null) = 7620; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7621
7622 // We're just here as a sentinel. Pass the value through directly.
7623 return emitTree(argsList->head());
7624}
7625
7626bool BytecodeEmitter::emitSelfHostedAllowContentIterWithNext(
7627 CallNode* callNode) {
7628 ListNode* argsList = callNode->args();
7629
7630 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7630); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2"
")"); do { *((volatile int*)__null) = 7630; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7631
7632 // We're just here as a sentinel. Pass the value through directly.
7633 return emitTree(argsList->head());
7634}
7635
7636bool BytecodeEmitter::emitSelfHostedDefineDataProperty(CallNode* callNode) {
7637 ListNode* argsList = callNode->args();
7638
7639 // Only optimize when 3 arguments are passed.
7640 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7640); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 3"
")"); do { *((volatile int*)__null) = 7640; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7641
7642 ParseNode* objNode = argsList->head();
7643 if (!emitTree(objNode)) {
7644 return false;
7645 }
7646
7647 ParseNode* idNode = objNode->pn_next;
7648 if (!emitTree(idNode)) {
7649 return false;
7650 }
7651
7652 ParseNode* valNode = idNode->pn_next;
7653 if (!emitTree(valNode)) {
7654 return false;
7655 }
7656
7657 // This will leave the object on the stack instead of pushing |undefined|,
7658 // but that's fine because the self-hosted code doesn't use the return
7659 // value.
7660 return emit1(JSOp::InitElem);
7661}
7662
7663bool BytecodeEmitter::emitSelfHostedHasOwn(CallNode* callNode) {
7664 ListNode* argsList = callNode->args();
7665
7666 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7666); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2"
")"); do { *((volatile int*)__null) = 7666; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7667
7668 ParseNode* idNode = argsList->head();
7669 if (!emitTree(idNode)) {
7670 return false;
7671 }
7672
7673 ParseNode* objNode = idNode->pn_next;
7674 if (!emitTree(objNode)) {
7675 return false;
7676 }
7677
7678 return emit1(JSOp::HasOwn);
7679}
7680
7681bool BytecodeEmitter::emitSelfHostedGetPropertySuper(CallNode* callNode) {
7682 ListNode* argsList = callNode->args();
7683
7684 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7684); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 3"
")"); do { *((volatile int*)__null) = 7684; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7685
7686 ParseNode* objNode = argsList->head();
7687 ParseNode* idNode = objNode->pn_next;
7688 ParseNode* receiverNode = idNode->pn_next;
7689
7690 if (!emitTree(receiverNode)) {
7691 return false;
7692 }
7693
7694 if (!emitTree(idNode)) {
7695 return false;
7696 }
7697
7698 if (!emitTree(objNode)) {
7699 return false;
7700 }
7701
7702 return emitElemOpBase(JSOp::GetElemSuper);
7703}
7704
7705bool BytecodeEmitter::emitSelfHostedToNumeric(CallNode* callNode) {
7706 ListNode* argsList = callNode->args();
7707
7708 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7708); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1"
")"); do { *((volatile int*)__null) = 7708; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7709
7710 ParseNode* argNode = argsList->head();
7711
7712 if (!emitTree(argNode)) {
7713 return false;
7714 }
7715
7716 return emit1(JSOp::ToNumeric);
7717}
7718
7719bool BytecodeEmitter::emitSelfHostedToString(CallNode* callNode) {
7720 ListNode* argsList = callNode->args();
7721
7722 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7722); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1"
")"); do { *((volatile int*)__null) = 7722; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7723
7724 ParseNode* argNode = argsList->head();
7725
7726 if (!emitTree(argNode)) {
7727 return false;
7728 }
7729
7730 return emit1(JSOp::ToString);
7731}
7732
7733bool BytecodeEmitter::emitSelfHostedIsNullOrUndefined(CallNode* callNode) {
7734 ListNode* argsList = callNode->args();
7735
7736 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7736); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1"
")"); do { *((volatile int*)__null) = 7736; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7737
7738 ParseNode* argNode = argsList->head();
7739
7740 if (!emitTree(argNode)) {
7741 // [stack] ARG
7742 return false;
7743 }
7744 if (!emit1(JSOp::IsNullOrUndefined)) {
7745 // [stack] ARG IS_NULL_OR_UNDEF
7746 return false;
7747 }
7748 if (!emit1(JSOp::Swap)) {
7749 // [stack] IS_NULL_OR_UNDEF ARG
7750 return false;
7751 }
7752 if (!emit1(JSOp::Pop)) {
7753 // [stack] IS_NULL_OR_UNDEF
7754 return false;
7755 }
7756 return true;
7757}
7758
7759bool BytecodeEmitter::emitSelfHostedIteratorClose(CallNode* callNode) {
7760 ListNode* argsList = callNode->args();
7761 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7761); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1"
")"); do { *((volatile int*)__null) = 7761; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7762
7763 ParseNode* argNode = argsList->head();
7764 if (!emitTree(argNode)) {
7765 // [stack] ARG
7766 return false;
7767 }
7768
7769 if (!emit2(JSOp::CloseIter, uint8_t(CompletionKind::Normal))) {
7770 // [stack]
7771 return false;
7772 }
7773
7774 // This is still a call node, so we must generate a stack value.
7775 if (!emit1(JSOp::Undefined)) {
7776 // [stack] RVAL
7777 return false;
7778 }
7779
7780 return true;
7781}
7782
7783bool BytecodeEmitter::emitSelfHostedGetBuiltinConstructorOrPrototype(
7784 CallNode* callNode, bool isConstructor) {
7785 ListNode* argsList = callNode->args();
7786
7787 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7787); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1"
")"); do { *((volatile int*)__null) = 7787; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7788
7789 ParseNode* argNode = argsList->head();
7790
7791 if (!argNode->isKind(ParseNodeKind::StringExpr)) {
7792 reportError(callNode, JSMSG_UNEXPECTED_TYPE, "built-in name",
7793 "not a string constant");
7794 return false;
7795 }
7796
7797 auto name = argNode->as<NameNode>().atom();
7798
7799 BuiltinObjectKind kind;
7800 if (isConstructor) {
7801 kind = BuiltinConstructorForName(name);
7802 } else {
7803 kind = BuiltinPrototypeForName(name);
7804 }
7805
7806 if (kind == BuiltinObjectKind::None) {
7807 reportError(callNode, JSMSG_UNEXPECTED_TYPE, "built-in name",
7808 "not a valid built-in");
7809 return false;
7810 }
7811
7812 return emitBuiltinObject(kind);
7813}
7814
7815bool BytecodeEmitter::emitSelfHostedGetBuiltinConstructor(CallNode* callNode) {
7816 return emitSelfHostedGetBuiltinConstructorOrPrototype(
7817 callNode, /* isConstructor = */ true);
7818}
7819
7820bool BytecodeEmitter::emitSelfHostedGetBuiltinPrototype(CallNode* callNode) {
7821 return emitSelfHostedGetBuiltinConstructorOrPrototype(
7822 callNode, /* isConstructor = */ false);
7823}
7824
7825JS::SymbolCode ParserAtomToSymbolCode(TaggedParserAtomIndex atom) {
7826 // NOTE: This is a linear search, but the set of entries is quite small and
7827 // this is only used for initial self-hosted parse.
7828#define MATCH_WELL_KNOWN_SYMBOL(NAME) \
7829 if (atom == TaggedParserAtomIndex::WellKnown::NAME()) { \
7830 return JS::SymbolCode::NAME; \
7831 }
7832 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)
7833#undef MATCH_WELL_KNOWN_SYMBOL
7834
7835 return JS::SymbolCode::Limit;
7836}
7837
7838bool BytecodeEmitter::emitSelfHostedGetBuiltinSymbol(CallNode* callNode) {
7839 ListNode* argsList = callNode->args();
7840
7841 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7841); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1"
")"); do { *((volatile int*)__null) = 7841; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7842
7843 ParseNode* argNode = argsList->head();
7844
7845 if (!argNode->isKind(ParseNodeKind::StringExpr)) {
7846 reportError(callNode, JSMSG_UNEXPECTED_TYPE, "built-in name",
7847 "not a string constant");
7848 return false;
7849 }
7850
7851 auto name = argNode->as<NameNode>().atom();
7852
7853 JS::SymbolCode code = ParserAtomToSymbolCode(name);
7854 if (code == JS::SymbolCode::Limit) {
7855 reportError(callNode, JSMSG_UNEXPECTED_TYPE, "built-in name",
7856 "not a valid built-in");
7857 return false;
7858 }
7859
7860 return emit2(JSOp::Symbol, uint8_t(code));
7861}
7862
7863bool BytecodeEmitter::emitSelfHostedArgumentsLength(CallNode* callNode) {
7864 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7864); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sc->asFunctionBox()->needsArgsObj()"
")"); do { *((volatile int*)__null) = 7864; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7865 sc->asFunctionBox()->setUsesArgumentsIntrinsics();
7866
7867 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7867); AnnotateMozCrashReason("MOZ_ASSERT" "(" "callNode->args()->count() == 0"
")"); do { *((volatile int*)__null) = 7867; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7868
7869 return emit1(JSOp::ArgumentsLength);
7870}
7871
7872bool BytecodeEmitter::emitSelfHostedGetArgument(CallNode* callNode) {
7873 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7873); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sc->asFunctionBox()->needsArgsObj()"
")"); do { *((volatile int*)__null) = 7873; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7874 sc->asFunctionBox()->setUsesArgumentsIntrinsics();
7875
7876 ListNode* argsList = callNode->args();
7877 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7877); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1"
")"); do { *((volatile int*)__null) = 7877; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7878
7879 ParseNode* argNode = argsList->head();
7880 if (!emitTree(argNode)) {
7881 return false;
7882 }
7883
7884 return emit1(JSOp::GetActualArg);
7885}
7886
7887#ifdef DEBUG1
7888void BytecodeEmitter::assertSelfHostedExpectedTopLevel(ParseNode* node) {
7889 // The function argument is expected to be a simple binding/function name.
7890 // Eg. `function foo() { }; SpecialIntrinsic(foo)`
7891 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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7892); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::Name)"
") (" "argument must be a function name" ")"); do { *((volatile
int*)__null) = 7892; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
7892 "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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7892); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::Name)"
") (" "argument must be a function name" ")"); do { *((volatile
int*)__null) = 7892; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
7893 TaggedParserAtomIndex targetName = node->as<NameNode>().name();
7894
7895 // The special intrinsics must follow the target functions definition. A
7896 // simple assert is fine here since any hoisted function will cause a non-null
7897 // value to be set here.
7898 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7898); AnnotateMozCrashReason("MOZ_ASSERT" "(" "prevSelfHostedTopLevelFunction"
")"); do { *((volatile int*)__null) = 7898; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7899
7900 // The target function must match the most recently defined top-level
7901 // self-hosted function.
7902 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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7903); AnnotateMozCrashReason("MOZ_ASSERT" "(" "prevSelfHostedTopLevelFunction->explicitName() == targetName"
") (" "selfhost decorator must immediately follow target function"
")"); do { *((volatile int*)__null) = 7903; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7903 "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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7903); AnnotateMozCrashReason("MOZ_ASSERT" "(" "prevSelfHostedTopLevelFunction->explicitName() == targetName"
") (" "selfhost decorator must immediately follow target function"
")"); do { *((volatile int*)__null) = 7903; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7904}
7905#endif
7906
7907bool BytecodeEmitter::emitSelfHostedSetIsInlinableLargeFunction(
7908 CallNode* callNode) {
7909#ifdef DEBUG1
7910 ListNode* argsList = callNode->args();
7911
7912 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7912); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1"
")"); do { *((volatile int*)__null) = 7912; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7913
7914 assertSelfHostedExpectedTopLevel(argsList->head());
7915#endif
7916
7917 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7917); AnnotateMozCrashReason("MOZ_ASSERT" "(" "prevSelfHostedTopLevelFunction->isInitialCompilation"
")"); do { *((volatile int*)__null) = 7917; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7918 prevSelfHostedTopLevelFunction->setIsInlinableLargeFunction();
7919
7920 // This is still a call node, so we must generate a stack value.
7921 return emit1(JSOp::Undefined);
7922}
7923
7924bool BytecodeEmitter::emitSelfHostedSetCanonicalName(CallNode* callNode) {
7925 ListNode* argsList = callNode->args();
7926
7927 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7927); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2"
")"); do { *((volatile int*)__null) = 7927; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7928
7929#ifdef DEBUG1
7930 assertSelfHostedExpectedTopLevel(argsList->head());
7931#endif
7932
7933 ParseNode* nameNode = argsList->last();
7934 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7934); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nameNode->isKind(ParseNodeKind::StringExpr)"
")"); do { *((volatile int*)__null) = 7934; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7935 TaggedParserAtomIndex specName = nameNode->as<NameNode>().atom();
7936 // Canonical name must be atomized.
7937 compilationState.parserAtoms.markUsedByStencil(specName,
7938 ParserAtom::Atomize::Yes);
7939
7940 // Store the canonical name for instantiation.
7941 prevSelfHostedTopLevelFunction->functionStencil().setSelfHostedCanonicalName(
7942 specName);
7943
7944 return emit1(JSOp::Undefined);
7945}
7946
7947#ifdef DEBUG1
7948void BytecodeEmitter::assertSelfHostedUnsafeGetReservedSlot(
7949 ListNode* argsList) {
7950 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7950); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2"
")"); do { *((volatile int*)__null) = 7950; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7951
7952 ParseNode* objNode = argsList->head();
7953 ParseNode* slotNode = objNode->pn_next;
7954
7955 // Ensure that the slot argument is fixed, this is required by the JITs.
7956 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7957); AnnotateMozCrashReason("MOZ_ASSERT" "(" "slotNode->isKind(ParseNodeKind::NumberExpr)"
") (" "slot argument must be a constant" ")"); do { *((volatile
int*)__null) = 7957; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
7957 "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7957); AnnotateMozCrashReason("MOZ_ASSERT" "(" "slotNode->isKind(ParseNodeKind::NumberExpr)"
") (" "slot argument must be a constant" ")"); do { *((volatile
int*)__null) = 7957; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
7958}
7959
7960void BytecodeEmitter::assertSelfHostedUnsafeSetReservedSlot(
7961 ListNode* argsList) {
7962 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7962); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 3"
")"); do { *((volatile int*)__null) = 7962; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7963
7964 ParseNode* objNode = argsList->head();
7965 ParseNode* slotNode = objNode->pn_next;
7966
7967 // Ensure that the slot argument is fixed, this is required by the JITs.
7968 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7969); AnnotateMozCrashReason("MOZ_ASSERT" "(" "slotNode->isKind(ParseNodeKind::NumberExpr)"
") (" "slot argument must be a constant" ")"); do { *((volatile
int*)__null) = 7969; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
7969 "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7969); AnnotateMozCrashReason("MOZ_ASSERT" "(" "slotNode->isKind(ParseNodeKind::NumberExpr)"
") (" "slot argument must be a constant" ")"); do { *((volatile
int*)__null) = 7969; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
7970}
7971#endif
7972
7973/* A version of emitCalleeAndThis for the optional cases:
7974 * * a?.()
7975 * * a?.b()
7976 * * a?.["b"]()
7977 * * (a?.b)()
7978 * * a?.#b()
7979 *
7980 * See emitCallOrNew and emitOptionalCall for more context.
7981 */
7982bool BytecodeEmitter::emitOptionalCalleeAndThis(ParseNode* callee,
7983 CallNode* call,
7984 CallOrNewEmitter& cone,
7985 OptionalEmitter& oe) {
7986 AutoCheckRecursionLimit recursion(fc);
7987 if (!recursion.check(fc)) {
7988 return false;
7989 }
7990
7991 switch (ParseNodeKind kind = callee->getKind()) {
7992 case ParseNodeKind::Name: {
7993 auto name = callee->as<NameNode>().name();
7994 if (!cone.emitNameCallee(name)) {
7995 // [stack] CALLEE THIS
7996 return false;
7997 }
7998 break;
7999 }
8000
8001 case ParseNodeKind::OptionalDotExpr: {
8002 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8002); AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode != BytecodeEmitter::SelfHosting"
")"); do { *((volatile int*)__null) = 8002; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8003 OptionalPropertyAccess* prop = &callee->as<OptionalPropertyAccess>();
8004 bool isSuper = false;
8005
8006 PropOpEmitter& poe = cone.prepareForPropCallee(isSuper);
8007 if (!emitOptionalDotExpression(prop, poe, isSuper, oe)) {
8008 // [stack] CALLEE THIS
8009 return false;
8010 }
8011 break;
8012 }
8013 case ParseNodeKind::ArgumentsLength:
8014 case ParseNodeKind::DotExpr: {
8015 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8015); AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode != BytecodeEmitter::SelfHosting"
")"); do { *((volatile int*)__null) = 8015; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8016 PropertyAccess* prop = &callee->as<PropertyAccess>();
8017 bool isSuper = prop->isSuper();
8018
8019 PropOpEmitter& poe = cone.prepareForPropCallee(isSuper);
8020 if (!emitOptionalDotExpression(prop, poe, isSuper, oe)) {
8021 // [stack] CALLEE THIS
8022 return false;
8023 }
8024 break;
8025 }
8026
8027 case ParseNodeKind::OptionalElemExpr: {
8028 OptionalPropertyByValue* elem = &callee->as<OptionalPropertyByValue>();
8029 bool isSuper = false;
8030 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8030); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 8030; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8031 ElemOpEmitter& eoe = cone.prepareForElemCallee(isSuper);
8032 if (!emitOptionalElemExpression(elem, eoe, isSuper, oe)) {
8033 // [stack] CALLEE THIS
8034 return false;
8035 }
8036 break;
8037 }
8038 case ParseNodeKind::ElemExpr: {
8039 PropertyByValue* elem = &callee->as<PropertyByValue>();
8040 bool isSuper = elem->isSuper();
8041 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8041); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 8041; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8042 ElemOpEmitter& eoe = cone.prepareForElemCallee(isSuper);
8043 if (!emitOptionalElemExpression(elem, eoe, isSuper, oe)) {
8044 // [stack] CALLEE THIS
8045 return false;
8046 }
8047 break;
8048 }
8049
8050 case ParseNodeKind::PrivateMemberExpr:
8051 case ParseNodeKind::OptionalPrivateMemberExpr: {
8052 PrivateMemberAccessBase* privateExpr =
8053 &callee->as<PrivateMemberAccessBase>();
8054 PrivateOpEmitter& xoe =
8055 cone.prepareForPrivateCallee(privateExpr->privateName().name());
8056 if (!emitOptionalPrivateExpression(privateExpr, xoe, oe)) {
8057 // [stack] CALLEE THIS
8058 return false;
8059 }
8060 break;
8061 }
8062
8063 case ParseNodeKind::Function:
8064 if (!cone.prepareForFunctionCallee()) {
8065 return false;
8066 }
8067 if (!emitOptionalTree(callee, oe)) {
8068 // [stack] CALLEE
8069 return false;
8070 }
8071 break;
8072
8073 case ParseNodeKind::OptionalChain: {
8074 return emitCalleeAndThisForOptionalChain(&callee->as<UnaryNode>(), call,
8075 cone);
8076 }
8077
8078 default:
8079 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8079); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "kind != ParseNodeKind::SuperBase"
")"); do { *((volatile int*)__null) = 8079; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8080
8081 if (!cone.prepareForOtherCallee()) {
8082 return false;
8083 }
8084 if (!emitOptionalTree(callee, oe)) {
8085 // [stack] CALLEE
8086 return false;
8087 }
8088 break;
8089 }
8090
8091 if (!cone.emitThis()) {
8092 // [stack] CALLEE THIS
8093 return false;
8094 }
8095
8096 return true;
8097}
8098
8099bool BytecodeEmitter::emitCalleeAndThis(ParseNode* callee, CallNode* maybeCall,
8100 CallOrNewEmitter& cone) {
8101 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8101); AnnotateMozCrashReason("MOZ_ASSERT" "(" "maybeCall->callee() == callee"
")"); do { *((volatile int*)__null) = 8101; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
8102
8103 switch (callee->getKind()) {
8104 case ParseNodeKind::Name: {
8105 auto name = callee->as<NameNode>().name();
8106 if (!cone.emitNameCallee(name)) {
8107 // [stack] CALLEE THIS?
8108 return false;
8109 }
8110 break;
8111 }
8112 case ParseNodeKind::ArgumentsLength:
8113 case ParseNodeKind::DotExpr: {
8114 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8114); AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode != BytecodeEmitter::SelfHosting"
")"); do { *((volatile int*)__null) = 8114; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8115 PropertyAccess* prop = &callee->as<PropertyAccess>();
8116 bool isSuper = prop->isSuper();
8117
8118 PropOpEmitter& poe = cone.prepareForPropCallee(isSuper);
8119 if (!poe.prepareForObj()) {
8120 return false;
8121 }
8122 if (isSuper) {
8123 UnaryNode* base = &prop->expression().as<UnaryNode>();
8124 if (!emitGetThisForSuperBase(base)) {
8125 // [stack] THIS
8126 return false;
8127 }
8128 } else {
8129 if (!emitPropLHS(prop)) {
8130 // [stack] OBJ
8131 return false;
8132 }
8133 }
8134 if (!poe.emitGet(prop->key().atom())) {
8135 // [stack] CALLEE THIS?
8136 return false;
8137 }
8138
8139 break;
8140 }
8141 case ParseNodeKind::ElemExpr: {
8142 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8142); AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode != BytecodeEmitter::SelfHosting"
")"); do { *((volatile int*)__null) = 8142; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8143 PropertyByValue* elem = &callee->as<PropertyByValue>();
8144 bool isSuper = elem->isSuper();
8145 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8145); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 8145; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8146 ElemOpEmitter& eoe = cone.prepareForElemCallee(isSuper);
8147 if (!emitElemObjAndKey(elem, eoe)) {
8148 // [stack] # if Super
8149 // [stack] THIS? THIS KEY
8150 // [stack] # otherwise
8151 // [stack] OBJ? OBJ KEY
8152 return false;
8153 }
8154 if (!eoe.emitGet()) {
8155 // [stack] CALLEE THIS?
8156 return false;
8157 }
8158
8159 break;
8160 }
8161 case ParseNodeKind::PrivateMemberExpr: {
8162 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8162); AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode != BytecodeEmitter::SelfHosting"
")"); do { *((volatile int*)__null) = 8162; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8163 PrivateMemberAccessBase* privateExpr =
8164 &callee->as<PrivateMemberAccessBase>();
8165 PrivateOpEmitter& xoe =
8166 cone.prepareForPrivateCallee(privateExpr->privateName().name());
8167 if (!emitTree(&privateExpr->expression())) {
8168 // [stack] OBJ
8169 return false;
8170 }
8171 if (!xoe.emitReference()) {
8172 // [stack] OBJ NAME
8173 return false;
8174 }
8175 if (!xoe.emitGetForCallOrNew()) {
8176 // [stack] CALLEE THIS
8177 return false;
8178 }
8179
8180 break;
8181 }
8182 case ParseNodeKind::Function:
8183 if (!cone.prepareForFunctionCallee()) {
8184 return false;
8185 }
8186 if (!emitTree(callee)) {
8187 // [stack] CALLEE
8188 return false;
8189 }
8190 break;
8191 case ParseNodeKind::SuperBase:
8192 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8192); AnnotateMozCrashReason("MOZ_ASSERT" "(" "maybeCall" ")"
); do { *((volatile int*)__null) = 8192; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8193 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8193); AnnotateMozCrashReason("MOZ_ASSERT" "(" "maybeCall->isKind(ParseNodeKind::SuperCallExpr)"
")"); do { *((volatile int*)__null) = 8193; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8194 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8194); AnnotateMozCrashReason("MOZ_ASSERT" "(" "callee->isKind(ParseNodeKind::SuperBase)"
")"); do { *((volatile int*)__null) = 8194; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8195 if (!cone.emitSuperCallee()) {
8196 // [stack] CALLEE IsConstructing
8197 return false;
8198 }
8199 break;
8200 case ParseNodeKind::OptionalChain: {
8201 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8201); AnnotateMozCrashReason("MOZ_ASSERT" "(" "maybeCall" ")"
); do { *((volatile int*)__null) = 8201; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8202 return emitCalleeAndThisForOptionalChain(&callee->as<UnaryNode>(),
8203 maybeCall, cone);
8204 }
8205 default:
8206 if (!cone.prepareForOtherCallee()) {
8207 return false;
8208 }
8209 if (!emitTree(callee)) {
8210 return false;
8211 }
8212 break;
8213 }
8214
8215 if (!cone.emitThis()) {
8216 // [stack] CALLEE THIS
8217 return false;
8218 }
8219
8220 return true;
8221}
8222
8223ParseNode* BytecodeEmitter::getCoordNode(ParseNode* callNode,
8224 ParseNode* calleeNode, JSOp op,
8225 ListNode* argsList) const {
8226 ParseNode* coordNode = callNode;
8227 if (op == JSOp::Call || op == JSOp::SpreadCall) {
8228 // Default to using the location of the `(` itself.
8229 // obj[expr]() // expression
8230 // ^ // column coord
8231 coordNode = argsList;
8232
8233 switch (calleeNode->getKind()) {
8234 case ParseNodeKind::ArgumentsLength:
8235 case ParseNodeKind::DotExpr:
8236 // Use the position of a property access identifier.
8237 //
8238 // obj().aprop() // expression
8239 // ^ // column coord
8240 //
8241 // Note: Because of the constant folding logic in FoldElement,
8242 // this case also applies for constant string properties.
8243 //
8244 // obj()['aprop']() // expression
8245 // ^ // column coord
8246 coordNode = &calleeNode->as<PropertyAccess>().key();
8247 break;
8248 case ParseNodeKind::Name: {
8249 // Use the start of callee name unless it is at a separator
8250 // or has no args.
8251 //
8252 // 2 + obj() // expression
8253 // ^ // column coord
8254 //
8255 if (argsList->empty() ||
8256 !bytecodeSection().atSeparator(calleeNode->pn_pos.begin)) {
8257 // Use the start of callee names.
8258 coordNode = calleeNode;
8259 }
8260 break;
8261 }
8262
8263 default:
8264 break;
8265 }
8266 }
8267 return coordNode;
8268}
8269
8270bool BytecodeEmitter::emitArguments(ListNode* argsList, bool isCall,
8271 bool isSpread, CallOrNewEmitter& cone) {
8272 uint32_t argc = argsList->count();
8273 if (argc >= ARGC_LIMIT) {
8274 reportError(argsList,
8275 isCall ? JSMSG_TOO_MANY_FUN_ARGS : JSMSG_TOO_MANY_CON_ARGS);
8276 return false;
8277 }
8278 if (!isSpread) {
8279 if (!cone.prepareForNonSpreadArguments()) {
8280 // [stack] CALLEE THIS
8281 return false;
8282 }
8283 for (ParseNode* arg : argsList->contents()) {
8284 if (!updateSourceCoordNotesIfNonLiteral(arg)) {
8285 return false;
8286 }
8287 if (!emitTree(arg)) {
8288 // [stack] CALLEE THIS ARG*
8289 return false;
8290 }
8291 }
8292 } else if (cone.wantSpreadOperand()) {
8293 auto* spreadNode = &argsList->head()->as<UnaryNode>();
8294 if (!updateSourceCoordNotesIfNonLiteral(spreadNode->kid())) {
8295 return false;
8296 }
8297 if (!emitTree(spreadNode->kid())) {
8298 // [stack] CALLEE THIS ARG0
8299 return false;
8300 }
8301
8302 if (!cone.emitSpreadArgumentsTest()) {
8303 // [stack] CALLEE THIS ARG0
8304 return false;
8305 }
8306
8307 if (cone.wantSpreadIteration()) {
8308 if (!emitSpreadIntoArray(spreadNode)) {
8309 // [stack] CALLEE THIS ARR
8310 return false;
8311 }
8312 }
8313
8314 if (!cone.emitSpreadArgumentsTestEnd()) {
8315 // [stack] CALLEE THIS ARR
8316 return false;
8317 }
8318 } else {
8319 if (!cone.prepareForSpreadArguments()) {
8320 // [stack] CALLEE THIS
8321 return false;
8322 }
8323 if (!emitArray(argsList)) {
8324 // [stack] CALLEE THIS ARR
8325 return false;
8326 }
8327 }
8328
8329 return true;
8330}
8331
8332bool BytecodeEmitter::emitOptionalCall(CallNode* callNode, OptionalEmitter& oe,
8333 ValueUsage valueUsage) {
8334 /*
8335 * A modified version of emitCallOrNew that handles optional calls.
8336 *
8337 * These include the following:
8338 * a?.()
8339 * a.b?.()
8340 * a.["b"]?.()
8341 * (a?.b)?.()
8342 *
8343 * See CallOrNewEmitter for more context.
8344 */
8345 ParseNode* calleeNode = callNode->callee();
8346 ListNode* argsList = callNode->args();
8347 bool isSpread = IsSpreadOp(callNode->callOp());
8348 JSOp op = callNode->callOp();
8349 uint32_t argc = argsList->count();
8350 bool isOptimizableSpread = isSpread && argc == 1;
8351
8352 CallOrNewEmitter cone(this, op,
8353 isOptimizableSpread
8354 ? CallOrNewEmitter::ArgumentsKind::SingleSpread
8355 : CallOrNewEmitter::ArgumentsKind::Other,
8356 valueUsage);
8357
8358 ParseNode* coordNode = getCoordNode(callNode, calleeNode, op, argsList);
8359
8360 if (!emitOptionalCalleeAndThis(calleeNode, callNode, cone, oe)) {
8361 // [stack] CALLEE THIS
8362 return false;
8363 }
8364
8365 if (callNode->isKind(ParseNodeKind::OptionalCallExpr)) {
8366 if (!oe.emitJumpShortCircuitForCall()) {
8367 // [stack] CALLEE THIS
8368 return false;
8369 }
8370 }
8371
8372 if (!emitArguments(argsList, /* isCall = */ true, isSpread, cone)) {
8373 // [stack] CALLEE THIS ARGS...
8374 return false;
8375 }
8376
8377 if (!cone.emitEnd(argc, coordNode->pn_pos.begin)) {
8378 // [stack] RVAL
8379 return false;
8380 }
8381
8382 return true;
8383}
8384
8385bool BytecodeEmitter::emitCallOrNew(CallNode* callNode, ValueUsage valueUsage) {
8386 /*
8387 * Emit callable invocation or operator new (constructor call) code.
8388 * First, emit code for the left operand to evaluate the callable or
8389 * constructable object expression.
8390 *
8391 * Then (or in a call case that has no explicit reference-base
8392 * object) we emit JSOp::Undefined to produce the undefined |this|
8393 * value required for calls (which non-strict mode functions
8394 * will box into the global object).
8395 */
8396 bool isCall = callNode->isKind(ParseNodeKind::CallExpr) ||
8397 callNode->isKind(ParseNodeKind::TaggedTemplateExpr);
8398 ParseNode* calleeNode = callNode->callee();
8399 ListNode* argsList = callNode->args();
8400 JSOp op = callNode->callOp();
8401
8402 if (calleeNode->isKind(ParseNodeKind::Name) &&
8403 emitterMode == BytecodeEmitter::SelfHosting && op == JSOp::Call) {
8404 // Calls to "forceInterpreter", "callFunction",
8405 // "callContentFunction", or "resumeGenerator" in self-hosted
8406 // code generate inline bytecode.
8407 //
8408 // NOTE: The list of special instruction names has to be kept in sync with
8409 // "js/src/builtin/.eslintrc.js".
8410 auto calleeName = calleeNode->as<NameNode>().name();
8411 if (calleeName == TaggedParserAtomIndex::WellKnown::callFunction()) {
8412 return emitSelfHostedCallFunction(callNode, JSOp::Call);
8413 }
8414 if (calleeName == TaggedParserAtomIndex::WellKnown::callContentFunction()) {
8415 return emitSelfHostedCallFunction(callNode, JSOp::CallContent);
8416 }
8417 if (calleeName ==
8418 TaggedParserAtomIndex::WellKnown::constructContentFunction()) {
8419 return emitSelfHostedCallFunction(callNode, JSOp::NewContent);
8420 }
8421 if (calleeName == TaggedParserAtomIndex::WellKnown::resumeGenerator()) {
8422 return emitSelfHostedResumeGenerator(callNode);
8423 }
8424 if (calleeName == TaggedParserAtomIndex::WellKnown::forceInterpreter()) {
8425 return emitSelfHostedForceInterpreter();
8426 }
8427 if (calleeName == TaggedParserAtomIndex::WellKnown::allowContentIter()) {
8428 return emitSelfHostedAllowContentIter(callNode);
8429 }
8430 if (calleeName ==
8431 TaggedParserAtomIndex::WellKnown::allowContentIterWith()) {
8432 return emitSelfHostedAllowContentIterWith(callNode);
8433 }
8434 if (calleeName ==
8435 TaggedParserAtomIndex::WellKnown::allowContentIterWithNext()) {
8436 return emitSelfHostedAllowContentIterWithNext(callNode);
8437 }
8438 if (calleeName == TaggedParserAtomIndex::WellKnown::DefineDataProperty() &&
8439 argsList->count() == 3) {
8440 return emitSelfHostedDefineDataProperty(callNode);
8441 }
8442 if (calleeName == TaggedParserAtomIndex::WellKnown::hasOwn()) {
8443 return emitSelfHostedHasOwn(callNode);
8444 }
8445 if (calleeName == TaggedParserAtomIndex::WellKnown::getPropertySuper()) {
8446 return emitSelfHostedGetPropertySuper(callNode);
8447 }
8448 if (calleeName == TaggedParserAtomIndex::WellKnown::ToNumeric()) {
8449 return emitSelfHostedToNumeric(callNode);
8450 }
8451 if (calleeName == TaggedParserAtomIndex::WellKnown::ToString()) {
8452 return emitSelfHostedToString(callNode);
8453 }
8454 if (calleeName ==
8455 TaggedParserAtomIndex::WellKnown::GetBuiltinConstructor()) {
8456 return emitSelfHostedGetBuiltinConstructor(callNode);
8457 }
8458 if (calleeName == TaggedParserAtomIndex::WellKnown::GetBuiltinPrototype()) {
8459 return emitSelfHostedGetBuiltinPrototype(callNode);
8460 }
8461 if (calleeName == TaggedParserAtomIndex::WellKnown::GetBuiltinSymbol()) {
8462 return emitSelfHostedGetBuiltinSymbol(callNode);
8463 }
8464 if (calleeName == TaggedParserAtomIndex::WellKnown::ArgumentsLength()) {
8465 return emitSelfHostedArgumentsLength(callNode);
8466 }
8467 if (calleeName == TaggedParserAtomIndex::WellKnown::GetArgument()) {
8468 return emitSelfHostedGetArgument(callNode);
8469 }
8470 if (calleeName ==
8471 TaggedParserAtomIndex::WellKnown::SetIsInlinableLargeFunction()) {
8472 return emitSelfHostedSetIsInlinableLargeFunction(callNode);
8473 }
8474 if (calleeName == TaggedParserAtomIndex::WellKnown::SetCanonicalName()) {
8475 return emitSelfHostedSetCanonicalName(callNode);
8476 }
8477 if (calleeName == TaggedParserAtomIndex::WellKnown::IsNullOrUndefined()) {
8478 return emitSelfHostedIsNullOrUndefined(callNode);
8479 }
8480 if (calleeName == TaggedParserAtomIndex::WellKnown::IteratorClose()) {
8481 return emitSelfHostedIteratorClose(callNode);
8482 }
8483#ifdef DEBUG1
8484 if (calleeName ==
8485 TaggedParserAtomIndex::WellKnown::UnsafeGetReservedSlot() ||
8486 calleeName == TaggedParserAtomIndex::WellKnown::
8487 UnsafeGetObjectFromReservedSlot() ||
8488 calleeName == TaggedParserAtomIndex::WellKnown::
8489 UnsafeGetInt32FromReservedSlot() ||
8490 calleeName == TaggedParserAtomIndex::WellKnown::
8491 UnsafeGetStringFromReservedSlot()) {
8492 // Make sure that this call is correct, but don't emit any special code.
8493 assertSelfHostedUnsafeGetReservedSlot(argsList);
8494 }
8495 if (calleeName ==
8496 TaggedParserAtomIndex::WellKnown::UnsafeSetReservedSlot()) {
8497 // Make sure that this call is correct, but don't emit any special code.
8498 assertSelfHostedUnsafeSetReservedSlot(argsList);
8499 }
8500#endif
8501 // Fall through
8502 }
8503
8504 uint32_t argc = argsList->count();
8505 bool isSpread = IsSpreadOp(op);
8506 bool isOptimizableSpread = isSpread && argc == 1;
8507 bool isDefaultDerivedClassConstructor =
8508 sc->isFunctionBox() && sc->asFunctionBox()->isDerivedClassConstructor() &&
8509 sc->asFunctionBox()->isSyntheticFunction();
8510 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8510); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isOptimizableSpread"
")"); do { *((volatile int*)__null) = 8510; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
8511 CallOrNewEmitter cone(
8512 this, op,
8513 isOptimizableSpread
8514 ? isDefaultDerivedClassConstructor
8515 ? CallOrNewEmitter::ArgumentsKind::PassthroughRest
8516 : CallOrNewEmitter::ArgumentsKind::SingleSpread
8517 : CallOrNewEmitter::ArgumentsKind::Other,
8518 valueUsage);
8519
8520 if (!emitCalleeAndThis(calleeNode, callNode, cone)) {
8521 // [stack] CALLEE THIS
8522 return false;
8523 }
8524 if (!emitArguments(argsList, isCall, isSpread, cone)) {
8525 // [stack] CALLEE THIS ARGS...
8526 return false;
8527 }
8528
8529 // Push new.target for construct calls.
8530 if (IsConstructOp(op)) {
8531 if (op == JSOp::SuperCall || op == JSOp::SpreadSuperCall) {
8532 if (!emitNewTarget(callNode)) {
8533 // [stack] CALLEE THIS ARGS.. NEW.TARGET
8534 return false;
8535 }
8536 } else {
8537 // Repush the callee as new.target
8538 uint32_t effectiveArgc = isSpread ? 1 : argc;
8539 if (!emitDupAt(effectiveArgc + 1)) {
8540 // [stack] CALLEE THIS ARGS.. CALLEE
8541 return false;
8542 }
8543 }
8544 }
8545
8546 ParseNode* coordNode = getCoordNode(callNode, calleeNode, op, argsList);
8547
8548 if (!cone.emitEnd(argc, coordNode->pn_pos.begin)) {
8549 // [stack] RVAL
8550 return false;
8551 }
8552
8553 return true;
8554}
8555
8556// This list must be kept in the same order in several places:
8557// - The binary operators in ParseNode.h ,
8558// - the binary operators in TokenKind.h
8559// - the precedence list in Parser.cpp
8560static const JSOp ParseNodeKindToJSOp[] = {
8561 // Some binary ops require special code generation (PrivateIn);
8562 // these should not use BinaryOpParseNodeKindToJSOp. This table fills those
8563 // slots with Nops to make the rest of the table lookup work.
8564 JSOp::Coalesce, JSOp::Or, JSOp::And, JSOp::BitOr, JSOp::BitXor,
8565 JSOp::BitAnd, JSOp::StrictEq, JSOp::Eq, JSOp::StrictNe, JSOp::Ne,
8566 JSOp::Lt, JSOp::Le, JSOp::Gt, JSOp::Ge, JSOp::Instanceof,
8567 JSOp::In, JSOp::Nop, JSOp::Lsh, JSOp::Rsh, JSOp::Ursh,
8568 JSOp::Add, JSOp::Sub, JSOp::Mul, JSOp::Div, JSOp::Mod,
8569 JSOp::Pow};
8570
8571static inline JSOp BinaryOpParseNodeKindToJSOp(ParseNodeKind pnk) {
8572 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8572); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pnk >= ParseNodeKind::BinOpFirst"
")"); do { *((volatile int*)__null) = 8572; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8573 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8573); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pnk <= ParseNodeKind::BinOpLast"
")"); do { *((volatile int*)__null) = 8573; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8574 int parseNodeFirst = size_t(ParseNodeKind::BinOpFirst);
8575#ifdef DEBUG1
8576 int jsopArraySize = std::size(ParseNodeKindToJSOp);
8577 int parseNodeKindListSize =
8578 size_t(ParseNodeKind::BinOpLast) - parseNodeFirst + 1;
8579 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8579); AnnotateMozCrashReason("MOZ_ASSERT" "(" "jsopArraySize == parseNodeKindListSize"
")"); do { *((volatile int*)__null) = 8579; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8580 // Ensure we don't use this to find an op for a parse node
8581 // requiring special emission rules.
8582 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8582); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ParseNodeKindToJSOp[size_t(pnk) - parseNodeFirst] != JSOp::Nop"
")"); do { *((volatile int*)__null) = 8582; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8583#endif
8584 return ParseNodeKindToJSOp[size_t(pnk) - parseNodeFirst];
8585}
8586
8587bool BytecodeEmitter::emitRightAssociative(ListNode* node) {
8588 // ** is the only right-associative operator.
8589 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8589); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::PowExpr)"
")"); do { *((volatile int*)__null) = 8589; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8590
8591 // Right-associative operator chain.
8592 for (ParseNode* subexpr : node->contents()) {
8593 if (!updateSourceCoordNotesIfNonLiteral(subexpr)) {
8594 return false;
8595 }
8596 if (!emitTree(subexpr)) {
8597 return false;
8598 }
8599 }
8600 for (uint32_t i = 0; i < node->count() - 1; i++) {
8601 if (!emit1(JSOp::Pow)) {
8602 return false;
8603 }
8604 }
8605 return true;
8606}
8607
8608bool BytecodeEmitter::emitLeftAssociative(ListNode* node) {
8609 // Left-associative operator chain.
8610 if (!emitTree(node->head())) {
8611 return false;
8612 }
8613 JSOp op = BinaryOpParseNodeKindToJSOp(node->getKind());
8614 ParseNode* nextExpr = node->head()->pn_next;
8615 do {
8616 if (!updateSourceCoordNotesIfNonLiteral(nextExpr)) {
8617 return false;
8618 }
8619 if (!emitTree(nextExpr)) {
8620 return false;
8621 }
8622 if (!emit1(op)) {
8623 return false;
8624 }
8625 } while ((nextExpr = nextExpr->pn_next));
8626 return true;
8627}
8628
8629bool BytecodeEmitter::emitPrivateInExpr(ListNode* node) {
8630 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)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8630); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->head()->isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 8630; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8631
8632 NameNode& privateNameNode = node->head()->as<NameNode>();
8633 TaggedParserAtomIndex privateName = privateNameNode.name();
8634
8635 PrivateOpEmitter xoe(this, PrivateOpEmitter::Kind::ErgonomicBrandCheck,
8636 privateName);
8637
8638 ParseNode* valueNode = node->head()->pn_next;
8639 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8639); AnnotateMozCrashReason("MOZ_ASSERT" "(" "valueNode->pn_next == nullptr"
")"); do { *((volatile int*)__null) = 8639; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8640
8641 if (!emitTree(valueNode)) {
8642 // [stack] OBJ
8643 return false;
8644 }
8645
8646 if (!xoe.emitReference()) {
8647 // [stack] OBJ BRAND if private method
8648 // [stack] OBJ NAME if private field or accessor.
8649 return false;
8650 }
8651
8652 if (!xoe.emitBrandCheck()) {
8653 // [stack] OBJ BRAND BOOL if private method
8654 // [stack] OBJ NAME BOOL if private field or accessor.
8655 return false;
8656 }
8657
8658 if (!emitUnpickN(2)) {
8659 // [stack] BOOL OBJ BRAND if private method
8660 // [stack] BOOL OBJ NAME if private field or accessor.
8661 return false;
8662 }
8663
8664 if (!emitPopN(2)) {
8665 // [stack] BOOL
8666 return false;
8667 }
8668
8669 return true;
8670}
8671
8672/*
8673 * Special `emitTree` for Optional Chaining case.
8674 * Examples of this are `emitOptionalChain`, `emitDeleteOptionalChain` and
8675 * `emitCalleeAndThisForOptionalChain`.
8676 */
8677bool BytecodeEmitter::emitOptionalTree(
8678 ParseNode* pn, OptionalEmitter& oe,
8679 ValueUsage valueUsage /* = ValueUsage::WantValue */) {
8680 AutoCheckRecursionLimit recursion(fc);
8681 if (!recursion.check(fc)) {
8682 return false;
8683 }
8684 ParseNodeKind kind = pn->getKind();
8685 switch (kind) {
8686 case ParseNodeKind::OptionalDotExpr: {
8687 OptionalPropertyAccess* prop = &pn->as<OptionalPropertyAccess>();
8688 bool isSuper = false;
8689 PropOpEmitter poe(this, PropOpEmitter::Kind::Get,
8690 PropOpEmitter::ObjKind::Other);
8691 if (!emitOptionalDotExpression(prop, poe, isSuper, oe)) {
8692 return false;
8693 }
8694 break;
8695 }
8696 case ParseNodeKind::ArgumentsLength:
8697 case ParseNodeKind::DotExpr: {
8698 PropertyAccess* prop = &pn->as<PropertyAccess>();
8699 bool isSuper = prop->isSuper();
8700 PropOpEmitter poe(this, PropOpEmitter::Kind::Get,
8701 isSuper ? PropOpEmitter::ObjKind::Super
8702 : PropOpEmitter::ObjKind::Other);
8703 if (!emitOptionalDotExpression(prop, poe, isSuper, oe)) {
8704 return false;
8705 }
8706 break;
8707 }
8708
8709 case ParseNodeKind::OptionalElemExpr: {
8710 OptionalPropertyByValue* elem = &pn->as<OptionalPropertyByValue>();
8711 bool isSuper = false;
8712 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8712); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 8712; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8713 ElemOpEmitter eoe(this, ElemOpEmitter::Kind::Get,
8714 ElemOpEmitter::ObjKind::Other);
8715
8716 if (!emitOptionalElemExpression(elem, eoe, isSuper, oe)) {
8717 return false;
8718 }
8719 break;
8720 }
8721 case ParseNodeKind::ElemExpr: {
8722 PropertyByValue* elem = &pn->as<PropertyByValue>();
8723 bool isSuper = elem->isSuper();
8724 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8724); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 8724; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8725 ElemOpEmitter eoe(this, ElemOpEmitter::Kind::Get,
8726 isSuper ? ElemOpEmitter::ObjKind::Super
8727 : ElemOpEmitter::ObjKind::Other);
8728
8729 if (!emitOptionalElemExpression(elem, eoe, isSuper, oe)) {
8730 return false;
8731 }
8732 break;
8733 }
8734 case ParseNodeKind::PrivateMemberExpr:
8735 case ParseNodeKind::OptionalPrivateMemberExpr: {
8736 PrivateMemberAccessBase* privateExpr = &pn->as<PrivateMemberAccessBase>();
8737 PrivateOpEmitter xoe(this, PrivateOpEmitter::Kind::Get,
8738 privateExpr->privateName().name());
8739 if (!emitOptionalPrivateExpression(privateExpr, xoe, oe)) {
8740 return false;
8741 }
8742 break;
8743 }
8744 case ParseNodeKind::CallExpr:
8745 case ParseNodeKind::OptionalCallExpr:
8746 if (!emitOptionalCall(&pn->as<CallNode>(), oe, valueUsage)) {
8747 return false;
8748 }
8749 break;
8750 // List of accepted ParseNodeKinds that might appear only at the beginning
8751 // of an Optional Chain.
8752 // For example, a taggedTemplateExpr node might occur if we have
8753 // `test`?.b, with `test` as the taggedTemplateExpr ParseNode.
8754 default:
8755#ifdef DEBUG1
8756 // https://tc39.es/ecma262/#sec-primary-expression
8757 bool isPrimaryExpression =
8758 kind == ParseNodeKind::ThisExpr || kind == ParseNodeKind::Name ||
8759 kind == ParseNodeKind::PrivateName ||
8760 kind == ParseNodeKind::NullExpr || kind == ParseNodeKind::TrueExpr ||
8761 kind == ParseNodeKind::FalseExpr ||
8762 kind == ParseNodeKind::NumberExpr ||
8763 kind == ParseNodeKind::BigIntExpr ||
8764 kind == ParseNodeKind::StringExpr ||
8765 kind == ParseNodeKind::ArrayExpr ||
8766 kind == ParseNodeKind::ObjectExpr ||
8767 kind == ParseNodeKind::Function || kind == ParseNodeKind::ClassDecl ||
8768 kind == ParseNodeKind::RegExpExpr ||
8769 kind == ParseNodeKind::TemplateStringExpr ||
8770 kind == ParseNodeKind::TemplateStringListExpr ||
8771 kind == ParseNodeKind::RawUndefinedExpr || pn->isInParens();
8772
8773 // https://tc39.es/ecma262/#sec-left-hand-side-expressions
8774 bool isMemberExpression = isPrimaryExpression ||
8775 kind == ParseNodeKind::TaggedTemplateExpr ||
8776 kind == ParseNodeKind::NewExpr ||
8777 kind == ParseNodeKind::NewTargetExpr ||
8778 kind == ParseNodeKind::ImportMetaExpr;
8779
8780 bool isCallExpression = kind == ParseNodeKind::SetThis ||
8781 kind == ParseNodeKind::CallImportExpr;
8782
8783 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8784); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isMemberExpression || isCallExpression"
") (" "Unknown ParseNodeKind for OptionalChain" ")"); do { *
((volatile int*)__null) = 8784; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
8784 "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8784); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isMemberExpression || isCallExpression"
") (" "Unknown ParseNodeKind for OptionalChain" ")"); do { *
((volatile int*)__null) = 8784; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
8785#endif
8786 return emitTree(pn);
8787 }
8788 return true;
8789}
8790
8791// Handle the case of a call made on a OptionalChainParseNode.
8792// For example `(a?.b)()` and `(a?.b)?.()`.
8793bool BytecodeEmitter::emitCalleeAndThisForOptionalChain(
8794 UnaryNode* optionalChain, CallNode* callNode, CallOrNewEmitter& cone) {
8795 ParseNode* calleeNode = optionalChain->kid();
8796
8797 // Create a new OptionalEmitter, in order to emit the right bytecode
8798 // in isolation.
8799 OptionalEmitter oe(this, bytecodeSection().stackDepth());
8800
8801 if (!emitOptionalCalleeAndThis(calleeNode, callNode, cone, oe)) {
8802 // [stack] CALLEE THIS
8803 return false;
8804 }
8805
8806 // complete the jump if necessary. This will set both the "this" value
8807 // and the "callee" value to undefined, if the callee is undefined. It
8808 // does not matter much what the this value is, the function call will
8809 // fail if it is not optional, and be set to undefined otherwise.
8810 if (!oe.emitOptionalJumpTarget(JSOp::Undefined,
8811 OptionalEmitter::Kind::Reference)) {
8812 // [stack] # If shortcircuit
8813 // [stack] UNDEFINED UNDEFINED
8814 // [stack] # otherwise
8815 // [stack] CALLEE THIS
8816 return false;
8817 }
8818 return true;
8819}
8820
8821bool BytecodeEmitter::emitOptionalChain(UnaryNode* optionalChain,
8822 ValueUsage valueUsage) {
8823 ParseNode* expr = optionalChain->kid();
8824
8825 OptionalEmitter oe(this, bytecodeSection().stackDepth());
8826
8827 if (!emitOptionalTree(expr, oe, valueUsage)) {
8828 // [stack] VAL
8829 return false;
8830 }
8831
8832 if (!oe.emitOptionalJumpTarget(JSOp::Undefined)) {
8833 // [stack] # If shortcircuit
8834 // [stack] UNDEFINED
8835 // [stack] # otherwise
8836 // [stack] VAL
8837 return false;
8838 }
8839
8840 return true;
8841}
8842
8843bool BytecodeEmitter::emitOptionalDotExpression(PropertyAccessBase* prop,
8844 PropOpEmitter& poe,
8845 bool isSuper,
8846 OptionalEmitter& oe) {
8847 if (!poe.prepareForObj()) {
8848 // [stack]
8849 return false;
8850 }
8851
8852 if (isSuper) {
8853 UnaryNode* base = &prop->expression().as<UnaryNode>();
8854 if (!emitGetThisForSuperBase(base)) {
8855 // [stack] OBJ
8856 return false;
8857 }
8858 } else {
8859 if (!emitOptionalTree(&prop->expression(), oe)) {
8860 // [stack] OBJ
8861 return false;
8862 }
8863 }
8864
8865 if (prop->isKind(ParseNodeKind::OptionalDotExpr)) {
8866 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8866); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!isSuper" ")"
); do { *((volatile int*)__null) = 8866; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8867 if (!oe.emitJumpShortCircuit()) {
8868 // [stack] # if Jump
8869 // [stack] UNDEFINED-OR-NULL
8870 // [stack] # otherwise
8871 // [stack] OBJ
8872 return false;
8873 }
8874 }
8875
8876 if (!poe.emitGet(prop->key().atom())) {
8877 // [stack] PROP
8878 return false;
8879 }
8880
8881 return true;
8882}
8883
8884bool BytecodeEmitter::emitOptionalElemExpression(PropertyByValueBase* elem,
8885 ElemOpEmitter& eoe,
8886 bool isSuper,
8887 OptionalEmitter& oe) {
8888 if (!eoe.prepareForObj()) {
8889 // [stack]
8890 return false;
8891 }
8892
8893 if (isSuper) {
8894 UnaryNode* base = &elem->expression().as<UnaryNode>();
8895 if (!emitGetThisForSuperBase(base)) {
8896 // [stack] OBJ
8897 return false;
8898 }
8899 } else {
8900 if (!emitOptionalTree(&elem->expression(), oe)) {
8901 // [stack] OBJ
8902 return false;
8903 }
8904 }
8905
8906 if (elem->isKind(ParseNodeKind::OptionalElemExpr)) {
8907 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8907); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!isSuper" ")"
); do { *((volatile int*)__null) = 8907; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8908 if (!oe.emitJumpShortCircuit()) {
8909 // [stack] # if Jump
8910 // [stack] UNDEFINED-OR-NULL
8911 // [stack] # otherwise
8912 // [stack] OBJ
8913 return false;
8914 }
8915 }
8916
8917 if (!eoe.prepareForKey()) {
8918 // [stack] OBJ? OBJ
8919 return false;
8920 }
8921
8922 if (!emitTree(&elem->key())) {
8923 // [stack] OBJ? OBJ KEY
8924 return false;
8925 }
8926
8927 if (!eoe.emitGet()) {
8928 // [stack] ELEM
8929 return false;
8930 }
8931
8932 return true;
8933}
8934
8935bool BytecodeEmitter::emitOptionalPrivateExpression(
8936 PrivateMemberAccessBase* privateExpr, PrivateOpEmitter& xoe,
8937 OptionalEmitter& oe) {
8938 if (!emitOptionalTree(&privateExpr->expression(), oe)) {
8939 // [stack] OBJ
8940 return false;
8941 }
8942
8943 if (privateExpr->isKind(ParseNodeKind::OptionalPrivateMemberExpr)) {
8944 if (!oe.emitJumpShortCircuit()) {
8945 // [stack] # if Jump
8946 // [stack] UNDEFINED-OR-NULL
8947 // [stack] # otherwise
8948 // [stack] OBJ
8949 return false;
8950 }
8951 }
8952
8953 if (!xoe.emitReference()) {
8954 // [stack] OBJ NAME
8955 return false;
8956 }
8957 if (!xoe.emitGet()) {
8958 // [stack] CALLEE THIS # if call
8959 // [stack] VALUE # otherwise
8960 return false;
8961 }
8962
8963 return true;
8964}
8965
8966bool BytecodeEmitter::emitShortCircuit(ListNode* node, ValueUsage valueUsage) {
8967 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8969); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::OrExpr) || node->isKind(ParseNodeKind::CoalesceExpr) || node->isKind(ParseNodeKind::AndExpr)"
")"); do { *((volatile int*)__null) = 8969; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8968 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8969); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::OrExpr) || node->isKind(ParseNodeKind::CoalesceExpr) || node->isKind(ParseNodeKind::AndExpr)"
")"); do { *((volatile int*)__null) = 8969; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8969 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8969); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::OrExpr) || node->isKind(ParseNodeKind::CoalesceExpr) || node->isKind(ParseNodeKind::AndExpr)"
")"); do { *((volatile int*)__null) = 8969; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8970
8971 /*
8972 * JSOp::Or converts the operand on the stack to boolean, leaves the original
8973 * value on the stack and jumps if true; otherwise it falls into the next
8974 * bytecode, which pops the left operand and then evaluates the right operand.
8975 * The jump goes around the right operand evaluation.
8976 *
8977 * JSOp::And converts the operand on the stack to boolean and jumps if false;
8978 * otherwise it falls into the right operand's bytecode.
8979 */
8980
8981 TDZCheckCache tdzCache(this);
8982
8983 JSOp op;
8984 switch (node->getKind()) {
8985 case ParseNodeKind::OrExpr:
8986 op = JSOp::Or;
8987 break;
8988 case ParseNodeKind::CoalesceExpr:
8989 op = JSOp::Coalesce;
8990 break;
8991 case ParseNodeKind::AndExpr:
8992 op = JSOp::And;
8993 break;
8994 default:
8995 MOZ_CRASH("Unexpected ParseNodeKind")do { do { } while (false); MOZ_ReportCrash("" "Unexpected ParseNodeKind"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8995); AnnotateMozCrashReason("MOZ_CRASH(" "Unexpected ParseNodeKind"
")"); do { *((volatile int*)__null) = 8995; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
8996 }
8997
8998 JumpList jump;
8999
9000 // Left-associative operator chain: avoid too much recursion.
9001 //
9002 // Emit all nodes but the last.
9003 for (ParseNode* expr : node->contentsTo(node->last())) {
9004 if (!emitTree(expr)) {
9005 return false;
9006 }
9007 if (!emitJump(op, &jump)) {
9008 return false;
9009 }
9010 if (!emit1(JSOp::Pop)) {
9011 return false;
9012 }
9013 }
9014
9015 // Emit the last node
9016 if (!emitTree(node->last(), valueUsage)) {
9017 return false;
9018 }
9019
9020 if (!emitJumpTargetAndPatch(jump)) {
9021 return false;
9022 }
9023 return true;
9024}
9025
9026bool BytecodeEmitter::emitSequenceExpr(ListNode* node, ValueUsage valueUsage) {
9027 for (ParseNode* child : node->contentsTo(node->last())) {
9028 if (!updateSourceCoordNotes(child->pn_pos.begin)) {
9029 return false;
9030 }
9031 if (!emitTree(child, ValueUsage::IgnoreValue)) {
9032 return false;
9033 }
9034 if (!emit1(JSOp::Pop)) {
9035 return false;
9036 }
9037 }
9038
9039 ParseNode* child = node->last();
9040 if (!updateSourceCoordNotes(child->pn_pos.begin)) {
9041 return false;
9042 }
9043 if (!emitTree(child, valueUsage)) {
9044 return false;
9045 }
9046 return true;
9047}
9048
9049// Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See
9050// the comment on emitSwitch.
9051MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitIncOrDec(UnaryNode* incDec,
9052 ValueUsage valueUsage) {
9053 switch (incDec->kid()->getKind()) {
9054 case ParseNodeKind::ArgumentsLength:
9055 case ParseNodeKind::DotExpr:
9056 return emitPropIncDec(incDec, valueUsage);
9057 case ParseNodeKind::ElemExpr:
9058 return emitElemIncDec(incDec, valueUsage);
9059 case ParseNodeKind::PrivateMemberExpr:
9060 return emitPrivateIncDec(incDec, valueUsage);
9061 case ParseNodeKind::CallExpr:
9062 return emitCallIncDec(incDec);
9063 default:
9064 return emitNameIncDec(incDec, valueUsage);
9065 }
9066}
9067
9068// Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See
9069// the comment on emitSwitch.
9070MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitLabeledStatement(
9071 const LabeledStatement* labeledStmt) {
9072 auto name = labeledStmt->label();
9073 LabelEmitter label(this);
9074
9075 label.emitLabel(name);
9076
9077 if (!emitTree(labeledStmt->statement())) {
9078 return false;
9079 }
9080 if (!label.emitEnd()) {
9081 return false;
9082 }
9083
9084 return true;
9085}
9086
9087bool BytecodeEmitter::emitConditionalExpression(
9088 ConditionalExpression& conditional, ValueUsage valueUsage) {
9089 CondEmitter cond(this);
9090 if (!cond.emitCond()) {
9091 return false;
9092 }
9093
9094 ParseNode* conditionNode = &conditional.condition();
9095 auto conditionKind = IfEmitter::ConditionKind::Positive;
9096 if (conditionNode->isKind(ParseNodeKind::NotExpr)) {
9097 conditionNode = conditionNode->as<UnaryNode>().kid();
9098 conditionKind = IfEmitter::ConditionKind::Negative;
9099 }
9100
9101 // NOTE: NotExpr of conditionNode may be unwrapped, and in that case the
9102 // negation is handled by conditionKind.
9103 if (!emitTree(conditionNode)) {
9104 return false;
9105 }
9106
9107 if (!cond.emitThenElse(conditionKind)) {
9108 return false;
9109 }
9110
9111 if (!emitTree(&conditional.thenExpression(), valueUsage)) {
9112 return false;
9113 }
9114
9115 if (!cond.emitElse()) {
9116 return false;
9117 }
9118
9119 if (!emitTree(&conditional.elseExpression(), valueUsage)) {
9120 return false;
9121 }
9122
9123 if (!cond.emitEnd()) {
9124 return false;
9125 }
9126 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9126); AnnotateMozCrashReason("MOZ_ASSERT" "(" "cond.pushed() == 1"
")"); do { *((volatile int*)__null) = 9126; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9127
9128 return true;
9129}
9130
9131// Check for an object-literal property list that can be handled by the
9132// ObjLiteral writer. We ensure that for each `prop: value` pair, the key is a
9133// constant name or numeric index, there is no accessor specified, and the value
9134// can be encoded by an ObjLiteral instruction (constant number, string,
9135// boolean, null/undefined).
9136void BytecodeEmitter::isPropertyListObjLiteralCompatible(
9137 ListNode* obj, bool* withValues, bool* withoutValues) const {
9138 bool keysOK = true;
9139 bool valuesOK = true;
9140 uint32_t propCount = 0;
9141
9142 for (ParseNode* propdef : obj->contents()) {
9143 if (!propdef->is<BinaryNode>()) {
9144 keysOK = false;
9145 break;
9146 }
9147 propCount++;
9148
9149 BinaryNode* prop = &propdef->as<BinaryNode>();
9150 ParseNode* key = prop->left();
9151 ParseNode* value = prop->right();
9152
9153 // Computed keys not OK (ObjLiteral data stores constant keys).
9154 if (key->isKind(ParseNodeKind::ComputedName)) {
9155 keysOK = false;
9156 break;
9157 }
9158
9159 // BigIntExprs should have been lowered to computed names at parse
9160 // time, and so should be excluded above.
9161 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9161); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!key->isKind(ParseNodeKind::BigIntExpr)"
")"); do { *((volatile int*)__null) = 9161; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9162
9163 // Numeric keys OK as long as they are integers and in range.
9164 if (key->isKind(ParseNodeKind::NumberExpr)) {
9165 double numValue = key->as<NumericLiteral>().value();
9166 int32_t i = 0;
9167 if (!NumberIsInt32(numValue, &i)) {
9168 keysOK = false;
9169 break;
9170 }
9171 if (!ObjLiteralWriter::arrayIndexInRange(i)) {
9172 keysOK = false;
9173 break;
9174 }
9175 }
9176
9177 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9179); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr)"
")"); do { *((volatile int*)__null) = 9179; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9178 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9179); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr)"
")"); do { *((volatile int*)__null) = 9179; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9179 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9179); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr)"
")"); do { *((volatile int*)__null) = 9179; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9180
9181 AccessorType accessorType =
9182 prop->is<PropertyDefinition>()
9183 ? prop->as<PropertyDefinition>().accessorType()
9184 : AccessorType::None;
9185 if (accessorType != AccessorType::None) {
9186 keysOK = false;
9187 break;
9188 }
9189
9190 if (!isRHSObjLiteralCompatible(value)) {
9191 valuesOK = false;
9192 }
9193 }
9194
9195 if (propCount > SharedPropMap::MaxPropsForNonDictionary) {
9196 // JSOp::NewObject cannot accept dictionary-mode objects.
9197 keysOK = false;
9198 }
9199
9200 *withValues = keysOK && valuesOK;
9201 *withoutValues = keysOK;
9202}
9203
9204bool BytecodeEmitter::isArrayObjLiteralCompatible(ListNode* array) const {
9205 for (ParseNode* elem : array->contents()) {
9206 if (elem->isKind(ParseNodeKind::Spread)) {
9207 return false;
9208 }
9209 if (!isRHSObjLiteralCompatible(elem)) {
9210 return false;
9211 }
9212 }
9213 return true;
9214}
9215
9216bool BytecodeEmitter::emitPropertyList(ListNode* obj, PropertyEmitter& pe,
9217 PropListType type) {
9218 // [stack] CTOR? OBJ
9219
9220 size_t curFieldKeyIndex = 0;
9221 size_t curStaticFieldKeyIndex = 0;
9222 for (ParseNode* propdef : obj->contents()) {
9223 if (propdef->is<ClassField>()) {
9224 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9224); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == ClassBody"
")"); do { *((volatile int*)__null) = 9224; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9225 // Only handle computing field keys here: the .initializers lambda array
9226 // is created elsewhere.
9227 ClassField* field = &propdef->as<ClassField>();
9228 if (field->name().getKind() == ParseNodeKind::ComputedName) {
9229 auto fieldKeys =
9230 field->isStatic()
9231 ? TaggedParserAtomIndex::WellKnown::dot_staticFieldKeys_()
9232 : TaggedParserAtomIndex::WellKnown::dot_fieldKeys_();
9233 if (!emitGetName(fieldKeys)) {
9234 // [stack] CTOR OBJ ARRAY
9235 return false;
9236 }
9237
9238 ParseNode* nameExpr = field->name().as<UnaryNode>().kid();
9239
9240 if (!emitTree(nameExpr, ValueUsage::WantValue)) {
9241 // [stack] CTOR OBJ ARRAY KEY
9242 return false;
9243 }
9244
9245 if (!emit1(JSOp::ToPropertyKey)) {
9246 // [stack] CTOR OBJ ARRAY KEY
9247 return false;
9248 }
9249
9250 size_t fieldKeysIndex;
9251 if (field->isStatic()) {
9252 fieldKeysIndex = curStaticFieldKeyIndex++;
9253 } else {
9254 fieldKeysIndex = curFieldKeyIndex++;
9255 }
9256
9257 if (!emitUint32Operand(JSOp::InitElemArray, fieldKeysIndex)) {
9258 // [stack] CTOR OBJ ARRAY
9259 return false;
9260 }
9261
9262 if (!emit1(JSOp::Pop)) {
9263 // [stack] CTOR OBJ
9264 return false;
9265 }
9266 }
9267 continue;
9268 }
9269
9270 if (propdef->isKind(ParseNodeKind::StaticClassBlock)) {
9271 // Static class blocks are emitted as part of
9272 // emitCreateMemberInitializers.
9273 continue;
9274 }
9275
9276 if (propdef->is<LexicalScopeNode>()) {
9277 // Constructors are sometimes wrapped in LexicalScopeNodes. As we
9278 // already handled emitting the constructor, skip it.
9279 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>()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9280); AnnotateMozCrashReason("MOZ_ASSERT" "(" "propdef->as<LexicalScopeNode>().scopeBody()->is<ClassMethod>()"
")"); do { *((volatile int*)__null) = 9280; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9280 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>()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9280); AnnotateMozCrashReason("MOZ_ASSERT" "(" "propdef->as<LexicalScopeNode>().scopeBody()->is<ClassMethod>()"
")"); do { *((volatile int*)__null) = 9280; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9281 continue;
9282 }
9283
9284 // Handle __proto__: v specially because *only* this form, and no other
9285 // involving "__proto__", performs [[Prototype]] mutation.
9286 if (propdef->isKind(ParseNodeKind::MutateProto)) {
9287 // [stack] OBJ
9288 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9288); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == ObjectLiteral"
")"); do { *((volatile int*)__null) = 9288; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9289 if (!pe.prepareForProtoValue(propdef->pn_pos.begin)) {
9290 // [stack] OBJ
9291 return false;
9292 }
9293 if (!emitTree(propdef->as<UnaryNode>().kid())) {
9294 // [stack] OBJ PROTO
9295 return false;
9296 }
9297 if (!pe.emitMutateProto()) {
9298 // [stack] OBJ
9299 return false;
9300 }
9301 continue;
9302 }
9303
9304 if (propdef->isKind(ParseNodeKind::Spread)) {
9305 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9305); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == ObjectLiteral"
")"); do { *((volatile int*)__null) = 9305; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9306 // [stack] OBJ
9307 if (!pe.prepareForSpreadOperand(propdef->pn_pos.begin)) {
9308 // [stack] OBJ OBJ
9309 return false;
9310 }
9311 if (!emitTree(propdef->as<UnaryNode>().kid())) {
9312 // [stack] OBJ OBJ VAL
9313 return false;
9314 }
9315 if (!pe.emitSpread()) {
9316 // [stack] OBJ
9317 return false;
9318 }
9319 continue;
9320 }
9321
9322 BinaryNode* prop = &propdef->as<BinaryNode>();
9323
9324 ParseNode* key = prop->left();
9325 AccessorType accessorType;
9326 if (prop->is<ClassMethod>()) {
9327 ClassMethod& method = prop->as<ClassMethod>();
9328 accessorType = method.accessorType();
9329
9330 if (!method.isStatic() && key->isKind(ParseNodeKind::PrivateName) &&
9331 accessorType != AccessorType::None) {
9332 // Private non-static accessors are stamped onto instances from
9333 // initializers; see emitCreateMemberInitializers.
9334 continue;
9335 }
9336 } else if (prop->is<PropertyDefinition>()) {
9337 accessorType = prop->as<PropertyDefinition>().accessorType();
9338 } else {
9339 accessorType = AccessorType::None;
9340 }
9341
9342 auto emitValue = [this, &key, &prop, accessorType, &pe]() {
9343 // [stack] CTOR? OBJ CTOR? KEY?
9344
9345 ParseNode* propVal = prop->right();
9346 if (propVal->isDirectRHSAnonFunction()) {
9347 // The following branches except for the last `else` clause emit the
9348 // cases handled in NameResolver::resolveFun (see NameFunctions.cpp)
9349 if (key->isKind(ParseNodeKind::ObjectPropertyName) ||
9350 key->isKind(ParseNodeKind::PrivateName) ||
9351 key->isKind(ParseNodeKind::StringExpr)) {
9352 auto keyAtom = key->as<NameNode>().atom();
9353 if (!emitAnonymousFunctionWithName(propVal, keyAtom)) {
9354 // [stack] CTOR? OBJ CTOR? VAL
9355 return false;
9356 }
9357 } else if (key->isKind(ParseNodeKind::NumberExpr)) {
9358 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9358); AnnotateMozCrashReason("MOZ_ASSERT" "(" "accessorType == AccessorType::None"
")"); do { *((volatile int*)__null) = 9358; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9359
9360 auto keyAtom = key->as<NumericLiteral>().toAtom(fc, parserAtoms());
9361 if (!keyAtom) {
9362 return false;
9363 }
9364 if (!emitAnonymousFunctionWithName(propVal, keyAtom)) {
9365 // [stack] CTOR? OBJ CTOR? KEY VAL
9366 return false;
9367 }
9368 } else if (key->isKind(ParseNodeKind::ComputedName) &&
9369 (key->as<UnaryNode>().kid()->isKind(
9370 ParseNodeKind::NumberExpr) ||
9371 key->as<UnaryNode>().kid()->isKind(
9372 ParseNodeKind::StringExpr)) &&
9373 accessorType == AccessorType::None) {
9374 ParseNode* keyKid = key->as<UnaryNode>().kid();
9375 if (keyKid->isKind(ParseNodeKind::NumberExpr)) {
9376 auto keyAtom =
9377 keyKid->as<NumericLiteral>().toAtom(fc, parserAtoms());
9378 if (!keyAtom) {
9379 return false;
9380 }
9381 if (!emitAnonymousFunctionWithName(propVal, keyAtom)) {
9382 // [stack] CTOR? OBJ CTOR? KEY VAL
9383 return false;
9384 }
9385 } else {
9386 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9386); AnnotateMozCrashReason("MOZ_ASSERT" "(" "keyKid->isKind(ParseNodeKind::StringExpr)"
")"); do { *((volatile int*)__null) = 9386; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9387 auto keyAtom = keyKid->as<NameNode>().atom();
9388 if (!emitAnonymousFunctionWithName(propVal, keyAtom)) {
9389 // [stack] CTOR? OBJ CTOR? KEY VAL
9390 return false;
9391 }
9392 }
9393 } else {
9394 // Either a proper computed property name or a synthetic computed
9395 // property name for BigInt keys.
9396 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9396); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::ComputedName)"
")"); do { *((volatile int*)__null) = 9396; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9397
9398 FunctionPrefixKind prefix =
9399 accessorType == AccessorType::None ? FunctionPrefixKind::None
9400 : accessorType == AccessorType::Getter ? FunctionPrefixKind::Get
9401 : FunctionPrefixKind::Set;
9402
9403 if (!emitAnonymousFunctionWithComputedName(propVal, prefix)) {
9404 // [stack] CTOR? OBJ CTOR? KEY VAL
9405 return false;
9406 }
9407 }
9408 } else {
9409 if (!emitTree(propVal)) {
9410 // [stack] CTOR? OBJ CTOR? KEY? VAL
9411 return false;
9412 }
9413 }
9414
9415 if (propVal->is<FunctionNode>() &&
9416 propVal->as<FunctionNode>().funbox()->needsHomeObject()) {
9417 if (!pe.emitInitHomeObject()) {
9418 // [stack] CTOR? OBJ CTOR? KEY? FUN
9419 return false;
9420 }
9421 }
9422
9423#ifdef ENABLE_DECORATORS
9424 if (prop->is<ClassMethod>()) {
9425 ClassMethod& method = prop->as<ClassMethod>();
9426 if (method.decorators() && !method.decorators()->empty()) {
9427 DecoratorEmitter::Kind kind;
9428 switch (method.accessorType()) {
9429 case AccessorType::Getter:
9430 kind = DecoratorEmitter::Getter;
9431 break;
9432 case AccessorType::Setter:
9433 kind = DecoratorEmitter::Setter;
9434 break;
9435 case AccessorType::None:
9436 kind = DecoratorEmitter::Method;
9437 break;
9438 }
9439
9440 if (!method.isStatic()) {
9441 bool hasKeyOnStack = key->isKind(ParseNodeKind::NumberExpr) ||
9442 key->isKind(ParseNodeKind::ComputedName);
9443 if (!emitDupAt(hasKeyOnStack ? 4 : 3)) {
9444 // [stack] ADDINIT OBJ KEY? VAL ADDINIT
9445 return false;
9446 }
9447 } else {
9448 // TODO: See bug 1868220 for support for static methods.
9449 // Note: Key will be present if this has a private name.
9450 if (!emit1(JSOp::Undefined)) {
9451 // [stack] CTOR OBJ CTOR KEY? VAL ADDINIT
9452 return false;
9453 }
9454 }
9455
9456 if (!emit1(JSOp::Swap)) {
9457 // [stack] ADDINIT CTOR? OBJ CTOR? KEY? ADDINIT VAL
9458 return false;
9459 }
9460
9461 // The decorators are applied to the current value on the stack,
9462 // possibly replacing it.
9463 DecoratorEmitter de(this);
9464 if (!de.emitApplyDecoratorsToElementDefinition(
9465 kind, key, method.decorators(), method.isStatic())) {
9466 // [stack] ADDINIT CTOR? OBJ CTOR? KEY? ADDINIT VAL
9467 return false;
9468 }
9469
9470 if (!emit1(JSOp::Swap)) {
9471 // [stack] ADDINIT CTOR? OBJ CTOR? KEY? VAL ADDINIT
9472 return false;
9473 }
9474
9475 if (!emitPopN(1)) {
9476 // [stack] ADDINIT CTOR? OBJ CTOR? KEY? VAL
9477 return false;
9478 }
9479 }
9480 }
9481#endif
9482
9483 return true;
9484 };
9485
9486 PropertyEmitter::Kind kind =
9487 (type == ClassBody && propdef->as<ClassMethod>().isStatic())
9488 ? PropertyEmitter::Kind::Static
9489 : PropertyEmitter::Kind::Prototype;
9490 if (key->isKind(ParseNodeKind::ObjectPropertyName) ||
9491 key->isKind(ParseNodeKind::StringExpr)) {
9492 // [stack] CTOR? OBJ
9493
9494 auto keyAtom = key->as<NameNode>().atom();
9495
9496 // emitClass took care of constructor already.
9497 if (type == ClassBody &&
9498 keyAtom == TaggedParserAtomIndex::WellKnown::constructor() &&
9499 !propdef->as<ClassMethod>().isStatic()) {
9500 continue;
9501 }
9502
9503 if (!pe.prepareForPropValue(propdef->pn_pos.begin, kind)) {
9504 // [stack] CTOR? OBJ CTOR?
9505 return false;
9506 }
9507
9508 if (!emitValue()) {
9509 // [stack] CTOR? OBJ CTOR? VAL
9510 return false;
9511 }
9512
9513 if (!pe.emitInit(accessorType, keyAtom)) {
9514 // [stack] CTOR? OBJ
9515 return false;
9516 }
9517
9518 continue;
9519 }
9520
9521 if (key->isKind(ParseNodeKind::NumberExpr)) {
9522 // [stack] CTOR? OBJ
9523 if (!pe.prepareForIndexPropKey(propdef->pn_pos.begin, kind)) {
9524 // [stack] CTOR? OBJ CTOR?
9525 return false;
9526 }
9527 if (!emitNumberOp(key->as<NumericLiteral>().value())) {
9528 // [stack] CTOR? OBJ CTOR? KEY
9529 return false;
9530 }
9531 if (!pe.prepareForIndexPropValue()) {
9532 // [stack] CTOR? OBJ CTOR? KEY
9533 return false;
9534 }
9535 if (!emitValue()) {
9536 // [stack] CTOR? OBJ CTOR? KEY VAL
9537 return false;
9538 }
9539
9540 if (!pe.emitInitIndexOrComputed(accessorType)) {
9541 // [stack] CTOR? OBJ
9542 return false;
9543 }
9544
9545 continue;
9546 }
9547
9548 if (key->isKind(ParseNodeKind::ComputedName)) {
9549 // Either a proper computed property name or a synthetic computed property
9550 // name for BigInt keys.
9551
9552 // [stack] CTOR? OBJ
9553
9554 if (!pe.prepareForComputedPropKey(propdef->pn_pos.begin, kind)) {
9555 // [stack] CTOR? OBJ CTOR?
9556 return false;
9557 }
9558 if (!emitTree(key->as<UnaryNode>().kid())) {
9559 // [stack] CTOR? OBJ CTOR? KEY
9560 return false;
9561 }
9562 if (!pe.prepareForComputedPropValue()) {
9563 // [stack] CTOR? OBJ CTOR? KEY
9564 return false;
9565 }
9566 if (!emitValue()) {
9567 // [stack] CTOR? OBJ CTOR? KEY VAL
9568 return false;
9569 }
9570
9571 if (!pe.emitInitIndexOrComputed(accessorType)) {
9572 // [stack] CTOR? OBJ
9573 return false;
9574 }
9575
9576 continue;
9577 }
9578
9579 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9579); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 9579; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9580 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9580); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == ClassBody"
")"); do { *((volatile int*)__null) = 9580; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9581
9582 auto* privateName = &key->as<NameNode>();
9583
9584 if (kind == PropertyEmitter::Kind::Prototype) {
9585 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9585); AnnotateMozCrashReason("MOZ_ASSERT" "(" "accessorType == AccessorType::None"
")"); do { *((volatile int*)__null) = 9585; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9586 if (!pe.prepareForPrivateMethod()) {
9587 // [stack] CTOR OBJ
9588 return false;
9589 }
9590 NameOpEmitter noe(this, privateName->atom(),
9591 NameOpEmitter::Kind::SimpleAssignment);
9592
9593 // Ensure the NameOp emitter doesn't push an environment onto the stack,
9594 // because that would change the stack location of the home object.
9595 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9596); AnnotateMozCrashReason("MOZ_ASSERT" "(" "noe.loc().kind() == NameLocation::Kind::FrameSlot || noe.loc().kind() == NameLocation::Kind::EnvironmentCoordinate"
")"); do { *((volatile int*)__null) = 9596; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9596 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9596); AnnotateMozCrashReason("MOZ_ASSERT" "(" "noe.loc().kind() == NameLocation::Kind::FrameSlot || noe.loc().kind() == NameLocation::Kind::EnvironmentCoordinate"
")"); do { *((volatile int*)__null) = 9596; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9597
9598 if (!noe.prepareForRhs()) {
9599 // [stack] CTOR OBJ
9600 return false;
9601 }
9602 if (!emitValue()) {
9603 // [stack] CTOR OBJ METHOD
9604 return false;
9605 }
9606 if (!noe.emitAssignment()) {
9607 // [stack] CTOR OBJ METHOD
9608 return false;
9609 }
9610 if (!emit1(JSOp::Pop)) {
9611 // [stack] CTOR OBJ
9612 return false;
9613 }
9614 if (!pe.skipInit()) {
9615 // [stack] CTOR OBJ
9616 return false;
9617 }
9618 continue;
9619 }
9620
9621 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9621); AnnotateMozCrashReason("MOZ_ASSERT" "(" "kind == PropertyEmitter::Kind::Static"
")"); do { *((volatile int*)__null) = 9621; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9622
9623 // [stack] CTOR OBJ
9624
9625 if (!pe.prepareForPrivateStaticMethod(propdef->pn_pos.begin)) {
9626 // [stack] CTOR OBJ CTOR
9627 return false;
9628 }
9629 if (!emitGetPrivateName(privateName)) {
9630 // [stack] CTOR OBJ CTOR KEY
9631 return false;
9632 }
9633 if (!emitValue()) {
9634 // [stack] CTOR OBJ CTOR KEY VAL
9635 return false;
9636 }
9637
9638 if (!pe.emitPrivateStaticMethod(accessorType)) {
9639 // [stack] CTOR OBJ
9640 return false;
9641 }
9642
9643 if (privateName->privateNameKind() == PrivateNameKind::Setter) {
9644 if (!emitDupAt(1)) {
9645 // [stack] CTOR OBJ CTOR
9646 return false;
9647 }
9648 if (!emitGetPrivateName(privateName)) {
9649 // [stack] CTOR OBJ CTOR NAME
9650 return false;
9651 }
9652 if (!emitAtomOp(JSOp::GetIntrinsic,
9653 TaggedParserAtomIndex::WellKnown::NoPrivateGetter())) {
9654 // [stack] CTOR OBJ CTOR NAME FUN
9655 return false;
9656 }
9657 if (!emit1(JSOp::InitHiddenElemGetter)) {
9658 // [stack] CTOR OBJ CTOR
9659 return false;
9660 }
9661 if (!emit1(JSOp::Pop)) {
9662 // [stack] CTOR OBJ
9663 return false;
9664 }
9665 }
9666 }
9667
9668 return true;
9669}
9670
9671bool BytecodeEmitter::emitPropertyListObjLiteral(ListNode* obj, JSOp op,
9672 bool useObjLiteralValues) {
9673 ObjLiteralWriter writer;
9674
9675#ifdef DEBUG1
9676 // In self-hosted JS, we check duplication only on debug build.
9677 mozilla::Maybe<mozilla::HashSet<frontend::TaggedParserAtomIndex,
9678 frontend::TaggedParserAtomIndexHasher>>
9679 selfHostedPropNames;
9680 if (emitterMode == BytecodeEmitter::SelfHosting) {
9681 selfHostedPropNames.emplace();
9682 }
9683#endif
9684
9685 if (op == JSOp::Object) {
9686 writer.beginObject(op);
9687 } else {
9688 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9688); AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::NewObject"
")"); do { *((volatile int*)__null) = 9688; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9689 writer.beginShape(op);
9690 }
9691
9692 for (ParseNode* propdef : obj->contents()) {
9693 BinaryNode* prop = &propdef->as<BinaryNode>();
9694 ParseNode* key = prop->left();
9695
9696 if (key->is<NameNode>()) {
9697 if (emitterMode == BytecodeEmitter::SelfHosting) {
9698 auto propName = key->as<NameNode>().atom();
9699#ifdef DEBUG1
9700 // Self-hosted JS shouldn't contain duplicate properties.
9701 auto p = selfHostedPropNames->lookupForAdd(propName);
9702 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9702); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!p" ")"); do
{ *((volatile int*)__null) = 9702; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
9703 if (!selfHostedPropNames->add(p, propName)) {
9704 js::ReportOutOfMemory(fc);
9705 return false;
9706 }
9707#endif
9708 writer.setPropNameNoDuplicateCheck(parserAtoms(), propName);
9709 } else {
9710 if (!writer.setPropName(parserAtoms(), key->as<NameNode>().atom())) {
9711 return false;
9712 }
9713 }
9714 } else {
9715 double numValue = key->as<NumericLiteral>().value();
9716 int32_t i = 0;
9717 DebugOnly<bool> numIsInt =
9718 NumberIsInt32(numValue, &i); // checked previously.
9719 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9719); AnnotateMozCrashReason("MOZ_ASSERT" "(" "numIsInt" ")"
); do { *((volatile int*)__null) = 9719; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9720 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9721); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ObjLiteralWriter::arrayIndexInRange(i)"
")"); do { *((volatile int*)__null) = 9721; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9721 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9721); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ObjLiteralWriter::arrayIndexInRange(i)"
")"); do { *((volatile int*)__null) = 9721; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
; // checked previously.
9722
9723 // Ignore indexed properties if we're not storing property values, and
9724 // rely on InitElem ops to define those. These properties will be either
9725 // dense elements (not possible to represent in the literal's shape) or
9726 // sparse elements (enumerated separately, so this doesn't affect property
9727 // iteration order).
9728 if (!useObjLiteralValues) {
9729 continue;
9730 }
9731
9732 writer.setPropIndex(i);
9733 }
9734
9735 if (useObjLiteralValues) {
9736 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9736); AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::Object"
")"); do { *((volatile int*)__null) = 9736; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9737 ParseNode* value = prop->right();
9738 if (!emitObjLiteralValue(writer, value)) {
9739 return false;
9740 }
9741 } else {
9742 if (!writer.propWithUndefinedValue(fc)) {
9743 return false;
9744 }
9745 }
9746 }
9747
9748 GCThingIndex index;
9749 if (!addObjLiteralData(writer, &index)) {
9750 return false;
9751 }
9752
9753 // JSOp::Object may only be used by (top-level) run-once scripts.
9754 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9755); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isTopLevelContext() && sc->treatAsRunOnce()"
")"); do { *((volatile int*)__null) = 9755; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
9755 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9755); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isTopLevelContext() && sc->treatAsRunOnce()"
")"); do { *((volatile int*)__null) = 9755; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
9756
9757 if (!emitGCIndexOp(op, index)) {
9758 // [stack] OBJ
9759 return false;
9760 }
9761
9762 return true;
9763}
9764
9765bool BytecodeEmitter::emitDestructuringRestExclusionSetObjLiteral(
9766 ListNode* pattern) {
9767 // Note: if we want to squeeze out a little more performance, we could switch
9768 // to the `JSOp::Object` opcode, because the exclusion set object is never
9769 // exposed to the user, so it's safe to bake the object into the bytecode.
9770 constexpr JSOp op = JSOp::NewObject;
9771
9772 ObjLiteralWriter writer;
9773 writer.beginShape(op);
9774
9775 for (ParseNode* member : pattern->contents()) {
9776 if (member->isKind(ParseNodeKind::Spread)) {
9777 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9777); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!member->pn_next"
") (" "unexpected trailing element after spread" ")"); do { *
((volatile int*)__null) = 9777; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
9778 break;
9779 }
9780
9781 TaggedParserAtomIndex atom;
9782 if (member->isKind(ParseNodeKind::MutateProto)) {
9783 atom = TaggedParserAtomIndex::WellKnown::proto_();
9784 } else {
9785 ParseNode* key = member->as<BinaryNode>().left();
9786 atom = key->as<NameNode>().atom();
9787 }
9788
9789 if (!writer.setPropName(parserAtoms(), atom)) {
9790 return false;
9791 }
9792
9793 if (!writer.propWithUndefinedValue(fc)) {
9794 return false;
9795 }
9796 }
9797
9798 GCThingIndex index;
9799 if (!addObjLiteralData(writer, &index)) {
9800 return false;
9801 }
9802
9803 if (!emitGCIndexOp(op, index)) {
9804 // [stack] OBJ
9805 return false;
9806 }
9807
9808 return true;
9809}
9810
9811bool BytecodeEmitter::emitObjLiteralArray(ListNode* array) {
9812 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9812); AnnotateMozCrashReason("MOZ_ASSERT" "(" "checkSingletonContext()"
")"); do { *((volatile int*)__null) = 9812; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9813
9814 constexpr JSOp op = JSOp::Object;
9815
9816 ObjLiteralWriter writer;
9817 writer.beginArray(op);
9818
9819 writer.beginDenseArrayElements();
9820 for (ParseNode* elem : array->contents()) {
9821 if (!emitObjLiteralValue(writer, elem)) {
9822 return false;
9823 }
9824 }
9825
9826 GCThingIndex index;
9827 if (!addObjLiteralData(writer, &index)) {
9828 return false;
9829 }
9830
9831 if (!emitGCIndexOp(op, index)) {
9832 // [stack] OBJ
9833 return false;
9834 }
9835
9836 return true;
9837}
9838
9839bool BytecodeEmitter::isRHSObjLiteralCompatible(ParseNode* value) const {
9840 return value->isKind(ParseNodeKind::NumberExpr) ||
9841 value->isKind(ParseNodeKind::TrueExpr) ||
9842 value->isKind(ParseNodeKind::FalseExpr) ||
9843 value->isKind(ParseNodeKind::NullExpr) ||
9844 value->isKind(ParseNodeKind::RawUndefinedExpr) ||
9845 value->isKind(ParseNodeKind::StringExpr) ||
9846 value->isKind(ParseNodeKind::TemplateStringExpr);
9847}
9848
9849bool BytecodeEmitter::emitObjLiteralValue(ObjLiteralWriter& writer,
9850 ParseNode* value) {
9851 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)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9851); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isRHSObjLiteralCompatible(value)"
")"); do { *((volatile int*)__null) = 9851; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9852 if (value->isKind(ParseNodeKind::NumberExpr)) {
9853 double numValue = value->as<NumericLiteral>().value();
9854 int32_t i = 0;
9855 js::Value v;
9856 if (NumberIsInt32(numValue, &i)) {
9857 v.setInt32(i);
9858 } else {
9859 v.setDouble(numValue);
9860 }
9861 if (!writer.propWithConstNumericValue(fc, v)) {
9862 return false;
9863 }
9864 } else if (value->isKind(ParseNodeKind::TrueExpr)) {
9865 if (!writer.propWithTrueValue(fc)) {
9866 return false;
9867 }
9868 } else if (value->isKind(ParseNodeKind::FalseExpr)) {
9869 if (!writer.propWithFalseValue(fc)) {
9870 return false;
9871 }
9872 } else if (value->isKind(ParseNodeKind::NullExpr)) {
9873 if (!writer.propWithNullValue(fc)) {
9874 return false;
9875 }
9876 } else if (value->isKind(ParseNodeKind::RawUndefinedExpr)) {
9877 if (!writer.propWithUndefinedValue(fc)) {
9878 return false;
9879 }
9880 } else if (value->isKind(ParseNodeKind::StringExpr) ||
9881 value->isKind(ParseNodeKind::TemplateStringExpr)) {
9882 if (!writer.propWithAtomValue(fc, parserAtoms(),
9883 value->as<NameNode>().atom())) {
9884 return false;
9885 }
9886 } else {
9887 MOZ_CRASH("Unexpected parse node")do { do { } while (false); MOZ_ReportCrash("" "Unexpected parse node"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9887); AnnotateMozCrashReason("MOZ_CRASH(" "Unexpected parse node"
")"); do { *((volatile int*)__null) = 9887; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
9888 }
9889 return true;
9890}
9891
9892static bool NeedsPrivateBrand(ParseNode* member) {
9893 return member->is<ClassMethod>() &&
9894 member->as<ClassMethod>().name().isKind(ParseNodeKind::PrivateName) &&
9895 !member->as<ClassMethod>().isStatic();
9896}
9897
9898#ifdef ENABLE_DECORATORS
9899static bool HasDecorators(ParseNode* member) {
9900 return member->is<ClassMethod>() && member->as<ClassMethod>().decorators();
9901}
9902#endif
9903
9904mozilla::Maybe<MemberInitializers> BytecodeEmitter::setupMemberInitializers(
9905 ListNode* classMembers, FieldPlacement placement) const {
9906 bool isStatic = placement == FieldPlacement::Static;
9907
9908 size_t numFields = 0;
9909 size_t numPrivateInitializers = 0;
9910 bool hasPrivateBrand = false;
9911#ifdef ENABLE_DECORATORS
9912 bool hasDecorators = false;
9913#endif
9914 for (ParseNode* member : classMembers->contents()) {
9915 if (NeedsFieldInitializer(member, isStatic)) {
9916 numFields++;
9917 } else if (NeedsAccessorInitializer(member, isStatic)) {
9918 numPrivateInitializers++;
9919 hasPrivateBrand = true;
9920 } else if (NeedsPrivateBrand(member)) {
9921 hasPrivateBrand = true;
9922 }
9923#ifdef ENABLE_DECORATORS
9924 if (!hasDecorators && HasDecorators(member)) {
9925 hasDecorators = true;
9926 }
9927#endif
9928 }
9929
9930 // If there are more initializers than can be represented, return invalid.
9931 if (numFields + numPrivateInitializers >
9932 MemberInitializers::MaxInitializers) {
9933 return Nothing();
9934 }
9935 return Some(MemberInitializers(hasPrivateBrand,
9936#ifdef ENABLE_DECORATORS
9937 hasDecorators,
9938#endif
9939 numFields + numPrivateInitializers));
9940}
9941
9942// Purpose of .fieldKeys:
9943// Computed field names (`["x"] = 2;`) must be ran at class-evaluation time,
9944// not object construction time. The transformation to do so is roughly as
9945// follows:
9946//
9947// class C {
9948// [keyExpr] = valueExpr;
9949// }
9950// -->
9951// let .fieldKeys = [keyExpr];
9952// let .initializers = [
9953// () => {
9954// this[.fieldKeys[0]] = valueExpr;
9955// }
9956// ];
9957// class C {
9958// constructor() {
9959// .initializers[0]();
9960// }
9961// }
9962//
9963// BytecodeEmitter::emitCreateFieldKeys does `let .fieldKeys = [...];`
9964// BytecodeEmitter::emitPropertyList fills in the elements of the array.
9965// See GeneralParser::fieldInitializer for the `this[.fieldKeys[0]]` part.
9966bool BytecodeEmitter::emitCreateFieldKeys(ListNode* obj,
9967 FieldPlacement placement) {
9968 bool isStatic = placement == FieldPlacement::Static;
9969 auto isFieldWithComputedName = [isStatic](ParseNode* propdef) {
9970 return propdef->is<ClassField>() &&
9971 propdef->as<ClassField>().isStatic() == isStatic &&
9972 propdef->as<ClassField>().name().getKind() ==
9973 ParseNodeKind::ComputedName;
9974 };
9975
9976 size_t numFieldKeys = std::count_if(
9977 obj->contents().begin(), obj->contents().end(), isFieldWithComputedName);
9978 if (numFieldKeys == 0) {
9979 return true;
9980 }
9981
9982 auto fieldKeys =
9983 isStatic ? TaggedParserAtomIndex::WellKnown::dot_staticFieldKeys_()
9984 : TaggedParserAtomIndex::WellKnown::dot_fieldKeys_();
9985 NameOpEmitter noe(this, fieldKeys, NameOpEmitter::Kind::Initialize);
9986 if (!noe.prepareForRhs()) {
9987 return false;
9988 }
9989
9990 if (!emitUint32Operand(JSOp::NewArray, numFieldKeys)) {
9991 // [stack] ARRAY
9992 return false;
9993 }
9994
9995 if (!noe.emitAssignment()) {
9996 // [stack] ARRAY
9997 return false;
9998 }
9999
10000 if (!emit1(JSOp::Pop)) {
10001 // [stack]
10002 return false;
10003 }
10004
10005 return true;
10006}
10007
10008static bool HasInitializer(ParseNode* node, bool isStaticContext) {
10009 return (node->is<ClassField>() &&
10010 node->as<ClassField>().isStatic() == isStaticContext) ||
10011 (isStaticContext && node->is<StaticClassBlock>());
10012}
10013
10014static FunctionNode* GetInitializer(ParseNode* node, bool isStaticContext) {
10015 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 10015); AnnotateMozCrashReason("MOZ_ASSERT" "(" "HasInitializer(node, isStaticContext)"
")"); do { *((volatile int*)__null) = 10015; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10016 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 10016); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isStaticContext"
")"); do { *((volatile int*)__null) = 10016; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
10017 return node->is<ClassField>() ? node->as<ClassField>().initializer()
10018 : node->as<StaticClassBlock>().function();
10019}
10020
10021static bool IsPrivateInstanceAccessor(const ClassMethod* classMethod) {
10022 return !classMethod->isStatic() &&
10023 classMethod->name().isKind(ParseNodeKind::PrivateName) &&
10024 classMethod->accessorType() != AccessorType::None;
10025}
10026
10027bool BytecodeEmitter::emitCreateMemberInitializers(ClassEmitter& ce,
10028 ListNode* obj,
10029 FieldPlacement placement
10030#ifdef ENABLE_DECORATORS
10031 ,
10032 bool hasHeritage
10033#endif
10034) {
10035 // FieldPlacement::Instance, hasHeritage == false
10036 // [stack] HOME
10037 //
10038 // FieldPlacement::Instance, hasHeritage == true
10039 // [stack] HOME HERIT
10040 //
10041 // FieldPlacement::Static
10042 // [stack] CTOR HOME
10043#ifdef ENABLE_DECORATORS
10044 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 10044); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!hasHeritage"
")"); do { *((volatile int*)__null) = 10044; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
10045#endif
10046 mozilla::Maybe<MemberInitializers> memberInitializers =
10047 setupMemberInitializers(obj, placement);
10048 if (!memberInitializers) {
10049 ReportAllocationOverflow(fc);
10050 return false;
10051 }
10052
10053 size_t numInitializers = memberInitializers->numMemberInitializers;
10054 if (numInitializers == 0) {
10055 return true;
10056 }
10057
10058 bool isStatic = placement == FieldPlacement::Static;
10059 if (!ce.prepareForMemberInitializers(numInitializers, isStatic)) {
10060 // [stack] HOME HERIT? ARR
10061 // or:
10062 // [stack] CTOR HOME ARR
10063 return false;
10064 }
10065
10066 // Private accessors could be used in the field initializers, so make sure
10067 // accessor initializers appear earlier in the .initializers array so they
10068 // run first. Static private methods are not initialized using initializers
10069 // (emitPropertyList emits bytecode to stamp them onto the constructor), so
10070 // skip this step if isStatic.
10071 if (!isStatic) {
10072 if (!emitPrivateMethodInitializers(ce, obj)) {
10073 return false;
10074 }
10075 }
10076
10077 for (ParseNode* propdef : obj->contents()) {
10078 if (!HasInitializer(propdef, isStatic)) {
10079 continue;
10080 }
10081
10082 FunctionNode* initializer = GetInitializer(propdef, isStatic);
10083
10084 if (!ce.prepareForMemberInitializer()) {
10085 return false;
10086 }
10087 if (!emitTree(initializer)) {
10088 // [stack] HOME HERIT? ARR LAMBDA
10089 // or:
10090 // [stack] CTOR HOME ARR LAMBDA
10091 return false;
10092 }
10093 if (initializer->funbox()->needsHomeObject()) {
10094 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 10094); AnnotateMozCrashReason("MOZ_ASSERT" "(" "initializer->funbox()->allowSuperProperty()"
")"); do { *((volatile int*)__null) = 10094; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10095 if (!ce.emitMemberInitializerHomeObject(isStatic)) {
10096 // [stack] HOME HERIT? ARR LAMBDA
10097 // or:
10098 // [stack] CTOR HOME ARR LAMBDA
10099 return false;
10100 }
10101 }
10102 if (!ce.emitStoreMemberInitializer()) {
10103 // [stack] HOME HERIT? ARR
10104 // or:
10105 // [stack] CTOR HOME ARR
10106 return false;
10107 }
10108 }
10109
10110#ifdef ENABLE_DECORATORS
10111 // Index to use to append new initializers returned by decorators to the array
10112 if (!emitNumberOp(numInitializers)) {
10113 // [stack] HOME HERIT? ARR I
10114 // or:
10115 // [stack] CTOR HOME ARR I
10116 return false;
10117 }
10118
10119 for (ParseNode* propdef : obj->contents()) {
10120 if (!propdef->is<ClassField>()) {
10121 continue;
10122 }
10123 ClassField* field = &propdef->as<ClassField>();
10124 if (field->isStatic() != isStatic) {
10125 continue;
10126 }
10127 if (field->decorators() && !field->decorators()->empty()) {
10128 DecoratorEmitter de(this);
10129 if (!field->hasAccessor()) {
10130 if (!emitDupAt((hasHeritage || isStatic) ? 4 : 3)) {
10131 // [stack] ADDINIT HOME HERIT? ARR I ADDINIT
10132 // or:
10133 // [stack] ADDINIT CTOR HOME ARR I ADDINIT
10134 return false;
10135 }
10136 if (!de.emitApplyDecoratorsToFieldDefinition(
10137 &field->name(), field->decorators(), field->isStatic())) {
10138 // [stack] HOME HERIT? ARR I ADDINIT INITS
10139 // or:
10140 // [stack] CTOR HOME ARR I ADDINIT INITS
10141 return false;
10142 }
10143 if (!emit1(JSOp::Swap)) {
10144 // [stack] HOME HERIT? ARR I INITS ADDINIT
10145 // or:
10146 // [stack] CTOR HOME ARR I INITS ADDINIT
10147 return false;
10148 }
10149 if (!emitPopN(1)) {
10150 // [stack] ADDINIT HOME HERIT? ARR I INITS
10151 // or:
10152 // [stack] ADDINIT CTOR HOME ARR I INITS
10153 return false;
10154 }
10155 } else {
10156 ClassMethod* accessorGetterNode = field->accessorGetterNode();
10157 auto accessorGetterKeyAtom =
10158 accessorGetterNode->left()->as<NameNode>().atom();
10159 ClassMethod* accessorSetterNode = field->accessorSetterNode();
10160 auto accessorSetterKeyAtom =
10161 accessorSetterNode->left()->as<NameNode>().atom();
10162 if (!IsPrivateInstanceAccessor(accessorGetterNode)) {
10163 if (!emitTree(&accessorGetterNode->method())) {
10164 // [stack] ADDINIT HOME HERIT? ARR I GET
10165 // or:
10166 // [stack] ADDINIT CTOR HOME ARR I GET
10167 return false;
10168 }
10169 if (!emitTree(&accessorSetterNode->method())) {
10170 // [stack] ADDINIT HOME HERIT? ARR I GET
10171 // SET
10172 // or:
10173 // [stack] ADDINIT CTOR HOME ARR I GET SET
10174 return false;
10175 }
10176 } else {
10177 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 10177); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsPrivateInstanceAccessor(accessorSetterNode)"
")"); do { *((volatile int*)__null) = 10177; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10178 auto getAccessor = [this](
10179 ClassMethod* classMethod,
10180 TaggedParserAtomIndex& updatedAtom) -> bool {
10181 // [stack]
10182
10183 // Synthesize a name for the lexical variable that will store the
10184 // private method body.
10185 TaggedParserAtomIndex name =
10186 classMethod->name().as<NameNode>().atom();
10187 AccessorType accessorType = classMethod->accessorType();
10188 StringBuilder storedMethodName(fc);
10189 if (!storedMethodName.append(parserAtoms(), name)) {
10190 return false;
10191 }
10192 if (!storedMethodName.append(accessorType == AccessorType::Getter
10193 ? ".getter"
10194 : ".setter")) {
10195 return false;
10196 }
10197 updatedAtom = storedMethodName.finishParserAtom(parserAtoms(), fc);
10198 if (!updatedAtom) {
10199 return false;
10200 }
10201
10202 return emitGetName(updatedAtom);
10203 // [stack] ACCESSOR
10204 };
10205
10206 if (!getAccessor(accessorGetterNode, accessorGetterKeyAtom)) {
10207 // [stack] ADDINIT HOME HERIT? ARR I GET
10208 // or:
10209 // [stack] ADDINIT CTOR HOME ARR I GET
10210 return false;
10211 };
10212
10213 if (!getAccessor(accessorSetterNode, accessorSetterKeyAtom)) {
10214 // [stack] ADDINIT HOME HERIT? ARR I GET SET
10215 // or:
10216 // [stack] ADDINIT CTOR HOME ARR I GET SET
10217 return false;
10218 };
10219 }
10220
10221 if (!emitDupAt((hasHeritage || isStatic) ? 6 : 5)) {
10222 // [stack] ADDINIT HOME HERIT? ARR I GET SET ADDINIT
10223 // or:
10224 // [stack] ADDINIT CTOR HOME ARR I GET SET ADDINIT
10225 return false;
10226 }
10227
10228 if (!emitUnpickN(2)) {
10229 // [stack] ADDINIT HOME HERIT? ARR I ADDINIT GET SET
10230 // or:
10231 // [stack] ADDINIT CTOR HOME ARR I ADDINIT GET SET
10232 return false;
10233 }
10234
10235 if (!de.emitApplyDecoratorsToAccessorDefinition(
10236 &field->name(), field->decorators(), field->isStatic())) {
10237 // [stack] ADDINIT HOME HERIT? ARR I ADDINIT GET SET INITS
10238 // or:
10239 // [stack] ADDINIT CTOR HOME ARR I ADDINIT GET SET INITS
10240 return false;
10241 }
10242
10243 if (!emitPickN(3)) {
10244 // [stack] HOME HERIT? ARR I GET SET INITS ADDINIT
10245 // or:
10246 // [stack] CTOR HOME ARR I GET SET INITS ADDINIT
10247 return false;
10248 }
10249
10250 if (!emitPopN(1)) {
10251 // [stack] ADDINIT HOME HERIT? ARR I GET SET INITS
10252 // or:
10253 // [stack] ADDINIT CTOR HOME ARR I GET SET INITS
10254 return false;
10255 }
10256
10257 if (!emitUnpickN(2)) {
10258 // [stack] ADDINIT HOME HERIT? ARR I INITS GET SET
10259 // or:
10260 // [stack] ADDINIT CTOR HOME ARR I INITS GET SET
10261 return false;
10262 }
10263
10264 if (!IsPrivateInstanceAccessor(accessorGetterNode)) {
10265 if (!isStatic) {
10266 if (!emitDupAt(hasHeritage ? 6 : 5)) {
10267 // [stack] ADDINIT HOME HERIT? ARR I INITS GET SET HOME
10268 return false;
10269 }
10270 } else {
10271 if (!emitDupAt(6)) {
10272 // [stack] ADDINIT CTOR HOME ARR I INITS GET SET CTOR
10273 return false;
10274 }
10275 if (!emitDupAt(6)) {
10276 // [stack] ADDINIT CTOR HOME ARR I INITS GET SET CTOR HOME
10277 return false;
10278 }
10279 }
10280
10281 PropertyEmitter::Kind kind = field->isStatic()
10282 ? PropertyEmitter::Kind::Static
10283 : PropertyEmitter::Kind::Prototype;
10284 if (!accessorGetterNode->name().isKind(ParseNodeKind::PrivateName)) {
10285 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 10286); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!accessorSetterNode->name().isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 10286; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10286 !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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 10286); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!accessorSetterNode->name().isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 10286; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10287
10288 if (!ce.prepareForPropValue(propdef->pn_pos.begin, kind)) {
10289 // [stack] ADDINIT HOME HERIT? ARR I INITS GET SET HOME
10290 // or:
10291 // [stack] ADDINIT CTOR HOME ARR I INITS GET SET CTOR HOME CTOR
10292 return false;
10293 }
10294 if (!emitPickN(isStatic ? 3 : 1)) {
10295 // [stack] ADDINIT HOME HERIT? ARR I INITS GET HOME SET
10296 // or:
10297 // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME CTOR SET
10298 return false;
10299 }
10300 if (!ce.emitInit(AccessorType::Setter, accessorSetterKeyAtom)) {
10301 // [stack] ADDINIT HOME HERIT? ARR I INITS GET HOME
10302 // or:
10303 // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME
10304 return false;
10305 }
10306
10307 if (!ce.prepareForPropValue(propdef->pn_pos.begin, kind)) {
10308 // [stack] ADDINIT HOME HERIT? ARR I INITS GET HOME
10309 // or:
10310 // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME CTOR
10311 return false;
10312 }
10313 if (!emitPickN(isStatic ? 3 : 1)) {
10314 // [stack] ADDINIT HOME HERIT? ARR I INITS HOME GET
10315 // or:
10316 // [stack] ADDINIT CTOR HOME ARR I INITS CTOR HOME CTOR GET
10317 return false;
10318 }
10319 if (!ce.emitInit(AccessorType::Getter, accessorGetterKeyAtom)) {
10320 // [stack] ADDINIT HOME HERIT? ARR I INITS HOME
10321 // or:
10322 // [stack] ADDINIT CTOR HOME ARR I INITS CTOR HOME
10323 return false;
10324 }
10325 } else {
10326 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 10326); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isStatic" ")"
); do { *((volatile int*)__null) = 10326; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10327 // The getter and setter share the same name.
10328 if (!emitNewPrivateName(accessorSetterKeyAtom,
10329 accessorSetterKeyAtom)) {
10330 return false;
10331 }
10332 if (!ce.prepareForPrivateStaticMethod(propdef->pn_pos.begin)) {
10333 // [stack] ADDINIT CTOR HOME ARR I INITS GET SET CTOR HOME CTOR
10334 return false;
10335 }
10336 if (!emitGetPrivateName(
10337 &accessorSetterNode->name().as<NameNode>())) {
10338 // [stack] ADDINIT CTOR HOME ARR I INITS GET SET CTOR HOME CTOR
10339 // KEY
10340 return false;
10341 }
10342 if (!emitPickN(4)) {
10343 // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME CTOR KEY
10344 // SET
10345 return false;
10346 }
10347 if (!ce.emitPrivateStaticMethod(AccessorType::Setter)) {
10348 // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME
10349 return false;
10350 }
10351
10352 if (!ce.prepareForPrivateStaticMethod(propdef->pn_pos.begin)) {
10353 // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME CTOR
10354 return false;
10355 }
10356 if (!emitGetPrivateName(
10357 &accessorGetterNode->name().as<NameNode>())) {
10358 // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME CTOR KEY
10359 return false;
10360 }
10361 if (!emitPickN(4)) {
10362 // [stack] ADDINIT CTOR HOME ARR I INITS CTOR HOME CTOR KEY GET
10363 return false;
10364 }
10365 if (!ce.emitPrivateStaticMethod(AccessorType::Getter)) {
10366 // [stack] ADDINIT CTOR HOME ARR I INITS CTOR HOME
10367 return false;
10368 }
10369 }
10370
10371 if (!isStatic) {
10372 if (!emitPopN(1)) {
10373 // [stack] ADDINIT HOME HERIT? ARR I INITS
10374 return false;
10375 }
10376 } else {
10377 if (!emitPopN(2)) {
10378 // [stack] ADDINIT CTOR HOME ARR I INITS
10379 return false;
10380 }
10381 }
10382 } else {
10383 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 10383); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsPrivateInstanceAccessor(accessorSetterNode)"
")"); do { *((volatile int*)__null) = 10383; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10384
10385 if (!emitLexicalInitialization(accessorSetterKeyAtom)) {
10386 // [stack] ADDINIT HOME HERIT? ARR I INITS GET SET
10387 // or:
10388 // [stack] ADDINIT CTOR HOME ARR I INITS GET SET
10389 return false;
10390 }
10391
10392 if (!emitPopN(1)) {
10393 // [stack] ADDINIT HOME HERIT? ARR I INITS GET
10394 // or:
10395 // [stack] ADDINIT CTOR HOME ARR I INITS GET
10396 return false;
10397 }
10398
10399 if (!emitLexicalInitialization(accessorGetterKeyAtom)) {
10400 // [stack] ADDINIT HOME HERIT? ARR I INITS GET
10401 // or:
10402 // [stack] ADDINIT CTOR HOME ARR I INITS GET
10403 return false;
10404 }
10405
10406 if (!emitPopN(1)) {
10407 // [stack] ADDINIT HOME HERIT? ARR I INITS
10408 // or:
10409 // [stack] ADDINIT CTOR HOME ARR I INITS
10410 return false;
10411 }
10412 }
10413 }
10414 if (!emit1(JSOp::InitElemInc)) {
10415 // [stack] ADDINIT HOME HERIT? ARR I
10416 // or:
10417 // [stack] ADDINIT CTOR HOME ARR I
10418 return false;
10419 }
10420 }
10421 }
10422
10423 // Pop I
10424 if (!emitPopN(1)) {
10425 // [stack] ADDINIT HOME HERIT? ARR
10426 // or:
10427 // [stack] ADDINIT CTOR HOME ARR
10428 return false;
10429 }
10430#endif
10431
10432 if (!ce.emitMemberInitializersEnd()) {
10433 // [stack] ADDINIT HOME HERIT?
10434 // or:
10435 // [stack] ADDINIT CTOR HOME
10436 return false;
10437 }
10438
10439 return true;
10440}
10441
10442bool BytecodeEmitter::emitPrivateMethodInitializers(ClassEmitter& ce,
10443 ListNode* obj) {
10444 for (ParseNode* propdef : obj->contents()) {
10445 if (!propdef->is<ClassMethod>()) {
10446 continue;
10447 }
10448 auto* classMethod = &propdef->as<ClassMethod>();
10449
10450 // Skip over anything which isn't a private instance accessor.
10451 if (!IsPrivateInstanceAccessor(classMethod)) {
10452 continue;
10453 }
10454
10455 if (!ce.prepareForMemberInitializer()) {
10456 // [stack] HOMEOBJ HERITAGE? ARRAY
10457 // or:
10458 // [stack] CTOR HOMEOBJ ARRAY
10459 return false;
10460 }
10461
10462 // Synthesize a name for the lexical variable that will store the
10463 // private method body.
10464 TaggedParserAtomIndex name = classMethod->name().as<NameNode>().atom();
10465 AccessorType accessorType = classMethod->accessorType();
10466 StringBuilder storedMethodName(fc);
10467 if (!storedMethodName.append(parserAtoms(), name)) {
10468 return false;
10469 }
10470 if (!storedMethodName.append(
10471 accessorType == AccessorType::Getter ? ".getter" : ".setter")) {
10472 return false;
10473 }
10474 auto storedMethodAtom =
10475 storedMethodName.finishParserAtom(parserAtoms(), fc);
10476
10477 // Emit the private method body and store it as a lexical var.
10478 if (!emitFunction(&classMethod->method())) {
10479 // [stack] HOMEOBJ HERITAGE? ARRAY METHOD
10480 // or:
10481 // [stack] CTOR HOMEOBJ ARRAY METHOD
10482 return false;
10483 }
10484 // The private method body needs to access the home object,
10485 // and the CE knows where that is on the stack.
10486 if (classMethod->method().funbox()->needsHomeObject()) {
10487 if (!ce.emitMemberInitializerHomeObject(false)) {
10488 // [stack] HOMEOBJ HERITAGE? ARRAY METHOD
10489 // or:
10490 // [stack] CTOR HOMEOBJ ARRAY METHOD
10491 return false;
10492 }
10493 }
10494 if (!emitLexicalInitialization(storedMethodAtom)) {
10495 // [stack] HOMEOBJ HERITAGE? ARRAY METHOD
10496 // or:
10497 // [stack] CTOR HOMEOBJ ARRAY METHOD
10498 return false;
10499 }
10500 if (!emit1(JSOp::Pop)) {
10501 // [stack] HOMEOBJ HERITAGE? ARRAY
10502 // or:
10503 // [stack] CTOR HOMEOBJ ARRAY
10504 return false;
10505 }
10506
10507 if (!emitPrivateMethodInitializer(classMethod, storedMethodAtom)) {
10508 // [stack] HOMEOBJ HERITAGE? ARRAY
10509 // or:
10510 // [stack] CTOR HOMEOBJ ARRAY
10511 return false;
10512 }
10513
10514 // Store the emitted initializer function into the .initializers array.
10515 if (!ce.emitStoreMemberInitializer()) {
10516 // [stack] HOMEOBJ HERITAGE? ARRAY
10517 // or:
10518 // [stack] CTOR HOMEOBJ ARRAY
10519 return false;
10520 }
10521 }
10522
10523 return true;
10524}
10525
10526bool BytecodeEmitter::emitPrivateMethodInitializer(
10527 ClassMethod* classMethod, TaggedParserAtomIndex storedMethodAtom) {
10528 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 10528); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsPrivateInstanceAccessor(classMethod)"
")"); do { *((volatile int*)__null) = 10528; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10529
10530 auto* name = &classMethod->name().as<NameNode>();
10531
10532 // Emit the synthesized initializer function.
10533 FunctionNode* funNode = classMethod->initializerIfPrivate();
10534 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 10534); AnnotateMozCrashReason("MOZ_ASSERT" "(" "funNode" ")"
); do { *((volatile int*)__null) = 10534; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10535 FunctionBox* funbox = funNode->funbox();
10536 FunctionEmitter fe(this, funbox, funNode->syntaxKind(),
10537 FunctionEmitter::IsHoisted::No);
10538 if (!fe.prepareForNonLazy()) {
10539 // [stack]
10540 return false;
10541 }
10542
10543 BytecodeEmitter bce2(this, funbox);
10544 if (!bce2.init(funNode->pn_pos)) {
10545 return false;
10546 }
10547 ParamsBodyNode* paramsBody = funNode->body();
10548 FunctionScriptEmitter fse(&bce2, funbox, Nothing(), Nothing());
10549 if (!fse.prepareForParameters()) {
10550 // [stack]
10551 return false;
10552 }
10553 if (!bce2.emitFunctionFormalParameters(paramsBody)) {
10554 // [stack]
10555 return false;
10556 }
10557 if (!fse.prepareForBody()) {
10558 // [stack]
10559 return false;
10560 }
10561
10562 if (!bce2.emit1(JSOp::FunctionThis)) {
10563 // [stack] THIS
10564 return false;
10565 }
10566 if (!bce2.emitGetPrivateName(name)) {
10567 // [stack] THIS NAME
10568 return false;
10569 }
10570 if (!bce2.emitGetName(storedMethodAtom)) {
10571 // [stack] THIS NAME METHOD
10572 return false;
10573 }
10574
10575 switch (name->privateNameKind()) {
10576 case PrivateNameKind::Setter:
10577 if (!bce2.emit1(JSOp::InitHiddenElemSetter)) {
10578 // [stack] THIS
10579 return false;
10580 }
10581 if (!bce2.emitGetPrivateName(name)) {
10582 // [stack] THIS NAME
10583 return false;
10584 }
10585 if (!bce2.emitAtomOp(
10586 JSOp::GetIntrinsic,
10587 TaggedParserAtomIndex::WellKnown::NoPrivateGetter())) {
10588 // [stack] THIS NAME FUN
10589 return false;
10590 }
10591 if (!bce2.emit1(JSOp::InitHiddenElemGetter)) {
10592 // [stack] THIS
10593 return false;
10594 }
10595 break;
10596 case PrivateNameKind::Getter:
10597 case PrivateNameKind::GetterSetter:
10598 if (classMethod->accessorType() == AccessorType::Getter) {
10599 if (!bce2.emit1(JSOp::InitHiddenElemGetter)) {
10600 // [stack] THIS
10601 return false;
10602 }
10603 } else {
10604 if (!bce2.emit1(JSOp::InitHiddenElemSetter)) {
10605 // [stack] THIS
10606 return false;
10607 }
10608 }
10609 break;
10610 default:
10611 MOZ_CRASH("Invalid op")do { do { } while (false); MOZ_ReportCrash("" "Invalid op", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 10611); AnnotateMozCrashReason("MOZ_CRASH(" "Invalid op" ")"
); do { *((volatile int*)__null) = 10611; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
10612 }
10613
10614 // Pop remaining THIS.
10615 if (!bce2.emit1(JSOp::Pop)) {
10616 // [stack]
10617 return false;
10618 }
10619
10620 if (!fse.emitEndBody()) {
10621 // [stack]
10622 return false;
10623 }
10624 if (!fse.intoStencil()) {
10625 return false;
10626 }
10627
10628 if (!fe.emitNonLazyEnd()) {
10629 // [stack] HOMEOBJ HERITAGE? ARRAY FUN
10630 // or:
10631 // [stack] CTOR HOMEOBJ ARRAY FUN
10632 return false;
10633 }
10634
10635 return true;
10636}
10637
10638const MemberInitializers& BytecodeEmitter::findMemberInitializersForCall()
10639 const {
10640 for (const auto* current = this; current; current = current->parent) {
10641 if (current->sc->isFunctionBox()) {
10642 FunctionBox* funbox = current->sc->asFunctionBox();
10643
10644 if (funbox->isArrow()) {
10645 continue;
10646 }
10647
10648 // If we found a non-arrow / non-constructor we were never allowed to
10649 // expect fields in the first place.
10650 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()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 10650); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "funbox->isClassConstructor()"
")"); do { *((volatile int*)__null) = 10650; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10651
10652 return funbox->useMemberInitializers() ? funbox->memberInitializers()
10653 : MemberInitializers::Empty();
10654 }
10655 }
10656
10657 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 10657); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "compilationState.scopeContext.memberInitializers"
")"); do { *((volatile int*)__null) = 10657; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10658 return *compilationState.scopeContext.memberInitializers;
10659}
10660
10661bool BytecodeEmitter::emitInitializeInstanceMembers(
10662 bool isDerivedClassConstructor) {
10663 const MemberInitializers& memberInitializers =
10664 findMemberInitializersForCall();
10665 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 10665); AnnotateMozCrashReason("MOZ_ASSERT" "(" "memberInitializers.valid"
")"); do { *((volatile int*)__null) = 10665; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10666
10667 if (memberInitializers.hasPrivateBrand) {
10668 // This is guaranteed to run after super(), so we don't need TDZ checks.
10669 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_this_())) {
10670 // [stack] THIS
10671 return false;
10672 }
10673 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_privateBrand_())) {
10674 // [stack] THIS BRAND
10675 return false;
10676 }
10677 if (isDerivedClassConstructor) {
10678 if (!emitCheckPrivateField(ThrowCondition::ThrowHas,
10679 ThrowMsgKind::PrivateBrandDoubleInit)) {
10680 // [stack] THIS BRAND BOOL
10681 return false;
10682 }
10683 if (!emit1(JSOp::Pop)) {
10684 // [stack] THIS BRAND
10685 return false;
10686 }
10687 }
10688 if (!emit1(JSOp::Null)) {
10689 // [stack] THIS BRAND NULL
10690 return false;
10691 }
10692 if (!emit1(JSOp::InitHiddenElem)) {
10693 // [stack] THIS
10694 return false;
10695 }
10696 if (!emit1(JSOp::Pop)) {
10697 // [stack]
10698 return false;
10699 }
10700 }
10701
10702 size_t numInitializers = memberInitializers.numMemberInitializers;
10703 if (numInitializers > 0) {
10704 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_initializers_())) {
10705 // [stack] ARRAY
10706 return false;
10707 }
10708
10709 for (size_t index = 0; index < numInitializers; index++) {
10710 if (index < numInitializers - 1) {
10711 // We Dup to keep the array around (it is consumed in the bytecode
10712 // below) for next iterations of this loop, except for the last
10713 // iteration, which avoids an extra Pop at the end of the loop.
10714 if (!emit1(JSOp::Dup)) {
10715 // [stack] ARRAY ARRAY
10716 return false;
10717 }
10718 }
10719
10720 if (!emitNumberOp(index)) {
10721 // [stack] ARRAY? ARRAY INDEX
10722 return false;
10723 }
10724
10725 if (!emit1(JSOp::GetElem)) {
10726 // [stack] ARRAY? FUNC
10727 return false;
10728 }
10729
10730 // This is guaranteed to run after super(), so we don't need TDZ checks.
10731 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_this_())) {
10732 // [stack] ARRAY? FUNC THIS
10733 return false;
10734 }
10735
10736 // Callee is always internal function.
10737 if (!emitCall(JSOp::CallIgnoresRv, 0)) {
10738 // [stack] ARRAY? RVAL
10739 return false;
10740 }
10741
10742 if (!emit1(JSOp::Pop)) {
10743 // [stack] ARRAY?
10744 return false;
10745 }
10746 }
10747#ifdef ENABLE_DECORATORS
10748 if (memberInitializers.hasDecorators) {
10749 // Decorators Proposal
10750 // https://arai-a.github.io/ecma262-compare/?pr=2417&id=sec-initializeinstanceelements
10751 // 4. For each element e of elements, do
10752 // 4.a. If elementRecord.[[Kind]] is field or accessor, then
10753 // 4.a.i. Perform ? InitializeFieldOrAccessor(O, elementRecord).
10754 //
10755
10756 // TODO: (See Bug 1817993) At the moment, we're applying the
10757 // initialization logic in two steps. The pre-decorator initialization
10758 // code runs, stores the initial value, and then we retrieve it here and
10759 // apply the initializers added by decorators. We should unify these two
10760 // steps.
10761 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_initializers_())) {
10762 // [stack] ARRAY
10763 return false;
10764 }
10765
10766 if (!emit1(JSOp::Dup)) {
10767 // [stack] ARRAY ARRAY
10768 return false;
10769 }
10770
10771 if (!emitAtomOp(JSOp::GetProp,
10772 TaggedParserAtomIndex::WellKnown::length())) {
10773 // [stack] ARRAY LENGTH
10774 return false;
10775 }
10776
10777 if (!emitNumberOp(static_cast<double>(numInitializers))) {
10778 // [stack] ARRAY LENGTH INDEX
10779 return false;
10780 }
10781
10782 InternalWhileEmitter wh(this);
10783 // At this point, we have no context to determine offsets in the
10784 // code for this while statement. Ideally, it would correspond to
10785 // the field we're initializing.
10786 if (!wh.emitCond()) {
10787 // [stack] ARRAY LENGTH INDEX
10788 return false;
10789 }
10790
10791 if (!emit1(JSOp::Dup)) {
10792 // [stack] ARRAY LENGTH INDEX INDEX
10793 return false;
10794 }
10795
10796 if (!emitDupAt(2)) {
10797 // [stack] ARRAY LENGTH INDEX INDEX LENGTH
10798 return false;
10799 }
10800
10801 if (!emit1(JSOp::Lt)) {
10802 // [stack] ARRAY LENGTH INDEX BOOL
10803 return false;
10804 }
10805
10806 if (!wh.emitBody()) {
10807 // [stack] ARRAY LENGTH INDEX
10808 return false;
10809 }
10810
10811 if (!emitDupAt(2)) {
10812 // [stack] ARRAY LENGTH INDEX ARRAY
10813 return false;
10814 }
10815
10816 if (!emitDupAt(1)) {
10817 // [stack] ARRAY LENGTH INDEX ARRAY INDEX
10818 return false;
10819 }
10820
10821 // Retrieve initializers for this field
10822 if (!emit1(JSOp::GetElem)) {
10823 // [stack] ARRAY LENGTH INDEX INITIALIZERS
10824 return false;
10825 }
10826
10827 // This is guaranteed to run after super(), so we don't need TDZ checks.
10828 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_this_())) {
10829 // [stack] ARRAY LENGTH INDEX INITIALIZERS THIS
10830 return false;
10831 }
10832
10833 if (!emit1(JSOp::Swap)) {
10834 // [stack] ARRAY LENGTH INDEX THIS INITIALIZERS
10835 return false;
10836 }
10837
10838 DecoratorEmitter de(this);
10839 if (!de.emitInitializeFieldOrAccessor()) {
10840 // [stack] ARRAY LENGTH INDEX
10841 return false;
10842 }
10843
10844 if (!emit1(JSOp::Inc)) {
10845 // [stack] ARRAY LENGTH INDEX
10846 return false;
10847 }
10848
10849 if (!wh.emitEnd()) {
10850 // [stack] ARRAY LENGTH INDEX
10851 return false;
10852 }
10853
10854 if (!emitPopN(3)) {
10855 // [stack]
10856 return false;
10857 }
10858 // 5. Return unused.
10859
10860 if (!de.emitCallExtraInitializers(TaggedParserAtomIndex::WellKnown::
10861 dot_instanceExtraInitializers_())) {
10862 return false;
10863 }
10864 }
10865#endif
10866 }
10867 return true;
10868}
10869
10870bool BytecodeEmitter::emitInitializeStaticFields(ListNode* classMembers) {
10871 auto isStaticField = [](ParseNode* propdef) {
10872 return HasInitializer(propdef, true);
10873 };
10874 size_t numFields =
10875 std::count_if(classMembers->contents().begin(),
10876 classMembers->contents().end(), isStaticField);
10877
10878 if (numFields == 0) {
10879 return true;
10880 }
10881
10882 if (!emitGetName(
10883 TaggedParserAtomIndex::WellKnown::dot_staticInitializers_())) {
10884 // [stack] CTOR ARRAY
10885 return false;
10886 }
10887
10888 for (size_t fieldIndex = 0; fieldIndex < numFields; fieldIndex++) {
10889 bool hasNext = fieldIndex < numFields - 1;
10890 if (hasNext) {
10891 // We Dup to keep the array around (it is consumed in the bytecode below)
10892 // for next iterations of this loop, except for the last iteration, which
10893 // avoids an extra Pop at the end of the loop.
10894 if (!emit1(JSOp::Dup)) {
10895 // [stack] CTOR ARRAY ARRAY
10896 return false;
10897 }
10898 }
10899
10900 if (!emitNumberOp(fieldIndex)) {
10901 // [stack] CTOR ARRAY? ARRAY INDEX
10902 return false;
10903 }
10904
10905 if (!emit1(JSOp::GetElem)) {
10906 // [stack] CTOR ARRAY? FUNC
10907 return false;
10908 }
10909
10910 if (!emitDupAt(1 + hasNext)) {
10911 // [stack] CTOR ARRAY? FUNC CTOR
10912 return false;
10913 }
10914
10915 // Callee is always internal function.
10916 if (!emitCall(JSOp::CallIgnoresRv, 0)) {
10917 // [stack] CTOR ARRAY? RVAL
10918 return false;
10919 }
10920
10921 if (!emit1(JSOp::Pop)) {
10922 // [stack] CTOR ARRAY?
10923 return false;
10924 }
10925 }
10926
10927#ifdef ENABLE_DECORATORS
10928 // Decorators Proposal
10929 // https://arai-a.github.io/ecma262-compare/?pr=2417&id=sec-initializeinstanceelements
10930 // 4. For each element e of elements, do
10931 // 4.a. If elementRecord.[[Kind]] is field or accessor, then
10932 // 4.a.i. Perform ? InitializeFieldOrAccessor(O, elementRecord).
10933 //
10934
10935 // TODO: (See Bug 1817993) At the moment, we're applying the initialization
10936 // logic in two steps. The pre-decorator initialization code runs, stores
10937 // the initial value, and then we retrieve it here and apply the
10938 // initializers added by decorators. We should unify these two steps.
10939 if (!emitGetName(
10940 TaggedParserAtomIndex::WellKnown::dot_staticInitializers_())) {
10941 // [stack] CTOR ARRAY
10942 return false;
10943 }
10944
10945 if (!emit1(JSOp::Dup)) {
10946 // [stack] CTOR ARRAY ARRAY
10947 return false;
10948 }
10949
10950 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::length())) {
10951 // [stack] CTOR ARRAY LENGTH
10952 return false;
10953 }
10954
10955 if (!emitNumberOp(static_cast<double>(numFields))) {
10956 // [stack] CTOR ARRAY LENGTH INDEX
10957 return false;
10958 }
10959
10960 InternalWhileEmitter wh(this);
10961 // At this point, we have no context to determine offsets in the
10962 // code for this while statement. Ideally, it would correspond to
10963 // the field we're initializing.
10964 if (!wh.emitCond()) {
10965 // [stack] CTOR ARRAY LENGTH INDEX
10966 return false;
10967 }
10968
10969 if (!emit1(JSOp::Dup)) {
10970 // [stack] CTOR ARRAY LENGTH INDEX INDEX
10971 return false;
10972 }
10973
10974 if (!emitDupAt(2)) {
10975 // [stack] CTOR ARRAY LENGTH INDEX INDEX LENGTH
10976 return false;
10977 }
10978
10979 if (!emit1(JSOp::Lt)) {
10980 // [stack] CTOR ARRAY LENGTH INDEX BOOL
10981 return false;
10982 }
10983
10984 if (!wh.emitBody()) {
10985 // [stack] CTOR ARRAY LENGTH INDEX
10986 return false;
10987 }
10988
10989 if (!emitDupAt(2)) {
10990 // [stack] CTOR ARRAY LENGTH INDEX ARRAY
10991 return false;
10992 }
10993
10994 if (!emitDupAt(1)) {
10995 // [stack] CTOR ARRAY LENGTH INDEX ARRAY INDEX
10996 return false;
10997 }
10998
10999 // Retrieve initializers for this field
11000 if (!emit1(JSOp::GetElem)) {
11001 // [stack] CTOR ARRAY LENGTH INDEX INITIALIZERS
11002 return false;
11003 }
11004
11005 if (!emitDupAt(4)) {
11006 // [stack] CTOR ARRAY LENGTH INDEX INITIALIZERS CTOR
11007 return false;
11008 }
11009
11010 if (!emit1(JSOp::Swap)) {
11011 // [stack] CTOR ARRAY LENGTH INDEX CTOR INITIALIZERS
11012 return false;
11013 }
11014
11015 DecoratorEmitter de(this);
11016 if (!de.emitInitializeFieldOrAccessor()) {
11017 // [stack] CTOR ARRAY LENGTH INDEX
11018 return false;
11019 }
11020
11021 if (!emit1(JSOp::Inc)) {
11022 // [stack] CTOR ARRAY LENGTH INDEX
11023 return false;
11024 }
11025
11026 if (!wh.emitEnd()) {
11027 // [stack] CTOR ARRAY LENGTH INDEX
11028 return false;
11029 }
11030
11031 if (!emitPopN(3)) {
11032 // [stack] CTOR
11033 return false;
11034 }
11035 // 5. Return unused.
11036#endif
11037
11038 // Overwrite |.staticInitializers| and |.staticFieldKeys| with undefined to
11039 // avoid keeping the arrays alive indefinitely.
11040 auto clearStaticFieldSlot = [&](TaggedParserAtomIndex name) {
11041 NameOpEmitter noe(this, name, NameOpEmitter::Kind::SimpleAssignment);
11042 if (!noe.prepareForRhs()) {
11043 // [stack] ENV? VAL?
11044 return false;
11045 }
11046
11047 if (!emit1(JSOp::Undefined)) {
11048 // [stack] ENV? VAL? UNDEFINED
11049 return false;
11050 }
11051
11052 if (!noe.emitAssignment()) {
11053 // [stack] VAL
11054 return false;
11055 }
11056
11057 if (!emit1(JSOp::Pop)) {
11058 // [stack]
11059 return false;
11060 }
11061
11062 return true;
11063 };
11064
11065 if (!clearStaticFieldSlot(
11066 TaggedParserAtomIndex::WellKnown::dot_staticInitializers_())) {
11067 return false;
11068 }
11069
11070 auto isStaticFieldWithComputedName = [](ParseNode* propdef) {
11071 return propdef->is<ClassField>() && propdef->as<ClassField>().isStatic() &&
11072 propdef->as<ClassField>().name().getKind() ==
11073 ParseNodeKind::ComputedName;
11074 };
11075
11076 if (std::any_of(classMembers->contents().begin(),
11077 classMembers->contents().end(),
11078 isStaticFieldWithComputedName)) {
11079 if (!clearStaticFieldSlot(
11080 TaggedParserAtomIndex::WellKnown::dot_staticFieldKeys_())) {
11081 return false;
11082 }
11083 }
11084
11085 return true;
11086}
11087
11088// Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See
11089// the comment on emitSwitch.
11090MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitObject(ListNode* objNode) {
11091 // Note: this method uses the ObjLiteralWriter and emits ObjLiteralStencil
11092 // objects into the GCThingList, which will evaluate them into real GC objects
11093 // or shapes during JSScript::fullyInitFromEmitter. Eventually we want
11094 // JSOp::Object to be a real opcode, but for now, performance constraints
11095 // limit us to evaluating object literals at the end of parse, when we're
11096 // allowed to allocate GC things.
11097 //
11098 // There are four cases here, in descending order of preference:
11099 //
11100 // 1. The list of property names is "normal" and constant (no computed
11101 // values, no integer indices), the values are all simple constants
11102 // (numbers, booleans, strings), *and* this occurs in a run-once
11103 // (singleton) context. In this case, we can emit ObjLiteral
11104 // instructions to build an object with values, and the object will be
11105 // attached to a JSOp::Object opcode, whose semantics are for the backend
11106 // to simply steal the object from the script.
11107 //
11108 // 2. The list of property names is "normal" and constant as above, *and* this
11109 // occurs in a run-once (singleton) context, but some values are complex
11110 // (computed expressions, sub-objects, functions, etc.). In this case, we
11111 // can still use JSOp::Object (because singleton context), but the object
11112 // has |undefined| property values and InitProp ops are emitted to set the
11113 // values.
11114 //
11115 // 3. The list of property names is "normal" and constant as above, but this
11116 // occurs in a non-run-once (non-singleton) context. In this case, we can
11117 // use the ObjLiteral functionality to describe an *empty* object (all
11118 // values left undefined) with the right fields, which will become a
11119 // JSOp::NewObject opcode using the object's shape to speed up the creation
11120 // of the object each time it executes. The emitted bytecode still needs
11121 // InitProp ops to set the values in this case.
11122 //
11123 // 4. Any other case. As a fallback, we use NewInit to create a new, empty
11124 // object (i.e., `{}`) and then emit bytecode to initialize its properties
11125 // one-by-one.
11126
11127 bool useObjLiteral = false;
11128 bool useObjLiteralValues = false;
11129 isPropertyListObjLiteralCompatible(objNode, &useObjLiteralValues,
11130 &useObjLiteral);
11131
11132 // [stack]
11133 //
11134 ObjectEmitter oe(this);
11135 if (useObjLiteral) {
11136 bool singleton = checkSingletonContext() &&
11137 !objNode->hasNonConstInitializer() && objNode->head();
11138 JSOp op;
11139 if (singleton) {
11140 // Case 1 or 2.
11141 op = JSOp::Object;
11142 } else {
11143 // Case 3.
11144 useObjLiteralValues = false;
11145 op = JSOp::NewObject;
11146 }
11147
11148 // Use an ObjLiteral op. This will record ObjLiteral insns in the
11149 // objLiteralWriter's buffer and add a fixup to the list of ObjLiteral
11150 // fixups so that at GC-publish time at the end of parse, the full object
11151 // (case 1 or 2) or shape (case 3) can be allocated and the bytecode can be
11152 // patched to refer to it.
11153 if (!emitPropertyListObjLiteral(objNode, op, useObjLiteralValues)) {
11154 // [stack] OBJ
11155 return false;
11156 }
11157 // Put the ObjectEmitter in the right state. This tells it that there will
11158 // already be an object on the stack as a result of the (eventual)
11159 // NewObject or Object op, and prepares it to emit values if needed.
11160 if (!oe.emitObjectWithTemplateOnStack()) {
11161 // [stack] OBJ
11162 return false;
11163 }
11164 if (!useObjLiteralValues) {
11165 // Case 2 or 3 above: we still need to emit bytecode to fill in the
11166 // object's property values.
11167 if (!emitPropertyList(objNode, oe, ObjectLiteral)) {
11168 // [stack] OBJ
11169 return false;
11170 }
11171 }
11172 } else {
11173 // Case 4 above: no ObjLiteral use, just bytecode to build the object from
11174 // scratch.
11175 if (!oe.emitObject(objNode->count())) {
11176 // [stack] OBJ
11177 return false;
11178 }
11179 if (!emitPropertyList(objNode, oe, ObjectLiteral)) {
11180 // [stack] OBJ
11181 return false;
11182 }
11183 }
11184
11185 if (!oe.emitEnd()) {
11186 // [stack] OBJ
11187 return false;
11188 }
11189
11190 return true;
11191}
11192
11193bool BytecodeEmitter::emitArrayLiteral(ListNode* array) {
11194 // Emit JSOp::Object if the array consists entirely of primitive values and we
11195 // are in a singleton context.
11196 if (checkSingletonContext() && !array->hasNonConstInitializer() &&
11197 !array->empty() && isArrayObjLiteralCompatible(array)) {
11198 return emitObjLiteralArray(array);
11199 }
11200
11201 return emitArray(array);
11202}
11203
11204bool BytecodeEmitter::emitArray(ListNode* array) {
11205 /*
11206 * Emit code for [a, b, c] that is equivalent to constructing a new
11207 * array and in source order evaluating each element value and adding
11208 * it to the array, without invoking latent setters. We use the
11209 * JSOp::NewInit and JSOp::InitElemArray bytecodes to ignore setters and
11210 * to avoid dup'ing and popping the array as each element is added, as
11211 * JSOp::SetElem/JSOp::SetProp would do.
11212 */
11213
11214 uint32_t nspread = 0;
11215 for (ParseNode* elem : array->contents()) {
11216 if (elem->isKind(ParseNodeKind::Spread)) {
11217 nspread++;
11218 }
11219 }
11220
11221 // Array literal's length is limited to NELEMENTS_LIMIT in parser.
11222 static_assert(NativeObject::MAX_DENSE_ELEMENTS_COUNT <= INT32_MAX(2147483647),
11223 "array literals' maximum length must not exceed limits "
11224 "required by BaselineCompiler::emit_NewArray, "
11225 "BaselineCompiler::emit_InitElemArray, "
11226 "and DoSetElemFallback's handling of JSOp::InitElemArray");
11227
11228 uint32_t count = array->count();
11229 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11229); AnnotateMozCrashReason("MOZ_ASSERT" "(" "count >= nspread"
")"); do { *((volatile int*)__null) = 11229; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11230 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11232); AnnotateMozCrashReason("MOZ_ASSERT" "(" "count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT"
") (" "the parser must throw an error if the array exceeds maximum "
"length" ")"); do { *((volatile int*)__null) = 11232; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
11231 "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11232); AnnotateMozCrashReason("MOZ_ASSERT" "(" "count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT"
") (" "the parser must throw an error if the array exceeds maximum "
"length" ")"); do { *((volatile int*)__null) = 11232; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
11232 "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11232); AnnotateMozCrashReason("MOZ_ASSERT" "(" "count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT"
") (" "the parser must throw an error if the array exceeds maximum "
"length" ")"); do { *((volatile int*)__null) = 11232; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
11233
11234 // For arrays with spread, this is a very pessimistic allocation, the
11235 // minimum possible final size.
11236 if (!emitUint32Operand(JSOp::NewArray, count - nspread)) {
11237 // [stack] ARRAY
11238 return false;
11239 }
11240
11241 uint32_t index = 0;
11242 bool afterSpread = false;
11243 for (ParseNode* elem : array->contents()) {
11244 if (elem->isKind(ParseNodeKind::Spread)) {
11245 if (!afterSpread) {
11246 afterSpread = true;
11247 if (!emitNumberOp(index)) {
11248 // [stack] ARRAY INDEX
11249 return false;
11250 }
11251 }
11252
11253 ParseNode* expr = elem->as<UnaryNode>().kid();
11254 SelfHostedIter selfHostedIter = getSelfHostedIterFor(expr);
11255
11256 if (!updateSourceCoordNotes(elem->pn_pos.begin)) {
11257 return false;
11258 }
11259 if (!emitIterable(expr, selfHostedIter)) {
11260 // [stack] ARRAY INDEX ITERABLE
11261 return false;
11262 }
11263 if (!emitIterator(selfHostedIter)) {
11264 // [stack] ARRAY INDEX NEXT ITER
11265 return false;
11266 }
11267 if (!emit2(JSOp::Pick, 3)) {
11268 // [stack] INDEX NEXT ITER ARRAY
11269 return false;
11270 }
11271 if (!emit2(JSOp::Pick, 3)) {
11272 // [stack] NEXT ITER ARRAY INDEX
11273 return false;
11274 }
11275 if (!emitSpread(selfHostedIter)) {
11276 // [stack] ARRAY INDEX
11277 return false;
11278 }
11279 } else {
11280 if (!updateSourceCoordNotesIfNonLiteral(elem)) {
11281 return false;
11282 }
11283 if (elem->isKind(ParseNodeKind::Elision)) {
11284 if (!emit1(JSOp::Hole)) {
11285 return false;
11286 }
11287 } else {
11288 if (!emitTree(elem, ValueUsage::WantValue)) {
11289 // [stack] ARRAY INDEX? VALUE
11290 return false;
11291 }
11292 }
11293
11294 if (afterSpread) {
11295 if (!emit1(JSOp::InitElemInc)) {
11296 // [stack] ARRAY (INDEX+1)
11297 return false;
11298 }
11299 } else {
11300 if (!emitUint32Operand(JSOp::InitElemArray, index)) {
11301 // [stack] ARRAY
11302 return false;
11303 }
11304 }
11305 }
11306
11307 index++;
11308 }
11309 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11309); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index == count"
")"); do { *((volatile int*)__null) = 11309; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11310 if (afterSpread) {
11311 if (!emit1(JSOp::Pop)) {
11312 // [stack] ARRAY
11313 return false;
11314 }
11315 }
11316 return true;
11317}
11318
11319bool BytecodeEmitter::emitSpreadIntoArray(UnaryNode* elem) {
11320 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11320); AnnotateMozCrashReason("MOZ_ASSERT" "(" "elem->isKind(ParseNodeKind::Spread)"
")"); do { *((volatile int*)__null) = 11320; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11321
11322 if (!updateSourceCoordNotes(elem->pn_pos.begin)) {
11323 // [stack] VALUE
11324 return false;
11325 }
11326
11327 SelfHostedIter selfHostedIter = getSelfHostedIterFor(elem->kid());
11328 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11329); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter == SelfHostedIter::Deny || selfHostedIter == SelfHostedIter::AllowContent"
")"); do { *((volatile int*)__null) = 11329; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11329 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11329); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter == SelfHostedIter::Deny || selfHostedIter == SelfHostedIter::AllowContent"
")"); do { *((volatile int*)__null) = 11329; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11330
11331 if (!emitIterator(selfHostedIter)) {
11332 // [stack] NEXT ITER
11333 return false;
11334 }
11335
11336 if (!emitUint32Operand(JSOp::NewArray, 0)) {
11337 // [stack] NEXT ITER ARRAY
11338 return false;
11339 }
11340
11341 if (!emitNumberOp(0)) {
11342 // [stack] NEXT ITER ARRAY INDEX
11343 return false;
11344 }
11345
11346 if (!emitSpread(selfHostedIter)) {
11347 // [stack] ARRAY INDEX
11348 return false;
11349 }
11350
11351 if (!emit1(JSOp::Pop)) {
11352 // [stack] ARRAY
11353 return false;
11354 }
11355 return true;
11356}
11357
11358#ifdef ENABLE_RECORD_TUPLE
11359bool BytecodeEmitter::emitRecordLiteral(ListNode* record) {
11360 if (!emitUint32Operand(JSOp::InitRecord, record->count())) {
11361 // [stack] RECORD
11362 return false;
11363 }
11364
11365 for (ParseNode* propdef : record->contents()) {
11366 if (propdef->isKind(ParseNodeKind::Spread)) {
11367 if (!emitTree(propdef->as<UnaryNode>().kid())) {
11368 // [stack] RECORD SPREADEE
11369 return false;
11370 }
11371 if (!emit1(JSOp::AddRecordSpread)) {
11372 // [stack] RECORD
11373 return false;
11374 }
11375 } else {
11376 BinaryNode* prop = &propdef->as<BinaryNode>();
11377
11378 ParseNode* key = prop->left();
11379 ParseNode* value = prop->right();
11380
11381 switch (key->getKind()) {
11382 case ParseNodeKind::ObjectPropertyName:
11383 if (!emitStringOp(JSOp::String, key->as<NameNode>().atom())) {
11384 return false;
11385 }
11386 break;
11387 case ParseNodeKind::ComputedName:
11388 if (!emitTree(key->as<UnaryNode>().kid())) {
11389 return false;
11390 }
11391 break;
11392 default:
11393 MOZ_ASSERT(key->isKind(ParseNodeKind::StringExpr) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(key->isKind(ParseNodeKind::StringExpr) || key->
isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind
::BigIntExpr))>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(key->isKind(ParseNodeKind::StringExpr
) || key->isKind(ParseNodeKind::NumberExpr) || key->isKind
(ParseNodeKind::BigIntExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11395); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr)"
")"); do { *((volatile int*)__null) = 11395; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11394 key->isKind(ParseNodeKind::NumberExpr) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(key->isKind(ParseNodeKind::StringExpr) || key->
isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind
::BigIntExpr))>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(key->isKind(ParseNodeKind::StringExpr
) || key->isKind(ParseNodeKind::NumberExpr) || key->isKind
(ParseNodeKind::BigIntExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11395); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr)"
")"); do { *((volatile int*)__null) = 11395; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11395 key->isKind(ParseNodeKind::BigIntExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(key->isKind(ParseNodeKind::StringExpr) || key->
isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind
::BigIntExpr))>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(key->isKind(ParseNodeKind::StringExpr
) || key->isKind(ParseNodeKind::NumberExpr) || key->isKind
(ParseNodeKind::BigIntExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11395); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr)"
")"); do { *((volatile int*)__null) = 11395; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11396 if (!emitTree(key)) {
11397 return false;
11398 }
11399 break;
11400 }
11401 // [stack] RECORD KEY
11402
11403 if (!emitTree(value)) {
11404 // [stack] RECORD KEY VALUE
11405 return false;
11406 }
11407
11408 if (!emit1(JSOp::AddRecordProperty)) {
11409 // [stack] RECORD
11410 return false;
11411 }
11412 }
11413 }
11414
11415 if (!emit1(JSOp::FinishRecord)) {
11416 // [stack] RECORD
11417 return false;
11418 }
11419
11420 return true;
11421}
11422
11423bool BytecodeEmitter::emitTupleLiteral(ListNode* tuple) {
11424 if (!emitUint32Operand(JSOp::InitTuple, tuple->count())) {
11425 // [stack] TUPLE
11426 return false;
11427 }
11428
11429 for (ParseNode* elt : tuple->contents()) {
11430 if (elt->isKind(ParseNodeKind::Spread)) {
11431 ParseNode* expr = elt->as<UnaryNode>().kid();
11432 auto selfHostedIter = getSelfHostedIterFor(expr);
11433
11434 if (!emitIterable(expr, selfHostedIter)) {
11435 // [stack] TUPLE ITERABLE
11436 return false;
11437 }
11438 if (!emitIterator(selfHostedIter)) {
11439 // [stack] TUPLE NEXT ITER
11440 return false;
11441 }
11442 if (!emit2(JSOp::Pick, 2)) {
11443 // [stack] NEXT ITER TUPLE
11444 return false;
11445 }
11446 if (!emitSpread(selfHostedIter, /* spreadeeStackItems = */ 1,
11447 JSOp::AddTupleElement)) {
11448 // [stack] TUPLE
11449 return false;
11450 }
11451 } else {
11452 // Update location to throw errors about non-primitive elements
11453 // in the correct position.
11454 if (!updateSourceCoordNotesIfNonLiteral(elt)) {
11455 return false;
11456 }
11457
11458 if (!emitTree(elt)) {
11459 // [stack] TUPLE VALUE
11460 return false;
11461 }
11462
11463 if (!emit1(JSOp::AddTupleElement)) {
11464 // [stack] TUPLE
11465 return false;
11466 }
11467 }
11468 }
11469
11470 if (!emit1(JSOp::FinishTuple)) {
11471 // [stack] TUPLE
11472 return false;
11473 }
11474
11475 return true;
11476}
11477#endif
11478
11479static inline JSOp UnaryOpParseNodeKindToJSOp(ParseNodeKind pnk) {
11480 switch (pnk) {
11481 case ParseNodeKind::ThrowStmt:
11482 return JSOp::Throw;
11483 case ParseNodeKind::VoidExpr:
11484 return JSOp::Void;
11485 case ParseNodeKind::NotExpr:
11486 return JSOp::Not;
11487 case ParseNodeKind::BitNotExpr:
11488 return JSOp::BitNot;
11489 case ParseNodeKind::PosExpr:
11490 return JSOp::Pos;
11491 case ParseNodeKind::NegExpr:
11492 return JSOp::Neg;
11493 default:
11494 MOZ_CRASH("unexpected unary op")do { do { } while (false); MOZ_ReportCrash("" "unexpected unary op"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11494); AnnotateMozCrashReason("MOZ_CRASH(" "unexpected unary op"
")"); do { *((volatile int*)__null) = 11494; __attribute__((
nomerge)) ::abort(); } while (false); } while (false)
;
11495 }
11496}
11497
11498bool BytecodeEmitter::emitUnary(UnaryNode* unaryNode) {
11499 if (!updateSourceCoordNotes(unaryNode->pn_pos.begin)) {
11500 return false;
11501 }
11502
11503 JSOp op = UnaryOpParseNodeKindToJSOp(unaryNode->getKind());
11504 ValueUsage valueUsage =
11505 op == JSOp::Void ? ValueUsage::IgnoreValue : ValueUsage::WantValue;
11506 if (!emitTree(unaryNode->kid(), valueUsage)) {
11507 return false;
11508 }
11509 return emit1(op);
11510}
11511
11512bool BytecodeEmitter::emitTypeof(UnaryNode* typeofNode, JSOp op) {
11513 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11513); AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::Typeof || op == JSOp::TypeofExpr"
")"); do { *((volatile int*)__null) = 11513; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11514
11515 if (!updateSourceCoordNotes(typeofNode->pn_pos.begin)) {
11516 return false;
11517 }
11518
11519 if (!emitTree(typeofNode->kid())) {
11520 return false;
11521 }
11522
11523 return emit1(op);
11524}
11525
11526bool BytecodeEmitter::tryEmitTypeofEq(ListNode* node, bool* emitted) {
11527 // Emit specialized opcode for `typeof val == "type` or `typeof val != "type`
11528 // if possible.
11529 //
11530 // NOTE: Given the comparison is done for string, `==` and `===` have
11531 // no difference. Same for `!=` and `!==`.
11532 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))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(node->isKind(ParseNodeKind::StrictEqExpr) || node
->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind
::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("node->isKind(ParseNodeKind::StrictEqExpr) || node->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11535); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::StrictEqExpr) || node->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)"
")"); do { *((volatile int*)__null) = 11535; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11533 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))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(node->isKind(ParseNodeKind::StrictEqExpr) || node
->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind
::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("node->isKind(ParseNodeKind::StrictEqExpr) || node->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11535); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::StrictEqExpr) || node->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)"
")"); do { *((volatile int*)__null) = 11535; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11534 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))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(node->isKind(ParseNodeKind::StrictEqExpr) || node
->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind
::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("node->isKind(ParseNodeKind::StrictEqExpr) || node->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11535); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::StrictEqExpr) || node->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)"
")"); do { *((volatile int*)__null) = 11535; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11535 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))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(node->isKind(ParseNodeKind::StrictEqExpr) || node
->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind
::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("node->isKind(ParseNodeKind::StrictEqExpr) || node->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11535); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::StrictEqExpr) || node->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)"
")"); do { *((volatile int*)__null) = 11535; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11536
11537 if (node->count() != 2) {
11538 *emitted = false;
11539 return true;
11540 }
11541
11542 ParseNode* left = node->head();
11543 ParseNode* right = left->pn_next;
11544 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11544); AnnotateMozCrashReason("MOZ_ASSERT" "(" "right" ")"
); do { *((volatile int*)__null) = 11544; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
11545
11546 UnaryNode* typeofNode;
11547 NameNode* typenameNode;
11548 JSOp op;
11549
11550 if (node->isKind(ParseNodeKind::StrictEqExpr) ||
11551 node->isKind(ParseNodeKind::EqExpr)) {
11552 op = JSOp::Eq;
11553 } else {
11554 op = JSOp::Ne;
11555 }
11556
11557 // NOTE: ParseNodeKind::TypeOfExpr cannot use JSOp::TypeofEq.
11558 // See JSOp::GetName document.
11559 if (left->isKind(ParseNodeKind::TypeOfNameExpr) &&
11560 right->isKind(ParseNodeKind::StringExpr)) {
11561 typeofNode = &left->as<UnaryNode>();
11562 typenameNode = &right->as<NameNode>();
11563 } else if (right->isKind(ParseNodeKind::TypeOfNameExpr) &&
11564 left->isKind(ParseNodeKind::StringExpr)) {
11565 typeofNode = &right->as<UnaryNode>();
11566 typenameNode = &left->as<NameNode>();
11567 } else {
11568 *emitted = false;
11569 return true;
11570 }
11571
11572 JSType type;
11573 TaggedParserAtomIndex typeName = typenameNode->atom();
11574 if (typeName == TaggedParserAtomIndex::WellKnown::undefined()) {
11575 type = JSTYPE_UNDEFINED;
11576 } else if (typeName == TaggedParserAtomIndex::WellKnown::object()) {
11577 type = JSTYPE_OBJECT;
11578 } else if (typeName == TaggedParserAtomIndex::WellKnown::function()) {
11579 type = JSTYPE_FUNCTION;
11580 } else if (typeName == TaggedParserAtomIndex::WellKnown::string()) {
11581 type = JSTYPE_STRING;
11582 } else if (typeName == TaggedParserAtomIndex::WellKnown::number()) {
11583 type = JSTYPE_NUMBER;
11584 } else if (typeName == TaggedParserAtomIndex::WellKnown::boolean()) {
11585 type = JSTYPE_BOOLEAN;
11586 } else if (typeName == TaggedParserAtomIndex::WellKnown::symbol()) {
11587 type = JSTYPE_SYMBOL;
11588 } else if (typeName == TaggedParserAtomIndex::WellKnown::bigint()) {
11589 type = JSTYPE_BIGINT;
11590 }
11591#ifdef ENABLE_RECORD_TUPLE
11592 else if (typeName == TaggedParserAtomIndex::WellKnown::record()) {
11593 type = JSTYPE_RECORD;
11594 } else if (typeName == TaggedParserAtomIndex::WellKnown::tuple()) {
11595 type = JSTYPE_TUPLE;
11596 }
11597#endif
11598 else {
11599 *emitted = false;
11600 return true;
11601 }
11602
11603 if (!updateSourceCoordNotes(typeofNode->pn_pos.begin)) {
11604 return false;
11605 }
11606
11607 if (!emitTree(typeofNode->kid())) {
11608 // [stack] VAL
11609 return false;
11610 }
11611
11612 if (!emit2(JSOp::TypeofEq, TypeofEqOperand(type, op).rawValue())) {
11613 // [stack] CMP
11614 return false;
11615 }
11616
11617 *emitted = true;
11618 return true;
11619}
11620
11621bool BytecodeEmitter::emitFunctionFormalParameters(ParamsBodyNode* paramsBody) {
11622 FunctionBox* funbox = sc->asFunctionBox();
11623
11624 bool hasRest = funbox->hasRest();
11625
11626 FunctionParamsEmitter fpe(this, funbox);
11627 for (ParseNode* arg : paramsBody->parameters()) {
11628 ParseNode* bindingElement = arg;
11629 ParseNode* initializer = nullptr;
11630 if (arg->isKind(ParseNodeKind::AssignExpr)) {
11631 bindingElement = arg->as<BinaryNode>().left();
11632 initializer = arg->as<BinaryNode>().right();
11633 }
11634 bool hasInitializer = !!initializer;
11635 bool isRest =
11636 hasRest && arg->pn_next == *std::end(paramsBody->parameters());
11637 bool isDestructuring = !bindingElement->isKind(ParseNodeKind::Name);
11638
11639 // Left-hand sides are either simple names or destructuring patterns.
11640 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11642); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bindingElement->isKind(ParseNodeKind::Name) || bindingElement->isKind(ParseNodeKind::ArrayExpr) || bindingElement->isKind(ParseNodeKind::ObjectExpr)"
")"); do { *((volatile int*)__null) = 11642; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11641 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11642); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bindingElement->isKind(ParseNodeKind::Name) || bindingElement->isKind(ParseNodeKind::ArrayExpr) || bindingElement->isKind(ParseNodeKind::ObjectExpr)"
")"); do { *((volatile int*)__null) = 11642; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11642 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11642); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bindingElement->isKind(ParseNodeKind::Name) || bindingElement->isKind(ParseNodeKind::ArrayExpr) || bindingElement->isKind(ParseNodeKind::ObjectExpr)"
")"); do { *((volatile int*)__null) = 11642; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11643
11644 auto emitDefaultInitializer = [this, &initializer, &bindingElement]() {
11645 // [stack]
11646
11647 if (!this->emitInitializer(initializer, bindingElement)) {
11648 // [stack] DEFAULT
11649 return false;
11650 }
11651 return true;
11652 };
11653
11654 auto emitDestructuring = [this, &bindingElement]() {
11655 // [stack] ARG
11656
11657 if (!this->emitDestructuringOps(&bindingElement->as<ListNode>(),
11658 DestructuringFlavor::Declaration)) {
11659 // [stack] ARG
11660 return false;
11661 }
11662
11663 return true;
11664 };
11665
11666 if (isRest) {
11667 if (isDestructuring) {
11668 if (!fpe.prepareForDestructuringRest()) {
11669 // [stack]
11670 return false;
11671 }
11672 if (!emitDestructuring()) {
11673 // [stack]
11674 return false;
11675 }
11676 if (!fpe.emitDestructuringRestEnd()) {
11677 // [stack]
11678 return false;
11679 }
11680 } else {
11681 auto paramName = bindingElement->as<NameNode>().name();
11682 if (!fpe.emitRest(paramName)) {
11683 // [stack]
11684 return false;
11685 }
11686 }
11687
11688 continue;
11689 }
11690
11691 if (isDestructuring) {
11692 if (hasInitializer) {
11693 if (!fpe.prepareForDestructuringDefaultInitializer()) {
11694 // [stack]
11695 return false;
11696 }
11697 if (!emitDefaultInitializer()) {
11698 // [stack]
11699 return false;
11700 }
11701 if (!fpe.prepareForDestructuringDefault()) {
11702 // [stack]
11703 return false;
11704 }
11705 if (!emitDestructuring()) {
11706 // [stack]
11707 return false;
11708 }
11709 if (!fpe.emitDestructuringDefaultEnd()) {
11710 // [stack]
11711 return false;
11712 }
11713 } else {
11714 if (!fpe.prepareForDestructuring()) {
11715 // [stack]
11716 return false;
11717 }
11718 if (!emitDestructuring()) {
11719 // [stack]
11720 return false;
11721 }
11722 if (!fpe.emitDestructuringEnd()) {
11723 // [stack]
11724 return false;
11725 }
11726 }
11727
11728 continue;
11729 }
11730
11731 if (hasInitializer) {
11732 if (!fpe.prepareForDefault()) {
11733 // [stack]
11734 return false;
11735 }
11736 if (!emitDefaultInitializer()) {
11737 // [stack]
11738 return false;
11739 }
11740 auto paramName = bindingElement->as<NameNode>().name();
11741 if (!fpe.emitDefaultEnd(paramName)) {
11742 // [stack]
11743 return false;
11744 }
11745
11746 continue;
11747 }
11748
11749 auto paramName = bindingElement->as<NameNode>().name();
11750 if (!fpe.emitSimple(paramName)) {
11751 // [stack]
11752 return false;
11753 }
11754 }
11755
11756 return true;
11757}
11758
11759bool BytecodeEmitter::emitInitializeFunctionSpecialNames() {
11760 FunctionBox* funbox = sc->asFunctionBox();
11761
11762 // [stack]
11763
11764 auto emitInitializeFunctionSpecialName =
11765 [](BytecodeEmitter* bce, TaggedParserAtomIndex name, JSOp op) {
11766 // A special name must be slotful, either on the frame or on the
11767 // call environment.
11768 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11768); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bce->lookupName(name).hasKnownSlot()"
")"); do { *((volatile int*)__null) = 11768; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11769
11770 NameOpEmitter noe(bce, name, NameOpEmitter::Kind::Initialize);
11771 if (!noe.prepareForRhs()) {
11772 // [stack]
11773 return false;
11774 }
11775 if (!bce->emit1(op)) {
11776 // [stack] THIS/ARGUMENTS/NEW.TARGET
11777 return false;
11778 }
11779 if (!noe.emitAssignment()) {
11780 // [stack] THIS/ARGUMENTS/NEW.TARGET
11781 return false;
11782 }
11783 if (!bce->emit1(JSOp::Pop)) {
11784 // [stack]
11785 return false;
11786 }
11787
11788 return true;
11789 };
11790
11791 // Do nothing if the function doesn't have an arguments binding.
11792 if (funbox->needsArgsObj()) {
11793 // Self-hosted code should use the more efficient ArgumentsLength and
11794 // GetArgument intrinsics instead of `arguments`.
11795 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11795); AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode != BytecodeEmitter::SelfHosting"
")"); do { *((volatile int*)__null) = 11795; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11796 if (!emitInitializeFunctionSpecialName(
11797 this, TaggedParserAtomIndex::WellKnown::arguments(),
11798 JSOp::Arguments)) {
11799 // [stack]
11800 return false;
11801 }
11802 }
11803
11804 // Do nothing if the function doesn't have a this-binding (this
11805 // happens for instance if it doesn't use this/eval or if it's an
11806 // arrow function).
11807 if (funbox->functionHasThisBinding()) {
11808 if (!emitInitializeFunctionSpecialName(
11809 this, TaggedParserAtomIndex::WellKnown::dot_this_(),
11810 JSOp::FunctionThis)) {
11811 return false;
11812 }
11813 }
11814
11815 // Do nothing if the function doesn't have a new.target-binding (this happens
11816 // for instance if it doesn't use new.target/eval or if it's an arrow
11817 // function).
11818 if (funbox->functionHasNewTargetBinding()) {
11819 if (!emitInitializeFunctionSpecialName(
11820 this, TaggedParserAtomIndex::WellKnown::dot_newTarget_(),
11821 JSOp::NewTarget)) {
11822 return false;
11823 }
11824 }
11825
11826 // Do nothing if the function doesn't implicitly return a promise result.
11827 if (funbox->needsPromiseResult()) {
11828 if (!emitInitializeFunctionSpecialName(
11829 this, TaggedParserAtomIndex::WellKnown::dot_generator_(),
11830 JSOp::Generator)) {
11831 // [stack]
11832 return false;
11833 }
11834 }
11835 return true;
11836}
11837
11838bool BytecodeEmitter::emitLexicalInitialization(NameNode* name) {
11839 return emitLexicalInitialization(name->name());
11840}
11841
11842bool BytecodeEmitter::emitLexicalInitialization(TaggedParserAtomIndex name) {
11843 NameOpEmitter noe(this, name, NameOpEmitter::Kind::Initialize);
11844 if (!noe.prepareForRhs()) {
11845 return false;
11846 }
11847
11848 // The caller has pushed the RHS to the top of the stack. Assert that the
11849 // binding can be initialized without a binding object on the stack, and that
11850 // no JSOp::BindUnqualifiedName or JSOp::BindUnqualifiedGName ops were
11851 // emitted.
11852 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11853); AnnotateMozCrashReason("MOZ_ASSERT" "(" "noe.loc().isLexical() || noe.loc().isSynthetic() || noe.loc().isPrivateMethod()"
")"); do { *((volatile int*)__null) = 11853; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11853 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11853); AnnotateMozCrashReason("MOZ_ASSERT" "(" "noe.loc().isLexical() || noe.loc().isSynthetic() || noe.loc().isPrivateMethod()"
")"); do { *((volatile int*)__null) = 11853; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11854 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11854); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!noe.emittedBindOp()"
")"); do { *((volatile int*)__null) = 11854; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11855
11856 if (!noe.emitAssignment()) {
11857 return false;
11858 }
11859
11860 return true;
11861}
11862
11863static MOZ_ALWAYS_INLINEinline ParseNode* FindConstructor(ListNode* classMethods) {
11864 for (ParseNode* classElement : classMethods->contents()) {
11865 ParseNode* unwrappedElement = classElement;
11866 if (unwrappedElement->is<LexicalScopeNode>()) {
11867 unwrappedElement = unwrappedElement->as<LexicalScopeNode>().scopeBody();
11868 }
11869 if (unwrappedElement->is<ClassMethod>()) {
11870 ClassMethod& method = unwrappedElement->as<ClassMethod>();
11871 ParseNode& methodName = method.name();
11872 if (!method.isStatic() &&
11873 (methodName.isKind(ParseNodeKind::ObjectPropertyName) ||
11874 methodName.isKind(ParseNodeKind::StringExpr)) &&
11875 methodName.as<NameNode>().atom() ==
11876 TaggedParserAtomIndex::WellKnown::constructor()) {
11877 return classElement;
11878 }
11879 }
11880 }
11881 return nullptr;
11882}
11883
11884bool BytecodeEmitter::emitNewPrivateName(TaggedParserAtomIndex bindingName,
11885 TaggedParserAtomIndex symbolName) {
11886 if (!emitAtomOp(JSOp::NewPrivateName, symbolName)) {
11887 // [stack] HERITAGE PRIVATENAME
11888 return false;
11889 }
11890
11891 // Add a binding for #name => privatename
11892 if (!emitLexicalInitialization(bindingName)) {
11893 // [stack] HERITAGE PRIVATENAME
11894 return false;
11895 }
11896
11897 // Pop Private name off the stack.
11898 if (!emit1(JSOp::Pop)) {
11899 // [stack] HERITAGE
11900 return false;
11901 }
11902
11903 return true;
11904}
11905
11906bool BytecodeEmitter::emitNewPrivateNames(
11907 TaggedParserAtomIndex privateBrandName, ListNode* classMembers) {
11908 bool hasPrivateBrand = false;
11909
11910 for (ParseNode* classElement : classMembers->contents()) {
11911 ParseNode* elementName;
11912 if (classElement->is<ClassMethod>()) {
11913 elementName = &classElement->as<ClassMethod>().name();
11914 } else if (classElement->is<ClassField>()) {
11915 elementName = &classElement->as<ClassField>().name();
11916 } else {
11917 continue;
11918 }
11919
11920 if (!elementName->isKind(ParseNodeKind::PrivateName)) {
11921 continue;
11922 }
11923
11924 // Non-static private methods' private names are optimized away.
11925 bool isOptimized = false;
11926 if (classElement->is<ClassMethod>() &&
11927 !classElement->as<ClassMethod>().isStatic()) {
11928 hasPrivateBrand = true;
11929 if (classElement->as<ClassMethod>().accessorType() ==
11930 AccessorType::None) {
11931 isOptimized = true;
11932 }
11933 }
11934
11935 if (!isOptimized) {
11936 auto privateName = elementName->as<NameNode>().name();
11937 if (!emitNewPrivateName(privateName, privateName)) {
11938 return false;
11939 }
11940 }
11941 }
11942
11943 if (hasPrivateBrand) {
11944 // We don't make a private name for every optimized method, but we need one
11945 // private name per class, the `.privateBrand`.
11946 if (!emitNewPrivateName(
11947 TaggedParserAtomIndex::WellKnown::dot_privateBrand_(),
11948 privateBrandName)) {
11949 return false;
11950 }
11951 }
11952 return true;
11953}
11954
11955// This follows ES6 14.5.14 (ClassDefinitionEvaluation) and ES6 14.5.15
11956// (BindingClassDeclarationEvaluation).
11957bool BytecodeEmitter::emitClass(
11958 ClassNode* classNode,
11959 ClassNameKind nameKind /* = ClassNameKind::BindingName */,
11960 TaggedParserAtomIndex
11961 nameForAnonymousClass /* = TaggedParserAtomIndex::null() */) {
11962 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11963); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(nameKind == ClassNameKind::InferredName) == bool(nameForAnonymousClass)"
")"); do { *((volatile int*)__null) = 11963; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11963 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11963); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(nameKind == ClassNameKind::InferredName) == bool(nameForAnonymousClass)"
")"); do { *((volatile int*)__null) = 11963; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11964
11965 ParseNode* heritageExpression = classNode->heritage();
11966 ListNode* classMembers = classNode->memberList();
11967 ParseNode* constructor = FindConstructor(classMembers);
11968
11969 // If |nameKind != ClassNameKind::ComputedName|
11970 // [stack]
11971 // Else
11972 // [stack] NAME
11973
11974 ClassEmitter ce(this);
11975 TaggedParserAtomIndex innerName;
11976 ClassEmitter::Kind kind = ClassEmitter::Kind::Expression;
11977 if (ClassNames* names = classNode->names()) {
11978 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11978); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nameKind == ClassNameKind::BindingName"
")"); do { *((volatile int*)__null) = 11978; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11979 innerName = names->innerBinding()->name();
11980 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11980); AnnotateMozCrashReason("MOZ_ASSERT" "(" "innerName"
")"); do { *((volatile int*)__null) = 11980; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11981
11982 if (names->outerBinding()) {
11983 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()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11983); AnnotateMozCrashReason("MOZ_ASSERT" "(" "names->outerBinding()->name()"
")"); do { *((volatile int*)__null) = 11983; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11984 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11984); AnnotateMozCrashReason("MOZ_ASSERT" "(" "names->outerBinding()->name() == innerName"
")"); do { *((volatile int*)__null) = 11984; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11985 kind = ClassEmitter::Kind::Declaration;
11986 }
11987 }
11988
11989 if (LexicalScopeNode* scopeBindings = classNode->scopeBindings()) {
11990 if (!ce.emitScope(scopeBindings->scopeBindings())) {
11991 // [stack]
11992 return false;
11993 }
11994 }
11995
11996 bool isDerived = !!heritageExpression;
11997 if (isDerived) {
11998 if (!updateSourceCoordNotes(classNode->pn_pos.begin)) {
11999 return false;
12000 }
12001 if (!markStepBreakpoint()) {
12002 return false;
12003 }
12004 if (!emitTree(heritageExpression)) {
12005 // [stack] HERITAGE
12006 return false;
12007 }
12008 }
12009
12010 // The class body scope holds any private names. Those mustn't be visible in
12011 // the heritage expression and hence the scope must be emitted after the
12012 // heritage expression.
12013 if (ClassBodyScopeNode* bodyScopeBindings = classNode->bodyScopeBindings()) {
12014 if (!ce.emitBodyScope(bodyScopeBindings->scopeBindings())) {
12015 // [stack] HERITAGE
12016 return false;
12017 }
12018
12019 // The spec does not say anything about private brands being symbols. It's
12020 // an implementation detail. So we can give the special private brand
12021 // symbol any description we want and users won't normally see it. For
12022 // debugging, use the class name.
12023 auto privateBrandName = innerName;
12024 if (!innerName) {
12025 privateBrandName = nameForAnonymousClass
12026 ? nameForAnonymousClass
12027 : TaggedParserAtomIndex::WellKnown::anonymous();
12028 }
12029 if (!emitNewPrivateNames(privateBrandName, classMembers)) {
12030 return false;
12031 }
12032 }
12033
12034 bool hasNameOnStack = nameKind == ClassNameKind::ComputedName;
12035 if (isDerived) {
12036 if (!ce.emitDerivedClass(innerName, nameForAnonymousClass,
12037 hasNameOnStack)) {
12038 // [stack] HOMEOBJ HERITAGE
12039 return false;
12040 }
12041 } else {
12042 if (!ce.emitClass(innerName, nameForAnonymousClass, hasNameOnStack)) {
12043 // [stack] HOMEOBJ
12044 return false;
12045 }
12046 }
12047
12048 // Stack currently has HOMEOBJ followed by optional HERITAGE. When HERITAGE
12049 // is not used, an implicit value of %FunctionPrototype% is implied.
12050
12051 // See |Parser::classMember(...)| for the reason why |.initializers| is
12052 // created within its own scope.
12053 Maybe<LexicalScopeEmitter> lse;
12054 FunctionNode* ctor;
12055#ifdef ENABLE_DECORATORS
12056 bool extraInitializersPresent = false;
12057#endif
12058 if (constructor->is<LexicalScopeNode>()) {
12059 LexicalScopeNode* constructorScope = &constructor->as<LexicalScopeNode>();
12060
12061 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()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12061); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!constructorScope->isEmptyScope()"
")"); do { *((volatile int*)__null) = 12061; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12062#ifdef ENABLE_DECORATORS
12063 // With decorators enabled we expect to see |.initializers|,
12064 // and |.instanceExtraInitializers| in this scope.
12065 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12065); AnnotateMozCrashReason("MOZ_ASSERT" "(" "constructorScope->scopeBindings()->length == 2"
")"); do { *((volatile int*)__null) = 12065; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12066 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_()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12068); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()"
")"); do { *((volatile int*)__null) = 12068; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12067 .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_()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12068); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()"
")"); do { *((volatile int*)__null) = 12068; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12068 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_()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12068); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()"
")"); do { *((volatile int*)__null) = 12068; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12069 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_()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12072); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_()"
")"); do { *((volatile int*)__null) = 12072; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12070 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_()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12072); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_()"
")"); do { *((volatile int*)__null) = 12072; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12071 .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_()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12072); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_()"
")"); do { *((volatile int*)__null) = 12072; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12072 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_()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12072); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_()"
")"); do { *((volatile int*)__null) = 12072; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12073
12074 // We should only call this code if we know decorators are present, see bug
12075 // 1871147.
12076 lse.emplace(this);
12077 if (!lse->emitScope(ScopeKind::Lexical,
12078 constructorScope->scopeBindings())) {
12079 return false;
12080 }
12081
12082 // TODO: See bug 1868220 for support for static extra initializers.
12083 if (!ce.prepareForExtraInitializers(TaggedParserAtomIndex::WellKnown::
12084 dot_instanceExtraInitializers_())) {
12085 return false;
12086 }
12087
12088 if (classNode->addInitializerFunction()) {
12089 DecoratorEmitter de(this);
12090 if (!de.emitCreateAddInitializerFunction(
12091 classNode->addInitializerFunction(),
12092 TaggedParserAtomIndex::WellKnown::
12093 dot_instanceExtraInitializers_())) {
12094 // [stack] HOMEOBJ HERITAGE? ADDINIT
12095 return false;
12096 }
12097
12098 if (!emitUnpickN(isDerived ? 2 : 1)) {
12099 // [stack] ADDINIT HOMEOBJ HERITAGE?
12100 return false;
12101 }
12102
12103 extraInitializersPresent = true;
12104 }
12105#else
12106 // The constructor scope should only contain the |.initializers| binding.
12107 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12107); AnnotateMozCrashReason("MOZ_ASSERT" "(" "constructorScope->scopeBindings()->length == 1"
")"); do { *((volatile int*)__null) = 12107; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12108 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_()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12110); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()"
")"); do { *((volatile int*)__null) = 12110; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12109 .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_()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12110); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()"
")"); do { *((volatile int*)__null) = 12110; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12110 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_()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12110); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()"
")"); do { *((volatile int*)__null) = 12110; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12111#endif
12112
12113 auto needsInitializer = [](ParseNode* propdef) {
12114 return NeedsFieldInitializer(propdef, false) ||
12115 NeedsAccessorInitializer(propdef, false);
12116 };
12117
12118 // As an optimization omit the |.initializers| binding when no instance
12119 // fields or private methods are present.
12120 bool needsInitializers =
12121 std::any_of(classMembers->contents().begin(),
12122 classMembers->contents().end(), needsInitializer);
12123 if (needsInitializers) {
12124#ifndef ENABLE_DECORATORS
12125 lse.emplace(this);
12126 if (!lse->emitScope(ScopeKind::Lexical,
12127 constructorScope->scopeBindings())) {
12128 return false;
12129 }
12130#endif
12131 // Any class with field initializers will have a constructor
12132 if (!emitCreateMemberInitializers(ce, classMembers,
12133 FieldPlacement::Instance
12134#ifdef ENABLE_DECORATORS
12135 ,
12136 isDerived
12137#endif
12138 )) {
12139 return false;
12140 }
12141 }
12142
12143 ctor = &constructorScope->scopeBody()->as<ClassMethod>().method();
12144 } else {
12145 // The |.initializers| binding is never emitted when in self-hosting mode.
12146 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12146); AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode == BytecodeEmitter::SelfHosting"
")"); do { *((volatile int*)__null) = 12146; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12147 ctor = &constructor->as<ClassMethod>().method();
12148 }
12149
12150 bool needsHomeObject = ctor->funbox()->needsHomeObject();
12151 // HERITAGE is consumed inside emitFunction.
12152 if (nameKind == ClassNameKind::InferredName) {
12153 setFunName(ctor->funbox(), nameForAnonymousClass);
12154 }
12155 if (!emitFunction(ctor, isDerived)) {
12156 // [stack] HOMEOBJ CTOR
12157 return false;
12158 }
12159 if (lse.isSome()) {
12160 if (!lse->emitEnd()) {
12161 return false;
12162 }
12163 lse.reset();
12164 }
12165 if (!ce.emitInitConstructor(needsHomeObject)) {
12166 // [stack] CTOR HOMEOBJ
12167 return false;
12168 }
12169
12170 if (!emitCreateFieldKeys(classMembers, FieldPlacement::Instance)) {
12171 return false;
12172 }
12173
12174#ifdef ENABLE_DECORATORS
12175 // TODO: See Bug 1868220 for support for static extra initializers.
12176 if (!emit1(JSOp::Undefined)) {
12177 // [stack] ADDINIT? CTOR HOMEOBJ UNDEFINED
12178 return false;
12179 }
12180 if (!emitUnpickN(2)) {
12181 // [stack] ADDINIT? UNDEFINED CTOR HOMEOBJ
12182 }
12183#endif
12184
12185 if (!emitCreateMemberInitializers(ce, classMembers, FieldPlacement::Static
12186#ifdef ENABLE_DECORATORS
12187 ,
12188 false
12189#endif
12190 )) {
12191 return false;
12192 }
12193
12194#ifdef ENABLE_DECORATORS
12195 if (!emitPickN(2)) {
12196 // [stack] ADDINIT? CTOR HOMEOBJ UNDEFINED
12197 return false;
12198 }
12199 if (!emitPopN(1)) {
12200 // [stack] ADDINIT? CTOR HOMEOBJ
12201 return false;
12202 }
12203#endif
12204
12205 if (!emitCreateFieldKeys(classMembers, FieldPlacement::Static)) {
12206 return false;
12207 }
12208
12209 if (!emitPropertyList(classMembers, ce, ClassBody)) {
12210 // [stack] CTOR HOMEOBJ
12211 return false;
12212 }
12213
12214#ifdef ENABLE_DECORATORS
12215 if (extraInitializersPresent) {
12216 if (!emitPickN(2)) {
12217 // [stack] CTOR HOMEOBJ ADDINIT
12218 return false;
12219 }
12220 if (!emitPopN(1)) {
12221 // [stack] CTOR HOMEOBJ
12222 return false;
12223 }
12224 }
12225#endif
12226
12227 if (!ce.emitBinding()) {
12228 // [stack] CTOR
12229 return false;
12230 }
12231
12232 if (!emitInitializeStaticFields(classMembers)) {
12233 // [stack] CTOR
12234 return false;
12235 }
12236
12237#if ENABLE_DECORATORS
12238 if (!ce.prepareForDecorators()) {
12239 // [stack] CTOR
12240 return false;
12241 }
12242 if (classNode->decorators() != nullptr) {
12243 DecoratorEmitter de(this);
12244 NameNode* className =
12245 classNode->names() ? classNode->names()->innerBinding() : nullptr;
12246 if (!de.emitApplyDecoratorsToClassDefinition(className,
12247 classNode->decorators())) {
12248 // [stack] CTOR
12249 return false;
12250 }
12251 }
12252#endif
12253
12254 if (!ce.emitEnd(kind)) {
12255 // [stack] # class declaration
12256 // [stack]
12257 // [stack] # class expression
12258 // [stack] CTOR
12259 return false;
12260 }
12261
12262 return true;
12263}
12264
12265bool BytecodeEmitter::emitExportDefault(BinaryNode* exportNode) {
12266 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)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12266); AnnotateMozCrashReason("MOZ_ASSERT" "(" "exportNode->isKind(ParseNodeKind::ExportDefaultStmt)"
")"); do { *((volatile int*)__null) = 12266; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12267
12268 ParseNode* valueNode = exportNode->left();
12269 if (valueNode->isDirectRHSAnonFunction()) {
12270 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12270); AnnotateMozCrashReason("MOZ_ASSERT" "(" "exportNode->right()"
")"); do { *((volatile int*)__null) = 12270; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12271
12272 if (!emitAnonymousFunctionWithName(
12273 valueNode, TaggedParserAtomIndex::WellKnown::default_())) {
12274 return false;
12275 }
12276 } else {
12277 if (!emitTree(valueNode)) {
12278 return false;
12279 }
12280 }
12281
12282 if (ParseNode* binding = exportNode->right()) {
12283 if (!emitLexicalInitialization(&binding->as<NameNode>())) {
12284 return false;
12285 }
12286
12287 if (!emit1(JSOp::Pop)) {
12288 return false;
12289 }
12290 }
12291
12292 return true;
12293}
12294
12295bool BytecodeEmitter::emitTree(
12296 ParseNode* pn, ValueUsage valueUsage /* = ValueUsage::WantValue */,
12297 EmitLineNumberNote emitLineNote /* = EMIT_LINENOTE */) {
12298 AutoCheckRecursionLimit recursion(fc);
12299 if (!recursion.check(fc)) {
12300 return false;
12301 }
12302
12303 /* Emit notes to tell the current bytecode's source line number.
12304 However, a couple trees require special treatment; see the
12305 relevant emitter functions for details. */
12306 if (emitLineNote == EMIT_LINENOTE &&
12307 !ParseNodeRequiresSpecialLineNumberNotes(pn)) {
12308 if (!updateLineNumberNotes(pn->pn_pos.begin)) {
12309 return false;
12310 }
12311 }
12312
12313 switch (pn->getKind()) {
12314 case ParseNodeKind::Function:
12315 if (!emitFunction(&pn->as<FunctionNode>())) {
12316 return false;
12317 }
12318 break;
12319
12320 case ParseNodeKind::ParamsBody:
12321 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." ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12322); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "ParamsBody should be handled in emitFunctionScript."
")"); do { *((volatile int*)__null) = 12322; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12322 "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." ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12322); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "ParamsBody should be handled in emitFunctionScript."
")"); do { *((volatile int*)__null) = 12322; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12323 break;
12324
12325 case ParseNodeKind::IfStmt:
12326 if (!emitIf(&pn->as<TernaryNode>())) {
12327 return false;
12328 }
12329 break;
12330
12331 case ParseNodeKind::SwitchStmt:
12332 if (!emitSwitch(&pn->as<SwitchStatement>())) {
12333 return false;
12334 }
12335 break;
12336
12337 case ParseNodeKind::WhileStmt:
12338 if (!emitWhile(&pn->as<BinaryNode>())) {
12339 return false;
12340 }
12341 break;
12342
12343 case ParseNodeKind::DoWhileStmt:
12344 if (!emitDo(&pn->as<BinaryNode>())) {
12345 return false;
12346 }
12347 break;
12348
12349 case ParseNodeKind::ForStmt:
12350 if (!emitFor(&pn->as<ForNode>())) {
12351 return false;
12352 }
12353 break;
12354
12355 case ParseNodeKind::BreakStmt:
12356 // Ensure that the column of the 'break' is set properly.
12357 if (!updateSourceCoordNotes(pn->pn_pos.begin)) {
12358 return false;
12359 }
12360 if (!markStepBreakpoint()) {
12361 return false;
12362 }
12363
12364 if (!emitBreak(pn->as<BreakStatement>().label())) {
12365 return false;
12366 }
12367 break;
12368
12369 case ParseNodeKind::ContinueStmt:
12370 // Ensure that the column of the 'continue' is set properly.
12371 if (!updateSourceCoordNotes(pn->pn_pos.begin)) {
12372 return false;
12373 }
12374 if (!markStepBreakpoint()) {
12375 return false;
12376 }
12377
12378 if (!emitContinue(pn->as<ContinueStatement>().label())) {
12379 return false;
12380 }
12381 break;
12382
12383 case ParseNodeKind::WithStmt:
12384 if (!emitWith(&pn->as<BinaryNode>())) {
12385 return false;
12386 }
12387 break;
12388
12389 case ParseNodeKind::TryStmt:
12390 if (!emitTry(&pn->as<TryNode>())) {
12391 return false;
12392 }
12393 break;
12394
12395 case ParseNodeKind::Catch:
12396 if (!emitCatch(&pn->as<BinaryNode>())) {
12397 return false;
12398 }
12399 break;
12400
12401 case ParseNodeKind::VarStmt:
12402 if (!emitDeclarationList(&pn->as<ListNode>())) {
12403 return false;
12404 }
12405 break;
12406
12407 case ParseNodeKind::ReturnStmt:
12408 if (!emitReturn(&pn->as<UnaryNode>())) {
12409 return false;
12410 }
12411 break;
12412
12413 case ParseNodeKind::YieldStarExpr:
12414 if (!emitYieldStar(pn->as<UnaryNode>().kid())) {
12415 return false;
12416 }
12417 break;
12418
12419 case ParseNodeKind::Generator:
12420 if (!emit1(JSOp::Generator)) {
12421 return false;
12422 }
12423 break;
12424
12425 case ParseNodeKind::InitialYield:
12426 if (!emitInitialYield(&pn->as<UnaryNode>())) {
12427 return false;
12428 }
12429 break;
12430
12431 case ParseNodeKind::YieldExpr:
12432 if (!emitYield(&pn->as<UnaryNode>())) {
12433 return false;
12434 }
12435 break;
12436
12437 case ParseNodeKind::AwaitExpr:
12438 if (!emitAwaitInInnermostScope(&pn->as<UnaryNode>())) {
12439 return false;
12440 }
12441 break;
12442
12443 case ParseNodeKind::StatementList:
12444 if (!emitStatementList(&pn->as<ListNode>())) {
12445 return false;
12446 }
12447 break;
12448
12449 case ParseNodeKind::EmptyStmt:
12450 break;
12451
12452 case ParseNodeKind::ExpressionStmt:
12453 if (!emitExpressionStatement(&pn->as<UnaryNode>())) {
12454 return false;
12455 }
12456 break;
12457
12458 case ParseNodeKind::LabelStmt:
12459 if (!emitLabeledStatement(&pn->as<LabeledStatement>())) {
12460 return false;
12461 }
12462 break;
12463
12464 case ParseNodeKind::CommaExpr:
12465 if (!emitSequenceExpr(&pn->as<ListNode>(), valueUsage)) {
12466 return false;
12467 }
12468 break;
12469
12470 case ParseNodeKind::InitExpr:
12471 case ParseNodeKind::AssignExpr:
12472 case ParseNodeKind::AddAssignExpr:
12473 case ParseNodeKind::SubAssignExpr:
12474 case ParseNodeKind::BitOrAssignExpr:
12475 case ParseNodeKind::BitXorAssignExpr:
12476 case ParseNodeKind::BitAndAssignExpr:
12477 case ParseNodeKind::LshAssignExpr:
12478 case ParseNodeKind::RshAssignExpr:
12479 case ParseNodeKind::UrshAssignExpr:
12480 case ParseNodeKind::MulAssignExpr:
12481 case ParseNodeKind::DivAssignExpr:
12482 case ParseNodeKind::ModAssignExpr:
12483 case ParseNodeKind::PowAssignExpr: {
12484 BinaryNode* assignNode = &pn->as<BinaryNode>();
12485 if (!emitAssignmentOrInit(assignNode->getKind(), assignNode->left(),
12486 assignNode->right())) {
12487 return false;
12488 }
12489 break;
12490 }
12491
12492 case ParseNodeKind::CoalesceAssignExpr:
12493 case ParseNodeKind::OrAssignExpr:
12494 case ParseNodeKind::AndAssignExpr:
12495 if (!emitShortCircuitAssignment(&pn->as<AssignmentNode>())) {
12496 return false;
12497 }
12498 break;
12499
12500 case ParseNodeKind::ConditionalExpr:
12501 if (!emitConditionalExpression(pn->as<ConditionalExpression>(),
12502 valueUsage)) {
12503 return false;
12504 }
12505 break;
12506
12507 case ParseNodeKind::OrExpr:
12508 case ParseNodeKind::CoalesceExpr:
12509 case ParseNodeKind::AndExpr:
12510 if (!emitShortCircuit(&pn->as<ListNode>(), valueUsage)) {
12511 return false;
12512 }
12513 break;
12514
12515 case ParseNodeKind::StrictEqExpr:
12516 case ParseNodeKind::EqExpr:
12517 case ParseNodeKind::StrictNeExpr:
12518 case ParseNodeKind::NeExpr: {
12519 bool emitted;
12520 if (!tryEmitTypeofEq(&pn->as<ListNode>(), &emitted)) {
12521 return false;
12522 }
12523 if (emitted) {
12524 return true;
12525 }
12526 }
12527 [[fallthrough]];
12528
12529 case ParseNodeKind::AddExpr:
12530 case ParseNodeKind::SubExpr:
12531 case ParseNodeKind::BitOrExpr:
12532 case ParseNodeKind::BitXorExpr:
12533 case ParseNodeKind::BitAndExpr:
12534 case ParseNodeKind::LtExpr:
12535 case ParseNodeKind::LeExpr:
12536 case ParseNodeKind::GtExpr:
12537 case ParseNodeKind::GeExpr:
12538 case ParseNodeKind::InExpr:
12539 case ParseNodeKind::InstanceOfExpr:
12540 case ParseNodeKind::LshExpr:
12541 case ParseNodeKind::RshExpr:
12542 case ParseNodeKind::UrshExpr:
12543 case ParseNodeKind::MulExpr:
12544 case ParseNodeKind::DivExpr:
12545 case ParseNodeKind::ModExpr:
12546 if (!emitLeftAssociative(&pn->as<ListNode>())) {
12547 return false;
12548 }
12549 break;
12550
12551 case ParseNodeKind::PrivateInExpr:
12552 if (!emitPrivateInExpr(&pn->as<ListNode>())) {
12553 return false;
12554 }
12555 break;
12556
12557 case ParseNodeKind::PowExpr:
12558 if (!emitRightAssociative(&pn->as<ListNode>())) {
12559 return false;
12560 }
12561 break;
12562
12563 case ParseNodeKind::TypeOfNameExpr:
12564 if (!emitTypeof(&pn->as<UnaryNode>(), JSOp::Typeof)) {
12565 return false;
12566 }
12567 break;
12568
12569 case ParseNodeKind::TypeOfExpr:
12570 if (!emitTypeof(&pn->as<UnaryNode>(), JSOp::TypeofExpr)) {
12571 return false;
12572 }
12573 break;
12574
12575 case ParseNodeKind::ThrowStmt:
12576 if (!updateSourceCoordNotes(pn->pn_pos.begin)) {
12577 return false;
12578 }
12579 if (!markStepBreakpoint()) {
12580 return false;
12581 }
12582 [[fallthrough]];
12583 case ParseNodeKind::VoidExpr:
12584 case ParseNodeKind::NotExpr:
12585 case ParseNodeKind::BitNotExpr:
12586 case ParseNodeKind::PosExpr:
12587 case ParseNodeKind::NegExpr:
12588 if (!emitUnary(&pn->as<UnaryNode>())) {
12589 return false;
12590 }
12591 break;
12592
12593 case ParseNodeKind::PreIncrementExpr:
12594 case ParseNodeKind::PreDecrementExpr:
12595 case ParseNodeKind::PostIncrementExpr:
12596 case ParseNodeKind::PostDecrementExpr:
12597 if (!emitIncOrDec(&pn->as<UnaryNode>(), valueUsage)) {
12598 return false;
12599 }
12600 break;
12601
12602 case ParseNodeKind::DeleteNameExpr:
12603 if (!emitDeleteName(&pn->as<UnaryNode>())) {
12604 return false;
12605 }
12606 break;
12607
12608 case ParseNodeKind::DeletePropExpr:
12609 if (!emitDeleteProperty(&pn->as<UnaryNode>())) {
12610 return false;
12611 }
12612 break;
12613
12614 case ParseNodeKind::DeleteElemExpr:
12615 if (!emitDeleteElement(&pn->as<UnaryNode>())) {
12616 return false;
12617 }
12618 break;
12619
12620 case ParseNodeKind::DeleteExpr:
12621 if (!emitDeleteExpression(&pn->as<UnaryNode>())) {
12622 return false;
12623 }
12624 break;
12625
12626 case ParseNodeKind::DeleteOptionalChainExpr:
12627 if (!emitDeleteOptionalChain(&pn->as<UnaryNode>())) {
12628 return false;
12629 }
12630 break;
12631
12632 case ParseNodeKind::OptionalChain:
12633 if (!emitOptionalChain(&pn->as<UnaryNode>(), valueUsage)) {
12634 return false;
12635 }
12636 break;
12637
12638 case ParseNodeKind::DotExpr: {
12639 PropertyAccess* prop = &pn->as<PropertyAccess>();
12640 bool isSuper = prop->isSuper();
12641 PropOpEmitter poe(this, PropOpEmitter::Kind::Get,
12642 isSuper ? PropOpEmitter::ObjKind::Super
12643 : PropOpEmitter::ObjKind::Other);
12644 if (!poe.prepareForObj()) {
12645 return false;
12646 }
12647 if (isSuper) {
12648 UnaryNode* base = &prop->expression().as<UnaryNode>();
12649 if (!emitGetThisForSuperBase(base)) {
12650 // [stack] THIS
12651 return false;
12652 }
12653 } else {
12654 if (!emitPropLHS(prop)) {
12655 // [stack] OBJ
12656 return false;
12657 }
12658 }
12659 if (!poe.emitGet(prop->key().atom())) {
12660 // [stack] PROP
12661 return false;
12662 }
12663 break;
12664 }
12665
12666 case ParseNodeKind::ArgumentsLength: {
12667 if (sc->isFunctionBox() &&
12668 sc->asFunctionBox()->isEligibleForArgumentsLength() &&
12669 !sc->asFunctionBox()->needsArgsObj()) {
12670 if (!emit1(JSOp::ArgumentsLength)) {
12671 return false;
12672 }
12673 } else {
12674 PropOpEmitter poe(this, PropOpEmitter::Kind::Get,
12675 PropOpEmitter::ObjKind::Other);
12676 if (!poe.prepareForObj()) {
12677 return false;
12678 }
12679
12680 NameOpEmitter noe(this, TaggedParserAtomIndex::WellKnown::arguments(),
12681 NameOpEmitter::Kind::Get);
12682 if (!noe.emitGet()) {
12683 return false;
12684 }
12685 if (!poe.emitGet(TaggedParserAtomIndex::WellKnown::length())) {
12686 return false;
12687 }
12688 }
12689 break;
12690 }
12691
12692 case ParseNodeKind::ElemExpr: {
12693 PropertyByValue* elem = &pn->as<PropertyByValue>();
12694 bool isSuper = elem->isSuper();
12695 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)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12695); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 12695; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12696 ElemOpEmitter eoe(this, ElemOpEmitter::Kind::Get,
12697 isSuper ? ElemOpEmitter::ObjKind::Super
12698 : ElemOpEmitter::ObjKind::Other);
12699 if (!emitElemObjAndKey(elem, eoe)) {
12700 // [stack] # if Super
12701 // [stack] THIS KEY
12702 // [stack] # otherwise
12703 // [stack] OBJ KEY
12704 return false;
12705 }
12706 if (!eoe.emitGet()) {
12707 // [stack] ELEM
12708 return false;
12709 }
12710
12711 break;
12712 }
12713
12714 case ParseNodeKind::PrivateMemberExpr: {
12715 PrivateMemberAccess* privateExpr = &pn->as<PrivateMemberAccess>();
12716 PrivateOpEmitter xoe(this, PrivateOpEmitter::Kind::Get,
12717 privateExpr->privateName().name());
12718 if (!emitTree(&privateExpr->expression())) {
12719 // [stack] OBJ
12720 return false;
12721 }
12722 if (!xoe.emitReference()) {
12723 // [stack] OBJ NAME
12724 return false;
12725 }
12726 if (!xoe.emitGet()) {
12727 // [stack] VALUE
12728 return false;
12729 }
12730
12731 break;
12732 }
12733
12734 case ParseNodeKind::NewExpr:
12735 case ParseNodeKind::TaggedTemplateExpr:
12736 case ParseNodeKind::CallExpr:
12737 case ParseNodeKind::SuperCallExpr:
12738 if (!emitCallOrNew(&pn->as<CallNode>(), valueUsage)) {
12739 return false;
12740 }
12741 break;
12742
12743 case ParseNodeKind::LexicalScope:
12744 if (!emitLexicalScope(&pn->as<LexicalScopeNode>())) {
12745 return false;
12746 }
12747 break;
12748
12749 case ParseNodeKind::ConstDecl:
12750 case ParseNodeKind::LetDecl:
12751 if (!emitDeclarationList(&pn->as<ListNode>())) {
12752 return false;
12753 }
12754 break;
12755#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
12756 case ParseNodeKind::AwaitUsingDecl:
12757 case ParseNodeKind::UsingDecl:
12758 if (!emitDeclarationList(&pn->as<ListNode>())) {
12759 return false;
12760 }
12761 break;
12762#endif
12763
12764 case ParseNodeKind::ImportDecl:
12765 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12765); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isModuleContext()"
")"); do { *((volatile int*)__null) = 12765; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12766 break;
12767
12768 case ParseNodeKind::ExportStmt: {
12769 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12769); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isModuleContext()"
")"); do { *((volatile int*)__null) = 12769; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12770 UnaryNode* node = &pn->as<UnaryNode>();
12771 ParseNode* decl = node->kid();
12772 if (decl->getKind() != ParseNodeKind::ExportSpecList) {
12773 if (!emitTree(decl)) {
12774 return false;
12775 }
12776 }
12777 break;
12778 }
12779
12780 case ParseNodeKind::ExportDefaultStmt:
12781 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12781); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isModuleContext()"
")"); do { *((volatile int*)__null) = 12781; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12782 if (!emitExportDefault(&pn->as<BinaryNode>())) {
12783 return false;
12784 }
12785 break;
12786
12787 case ParseNodeKind::ExportFromStmt:
12788 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12788); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isModuleContext()"
")"); do { *((volatile int*)__null) = 12788; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12789 break;
12790
12791 case ParseNodeKind::CallSiteObj:
12792 if (!emitCallSiteObject(&pn->as<CallSiteNode>())) {
12793 return false;
12794 }
12795 break;
12796
12797 case ParseNodeKind::ArrayExpr:
12798 if (!emitArrayLiteral(&pn->as<ListNode>())) {
12799 return false;
12800 }
12801 break;
12802
12803 case ParseNodeKind::ObjectExpr:
12804 if (!emitObject(&pn->as<ListNode>())) {
12805 return false;
12806 }
12807 break;
12808
12809 case ParseNodeKind::Name:
12810 if (!emitGetName(&pn->as<NameNode>())) {
12811 return false;
12812 }
12813 break;
12814
12815 case ParseNodeKind::PrivateName:
12816 if (!emitGetPrivateName(&pn->as<NameNode>())) {
12817 return false;
12818 }
12819 break;
12820
12821 case ParseNodeKind::TemplateStringListExpr:
12822 if (!emitTemplateString(&pn->as<ListNode>())) {
12823 return false;
12824 }
12825 break;
12826
12827 case ParseNodeKind::TemplateStringExpr:
12828 case ParseNodeKind::StringExpr:
12829 if (!emitStringOp(JSOp::String, pn->as<NameNode>().atom())) {
12830 return false;
12831 }
12832 break;
12833
12834 case ParseNodeKind::NumberExpr:
12835 if (!emitNumberOp(pn->as<NumericLiteral>().value())) {
12836 return false;
12837 }
12838 break;
12839
12840 case ParseNodeKind::BigIntExpr:
12841 if (!emitBigIntOp(&pn->as<BigIntLiteral>())) {
12842 return false;
12843 }
12844 break;
12845
12846 case ParseNodeKind::RegExpExpr: {
12847 GCThingIndex index;
12848 if (!perScriptData().gcThingList().append(&pn->as<RegExpLiteral>(),
12849 &index)) {
12850 return false;
12851 }
12852 if (!emitRegExp(index)) {
12853 return false;
12854 }
12855 break;
12856 }
12857
12858 case ParseNodeKind::TrueExpr:
12859 if (!emit1(JSOp::True)) {
12860 return false;
12861 }
12862 break;
12863 case ParseNodeKind::FalseExpr:
12864 if (!emit1(JSOp::False)) {
12865 return false;
12866 }
12867 break;
12868 case ParseNodeKind::NullExpr:
12869 if (!emit1(JSOp::Null)) {
12870 return false;
12871 }
12872 break;
12873 case ParseNodeKind::RawUndefinedExpr:
12874 if (!emit1(JSOp::Undefined)) {
12875 return false;
12876 }
12877 break;
12878
12879 case ParseNodeKind::ThisExpr:
12880 if (!emitThisLiteral(&pn->as<ThisLiteral>())) {
12881 return false;
12882 }
12883 break;
12884
12885 case ParseNodeKind::DebuggerStmt:
12886 if (!updateSourceCoordNotes(pn->pn_pos.begin)) {
12887 return false;
12888 }
12889 if (!markStepBreakpoint()) {
12890 return false;
12891 }
12892 if (!emit1(JSOp::Debugger)) {
12893 return false;
12894 }
12895 break;
12896
12897 case ParseNodeKind::ClassDecl:
12898 if (!emitClass(&pn->as<ClassNode>())) {
12899 return false;
12900 }
12901 break;
12902
12903 case ParseNodeKind::NewTargetExpr:
12904 if (!emitNewTarget(&pn->as<NewTargetNode>())) {
12905 return false;
12906 }
12907 break;
12908
12909 case ParseNodeKind::ImportMetaExpr:
12910 if (!emit1(JSOp::ImportMeta)) {
12911 return false;
12912 }
12913 break;
12914
12915 case ParseNodeKind::CallImportExpr: {
12916 BinaryNode* spec = &pn->as<BinaryNode>().right()->as<BinaryNode>();
12917
12918 if (!emitTree(spec->left())) {
12919 // [stack] specifier
12920 return false;
12921 }
12922
12923 if (!spec->right()->isKind(ParseNodeKind::PosHolder)) {
12924 // [stack] specifier options
12925 if (!emitTree(spec->right())) {
12926 return false;
12927 }
12928 } else {
12929 // [stack] specifier undefined
12930 if (!emit1(JSOp::Undefined)) {
12931 return false;
12932 }
12933 }
12934
12935 if (!emit1(JSOp::DynamicImport)) {
12936 return false;
12937 }
12938
12939 break;
12940 }
12941
12942 case ParseNodeKind::SetThis:
12943 if (!emitSetThis(&pn->as<BinaryNode>())) {
12944 return false;
12945 }
12946 break;
12947
12948#ifdef ENABLE_RECORD_TUPLE
12949 case ParseNodeKind::RecordExpr:
12950 if (!emitRecordLiteral(&pn->as<ListNode>())) {
12951 return false;
12952 }
12953 break;
12954
12955 case ParseNodeKind::TupleExpr:
12956 if (!emitTupleLiteral(&pn->as<ListNode>())) {
12957 return false;
12958 }
12959 break;
12960#endif
12961
12962 case ParseNodeKind::PropertyNameExpr:
12963 case ParseNodeKind::PosHolder:
12964 MOZ_FALLTHROUGH_ASSERT(do { do { } while (false); MOZ_ReportCrash("" "MOZ_FALLTHROUGH_ASSERT: "
"Should never try to emit ParseNodeKind::PosHolder or ::Property"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12965); AnnotateMozCrashReason("MOZ_CRASH(" "MOZ_FALLTHROUGH_ASSERT: "
"Should never try to emit ParseNodeKind::PosHolder or ::Property"
")"); do { *((volatile int*)__null) = 12965; __attribute__((
nomerge)) ::abort(); } while (false); } while (false)
12965 "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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12965); AnnotateMozCrashReason("MOZ_CRASH(" "MOZ_FALLTHROUGH_ASSERT: "
"Should never try to emit ParseNodeKind::PosHolder or ::Property"
")"); do { *((volatile int*)__null) = 12965; __attribute__((
nomerge)) ::abort(); } while (false); } while (false)
;
12966
12967 default:
12968 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", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12968); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0" ")"); do
{ *((volatile int*)__null) = 12968; __attribute__((nomerge))
::abort(); } while (false); } } while (false)
;
12969 }
12970
12971 return true;
12972}
12973
12974static bool AllocSrcNote(FrontendContext* fc, SrcNotesVector& notes,
12975 unsigned size, unsigned* index) {
12976 size_t oldLength = notes.length();
12977
12978 if (MOZ_UNLIKELY(oldLength + size > MaxSrcNotesLength)(__builtin_expect(!!(oldLength + size > MaxSrcNotesLength)
, 0))
) {
12979 ReportAllocationOverflow(fc);
12980 return false;
12981 }
12982
12983 if (!notes.growByUninitialized(size)) {
12984 return false;
12985 }
12986
12987 *index = oldLength;
12988 return true;
12989}
12990
12991bool BytecodeEmitter::addTryNote(TryNoteKind kind, uint32_t stackDepth,
12992 BytecodeOffset start, BytecodeOffset end) {
12993 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()",
"/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12993); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inPrologue()"
")"); do { *((volatile int*)__null) = 12993; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12994 return bytecodeSection().tryNoteList().append(kind, stackDepth, start, end);
12995}
12996
12997bool BytecodeEmitter::newSrcNote(SrcNoteType type, unsigned* indexp) {
12998 SrcNotesVector& notes = bytecodeSection().notes();
12999 unsigned index;
13000
13001 /*
13002 * Compute delta from the last annotated bytecode's offset. If it's too
13003 * big to fit in sn, allocate one or more xdelta notes and reset sn.
13004 */
13005 BytecodeOffset offset = bytecodeSection().offset();
13006 ptrdiff_t delta = (offset - bytecodeSection().lastNoteOffset()).value();
13007 bytecodeSection().setLastNoteOffset(offset);
13008
13009 auto allocator = [&](unsigned size) -> SrcNote* {
13010 if (!AllocSrcNote(fc, notes, size, &index)) {
13011 return nullptr;
13012 }
13013 return &notes[index];
13014 };
13015
13016 if (!SrcNoteWriter::writeNote(type, delta, allocator)) {
13017 return false;
13018 }
13019
13020 if (indexp) {
13021 *indexp = index;
13022 }
13023
13024 if (type == SrcNoteType::NewLine || type == SrcNoteType::SetLine) {
13025 lastLineOnlySrcNoteIndex = index;
13026 } else {
13027 lastLineOnlySrcNoteIndex = LastSrcNoteIsNotLineOnly;
13028 }
13029
13030 return true;
13031}
13032
13033bool BytecodeEmitter::newSrcNote2(SrcNoteType type, ptrdiff_t offset,
13034 unsigned* indexp) {
13035 unsigned index;
13036 if (!newSrcNote(type, &index)) {
13037 return false;
13038 }
13039 if (!newSrcNoteOperand(offset)) {
13040 return false;
13041 }
13042 if (indexp) {
13043 *indexp = index;
13044 }
13045 return true;
13046}
13047
13048bool BytecodeEmitter::convertLastNewLineToNewLineColumn(
13049 JS::LimitedColumnNumberOneOrigin column) {
13050 SrcNotesVector& notes = bytecodeSection().notes();
13051 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 13051); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lastLineOnlySrcNoteIndex == notes.length() - 1"
")"); do { *((volatile int*)__null) = 13051; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13052 SrcNote* sn = &notes[lastLineOnlySrcNoteIndex];
13053 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 13053); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sn->type() == SrcNoteType::NewLine"
")"); do { *((volatile int*)__null) = 13053; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13054
13055 SrcNoteWriter::convertNote(sn, SrcNoteType::NewLineColumn);
13056 if (!newSrcNoteOperand(SrcNote::NewLineColumn::toOperand(column))) {
13057 return false;
13058 }
13059
13060 lastLineOnlySrcNoteIndex = LastSrcNoteIsNotLineOnly;
13061 return true;
13062}
13063
13064bool BytecodeEmitter::convertLastSetLineToSetLineColumn(
13065 JS::LimitedColumnNumberOneOrigin column) {
13066 SrcNotesVector& notes = bytecodeSection().notes();
13067 // The Line operand is either 1 byte or 4 bytes.
13068 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 13069); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lastLineOnlySrcNoteIndex == notes.length() - 1 - 1 || lastLineOnlySrcNoteIndex == notes.length() - 1 - 4"
")"); do { *((volatile int*)__null) = 13069; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
13069 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 13069); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lastLineOnlySrcNoteIndex == notes.length() - 1 - 1 || lastLineOnlySrcNoteIndex == notes.length() - 1 - 4"
")"); do { *((volatile int*)__null) = 13069; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13070 SrcNote* sn = &notes[lastLineOnlySrcNoteIndex];
13071 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 13071); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sn->type() == SrcNoteType::SetLine"
")"); do { *((volatile int*)__null) = 13071; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13072
13073 SrcNoteWriter::convertNote(sn, SrcNoteType::SetLineColumn);
13074 if (!newSrcNoteOperand(SrcNote::SetLineColumn::columnToOperand(column))) {
13075 return false;
13076 }
13077
13078 lastLineOnlySrcNoteIndex = LastSrcNoteIsNotLineOnly;
13079 return true;
13080}
13081
13082bool BytecodeEmitter::newSrcNoteOperand(ptrdiff_t operand) {
13083 if (!SrcNote::isRepresentableOperand(operand)) {
13084 reportError(nullptr, JSMSG_NEED_DIET, "script");
13085 return false;
13086 }
13087
13088 SrcNotesVector& notes = bytecodeSection().notes();
13089
13090 auto allocator = [&](unsigned size) -> SrcNote* {
13091 unsigned index;
13092 if (!AllocSrcNote(fc, notes, size, &index)) {
13093 return nullptr;
13094 }
13095 return &notes[index];
13096 };
13097
13098 return SrcNoteWriter::writeOperand(operand, allocator);
13099}
13100
13101bool BytecodeEmitter::intoScriptStencil(ScriptIndex scriptIndex) {
13102 js::UniquePtr<ImmutableScriptData> immutableScriptData =
13103 createImmutableScriptData();
13104 if (!immutableScriptData) {
13105 return false;
13106 }
13107
13108 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 13109); AnnotateMozCrashReason("MOZ_ASSERT" "(" "outermostScope().hasNonSyntacticScopeOnChain() == sc->hasNonSyntacticScope()"
")"); do { *((volatile int*)__null) = 13109; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
13109 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 13109); AnnotateMozCrashReason("MOZ_ASSERT" "(" "outermostScope().hasNonSyntacticScopeOnChain() == sc->hasNonSyntacticScope()"
")"); do { *((volatile int*)__null) = 13109; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13110
13111 auto& things = perScriptData().gcThingList().objects();
13112 if (!compilationState.appendGCThings(fc, scriptIndex, things)) {
13113 return false;
13114 }
13115
13116 // Hand over the ImmutableScriptData instance generated by BCE.
13117 auto* sharedData =
13118 SharedImmutableScriptData::createWith(fc, std::move(immutableScriptData));
13119 if (!sharedData) {
13120 return false;
13121 }
13122
13123 // De-duplicate the bytecode within the runtime.
13124 if (!compilationState.sharedData.addAndShare(fc, scriptIndex, sharedData)) {
13125 return false;
13126 }
13127
13128 ScriptStencil& script = compilationState.scriptData[scriptIndex];
13129 script.setHasSharedData();
13130
13131 // Update flags specific to functions.
13132 if (sc->isFunctionBox()) {
13133 FunctionBox* funbox = sc->asFunctionBox();
13134 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 13134); AnnotateMozCrashReason("MOZ_ASSERT" "(" "&script == &funbox->functionStencil()"
")"); do { *((volatile int*)__null) = 13134; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13135 funbox->copyUpdatedImmutableFlags();
13136 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 13136); AnnotateMozCrashReason("MOZ_ASSERT" "(" "script.isFunction()"
")"); do { *((volatile int*)__null) = 13136; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13137 } else {
13138 ScriptStencilExtra& scriptExtra = compilationState.scriptExtra[scriptIndex];
13139 sc->copyScriptExtraFields(scriptExtra);
13140 }
13141
13142 return true;
13143}
13144
13145SelfHostedIter BytecodeEmitter::getSelfHostedIterFor(
13146 ParseNode* parseNode) const {
13147 if (emitterMode == BytecodeEmitter::SelfHosting &&
13148 parseNode->isKind(ParseNodeKind::CallExpr)) {
13149 auto* callee = parseNode->as<CallNode>().callee();
13150 if (callee->isName(TaggedParserAtomIndex::WellKnown::allowContentIter())) {
13151 return SelfHostedIter::AllowContent;
13152 }
13153 if (callee->isName(
13154 TaggedParserAtomIndex::WellKnown::allowContentIterWith())) {
13155 return SelfHostedIter::AllowContentWith;
13156 }
13157 if (callee->isName(
13158 TaggedParserAtomIndex::WellKnown::allowContentIterWithNext())) {
13159 return SelfHostedIter::AllowContentWithNext;
13160 }
13161 }
13162
13163 return SelfHostedIter::Deny;
13164}
13165
13166#if defined(DEBUG1) || defined(JS_JITSPEW1)
13167void BytecodeEmitter::dumpAtom(TaggedParserAtomIndex index) const {
13168 parserAtoms().dump(index);
13169}
13170#endif