Bug Summary

File:var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp
Warning:line 822, 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-18/lib/clang/18 -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/js/src/js-confdefs.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 -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/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13 -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/x86_64-linux-gnu/c++/13 -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/backward -internal-isystem /usr/lib/llvm-18/lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../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 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -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-05-16-034744-15991-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/PodOperations.h" // mozilla::PodCopy
19#include "mozilla/Saturate.h"
20#include "mozilla/Variant.h" // mozilla::AsVariant
21
22#include <algorithm>
23#include <iterator>
24#include <string.h>
25
26#include "jstypes.h" // JS_BIT
27
28#include "frontend/AbstractScopePtr.h" // ScopeIndex
29#include "frontend/BytecodeControlStructures.h" // NestableControl, BreakableControl, LabelControl, LoopControl, TryFinallyControl
30#include "frontend/CallOrNewEmitter.h" // CallOrNewEmitter
31#include "frontend/CForEmitter.h" // CForEmitter
32#include "frontend/DecoratorEmitter.h" // DecoratorEmitter
33#include "frontend/DefaultEmitter.h" // DefaultEmitter
34#include "frontend/DoWhileEmitter.h" // DoWhileEmitter
35#include "frontend/ElemOpEmitter.h" // ElemOpEmitter
36#include "frontend/EmitterScope.h" // EmitterScope
37#include "frontend/ExpressionStatementEmitter.h" // ExpressionStatementEmitter
38#include "frontend/ForInEmitter.h" // ForInEmitter
39#include "frontend/ForOfEmitter.h" // ForOfEmitter
40#include "frontend/FunctionEmitter.h" // FunctionEmitter, FunctionScriptEmitter, FunctionParamsEmitter
41#include "frontend/IfEmitter.h" // IfEmitter, InternalIfEmitter, CondEmitter
42#include "frontend/LabelEmitter.h" // LabelEmitter
43#include "frontend/LexicalScopeEmitter.h" // LexicalScopeEmitter
44#include "frontend/ModuleSharedContext.h" // ModuleSharedContext
45#include "frontend/NameAnalysisTypes.h" // PrivateNameKind
46#include "frontend/NameFunctions.h" // NameFunctions
47#include "frontend/NameOpEmitter.h" // NameOpEmitter
48#include "frontend/ObjectEmitter.h" // PropertyEmitter, ObjectEmitter, ClassEmitter
49#include "frontend/OptionalEmitter.h" // OptionalEmitter
50#include "frontend/ParseContext.h" // ParseContext::Scope
51#include "frontend/ParseNode.h" // ParseNodeKind, ParseNode and subclasses
52#include "frontend/Parser.h" // Parser
53#include "frontend/ParserAtom.h" // ParserAtomsTable, ParserAtom
54#include "frontend/PrivateOpEmitter.h" // PrivateOpEmitter
55#include "frontend/PropOpEmitter.h" // PropOpEmitter
56#include "frontend/SourceNotes.h" // SrcNote, SrcNoteType, SrcNoteWriter
57#include "frontend/SwitchEmitter.h" // SwitchEmitter
58#include "frontend/TaggedParserAtomIndexHasher.h" // TaggedParserAtomIndexHasher
59#include "frontend/TDZCheckCache.h" // TDZCheckCache
60#include "frontend/TryEmitter.h" // TryEmitter
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/StringBuffer.h" // StringBuffer
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::PodCopy;
88using mozilla::Some;
89
90static bool ParseNodeRequiresSpecialLineNumberNotes(ParseNode* pn) {
91 // The few node types listed below are exceptions to the usual
92 // location-source-note-emitting code in BytecodeEmitter::emitTree().
93 // Single-line `while` loops and C-style `for` loops require careful
94 // handling to avoid strange stepping behavior.
95 // Functions usually shouldn't have location information (bug 1431202).
96
97 ParseNodeKind kind = pn->getKind();
98 return kind == ParseNodeKind::WhileStmt || kind == ParseNodeKind::ForStmt ||
99 kind == ParseNodeKind::Function;
100}
101
102static bool NeedsFieldInitializer(ParseNode* member, bool inStaticContext) {
103 // For the purposes of bytecode emission, StaticClassBlocks are treated as if
104 // they were static initializers.
105 return (member->is<StaticClassBlock>() && inStaticContext) ||
106 (member->is<ClassField>() &&
107 member->as<ClassField>().isStatic() == inStaticContext);
108}
109
110static bool NeedsAccessorInitializer(ParseNode* member, bool isStatic) {
111 if (isStatic) {
112 return false;
113 }
114 return member->is<ClassMethod>() &&
115 member->as<ClassMethod>().name().isKind(ParseNodeKind::PrivateName) &&
116 !member->as<ClassMethod>().isStatic() &&
117 member->as<ClassMethod>().accessorType() != AccessorType::None;
118}
119
120static bool ShouldSuppressBreakpointsAndSourceNotes(
121 SharedContext* sc, BytecodeEmitter::EmitterMode emitterMode) {
122 // Suppress for all self-hosting code.
123 if (emitterMode == BytecodeEmitter::EmitterMode::SelfHosting) {
124 return true;
125 }
126
127 // Suppress for synthesized class constructors.
128 if (sc->isFunctionBox()) {
129 FunctionBox* funbox = sc->asFunctionBox();
130 return funbox->isSyntheticFunction() && funbox->isClassConstructor();
131 }
132
133 return false;
134}
135
136BytecodeEmitter::BytecodeEmitter(BytecodeEmitter* parent, FrontendContext* fc,
137 SharedContext* sc,
138 const ErrorReporter& errorReporter,
139 CompilationState& compilationState,
140 EmitterMode emitterMode)
141 : sc(sc),
142 fc(fc),
143 parent(parent),
144 bytecodeSection_(fc, sc->extent().lineno,
145 JS::LimitedColumnNumberOneOrigin(sc->extent().column)),
146 perScriptData_(fc, compilationState),
147 errorReporter_(errorReporter),
148 compilationState(compilationState),
149 suppressBreakpointsAndSourceNotes(
150 ShouldSuppressBreakpointsAndSourceNotes(sc, emitterMode)),
151 emitterMode(emitterMode) {
152 MOZ_ASSERT_IF(parent, fc == parent->fc)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"
, 152); AnnotateMozCrashReason("MOZ_ASSERT" "(" "fc == parent->fc"
")"); do { *((volatile int*)__null) = 152; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
153}
154
155BytecodeEmitter::BytecodeEmitter(BytecodeEmitter* parent, SharedContext* sc)
156 : BytecodeEmitter(parent, parent->fc, sc, parent->errorReporter_,
157 parent->compilationState, parent->emitterMode) {}
158
159BytecodeEmitter::BytecodeEmitter(FrontendContext* fc,
160 const EitherParser& parser, SharedContext* sc,
161 CompilationState& compilationState,
162 EmitterMode emitterMode)
163 : BytecodeEmitter(nullptr, fc, sc, parser.errorReporter(), compilationState,
164 emitterMode) {
165 ep_.emplace(parser);
166}
167
168void BytecodeEmitter::initFromBodyPosition(TokenPos bodyPosition) {
169 setScriptStartOffsetIfUnset(bodyPosition.begin);
170 setFunctionBodyEndPos(bodyPosition.end);
171}
172
173bool BytecodeEmitter::init() {
174 if (!parent) {
175 if (!compilationState.prepareSharedDataStorage(fc)) {
176 return false;
177 }
178 }
179 return perScriptData_.init(fc);
180}
181
182bool BytecodeEmitter::init(TokenPos bodyPosition) {
183 initFromBodyPosition(bodyPosition);
184 return init();
185}
186
187template <typename T>
188T* BytecodeEmitter::findInnermostNestableControl() const {
189 return NestableControl::findNearest<T>(innermostNestableControl);
190}
191
192template <typename T, typename Predicate /* (T*) -> bool */>
193T* BytecodeEmitter::findInnermostNestableControl(Predicate predicate) const {
194 return NestableControl::findNearest<T>(innermostNestableControl, predicate);
195}
196
197NameLocation BytecodeEmitter::lookupName(TaggedParserAtomIndex name) {
198 return innermostEmitterScope()->lookup(this, name);
199}
200
201void BytecodeEmitter::lookupPrivate(TaggedParserAtomIndex name,
202 NameLocation& loc,
203 Maybe<NameLocation>& brandLoc) {
204 innermostEmitterScope()->lookupPrivate(this, name, loc, brandLoc);
205}
206
207Maybe<NameLocation> BytecodeEmitter::locationOfNameBoundInScope(
208 TaggedParserAtomIndex name, EmitterScope* target) {
209 return innermostEmitterScope()->locationBoundInScope(name, target);
210}
211
212template <typename T>
213Maybe<NameLocation> BytecodeEmitter::locationOfNameBoundInScopeType(
214 TaggedParserAtomIndex name, EmitterScope* source) {
215 EmitterScope* aScope = source;
216 while (!aScope->scope(this).is<T>()) {
217 aScope = aScope->enclosingInFrame();
218 }
219 return source->locationBoundInScope(name, aScope);
220}
221
222bool BytecodeEmitter::markStepBreakpoint() {
223 if (skipBreakpointSrcNotes()) {
224 return true;
225 }
226
227 if (!newSrcNote(SrcNoteType::BreakpointStepSep)) {
228 return false;
229 }
230
231 // We track the location of the most recent separator for use in
232 // markSimpleBreakpoint. Note that this means that the position must already
233 // be set before markStepBreakpoint is called.
234 bytecodeSection().updateSeparatorPosition();
235
236 return true;
237}
238
239bool BytecodeEmitter::markSimpleBreakpoint() {
240 if (skipBreakpointSrcNotes()) {
241 return true;
242 }
243
244 // If a breakable call ends up being the same location as the most recent
245 // expression start, we need to skip marking it breakable in order to avoid
246 // having two breakpoints with the same line/column position.
247 // Note: This assumes that the position for the call has already been set.
248 if (!bytecodeSection().isDuplicateLocation()) {
249 if (!newSrcNote(SrcNoteType::Breakpoint)) {
250 return false;
251 }
252 }
253
254 return true;
255}
256
257bool BytecodeEmitter::emitCheck(JSOp op, ptrdiff_t delta,
258 BytecodeOffset* offset) {
259 size_t oldLength = bytecodeSection().code().length();
260 *offset = BytecodeOffset(oldLength);
261
262 size_t newLength = oldLength + size_t(delta);
263 if (MOZ_UNLIKELY(newLength > MaxBytecodeLength)(__builtin_expect(!!(newLength > MaxBytecodeLength), 0))) {
264 ReportAllocationOverflow(fc);
265 return false;
266 }
267
268 if (!bytecodeSection().code().growByUninitialized(delta)) {
269 return false;
270 }
271
272 if (BytecodeOpHasIC(op)) {
273 // Even if every bytecode op is a JOF_IC op and the function has ARGC_LIMIT
274 // arguments, numICEntries cannot overflow.
275 static_assert(MaxBytecodeLength + 1 /* this */ + ARGC_LIMIT <= UINT32_MAX(4294967295U),
276 "numICEntries must not overflow");
277 bytecodeSection().incrementNumICEntries();
278 }
279
280 return true;
281}
282
283#ifdef DEBUG1
284bool BytecodeEmitter::checkStrictOrSloppy(JSOp op) {
285 if (IsCheckStrictOp(op) && !sc->strict()) {
286 return false;
287 }
288 if (IsCheckSloppyOp(op) && sc->strict()) {
289 return false;
290 }
291 return true;
292}
293#endif
294
295bool BytecodeEmitter::emit1(JSOp op) {
296 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"
, 296); AnnotateMozCrashReason("MOZ_ASSERT" "(" "checkStrictOrSloppy(op)"
")"); do { *((volatile int*)__null) = 296; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
297
298 BytecodeOffset offset;
299 if (!emitCheck(op, 1, &offset)) {
300 return false;
301 }
302
303 jsbytecode* code = bytecodeSection().code(offset);
304 code[0] = jsbytecode(op);
305 bytecodeSection().updateDepth(op, offset);
306 return true;
307}
308
309bool BytecodeEmitter::emit2(JSOp op, uint8_t op1) {
310 MOZ_ASSERT(checkStrictOrSloppy(op))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(checkStrictOrSloppy(op))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(checkStrictOrSloppy(op)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("checkStrictOrSloppy(op)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 310); AnnotateMozCrashReason("MOZ_ASSERT" "(" "checkStrictOrSloppy(op)"
")"); do { *((volatile int*)__null) = 310; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
311
312 BytecodeOffset offset;
313 if (!emitCheck(op, 2, &offset)) {
314 return false;
315 }
316
317 jsbytecode* code = bytecodeSection().code(offset);
318 code[0] = jsbytecode(op);
319 code[1] = jsbytecode(op1);
320 bytecodeSection().updateDepth(op, offset);
321 return true;
322}
323
324bool BytecodeEmitter::emit3(JSOp op, jsbytecode op1, jsbytecode op2) {
325 MOZ_ASSERT(checkStrictOrSloppy(op))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(checkStrictOrSloppy(op))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(checkStrictOrSloppy(op)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("checkStrictOrSloppy(op)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 325); AnnotateMozCrashReason("MOZ_ASSERT" "(" "checkStrictOrSloppy(op)"
")"); do { *((volatile int*)__null) = 325; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
326
327 /* These should filter through emitVarOp. */
328 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"
, 328); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsArgOp(op)"
")"); do { *((volatile int*)__null) = 328; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
329 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"
, 329); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsLocalOp(op)"
")"); do { *((volatile int*)__null) = 329; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
330
331 BytecodeOffset offset;
332 if (!emitCheck(op, 3, &offset)) {
333 return false;
334 }
335
336 jsbytecode* code = bytecodeSection().code(offset);
337 code[0] = jsbytecode(op);
338 code[1] = op1;
339 code[2] = op2;
340 bytecodeSection().updateDepth(op, offset);
341 return true;
342}
343
344bool BytecodeEmitter::emitN(JSOp op, size_t extra, BytecodeOffset* offset) {
345 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"
, 345); AnnotateMozCrashReason("MOZ_ASSERT" "(" "checkStrictOrSloppy(op)"
")"); do { *((volatile int*)__null) = 345; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
346 ptrdiff_t length = 1 + ptrdiff_t(extra);
347
348 BytecodeOffset off;
349 if (!emitCheck(op, length, &off)) {
350 return false;
351 }
352
353 jsbytecode* code = bytecodeSection().code(off);
354 code[0] = jsbytecode(op);
355 /* The remaining |extra| bytes are set by the caller */
356
357 /*
358 * Don't updateDepth if op's use-count comes from the immediate
359 * operand yet to be stored in the extra bytes after op.
360 */
361 if (CodeSpec(op).nuses >= 0) {
362 bytecodeSection().updateDepth(op, off);
363 }
364
365 if (offset) {
366 *offset = off;
367 }
368 return true;
369}
370
371bool BytecodeEmitter::emitJumpTargetOp(JSOp op, BytecodeOffset* off) {
372 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"
, 372); AnnotateMozCrashReason("MOZ_ASSERT" "(" "BytecodeIsJumpTarget(op)"
")"); do { *((volatile int*)__null) = 372; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
373
374 // Record the current IC-entry index at start of this op.
375 uint32_t numEntries = bytecodeSection().numICEntries();
376
377 size_t n = GetOpLength(op) - 1;
378 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"
, 378); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetOpLength(op) >= 1 + ICINDEX_LEN"
")"); do { *((volatile int*)__null) = 378; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
379
380 if (!emitN(op, n, off)) {
381 return false;
382 }
383
384 SET_ICINDEX(bytecodeSection().code(*off), numEntries);
385 return true;
386}
387
388bool BytecodeEmitter::emitJumpTarget(JumpTarget* target) {
389 BytecodeOffset off = bytecodeSection().offset();
390
391 // Alias consecutive jump targets.
392 if (bytecodeSection().lastTargetOffset().valid() &&
393 off == bytecodeSection().lastTargetOffset() +
394 BytecodeOffsetDiff(JSOpLength_JumpTarget)) {
395 target->offset = bytecodeSection().lastTargetOffset();
396 return true;
397 }
398
399 target->offset = off;
400 bytecodeSection().setLastTargetOffset(off);
401
402 BytecodeOffset opOff;
403 return emitJumpTargetOp(JSOp::JumpTarget, &opOff);
404}
405
406bool BytecodeEmitter::emitJumpNoFallthrough(JSOp op, JumpList* jump) {
407 BytecodeOffset offset;
408 if (!emitCheck(op, 5, &offset)) {
409 return false;
410 }
411
412 jsbytecode* code = bytecodeSection().code(offset);
413 code[0] = jsbytecode(op);
414 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"
, 415); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!jump->offset.valid() || (0 <= jump->offset.value() && jump->offset < offset)"
")"); do { *((volatile int*)__null) = 415; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
415 (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"
, 415); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!jump->offset.valid() || (0 <= jump->offset.value() && jump->offset < offset)"
")"); do { *((volatile int*)__null) = 415; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
416 jump->push(bytecodeSection().code(BytecodeOffset(0)), offset);
417 bytecodeSection().updateDepth(op, offset);
418 return true;
419}
420
421bool BytecodeEmitter::emitJump(JSOp op, JumpList* jump) {
422 if (!emitJumpNoFallthrough(op, jump)) {
423 return false;
424 }
425 if (BytecodeFallsThrough(op)) {
426 JumpTarget fallthrough;
427 if (!emitJumpTarget(&fallthrough)) {
428 return false;
429 }
430 }
431 return true;
432}
433
434void BytecodeEmitter::patchJumpsToTarget(JumpList jump, JumpTarget target) {
435 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"
, 437); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset())"
")"); do { *((volatile int*)__null) = 437; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
436 !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"
, 437); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset())"
")"); do { *((volatile int*)__null) = 437; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
437 (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"
, 437); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset())"
")"); do { *((volatile int*)__null) = 437; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
438 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"
, 439); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0 <= target.offset.value() && target.offset <= bytecodeSection().offset()"
")"); do { *((volatile int*)__null) = 439; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
439 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"
, 439); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0 <= target.offset.value() && target.offset <= bytecodeSection().offset()"
")"); do { *((volatile int*)__null) = 439; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
440 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"
, 443); AnnotateMozCrashReason("MOZ_ASSERT" "(" "BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))"
")"); do { *((volatile int*)__null) = 443; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
441 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"
, 443); AnnotateMozCrashReason("MOZ_ASSERT" "(" "BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))"
")"); do { *((volatile int*)__null) = 443; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
442 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"
, 443); AnnotateMozCrashReason("MOZ_ASSERT" "(" "BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))"
")"); do { *((volatile int*)__null) = 443; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
443 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"
, 443); AnnotateMozCrashReason("MOZ_ASSERT" "(" "BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))"
")"); do { *((volatile int*)__null) = 443; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
444 jump.patchAll(bytecodeSection().code(BytecodeOffset(0)), target);
445}
446
447bool BytecodeEmitter::emitJumpTargetAndPatch(JumpList jump) {
448 if (!jump.offset.valid()) {
449 return true;
450 }
451 JumpTarget target;
452 if (!emitJumpTarget(&target)) {
453 return false;
454 }
455 patchJumpsToTarget(jump, target);
456 return true;
457}
458
459bool BytecodeEmitter::emitCall(JSOp op, uint16_t argc,
460 const Maybe<uint32_t>& sourceCoordOffset) {
461 if (sourceCoordOffset.isSome()) {
462 if (!updateSourceCoordNotes(*sourceCoordOffset)) {
463 return false;
464 }
465 }
466 return emit3(op, ARGC_LO(argc), ARGC_HI(argc));
467}
468
469bool BytecodeEmitter::emitCall(JSOp op, uint16_t argc, ParseNode* pn) {
470 return emitCall(op, argc, pn ? Some(pn->pn_pos.begin) : Nothing());
471}
472
473bool BytecodeEmitter::emitDupAt(unsigned slotFromTop, unsigned count) {
474 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"
, 474); AnnotateMozCrashReason("MOZ_ASSERT" "(" "slotFromTop < unsigned(bytecodeSection().stackDepth())"
")"); do { *((volatile int*)__null) = 474; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
475 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"
, 475); AnnotateMozCrashReason("MOZ_ASSERT" "(" "slotFromTop + 1 >= count"
")"); do { *((volatile int*)__null) = 475; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
476
477 if (slotFromTop == 0 && count == 1) {
478 return emit1(JSOp::Dup);
479 }
480
481 if (slotFromTop == 1 && count == 2) {
482 return emit1(JSOp::Dup2);
483 }
484
485 if (slotFromTop >= Bit(24)) {
486 reportError(nullptr, JSMSG_TOO_MANY_LOCALS);
487 return false;
488 }
489
490 for (unsigned i = 0; i < count; i++) {
491 BytecodeOffset off;
492 if (!emitN(JSOp::DupAt, 3, &off)) {
493 return false;
494 }
495
496 jsbytecode* pc = bytecodeSection().code(off);
497 SET_UINT24(pc, slotFromTop);
498 }
499
500 return true;
501}
502
503bool BytecodeEmitter::emitPopN(unsigned n) {
504 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"
, 504); AnnotateMozCrashReason("MOZ_ASSERT" "(" "n != 0" ")")
; do { *((volatile int*)__null) = 504; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
505
506 if (n == 1) {
507 return emit1(JSOp::Pop);
508 }
509
510 // 2 JSOp::Pop instructions (2 bytes) are shorter than JSOp::PopN (3 bytes).
511 if (n == 2) {
512 return emit1(JSOp::Pop) && emit1(JSOp::Pop);
513 }
514
515 return emitUint16Operand(JSOp::PopN, n);
516}
517
518bool BytecodeEmitter::emitPickN(uint8_t n) {
519 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"
, 519); AnnotateMozCrashReason("MOZ_ASSERT" "(" "n != 0" ")")
; do { *((volatile int*)__null) = 519; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
520
521 if (n == 1) {
522 return emit1(JSOp::Swap);
523 }
524
525 return emit2(JSOp::Pick, n);
526}
527
528bool BytecodeEmitter::emitUnpickN(uint8_t n) {
529 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"
, 529); AnnotateMozCrashReason("MOZ_ASSERT" "(" "n != 0" ")")
; do { *((volatile int*)__null) = 529; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
530
531 if (n == 1) {
532 return emit1(JSOp::Swap);
533 }
534
535 return emit2(JSOp::Unpick, n);
536}
537
538bool BytecodeEmitter::emitCheckIsObj(CheckIsObjectKind kind) {
539 return emit2(JSOp::CheckIsObj, uint8_t(kind));
540}
541
542bool BytecodeEmitter::emitBuiltinObject(BuiltinObjectKind kind) {
543 return emit2(JSOp::BuiltinObject, uint8_t(kind));
544}
545
546/* Updates line number notes, not column notes. */
547bool BytecodeEmitter::updateLineNumberNotes(uint32_t offset) {
548 if (skipLocationSrcNotes()) {
549 return true;
550 }
551
552 const ErrorReporter& er = errorReporter();
553 std::optional<bool> onThisLineStatus =
554 er.isOnThisLine(offset, bytecodeSection().currentLine());
555 if (!onThisLineStatus.has_value()) {
556 er.errorNoOffset(JSMSG_OUT_OF_MEMORY);
557 return false;
558 }
559
560 bool onThisLine = *onThisLineStatus;
561
562 if (!onThisLine) {
563 unsigned line = er.lineAt(offset);
564 unsigned delta = line - bytecodeSection().currentLine();
565
566 // If we use a `SetLine` note below, we want it to be relative to the
567 // scripts initial line number for better chance of sharing.
568 unsigned initialLine = sc->extent().lineno;
569 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"
, 569); AnnotateMozCrashReason("MOZ_ASSERT" "(" "line >= initialLine"
")"); do { *((volatile int*)__null) = 569; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
570
571 /*
572 * Encode any change in the current source line number by using
573 * either several SrcNoteType::NewLine notes or just one
574 * SrcNoteType::SetLine note, whichever consumes less space.
575 *
576 * NB: We handle backward line number deltas (possible with for
577 * loops where the update part is emitted after the body, but its
578 * line number is <= any line number in the body) here by letting
579 * unsigned delta_ wrap to a very large number, which triggers a
580 * SrcNoteType::SetLine.
581 */
582 bytecodeSection().setCurrentLine(line, offset);
583 if (delta >= SrcNote::SetLine::lengthFor(line, initialLine)) {
584 if (!newSrcNote2(SrcNoteType::SetLine,
585 SrcNote::SetLine::toOperand(line, initialLine))) {
586 return false;
587 }
588 } else {
589 do {
590 if (!newSrcNote(SrcNoteType::NewLine)) {
591 return false;
592 }
593 } while (--delta != 0);
594 }
595
596 bytecodeSection().updateSeparatorPositionIfPresent();
597 }
598 return true;
599}
600
601/* Updates the line number and column number information in the source notes. */
602bool BytecodeEmitter::updateSourceCoordNotes(uint32_t offset) {
603 if (skipLocationSrcNotes()) {
604 return true;
605 }
606
607 if (!updateLineNumberNotes(offset)) {
608 return false;
609 }
610
611 JS::LimitedColumnNumberOneOrigin columnIndex =
612 errorReporter().columnAt(offset);
613
614 // Assert colspan is always representable.
615 static_assert((0 - ptrdiff_t(JS::LimitedColumnNumberOneOrigin::Limit)) >=
616 SrcNote::ColSpan::MinColSpan);
617 static_assert((ptrdiff_t(JS::LimitedColumnNumberOneOrigin::Limit) - 0) <=
618 SrcNote::ColSpan::MaxColSpan);
619
620 JS::ColumnNumberOffset colspan = columnIndex - bytecodeSection().lastColumn();
621
622 if (colspan != JS::ColumnNumberOffset::zero()) {
623 if (lastLineOnlySrcNoteIndex != LastSrcNoteIsNotLineOnly) {
624 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"
, 625); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().lastColumn() == JS::LimitedColumnNumberOneOrigin()"
")"); do { *((volatile int*)__null) = 625; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
625 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"
, 625); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().lastColumn() == JS::LimitedColumnNumberOneOrigin()"
")"); do { *((volatile int*)__null) = 625; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
626
627 const SrcNotesVector& notes = bytecodeSection().notes();
628 SrcNoteType type = notes[lastLineOnlySrcNoteIndex].type();
629 if (type == SrcNoteType::NewLine) {
630 if (!convertLastNewLineToNewLineColumn(columnIndex)) {
631 return false;
632 }
633 } else {
634 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"
, 634); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == SrcNoteType::SetLine"
")"); do { *((volatile int*)__null) = 634; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
635 if (!convertLastSetLineToSetLineColumn(columnIndex)) {
636 return false;
637 }
638 }
639 } else {
640 if (!newSrcNote2(SrcNoteType::ColSpan,
641 SrcNote::ColSpan::toOperand(colspan))) {
642 return false;
643 }
644 }
645 bytecodeSection().setLastColumn(columnIndex, offset);
646 bytecodeSection().updateSeparatorPositionIfPresent();
647 }
648 return true;
649}
650
651bool BytecodeEmitter::updateSourceCoordNotesIfNonLiteral(ParseNode* node) {
652 if (node->isLiteral()) {
653 return true;
654 }
655 return updateSourceCoordNotes(node->pn_pos.begin);
656}
657
658uint32_t BytecodeEmitter::getOffsetForLoop(ParseNode* nextpn) {
659 // Try to give the JSOp::LoopHead the same line number as the next
660 // instruction. nextpn is often a block, in which case the next instruction
661 // typically comes from the first statement inside.
662 if (nextpn->is<LexicalScopeNode>()) {
663 nextpn = nextpn->as<LexicalScopeNode>().scopeBody();
664 }
665 if (nextpn->isKind(ParseNodeKind::StatementList)) {
666 if (ParseNode* firstStatement = nextpn->as<ListNode>().head()) {
667 nextpn = firstStatement;
668 }
669 }
670
671 return nextpn->pn_pos.begin;
672}
673
674bool BytecodeEmitter::emitUint16Operand(JSOp op, uint32_t operand) {
675 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"
, 675); AnnotateMozCrashReason("MOZ_ASSERT" "(" "operand <= (65535)"
")"); do { *((volatile int*)__null) = 675; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
676 if (!emit3(op, UINT16_LO(operand), UINT16_HI(operand))) {
677 return false;
678 }
679 return true;
680}
681
682bool BytecodeEmitter::emitUint32Operand(JSOp op, uint32_t operand) {
683 BytecodeOffset off;
684 if (!emitN(op, 4, &off)) {
685 return false;
686 }
687 SET_UINT32(bytecodeSection().code(off), operand);
688 return true;
689}
690
691bool BytecodeEmitter::emitGoto(NestableControl* target, GotoKind kind) {
692 NonLocalExitControl nle(this, kind == GotoKind::Continue
693 ? NonLocalExitKind::Continue
694 : NonLocalExitKind::Break);
695 return nle.emitNonLocalJump(target);
696}
697
698AbstractScopePtr BytecodeEmitter::innermostScope() const {
699 return innermostEmitterScope()->scope(this);
700}
701
702ScopeIndex BytecodeEmitter::innermostScopeIndex() const {
703 return *innermostEmitterScope()->scopeIndex(this);
704}
705
706bool BytecodeEmitter::emitGCIndexOp(JSOp op, GCThingIndex index) {
707 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"
, 707); AnnotateMozCrashReason("MOZ_ASSERT" "(" "checkStrictOrSloppy(op)"
")"); do { *((volatile int*)__null) = 707; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
708
709 constexpr size_t OpLength = 1 + GCTHING_INDEX_LEN;
710 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"
, 710); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetOpLength(op) == OpLength"
")"); do { *((volatile int*)__null) = 710; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
711
712 BytecodeOffset offset;
713 if (!emitCheck(op, OpLength, &offset)) {
714 return false;
715 }
716
717 jsbytecode* code = bytecodeSection().code(offset);
718 code[0] = jsbytecode(op);
719 SET_GCTHING_INDEX(code, index);
720 bytecodeSection().updateDepth(op, offset);
721 return true;
722}
723
724bool BytecodeEmitter::emitAtomOp(JSOp op, TaggedParserAtomIndex atom) {
725 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"
, 725); AnnotateMozCrashReason("MOZ_ASSERT" "(" "atom" ")"); do
{ *((volatile int*)__null) = 725; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
726
727 // .generator lookups should be emitted as JSOp::GetAliasedVar instead of
728 // JSOp::GetName etc, to bypass |with| objects on the scope chain.
729 // It's safe to emit .this lookups though because |with| objects skip
730 // those.
731 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"
, 732); AnnotateMozCrashReason("MOZ_ASSERT" "(" "atom != TaggedParserAtomIndex::WellKnown::dot_generator_()"
")"); do { *((volatile int*)__null) = 732; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
732 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"
, 732); AnnotateMozCrashReason("MOZ_ASSERT" "(" "atom != TaggedParserAtomIndex::WellKnown::dot_generator_()"
")"); do { *((volatile int*)__null) = 732; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
733
734 GCThingIndex index;
735 if (!makeAtomIndex(atom, ParserAtom::Atomize::Yes, &index)) {
736 return false;
737 }
738
739 return emitAtomOp(op, index);
740}
741
742bool BytecodeEmitter::emitAtomOp(JSOp op, GCThingIndex atomIndex) {
743 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"
, 743); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JOF_OPTYPE(op) == JOF_ATOM"
")"); do { *((volatile int*)__null) = 743; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
744#ifdef DEBUG1
745 auto atom = perScriptData().gcThingList().getAtom(atomIndex);
746 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"
, 746); AnnotateMozCrashReason("MOZ_ASSERT" "(" "compilationState.parserAtoms.isInstantiatedAsJSAtom(atom)"
")"); do { *((volatile int*)__null) = 746; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
747#endif
748 return emitGCIndexOp(op, atomIndex);
749}
750
751bool BytecodeEmitter::emitStringOp(JSOp op, TaggedParserAtomIndex atom) {
752 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"
, 752); AnnotateMozCrashReason("MOZ_ASSERT" "(" "atom" ")"); do
{ *((volatile int*)__null) = 752; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
753 GCThingIndex index;
754 if (!makeAtomIndex(atom, ParserAtom::Atomize::No, &index)) {
755 return false;
756 }
757
758 return emitStringOp(op, index);
759}
760
761bool BytecodeEmitter::emitStringOp(JSOp op, GCThingIndex atomIndex) {
762 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"
, 762); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JOF_OPTYPE(op) == JOF_STRING"
")"); do { *((volatile int*)__null) = 762; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
763 return emitGCIndexOp(op, atomIndex);
764}
765
766bool BytecodeEmitter::emitInternedScopeOp(GCThingIndex index, JSOp op) {
767 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"
, 767); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JOF_OPTYPE(op) == JOF_SCOPE"
")"); do { *((volatile int*)__null) = 767; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
768 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"
, 768); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index < perScriptData().gcThingList().length()"
")"); do { *((volatile int*)__null) = 768; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
769 return emitGCIndexOp(op, index);
770}
771
772bool BytecodeEmitter::emitInternedObjectOp(GCThingIndex index, JSOp op) {
773 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"
, 773); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JOF_OPTYPE(op) == JOF_OBJECT"
")"); do { *((volatile int*)__null) = 773; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
774 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"
, 774); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index < perScriptData().gcThingList().length()"
")"); do { *((volatile int*)__null) = 774; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
775 return emitGCIndexOp(op, index);
776}
777
778bool BytecodeEmitter::emitRegExp(GCThingIndex index) {
779 return emitGCIndexOp(JSOp::RegExp, index);
780}
781
782bool BytecodeEmitter::emitLocalOp(JSOp op, uint32_t slot) {
783 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"
, 783); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JOF_OPTYPE(op) != JOF_ENVCOORD"
")"); do { *((volatile int*)__null) = 783; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
784 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"
, 784); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsLocalOp(op)"
")"); do { *((volatile int*)__null) = 784; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
785
786 BytecodeOffset off;
787 if (!emitN(op, LOCALNO_LEN, &off)) {
788 return false;
789 }
790
791 SET_LOCALNO(bytecodeSection().code(off), slot);
792 return true;
793}
794
795bool BytecodeEmitter::emitArgOp(JSOp op, uint16_t slot) {
796 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"
, 796); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsArgOp(op)"
")"); do { *((volatile int*)__null) = 796; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
797 BytecodeOffset off;
798 if (!emitN(op, ARGNO_LEN, &off)) {
799 return false;
800 }
801
802 SET_ARGNO(bytecodeSection().code(off), slot);
803 return true;
804}
805
806bool BytecodeEmitter::emitEnvCoordOp(JSOp op, EnvironmentCoordinate ec) {
807 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"
, 808); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JOF_OPTYPE(op) == JOF_ENVCOORD || JOF_OPTYPE(op) == JOF_DEBUGCOORD"
")"); do { *((volatile int*)__null) = 808; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
808 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"
, 808); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JOF_OPTYPE(op) == JOF_ENVCOORD || JOF_OPTYPE(op) == JOF_DEBUGCOORD"
")"); do { *((volatile int*)__null) = 808; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
809
810 constexpr size_t N = ENVCOORD_HOPS_LEN + ENVCOORD_SLOT_LEN;
811 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"
, 811); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetOpLength(op) == 1 + N"
")"); do { *((volatile int*)__null) = 811; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
812
813 BytecodeOffset off;
814 if (!emitN(op, N, &off)) {
815 return false;
816 }
817
818 jsbytecode* pc = bytecodeSection().code(off);
819 SET_ENVCOORD_HOPS(pc, ec.hops());
820 pc += ENVCOORD_HOPS_LEN;
821 SET_ENVCOORD_SLOT(pc, ec.slot());
822 pc += ENVCOORD_SLOT_LEN;
Value stored to 'pc' is never read
823 return true;
824}
825
826JSOp BytecodeEmitter::strictifySetNameOp(JSOp op) {
827 switch (op) {
828 case JSOp::SetName:
829 if (sc->strict()) {
830 op = JSOp::StrictSetName;
831 }
832 break;
833 case JSOp::SetGName:
834 if (sc->strict()) {
835 op = JSOp::StrictSetGName;
836 }
837 break;
838 default:;
839 }
840 return op;
841}
842
843bool BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer) {
844 AutoCheckRecursionLimit recursion(fc);
845 if (!recursion.check(fc)) {
846 return false;
847 }
848
849restart:
850
851 switch (pn->getKind()) {
852 // Trivial cases with no side effects.
853 case ParseNodeKind::EmptyStmt:
854 case ParseNodeKind::TrueExpr:
855 case ParseNodeKind::FalseExpr:
856 case ParseNodeKind::NullExpr:
857 case ParseNodeKind::RawUndefinedExpr:
858 case ParseNodeKind::Elision:
859 case ParseNodeKind::Generator:
860 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"
, 860); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<NullaryNode>()"
")"); do { *((volatile int*)__null) = 860; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
861 *answer = false;
862 return true;
863
864 case ParseNodeKind::ObjectPropertyName:
865 case ParseNodeKind::PrivateName: // no side effects, unlike
866 // ParseNodeKind::Name
867 case ParseNodeKind::StringExpr:
868 case ParseNodeKind::TemplateStringExpr:
869 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"
, 869); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<NameNode>()"
")"); do { *((volatile int*)__null) = 869; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
870 *answer = false;
871 return true;
872
873 case ParseNodeKind::RegExpExpr:
874 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"
, 874); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<RegExpLiteral>()"
")"); do { *((volatile int*)__null) = 874; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
875 *answer = false;
876 return true;
877
878 case ParseNodeKind::NumberExpr:
879 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"
, 879); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<NumericLiteral>()"
")"); do { *((volatile int*)__null) = 879; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
880 *answer = false;
881 return true;
882
883 case ParseNodeKind::BigIntExpr:
884 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"
, 884); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BigIntLiteral>()"
")"); do { *((volatile int*)__null) = 884; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
885 *answer = false;
886 return true;
887
888 // |this| can throw in derived class constructors, including nested arrow
889 // functions or eval.
890 case ParseNodeKind::ThisExpr:
891 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"
, 891); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { *((volatile int*)__null) = 891; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
892 *answer = sc->needsThisTDZChecks();
893 return true;
894
895 // |new.target| doesn't have any side-effects.
896 case ParseNodeKind::NewTargetExpr: {
897 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"
, 897); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<NewTargetNode>()"
")"); do { *((volatile int*)__null) = 897; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
898 *answer = false;
899 return true;
900 }
901
902 // Trivial binary nodes with more token pos holders.
903 case ParseNodeKind::ImportMetaExpr: {
904 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"
, 904); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->as<BinaryNode>().left()->isKind(ParseNodeKind::PosHolder)"
")"); do { *((volatile int*)__null) = 904; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
905 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"
, 906); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->as<BinaryNode>().right()->isKind(ParseNodeKind::PosHolder)"
")"); do { *((volatile int*)__null) = 906; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
906 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"
, 906); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->as<BinaryNode>().right()->isKind(ParseNodeKind::PosHolder)"
")"); do { *((volatile int*)__null) = 906; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
907 *answer = false;
908 return true;
909 }
910
911 case ParseNodeKind::BreakStmt:
912 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"
, 912); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BreakStatement>()"
")"); do { *((volatile int*)__null) = 912; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
913 *answer = true;
914 return true;
915
916 case ParseNodeKind::ContinueStmt:
917 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"
, 917); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<ContinueStatement>()"
")"); do { *((volatile int*)__null) = 917; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
918 *answer = true;
919 return true;
920
921 case ParseNodeKind::DebuggerStmt:
922 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"
, 922); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<DebuggerStatement>()"
")"); do { *((volatile int*)__null) = 922; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
923 *answer = true;
924 return true;
925
926 // Watch out for getters!
927 case ParseNodeKind::OptionalDotExpr:
928 case ParseNodeKind::DotExpr:
929 case ParseNodeKind::ArgumentsLength:
930 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"
, 930); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { *((volatile int*)__null) = 930; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
931 *answer = true;
932 return true;
933
934 // Unary cases with side effects only if the child has them.
935 case ParseNodeKind::TypeOfExpr:
936 case ParseNodeKind::VoidExpr:
937 case ParseNodeKind::NotExpr:
938 return checkSideEffects(pn->as<UnaryNode>().kid(), answer);
939
940 // Even if the name expression is effect-free, performing ToPropertyKey on
941 // it might not be effect-free:
942 //
943 // RegExp.prototype.toString = () => { throw 42; };
944 // ({ [/regex/]: 0 }); // ToPropertyKey(/regex/) throws 42
945 //
946 // function Q() {
947 // ({ [new.target]: 0 });
948 // }
949 // Q.toString = () => { throw 17; };
950 // new Q; // new.target will be Q, ToPropertyKey(Q) throws 17
951 case ParseNodeKind::ComputedName:
952 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"
, 952); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { *((volatile int*)__null) = 952; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
953 *answer = true;
954 return true;
955
956 // Looking up or evaluating the associated name could throw.
957 case ParseNodeKind::TypeOfNameExpr:
958 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"
, 958); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { *((volatile int*)__null) = 958; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
959 *answer = true;
960 return true;
961
962 // This unary case has side effects on the enclosing object, sure. But
963 // that's not the question this function answers: it's whether the
964 // operation may have a side effect on something *other* than the result
965 // of the overall operation in which it's embedded. The answer to that
966 // is no, because an object literal having a mutated prototype only
967 // produces a value, without affecting anything else.
968 case ParseNodeKind::MutateProto:
969 return checkSideEffects(pn->as<UnaryNode>().kid(), answer);
970
971 // Unary cases with obvious side effects.
972 case ParseNodeKind::PreIncrementExpr:
973 case ParseNodeKind::PostIncrementExpr:
974 case ParseNodeKind::PreDecrementExpr:
975 case ParseNodeKind::PostDecrementExpr:
976 case ParseNodeKind::ThrowStmt:
977 MOZ_ASSERT(pn->is<UnaryNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<UnaryNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<UnaryNode>()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"pn->is<UnaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 977); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { *((volatile int*)__null) = 977; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
978 *answer = true;
979 return true;
980
981 // These might invoke valueOf/toString, even with a subexpression without
982 // side effects! Consider |+{ valueOf: null, toString: null }|.
983 case ParseNodeKind::BitNotExpr:
984 case ParseNodeKind::PosExpr:
985 case ParseNodeKind::NegExpr:
986 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"
, 986); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { *((volatile int*)__null) = 986; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
987 *answer = true;
988 return true;
989
990 // This invokes the (user-controllable) iterator protocol.
991 case ParseNodeKind::Spread:
992 MOZ_ASSERT(pn->is<UnaryNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<UnaryNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<UnaryNode>()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"pn->is<UnaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 992); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { *((volatile int*)__null) = 992; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
993 *answer = true;
994 return true;
995
996 case ParseNodeKind::InitialYield:
997 case ParseNodeKind::YieldStarExpr:
998 case ParseNodeKind::YieldExpr:
999 case ParseNodeKind::AwaitExpr:
1000 MOZ_ASSERT(pn->is<UnaryNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<UnaryNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<UnaryNode>()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"pn->is<UnaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1000); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { *((volatile int*)__null) = 1000; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1001 *answer = true;
1002 return true;
1003
1004 // Deletion generally has side effects, even if isolated cases have none.
1005 case ParseNodeKind::DeleteNameExpr:
1006 case ParseNodeKind::DeletePropExpr:
1007 case ParseNodeKind::DeleteElemExpr:
1008 case ParseNodeKind::DeleteOptionalChainExpr:
1009 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"
, 1009); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { *((volatile int*)__null) = 1009; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1010 *answer = true;
1011 return true;
1012
1013 // Deletion of a non-Reference expression has side effects only through
1014 // evaluating the expression.
1015 case ParseNodeKind::DeleteExpr: {
1016 ParseNode* expr = pn->as<UnaryNode>().kid();
1017 return checkSideEffects(expr, answer);
1018 }
1019
1020 case ParseNodeKind::ExpressionStmt:
1021 return checkSideEffects(pn->as<UnaryNode>().kid(), answer);
1022
1023 // Binary cases with obvious side effects.
1024 case ParseNodeKind::InitExpr:
1025 *answer = true;
1026 return true;
1027
1028 case ParseNodeKind::AssignExpr:
1029 case ParseNodeKind::AddAssignExpr:
1030 case ParseNodeKind::SubAssignExpr:
1031 case ParseNodeKind::CoalesceAssignExpr:
1032 case ParseNodeKind::OrAssignExpr:
1033 case ParseNodeKind::AndAssignExpr:
1034 case ParseNodeKind::BitOrAssignExpr:
1035 case ParseNodeKind::BitXorAssignExpr:
1036 case ParseNodeKind::BitAndAssignExpr:
1037 case ParseNodeKind::LshAssignExpr:
1038 case ParseNodeKind::RshAssignExpr:
1039 case ParseNodeKind::UrshAssignExpr:
1040 case ParseNodeKind::MulAssignExpr:
1041 case ParseNodeKind::DivAssignExpr:
1042 case ParseNodeKind::ModAssignExpr:
1043 case ParseNodeKind::PowAssignExpr:
1044 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"
, 1044); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<AssignmentNode>()"
")"); do { *((volatile int*)__null) = 1044; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1045 *answer = true;
1046 return true;
1047
1048 case ParseNodeKind::SetThis:
1049 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"
, 1049); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { *((volatile int*)__null) = 1049; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1050 *answer = true;
1051 return true;
1052
1053 case ParseNodeKind::StatementList:
1054 // Strict equality operations and short circuit operators are well-behaved
1055 // and perform no conversions.
1056 case ParseNodeKind::CoalesceExpr:
1057 case ParseNodeKind::OrExpr:
1058 case ParseNodeKind::AndExpr:
1059 case ParseNodeKind::StrictEqExpr:
1060 case ParseNodeKind::StrictNeExpr:
1061 // Any subexpression of a comma expression could be effectful.
1062 case ParseNodeKind::CommaExpr:
1063 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"
, 1063); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!pn->as<ListNode>().empty()"
")"); do { *((volatile int*)__null) = 1063; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1064 [[fallthrough]];
1065 // Subcomponents of a literal may be effectful.
1066 case ParseNodeKind::ArrayExpr:
1067 case ParseNodeKind::ObjectExpr:
1068 for (ParseNode* item : pn->as<ListNode>().contents()) {
1069 if (!checkSideEffects(item, answer)) {
1070 return false;
1071 }
1072 if (*answer) {
1073 return true;
1074 }
1075 }
1076 return true;
1077
1078#ifdef ENABLE_RECORD_TUPLE
1079 case ParseNodeKind::RecordExpr:
1080 case ParseNodeKind::TupleExpr:
1081 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"
, 1081); AnnotateMozCrashReason("MOZ_CRASH(" "Record and Tuple are not supported yet"
")"); do { *((volatile int*)__null) = 1081; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
1082#endif
1083
1084#ifdef ENABLE_DECORATORS
1085 case ParseNodeKind::DecoratorList:
1086 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"
, 1086); AnnotateMozCrashReason("MOZ_CRASH(" "Decorators are not supported yet"
")"); do { *((volatile int*)__null) = 1086; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
1087#endif
1088
1089 // Most other binary operations (parsed as lists in SpiderMonkey) may
1090 // perform conversions triggering side effects. Math operations perform
1091 // ToNumber and may fail invoking invalid user-defined toString/valueOf:
1092 // |5 < { toString: null }|. |instanceof| throws if provided a
1093 // non-object constructor: |null instanceof null|. |in| throws if given
1094 // a non-object RHS: |5 in null|.
1095 case ParseNodeKind::BitOrExpr:
1096 case ParseNodeKind::BitXorExpr:
1097 case ParseNodeKind::BitAndExpr:
1098 case ParseNodeKind::EqExpr:
1099 case ParseNodeKind::NeExpr:
1100 case ParseNodeKind::LtExpr:
1101 case ParseNodeKind::LeExpr:
1102 case ParseNodeKind::GtExpr:
1103 case ParseNodeKind::GeExpr:
1104 case ParseNodeKind::InstanceOfExpr:
1105 case ParseNodeKind::InExpr:
1106 case ParseNodeKind::PrivateInExpr:
1107 case ParseNodeKind::LshExpr:
1108 case ParseNodeKind::RshExpr:
1109 case ParseNodeKind::UrshExpr:
1110 case ParseNodeKind::AddExpr:
1111 case ParseNodeKind::SubExpr:
1112 case ParseNodeKind::MulExpr:
1113 case ParseNodeKind::DivExpr:
1114 case ParseNodeKind::ModExpr:
1115 case ParseNodeKind::PowExpr:
1116 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"
, 1116); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->as<ListNode>().count() >= 2"
")"); do { *((volatile int*)__null) = 1116; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1117 *answer = true;
1118 return true;
1119
1120 case ParseNodeKind::PropertyDefinition:
1121 case ParseNodeKind::Case: {
1122 BinaryNode* node = &pn->as<BinaryNode>();
1123 if (!checkSideEffects(node->left(), answer)) {
1124 return false;
1125 }
1126 if (*answer) {
1127 return true;
1128 }
1129 return checkSideEffects(node->right(), answer);
1130 }
1131
1132 // More getters.
1133 case ParseNodeKind::ElemExpr:
1134 case ParseNodeKind::OptionalElemExpr:
1135 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"
, 1135); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { *((volatile int*)__null) = 1135; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1136 *answer = true;
1137 return true;
1138
1139 // Throws if the operand is not of the right class. Can also call a private
1140 // getter.
1141 case ParseNodeKind::PrivateMemberExpr:
1142 case ParseNodeKind::OptionalPrivateMemberExpr:
1143 *answer = true;
1144 return true;
1145
1146 // These affect visible names in this code, or in other code.
1147 case ParseNodeKind::ImportDecl:
1148 case ParseNodeKind::ExportFromStmt:
1149 case ParseNodeKind::ExportDefaultStmt:
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 // Likewise.
1155 case ParseNodeKind::ExportStmt:
1156 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"
, 1156); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { *((volatile int*)__null) = 1156; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1157 *answer = true;
1158 return true;
1159
1160 case ParseNodeKind::CallImportExpr:
1161 case ParseNodeKind::CallImportSpec:
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 // Every part of a loop might be effect-free, but looping infinitely *is*
1167 // an effect. (Language lawyer trivia: C++ says threads can be assumed
1168 // to exit or have side effects, C++14 [intro.multithread]p27, so a C++
1169 // implementation's equivalent of the below could set |*answer = false;|
1170 // if all loop sub-nodes set |*answer = false|!)
1171 case ParseNodeKind::DoWhileStmt:
1172 case ParseNodeKind::WhileStmt:
1173 case ParseNodeKind::ForStmt:
1174 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"
, 1174); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { *((volatile int*)__null) = 1174; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1175 *answer = true;
1176 return true;
1177
1178 // Declarations affect the name set of the relevant scope.
1179 case ParseNodeKind::VarStmt:
1180 case ParseNodeKind::ConstDecl:
1181 case ParseNodeKind::LetDecl:
1182 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"
, 1182); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<ListNode>()"
")"); do { *((volatile int*)__null) = 1182; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1183 *answer = true;
1184 return true;
1185
1186 case ParseNodeKind::IfStmt:
1187 case ParseNodeKind::ConditionalExpr: {
1188 TernaryNode* node = &pn->as<TernaryNode>();
1189 if (!checkSideEffects(node->kid1(), answer)) {
1190 return false;
1191 }
1192 if (*answer) {
1193 return true;
1194 }
1195 if (!checkSideEffects(node->kid2(), answer)) {
1196 return false;
1197 }
1198 if (*answer) {
1199 return true;
1200 }
1201 if ((pn = node->kid3())) {
1202 goto restart;
1203 }
1204 return true;
1205 }
1206
1207 // Function calls can invoke non-local code.
1208 case ParseNodeKind::NewExpr:
1209 case ParseNodeKind::CallExpr:
1210 case ParseNodeKind::OptionalCallExpr:
1211 case ParseNodeKind::TaggedTemplateExpr:
1212 case ParseNodeKind::SuperCallExpr:
1213 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"
, 1213); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { *((volatile int*)__null) = 1213; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1214 *answer = true;
1215 return true;
1216
1217 // Function arg lists can contain arbitrary expressions. Technically
1218 // this only causes side-effects if one of the arguments does, but since
1219 // the call being made will always trigger side-effects, it isn't needed.
1220 case ParseNodeKind::Arguments:
1221 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"
, 1221); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<ListNode>()"
")"); do { *((volatile int*)__null) = 1221; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1222 *answer = true;
1223 return true;
1224
1225 case ParseNodeKind::OptionalChain:
1226 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"
, 1226); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { *((volatile int*)__null) = 1226; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1227 *answer = true;
1228 return true;
1229
1230 // Classes typically introduce names. Even if no name is introduced,
1231 // the heritage and/or class body (through computed property names)
1232 // usually have effects.
1233 case ParseNodeKind::ClassDecl:
1234 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"
, 1234); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<ClassNode>()"
")"); do { *((volatile int*)__null) = 1234; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1235 *answer = true;
1236 return true;
1237
1238 // |with| calls |ToObject| on its expression and so throws if that value
1239 // is null/undefined.
1240 case ParseNodeKind::WithStmt:
1241 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"
, 1241); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { *((volatile int*)__null) = 1241; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1242 *answer = true;
1243 return true;
1244
1245 case ParseNodeKind::ReturnStmt:
1246 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"
, 1246); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { *((volatile int*)__null) = 1246; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1247 *answer = true;
1248 return true;
1249
1250 case ParseNodeKind::Name:
1251 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"
, 1251); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<NameNode>()"
")"); do { *((volatile int*)__null) = 1251; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1252 *answer = true;
1253 return true;
1254
1255 // Shorthands could trigger getters: the |x| in the object literal in
1256 // |with ({ get x() { throw 42; } }) ({ x });|, for example, triggers
1257 // one. (Of course, it isn't necessary to use |with| for a shorthand to
1258 // trigger a getter.)
1259 case ParseNodeKind::Shorthand:
1260 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"
, 1260); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { *((volatile int*)__null) = 1260; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1261 *answer = true;
1262 return true;
1263
1264 case ParseNodeKind::Function:
1265 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"
, 1265); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<FunctionNode>()"
")"); do { *((volatile int*)__null) = 1265; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1266 /*
1267 * A named function, contrary to ES3, is no longer effectful, because
1268 * we bind its name lexically (using JSOp::Callee) instead of creating
1269 * an Object instance and binding a readonly, permanent property in it
1270 * (the object and binding can be detected and hijacked or captured).
1271 * This is a bug fix to ES3; it is fixed in ES3.1 drafts.
1272 */
1273 *answer = false;
1274 return true;
1275
1276 case ParseNodeKind::Module:
1277 *answer = false;
1278 return true;
1279
1280 case ParseNodeKind::TryStmt: {
1281 TryNode* tryNode = &pn->as<TryNode>();
1282 if (!checkSideEffects(tryNode->body(), answer)) {
1283 return false;
1284 }
1285 if (*answer) {
1286 return true;
1287 }
1288 if (LexicalScopeNode* catchScope = tryNode->catchScope()) {
1289 if (!checkSideEffects(catchScope, answer)) {
1290 return false;
1291 }
1292 if (*answer) {
1293 return true;
1294 }
1295 }
1296 if (ParseNode* finallyBlock = tryNode->finallyBlock()) {
1297 if (!checkSideEffects(finallyBlock, answer)) {
1298 return false;
1299 }
1300 }
1301 return true;
1302 }
1303
1304 case ParseNodeKind::Catch: {
1305 BinaryNode* catchClause = &pn->as<BinaryNode>();
1306 if (ParseNode* name = catchClause->left()) {
1307 if (!checkSideEffects(name, answer)) {
1308 return false;
1309 }
1310 if (*answer) {
1311 return true;
1312 }
1313 }
1314 return checkSideEffects(catchClause->right(), answer);
1315 }
1316
1317 case ParseNodeKind::SwitchStmt: {
1318 SwitchStatement* switchStmt = &pn->as<SwitchStatement>();
1319 if (!checkSideEffects(&switchStmt->discriminant(), answer)) {
1320 return false;
1321 }
1322 return *answer ||
1323 checkSideEffects(&switchStmt->lexicalForCaseList(), answer);
1324 }
1325
1326 case ParseNodeKind::LabelStmt:
1327 return checkSideEffects(pn->as<LabeledStatement>().statement(), answer);
1328
1329 case ParseNodeKind::LexicalScope:
1330 return checkSideEffects(pn->as<LexicalScopeNode>().scopeBody(), answer);
1331
1332 // We could methodically check every interpolated expression, but it's
1333 // probably not worth the trouble. Treat template strings as effect-free
1334 // only if they don't contain any substitutions.
1335 case ParseNodeKind::TemplateStringListExpr: {
1336 ListNode* list = &pn->as<ListNode>();
1337 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"
, 1337); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!list->empty()"
")"); do { *((volatile int*)__null) = 1337; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1338 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"
, 1340); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(list->count() % 2) == 1"
") (" "template strings must alternate template and substitution "
"parts" ")"); do { *((volatile int*)__null) = 1340; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
1339 "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"
, 1340); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(list->count() % 2) == 1"
") (" "template strings must alternate template and substitution "
"parts" ")"); do { *((volatile int*)__null) = 1340; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
1340 "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"
, 1340); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(list->count() % 2) == 1"
") (" "template strings must alternate template and substitution "
"parts" ")"); do { *((volatile int*)__null) = 1340; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
1341 *answer = list->count() > 1;
1342 return true;
1343 }
1344
1345 // This should be unreachable but is left as-is for now.
1346 case ParseNodeKind::ParamsBody:
1347 *answer = true;
1348 return true;
1349
1350 case ParseNodeKind::ForIn: // by ParseNodeKind::For
1351 case ParseNodeKind::ForOf: // by ParseNodeKind::For
1352 case ParseNodeKind::ForHead: // by ParseNodeKind::For
1353 case ParseNodeKind::DefaultConstructor: // by ParseNodeKind::ClassDecl
1354 case ParseNodeKind::ClassBodyScope: // by ParseNodeKind::ClassDecl
1355 case ParseNodeKind::ClassMethod: // by ParseNodeKind::ClassDecl
1356 case ParseNodeKind::ClassField: // by ParseNodeKind::ClassDecl
1357 case ParseNodeKind::ClassNames: // by ParseNodeKind::ClassDecl
1358 case ParseNodeKind::StaticClassBlock: // by ParseNodeKind::ClassDecl
1359 case ParseNodeKind::ClassMemberList: // by ParseNodeKind::ClassDecl
1360 case ParseNodeKind::ImportSpecList: // by ParseNodeKind::Import
1361 case ParseNodeKind::ImportSpec: // by ParseNodeKind::Import
1362 case ParseNodeKind::ImportNamespaceSpec: // by ParseNodeKind::Import
1363 case ParseNodeKind::ImportAttribute: // by ParseNodeKind::Import
1364 case ParseNodeKind::ImportAttributeList: // by ParseNodeKind::Import
1365 case ParseNodeKind::ImportModuleRequest: // by ParseNodeKind::Import
1366 case ParseNodeKind::ExportBatchSpecStmt: // by ParseNodeKind::Export
1367 case ParseNodeKind::ExportSpecList: // by ParseNodeKind::Export
1368 case ParseNodeKind::ExportSpec: // by ParseNodeKind::Export
1369 case ParseNodeKind::ExportNamespaceSpec: // by ParseNodeKind::Export
1370 case ParseNodeKind::CallSiteObj: // by ParseNodeKind::TaggedTemplate
1371 case ParseNodeKind::PosHolder: // by ParseNodeKind::NewTarget
1372 case ParseNodeKind::SuperBase: // by ParseNodeKind::Elem and others
1373 case ParseNodeKind::PropertyNameExpr: // by ParseNodeKind::Dot
1374 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"
, 1374); AnnotateMozCrashReason("MOZ_CRASH(" "handled by parent nodes"
")"); do { *((volatile int*)__null) = 1374; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
1375
1376 case ParseNodeKind::LastUnused:
1377 case ParseNodeKind::Limit:
1378 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"
, 1378); AnnotateMozCrashReason("MOZ_CRASH(" "invalid node kind"
")"); do { *((volatile int*)__null) = 1378; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
1379 }
1380
1381 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"
, 1383); AnnotateMozCrashReason("MOZ_CRASH(" "invalid, unenumerated ParseNodeKind value encountered in "
"BytecodeEmitter::checkSideEffects" ")"); do { *((volatile int
*)__null) = 1383; __attribute__((nomerge)) ::abort(); } while
(false); } while (false)
1382 "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"
, 1383); AnnotateMozCrashReason("MOZ_CRASH(" "invalid, unenumerated ParseNodeKind value encountered in "
"BytecodeEmitter::checkSideEffects" ")"); do { *((volatile int
*)__null) = 1383; __attribute__((nomerge)) ::abort(); } while
(false); } while (false)
1383 "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"
, 1383); AnnotateMozCrashReason("MOZ_CRASH(" "invalid, unenumerated ParseNodeKind value encountered in "
"BytecodeEmitter::checkSideEffects" ")"); do { *((volatile int
*)__null) = 1383; __attribute__((nomerge)) ::abort(); } while
(false); } while (false)
;
1384}
1385
1386bool BytecodeEmitter::isInLoop() {
1387 return findInnermostNestableControl<LoopControl>();
1388}
1389
1390bool BytecodeEmitter::checkSingletonContext() {
1391 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"
, 1391); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isTopLevelContext()"
")"); do { *((volatile int*)__null) = 1391; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
1392 return sc->treatAsRunOnce() && !isInLoop();
1393}
1394
1395bool BytecodeEmitter::needsImplicitThis() {
1396 // Short-circuit if there is an enclosing 'with' scope.
1397 if (sc->inWith()) {
1398 return true;
1399 }
1400
1401 // Otherwise see if the current point is under a 'with'.
1402 for (EmitterScope* es = innermostEmitterScope(); es;
1403 es = es->enclosingInFrame()) {
1404 if (es->scope(this).kind() == ScopeKind::With) {
1405 return true;
1406 }
1407 }
1408
1409 return false;
1410}
1411
1412size_t BytecodeEmitter::countThisEnvironmentHops() {
1413 unsigned numHops = 0;
1414
1415 for (BytecodeEmitter* current = this; current; current = current->parent) {
1416 for (EmitterScope* es = current->innermostEmitterScope(); es;
1417 es = es->enclosingInFrame()) {
1418 if (es->scope(current).is<FunctionScope>()) {
1419 if (!es->scope(current).isArrow()) {
1420 // The Parser is responsible for marking the environment as either
1421 // closed-over or used-by-eval which ensure that is must exist.
1422 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"
, 1422); AnnotateMozCrashReason("MOZ_ASSERT" "(" "es->scope(current).hasEnvironment()"
")"); do { *((volatile int*)__null) = 1422; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1423 return numHops;
1424 }
1425 }
1426 if (es->scope(current).hasEnvironment()) {
1427 numHops++;
1428 }
1429 }
1430 }
1431
1432 // The "this" environment exists outside of the compilation, but the
1433 // `ScopeContext` recorded the number of additional hops needed, so add
1434 // those in now.
1435 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"
, 1435); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->allowSuperProperty()"
")"); do { *((volatile int*)__null) = 1435; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1436 numHops += compilationState.scopeContext.enclosingThisEnvironmentHops;
1437 return numHops;
1438}
1439
1440bool BytecodeEmitter::emitThisEnvironmentCallee() {
1441 // Get the innermost enclosing function that has a |this| binding.
1442
1443 // Directly load callee from the frame if possible.
1444 if (sc->isFunctionBox() && !sc->asFunctionBox()->isArrow()) {
1445 return emit1(JSOp::Callee);
1446 }
1447
1448 // We have to load the callee from the environment chain.
1449 size_t numHops = countThisEnvironmentHops();
1450
1451 static_assert(
1452 ENVCOORD_HOPS_LIMIT - 1 <= UINT8_MAX(255),
1453 "JSOp::EnvCallee operand size should match ENVCOORD_HOPS_LIMIT");
1454
1455 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"
, 1455); AnnotateMozCrashReason("MOZ_ASSERT" "(" "numHops < ENVCOORD_HOPS_LIMIT - 1"
")"); do { *((volatile int*)__null) = 1455; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1456
1457 return emit2(JSOp::EnvCallee, numHops);
1458}
1459
1460bool BytecodeEmitter::emitSuperBase() {
1461 if (!emitThisEnvironmentCallee()) {
1462 return false;
1463 }
1464
1465 return emit1(JSOp::SuperBase);
1466}
1467
1468void BytecodeEmitter::reportError(ParseNode* pn, unsigned errorNumber, ...) {
1469 uint32_t offset = pn ? pn->pn_pos.begin : *scriptStartOffset;
1470
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
1480void BytecodeEmitter::reportError(uint32_t offset, unsigned errorNumber, ...) {
1481 va_list args;
1482 va_start(args, errorNumber)__builtin_va_start(args, errorNumber);
1483
1484 errorReporter().errorWithNotesAtVA(nullptr, AsVariant(offset), errorNumber,
1485 &args);
1486
1487 va_end(args)__builtin_va_end(args);
1488}
1489
1490bool BytecodeEmitter::addObjLiteralData(ObjLiteralWriter& writer,
1491 GCThingIndex* outIndex) {
1492 if (!writer.checkForDuplicatedNames(fc)) {
1493 return false;
1494 }
1495
1496 size_t len = writer.getCode().size();
1497 auto* code = compilationState.alloc.newArrayUninitialized<uint8_t>(len);
1498 if (!code) {
1499 js::ReportOutOfMemory(fc);
1500 return false;
1501 }
1502 memcpy(code, writer.getCode().data(), len);
1503
1504 ObjLiteralIndex objIndex(compilationState.objLiteralData.length());
1505 if (uint32_t(objIndex) >= TaggedScriptThingIndex::IndexLimit) {
1506 ReportAllocationOverflow(fc);
1507 return false;
1508 }
1509 if (!compilationState.objLiteralData.emplaceBack(code, len, writer.getKind(),
1510 writer.getFlags(),
1511 writer.getPropertyCount())) {
1512 js::ReportOutOfMemory(fc);
1513 return false;
1514 }
1515
1516 return perScriptData().gcThingList().append(objIndex, outIndex);
1517}
1518
1519bool BytecodeEmitter::emitPrepareIteratorResult() {
1520 constexpr JSOp op = JSOp::NewObject;
1521
1522 ObjLiteralWriter writer;
1523 writer.beginShape(op);
1524
1525 writer.setPropNameNoDuplicateCheck(parserAtoms(),
1526 TaggedParserAtomIndex::WellKnown::value());
1527 if (!writer.propWithUndefinedValue(fc)) {
1528 return false;
1529 }
1530 writer.setPropNameNoDuplicateCheck(parserAtoms(),
1531 TaggedParserAtomIndex::WellKnown::done());
1532 if (!writer.propWithUndefinedValue(fc)) {
1533 return false;
1534 }
1535
1536 GCThingIndex shape;
1537 if (!addObjLiteralData(writer, &shape)) {
1538 return false;
1539 }
1540
1541 return emitGCIndexOp(op, shape);
1542}
1543
1544bool BytecodeEmitter::emitFinishIteratorResult(bool done) {
1545 if (!emitAtomOp(JSOp::InitProp, TaggedParserAtomIndex::WellKnown::value())) {
1546 return false;
1547 }
1548 if (!emit1(done ? JSOp::True : JSOp::False)) {
1549 return false;
1550 }
1551 if (!emitAtomOp(JSOp::InitProp, TaggedParserAtomIndex::WellKnown::done())) {
1552 return false;
1553 }
1554 return true;
1555}
1556
1557bool BytecodeEmitter::emitGetNameAtLocation(TaggedParserAtomIndex name,
1558 const NameLocation& loc) {
1559 NameOpEmitter noe(this, name, loc, NameOpEmitter::Kind::Get);
1560 if (!noe.emitGet()) {
1561 return false;
1562 }
1563
1564 return true;
1565}
1566
1567bool BytecodeEmitter::emitGetName(NameNode* name) {
1568 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"
, 1568); AnnotateMozCrashReason("MOZ_ASSERT" "(" "name->isKind(ParseNodeKind::Name)"
")"); do { *((volatile int*)__null) = 1568; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1569
1570 return emitGetName(name->name());
1571}
1572
1573bool BytecodeEmitter::emitGetPrivateName(NameNode* name) {
1574 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"
, 1574); AnnotateMozCrashReason("MOZ_ASSERT" "(" "name->isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 1574; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1575 return emitGetPrivateName(name->name());
1576}
1577
1578bool BytecodeEmitter::emitGetPrivateName(TaggedParserAtomIndex nameAtom) {
1579 // The parser ensures the private name is present on the environment chain,
1580 // but its location can be Dynamic or Global when emitting debugger
1581 // eval-in-frame code.
1582 NameLocation location = lookupName(nameAtom);
1583 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"
, 1586); 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) = 1586; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1584 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"
, 1586); 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) = 1586; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1585 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"
, 1586); 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) = 1586; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1586 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"
, 1586); 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) = 1586; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1587
1588 return emitGetNameAtLocation(nameAtom, location);
1589}
1590
1591bool BytecodeEmitter::emitTDZCheckIfNeeded(TaggedParserAtomIndex name,
1592 const NameLocation& loc,
1593 ValueIsOnStack isOnStack) {
1594 // Dynamic accesses have TDZ checks built into their VM code and should
1595 // never emit explicit TDZ checks.
1596 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"
, 1596); AnnotateMozCrashReason("MOZ_ASSERT" "(" "loc.hasKnownSlot()"
")"); do { *((volatile int*)__null) = 1596; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1597 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"
, 1597); AnnotateMozCrashReason("MOZ_ASSERT" "(" "loc.isLexical() || loc.isPrivateMethod() || loc.isSynthetic()"
")"); do { *((volatile int*)__null) = 1597; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1598
1599 // Private names are implemented as lexical bindings, but it's just an
1600 // implementation detail. Per spec there's no TDZ check when using them.
1601 if (parserAtoms().isPrivateName(name)) {
1602 return true;
1603 }
1604
1605 Maybe<MaybeCheckTDZ> check =
1606 innermostTDZCheckCache->needsTDZCheck(this, name);
1607 if (!check) {
1608 return false;
1609 }
1610
1611 // We've already emitted a check in this basic block.
1612 if (*check == DontCheckTDZ) {
1613 return true;
1614 }
1615
1616 // If the value is not on the stack, we have to load it first.
1617 if (isOnStack == ValueIsOnStack::No) {
1618 if (loc.kind() == NameLocation::Kind::FrameSlot) {
1619 if (!emitLocalOp(JSOp::GetLocal, loc.frameSlot())) {
1620 return false;
1621 }
1622 } else {
1623 if (!emitEnvCoordOp(JSOp::GetAliasedVar, loc.environmentCoordinate())) {
1624 return false;
1625 }
1626 }
1627 }
1628
1629 // Emit the lexical check.
1630 if (loc.kind() == NameLocation::Kind::FrameSlot) {
1631 if (!emitLocalOp(JSOp::CheckLexical, loc.frameSlot())) {
1632 return false;
1633 }
1634 } else {
1635 if (!emitEnvCoordOp(JSOp::CheckAliasedLexical,
1636 loc.environmentCoordinate())) {
1637 return false;
1638 }
1639 }
1640
1641 // Pop the value if needed.
1642 if (isOnStack == ValueIsOnStack::No) {
1643 if (!emit1(JSOp::Pop)) {
1644 return false;
1645 }
1646 }
1647
1648 return innermostTDZCheckCache->noteTDZCheck(this, name, DontCheckTDZ);
1649}
1650
1651bool BytecodeEmitter::emitPropLHS(PropertyAccess* prop) {
1652 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"
, 1652); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!prop->isSuper()"
")"); do { *((volatile int*)__null) = 1652; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1653
1654 ParseNode* expr = &prop->expression();
1655
1656 if (!expr->is<PropertyAccess>() || expr->as<PropertyAccess>().isSuper()) {
1657 // The non-optimized case.
1658 return emitTree(expr);
1659 }
1660
1661 // If the object operand is also a dotted property reference, reverse the
1662 // list linked via expression() temporarily so we can iterate over it from
1663 // the bottom up (reversing again as we go), to avoid excessive recursion.
1664 PropertyAccess* pndot = &expr->as<PropertyAccess>();
1665 ParseNode* pnup = nullptr;
1666 ParseNode* pndown;
1667 for (;;) {
1668 // Reverse pndot->expression() to point up, not down.
1669 pndown = &pndot->expression();
1670 pndot->setExpression(pnup);
1671 if (!pndown->is<PropertyAccess>() ||
1672 pndown->as<PropertyAccess>().isSuper()) {
1673 break;
1674 }
1675 pnup = pndot;
1676 pndot = &pndown->as<PropertyAccess>();
1677 }
1678
1679 // pndown is a primary expression, not a dotted property reference.
1680 if (!emitTree(pndown)) {
1681 return false;
1682 }
1683
1684 while (true) {
1685 // Walk back up the list, emitting annotated name ops.
1686 if (!emitAtomOp(JSOp::GetProp, pndot->key().atom())) {
1687 return false;
1688 }
1689
1690 // Reverse the pndot->expression() link again.
1691 pnup = pndot->maybeExpression();
1692 pndot->setExpression(pndown);
1693 pndown = pndot;
1694 if (!pnup) {
1695 break;
1696 }
1697 pndot = &pnup->as<PropertyAccess>();
1698 }
1699 return true;
1700}
1701
1702bool BytecodeEmitter::emitPropIncDec(UnaryNode* incDec, ValueUsage valueUsage) {
1703 PropertyAccess* prop = &incDec->kid()->as<PropertyAccess>();
1704 bool isSuper = prop->isSuper();
1705 ParseNodeKind kind = incDec->getKind();
1706 PropOpEmitter poe(
1707 this,
1708 kind == ParseNodeKind::PostIncrementExpr
1709 ? PropOpEmitter::Kind::PostIncrement
1710 : kind == ParseNodeKind::PreIncrementExpr
1711 ? PropOpEmitter::Kind::PreIncrement
1712 : kind == ParseNodeKind::PostDecrementExpr
1713 ? PropOpEmitter::Kind::PostDecrement
1714 : PropOpEmitter::Kind::PreDecrement,
1715 isSuper ? PropOpEmitter::ObjKind::Super : PropOpEmitter::ObjKind::Other);
1716 if (!poe.prepareForObj()) {
1717 return false;
1718 }
1719 if (isSuper) {
1720 UnaryNode* base = &prop->expression().as<UnaryNode>();
1721 if (!emitGetThisForSuperBase(base)) {
1722 // [stack] THIS
1723 return false;
1724 }
1725 } else {
1726 if (!emitPropLHS(prop)) {
1727 // [stack] OBJ
1728 return false;
1729 }
1730 }
1731 if (!poe.emitIncDec(prop->key().atom(), valueUsage)) {
1732 // [stack] RESULT
1733 return false;
1734 }
1735
1736 return true;
1737}
1738
1739bool BytecodeEmitter::emitNameIncDec(UnaryNode* incDec, ValueUsage valueUsage) {
1740 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"
, 1740); AnnotateMozCrashReason("MOZ_ASSERT" "(" "incDec->kid()->isKind(ParseNodeKind::Name)"
")"); do { *((volatile int*)__null) = 1740; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1741
1742 ParseNodeKind kind = incDec->getKind();
1743 NameNode* name = &incDec->kid()->as<NameNode>();
1744 NameOpEmitter noe(this, name->atom(),
1745 kind == ParseNodeKind::PostIncrementExpr
1746 ? NameOpEmitter::Kind::PostIncrement
1747 : kind == ParseNodeKind::PreIncrementExpr
1748 ? NameOpEmitter::Kind::PreIncrement
1749 : kind == ParseNodeKind::PostDecrementExpr
1750 ? NameOpEmitter::Kind::PostDecrement
1751 : NameOpEmitter::Kind::PreDecrement);
1752 if (!noe.emitIncDec(valueUsage)) {
1753 return false;
1754 }
1755
1756 return true;
1757}
1758
1759bool BytecodeEmitter::emitObjAndKey(ParseNode* exprOrSuper, ParseNode* key,
1760 ElemOpEmitter& eoe) {
1761 if (exprOrSuper->isKind(ParseNodeKind::SuperBase)) {
1762 if (!eoe.prepareForObj()) {
1763 // [stack]
1764 return false;
1765 }
1766 UnaryNode* base = &exprOrSuper->as<UnaryNode>();
1767 if (!emitGetThisForSuperBase(base)) {
1768 // [stack] THIS
1769 return false;
1770 }
1771 if (!eoe.prepareForKey()) {
1772 // [stack] THIS
1773 return false;
1774 }
1775 if (!emitTree(key)) {
1776 // [stack] THIS KEY
1777 return false;
1778 }
1779
1780 return true;
1781 }
1782
1783 if (!eoe.prepareForObj()) {
1784 // [stack]
1785 return false;
1786 }
1787 if (!emitTree(exprOrSuper)) {
1788 // [stack] OBJ
1789 return false;
1790 }
1791 if (!eoe.prepareForKey()) {
1792 // [stack] OBJ? OBJ
1793 return false;
1794 }
1795 if (!emitTree(key)) {
1796 // [stack] OBJ? OBJ KEY
1797 return false;
1798 }
1799
1800 return true;
1801}
1802
1803bool BytecodeEmitter::emitElemOpBase(JSOp op) {
1804 if (!emit1(op)) {
1805 return false;
1806 }
1807
1808 return true;
1809}
1810
1811bool BytecodeEmitter::emitElemObjAndKey(PropertyByValue* elem, bool isSuper,
1812 ElemOpEmitter& eoe) {
1813 MOZ_ASSERT(isSuper == elem->expression().isKind(ParseNodeKind::SuperBase))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(isSuper == elem->expression().isKind(ParseNodeKind
::SuperBase))>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(isSuper == elem->expression().
isKind(ParseNodeKind::SuperBase)))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("isSuper == elem->expression().isKind(ParseNodeKind::SuperBase)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1813); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isSuper == elem->expression().isKind(ParseNodeKind::SuperBase)"
")"); do { *((volatile int*)__null) = 1813; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1814 return emitObjAndKey(&elem->expression(), &elem->key(), eoe);
1815}
1816
1817static ElemOpEmitter::Kind ConvertIncDecKind(ParseNodeKind kind) {
1818 switch (kind) {
1819 case ParseNodeKind::PostIncrementExpr:
1820 return ElemOpEmitter::Kind::PostIncrement;
1821 case ParseNodeKind::PreIncrementExpr:
1822 return ElemOpEmitter::Kind::PreIncrement;
1823 case ParseNodeKind::PostDecrementExpr:
1824 return ElemOpEmitter::Kind::PostDecrement;
1825 case ParseNodeKind::PreDecrementExpr:
1826 return ElemOpEmitter::Kind::PreDecrement;
1827 default:
1828 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"
, 1828); AnnotateMozCrashReason("MOZ_CRASH(" "unexpected inc/dec node kind"
")"); do { *((volatile int*)__null) = 1828; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
1829 }
1830}
1831
1832static PrivateOpEmitter::Kind PrivateConvertIncDecKind(ParseNodeKind kind) {
1833 switch (kind) {
1834 case ParseNodeKind::PostIncrementExpr:
1835 return PrivateOpEmitter::Kind::PostIncrement;
1836 case ParseNodeKind::PreIncrementExpr:
1837 return PrivateOpEmitter::Kind::PreIncrement;
1838 case ParseNodeKind::PostDecrementExpr:
1839 return PrivateOpEmitter::Kind::PostDecrement;
1840 case ParseNodeKind::PreDecrementExpr:
1841 return PrivateOpEmitter::Kind::PreDecrement;
1842 default:
1843 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"
, 1843); AnnotateMozCrashReason("MOZ_CRASH(" "unexpected inc/dec node kind"
")"); do { *((volatile int*)__null) = 1843; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
1844 }
1845}
1846
1847bool BytecodeEmitter::emitElemIncDec(UnaryNode* incDec, ValueUsage valueUsage) {
1848 PropertyByValue* elemExpr = &incDec->kid()->as<PropertyByValue>();
1849 bool isSuper = elemExpr->isSuper();
1850 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"
, 1850); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elemExpr->key().isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 1850; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1851 ParseNodeKind kind = incDec->getKind();
1852 ElemOpEmitter eoe(
1853 this, ConvertIncDecKind(kind),
1854 isSuper ? ElemOpEmitter::ObjKind::Super : ElemOpEmitter::ObjKind::Other);
1855 if (!emitElemObjAndKey(elemExpr, isSuper, eoe)) {
1856 // [stack] # if Super
1857 // [stack] THIS KEY
1858 // [stack] # otherwise
1859 // [stack] OBJ KEY
1860 return false;
1861 }
1862 if (!eoe.emitIncDec(valueUsage)) {
1863 // [stack] RESULT
1864 return false;
1865 }
1866
1867 return true;
1868}
1869
1870bool BytecodeEmitter::emitCallIncDec(UnaryNode* incDec) {
1871 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"
, 1874); AnnotateMozCrashReason("MOZ_ASSERT" "(" "incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind(ParseNodeKind::PostDecrementExpr)"
")"); do { *((volatile int*)__null) = 1874; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1872 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"
, 1874); AnnotateMozCrashReason("MOZ_ASSERT" "(" "incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind(ParseNodeKind::PostDecrementExpr)"
")"); do { *((volatile int*)__null) = 1874; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1873 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"
, 1874); AnnotateMozCrashReason("MOZ_ASSERT" "(" "incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind(ParseNodeKind::PostDecrementExpr)"
")"); do { *((volatile int*)__null) = 1874; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1874 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"
, 1874); AnnotateMozCrashReason("MOZ_ASSERT" "(" "incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind(ParseNodeKind::PostDecrementExpr)"
")"); do { *((volatile int*)__null) = 1874; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1875
1876 ParseNode* call = incDec->kid();
1877 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"
, 1877); AnnotateMozCrashReason("MOZ_ASSERT" "(" "call->isKind(ParseNodeKind::CallExpr)"
")"); do { *((volatile int*)__null) = 1877; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1878 if (!emitTree(call)) {
1879 // [stack] CALLRESULT
1880 return false;
1881 }
1882 if (!emit1(JSOp::ToNumeric)) {
1883 // [stack] N
1884 return false;
1885 }
1886
1887 // The increment/decrement has no side effects, so proceed to throw for
1888 // invalid assignment target.
1889 return emit2(JSOp::ThrowMsg, uint8_t(ThrowMsgKind::AssignToCall));
1890}
1891
1892bool BytecodeEmitter::emitPrivateIncDec(UnaryNode* incDec,
1893 ValueUsage valueUsage) {
1894 PrivateMemberAccess* privateExpr = &incDec->kid()->as<PrivateMemberAccess>();
1895 ParseNodeKind kind = incDec->getKind();
1896 PrivateOpEmitter xoe(this, PrivateConvertIncDecKind(kind),
1897 privateExpr->privateName().name());
1898 if (!emitTree(&privateExpr->expression())) {
1899 // [stack] OBJ
1900 return false;
1901 }
1902 if (!xoe.emitReference()) {
1903 // [stack] OBJ NAME
1904 return false;
1905 }
1906 if (!xoe.emitIncDec(valueUsage)) {
1907 // [stack] RESULT
1908 return false;
1909 }
1910
1911 return true;
1912}
1913
1914bool BytecodeEmitter::emitDouble(double d) {
1915 BytecodeOffset offset;
1916 if (!emitCheck(JSOp::Double, 9, &offset)) {
1917 return false;
1918 }
1919
1920 jsbytecode* code = bytecodeSection().code(offset);
1921 code[0] = jsbytecode(JSOp::Double);
1922 SET_INLINE_VALUE(code, DoubleValue(d));
1923 bytecodeSection().updateDepth(JSOp::Double, offset);
1924 return true;
1925}
1926
1927bool BytecodeEmitter::emitNumberOp(double dval) {
1928 int32_t ival;
1929 if (NumberIsInt32(dval, &ival)) {
1930 if (ival == 0) {
1931 return emit1(JSOp::Zero);
1932 }
1933 if (ival == 1) {
1934 return emit1(JSOp::One);
1935 }
1936 if ((int)(int8_t)ival == ival) {
1937 return emit2(JSOp::Int8, uint8_t(int8_t(ival)));
1938 }
1939
1940 uint32_t u = uint32_t(ival);
1941 if (u < Bit(16)) {
1942 if (!emitUint16Operand(JSOp::Uint16, u)) {
1943 return false;
1944 }
1945 } else if (u < Bit(24)) {
1946 BytecodeOffset off;
1947 if (!emitN(JSOp::Uint24, 3, &off)) {
1948 return false;
1949 }
1950 SET_UINT24(bytecodeSection().code(off), u);
1951 } else {
1952 BytecodeOffset off;
1953 if (!emitN(JSOp::Int32, 4, &off)) {
1954 return false;
1955 }
1956 SET_INT32(bytecodeSection().code(off), ival);
1957 }
1958 return true;
1959 }
1960
1961 return emitDouble(dval);
1962}
1963
1964/*
1965 * Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047.
1966 * LLVM is deciding to inline this function which uses a lot of stack space
1967 * into emitTree which is recursive and uses relatively little stack space.
1968 */
1969MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitSwitch(SwitchStatement* switchStmt) {
1970 LexicalScopeNode& lexical = switchStmt->lexicalForCaseList();
1971 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"
, 1971); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lexical.isKind(ParseNodeKind::LexicalScope)"
")"); do { *((volatile int*)__null) = 1971; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1972 ListNode* cases = &lexical.scopeBody()->as<ListNode>();
1973 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"
, 1973); AnnotateMozCrashReason("MOZ_ASSERT" "(" "cases->isKind(ParseNodeKind::StatementList)"
")"); do { *((volatile int*)__null) = 1973; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1974
1975 SwitchEmitter se(this);
1976 if (!se.emitDiscriminant(switchStmt->discriminant().pn_pos.begin)) {
1977 return false;
1978 }
1979
1980 if (!markStepBreakpoint()) {
1981 return false;
1982 }
1983 if (!emitTree(&switchStmt->discriminant())) {
1984 return false;
1985 }
1986
1987 // Enter the scope before pushing the switch BreakableControl since all
1988 // breaks are under this scope.
1989
1990 if (!lexical.isEmptyScope()) {
1991 if (!se.emitLexical(lexical.scopeBindings())) {
1992 return false;
1993 }
1994
1995 // A switch statement may contain hoisted functions inside its
1996 // cases. The hasTopLevelFunctionDeclarations flag is propagated from the
1997 // StatementList bodies of the cases to the case list.
1998 if (cases->hasTopLevelFunctionDeclarations()) {
1999 for (ParseNode* item : cases->contents()) {
2000 CaseClause* caseClause = &item->as<CaseClause>();
2001 ListNode* statements = caseClause->statementList();
2002 if (statements->hasTopLevelFunctionDeclarations()) {
2003 if (!emitHoistedFunctionsInList(statements)) {
2004 return false;
2005 }
2006 }
2007 }
2008 }
2009 } else {
2010 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"
, 2010); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!cases->hasTopLevelFunctionDeclarations()"
")"); do { *((volatile int*)__null) = 2010; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2011 }
2012
2013 SwitchEmitter::TableGenerator tableGen(this);
2014 uint32_t caseCount = cases->count() - (switchStmt->hasDefault() ? 1 : 0);
2015 if (caseCount == 0) {
2016 tableGen.finish(0);
2017 } else {
2018 for (ParseNode* item : cases->contents()) {
2019 CaseClause* caseClause = &item->as<CaseClause>();
2020 if (caseClause->isDefault()) {
2021 continue;
2022 }
2023
2024 ParseNode* caseValue = caseClause->caseExpression();
2025
2026 if (caseValue->getKind() != ParseNodeKind::NumberExpr) {
2027 tableGen.setInvalid();
2028 break;
2029 }
2030
2031 int32_t i;
2032 if (!NumberEqualsInt32(caseValue->as<NumericLiteral>().value(), &i)) {
2033 tableGen.setInvalid();
2034 break;
2035 }
2036
2037 if (!tableGen.addNumber(i)) {
2038 return false;
2039 }
2040 }
2041
2042 tableGen.finish(caseCount);
2043 }
2044
2045 if (!se.validateCaseCount(caseCount)) {
2046 return false;
2047 }
2048
2049 bool isTableSwitch = tableGen.isValid();
2050 if (isTableSwitch) {
2051 if (!se.emitTable(tableGen)) {
2052 return false;
2053 }
2054 } else {
2055 if (!se.emitCond()) {
2056 return false;
2057 }
2058
2059 // Emit code for evaluating cases and jumping to case statements.
2060 for (ParseNode* item : cases->contents()) {
2061 CaseClause* caseClause = &item->as<CaseClause>();
2062 if (caseClause->isDefault()) {
2063 continue;
2064 }
2065
2066 if (!se.prepareForCaseValue()) {
2067 return false;
2068 }
2069
2070 ParseNode* caseValue = caseClause->caseExpression();
2071 // If the expression is a literal, suppress line number emission so
2072 // that debugging works more naturally.
2073 if (!emitTree(
2074 caseValue, ValueUsage::WantValue,
2075 caseValue->isLiteral() ? SUPPRESS_LINENOTE : EMIT_LINENOTE)) {
2076 return false;
2077 }
2078
2079 if (!se.emitCaseJump()) {
2080 return false;
2081 }
2082 }
2083 }
2084
2085 // Emit code for each case's statements.
2086 for (ParseNode* item : cases->contents()) {
2087 CaseClause* caseClause = &item->as<CaseClause>();
2088 if (caseClause->isDefault()) {
2089 if (!se.emitDefaultBody()) {
2090 return false;
2091 }
2092 } else {
2093 if (isTableSwitch) {
2094 ParseNode* caseValue = caseClause->caseExpression();
2095 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"
, 2095); AnnotateMozCrashReason("MOZ_ASSERT" "(" "caseValue->isKind(ParseNodeKind::NumberExpr)"
")"); do { *((volatile int*)__null) = 2095; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2096
2097 NumericLiteral* literal = &caseValue->as<NumericLiteral>();
2098#ifdef DEBUG1
2099 // Use NumberEqualsInt32 here because switches compare using
2100 // strict equality, which will equate -0 and +0. In contrast
2101 // NumberIsInt32 would return false for -0.
2102 int32_t v;
2103 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"
, 2103); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mozilla::NumberEqualsInt32(literal->value(), &v)"
")"); do { *((volatile int*)__null) = 2103; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2104#endif
2105 int32_t i = int32_t(literal->value());
2106
2107 if (!se.emitCaseBody(i, tableGen)) {
2108 return false;
2109 }
2110 } else {
2111 if (!se.emitCaseBody()) {
2112 return false;
2113 }
2114 }
2115 }
2116
2117 if (!emitTree(caseClause->statementList())) {
2118 return false;
2119 }
2120 }
2121
2122 if (!se.emitEnd()) {
2123 return false;
2124 }
2125
2126 return true;
2127}
2128
2129bool BytecodeEmitter::allocateResumeIndex(BytecodeOffset offset,
2130 uint32_t* resumeIndex) {
2131 static constexpr uint32_t MaxResumeIndex = BitMask(24);
2132
2133 static_assert(
2134 MaxResumeIndex < uint32_t(AbstractGeneratorObject::RESUME_INDEX_RUNNING),
2135 "resumeIndex should not include magic AbstractGeneratorObject "
2136 "resumeIndex values");
2137 static_assert(
2138 MaxResumeIndex <= INT32_MAX(2147483647) / sizeof(uintptr_t),
2139 "resumeIndex * sizeof(uintptr_t) must fit in an int32. JIT code relies "
2140 "on this when loading resume entries from BaselineScript");
2141
2142 *resumeIndex = bytecodeSection().resumeOffsetList().length();
2143 if (*resumeIndex > MaxResumeIndex) {
2144 reportError(nullptr, JSMSG_TOO_MANY_RESUME_INDEXES);
2145 return false;
2146 }
2147
2148 return bytecodeSection().resumeOffsetList().append(offset.value());
2149}
2150
2151bool BytecodeEmitter::allocateResumeIndexRange(
2152 mozilla::Span<BytecodeOffset> offsets, uint32_t* firstResumeIndex) {
2153 *firstResumeIndex = 0;
2154
2155 for (size_t i = 0, len = offsets.size(); i < len; i++) {
2156 uint32_t resumeIndex;
2157 if (!allocateResumeIndex(offsets[i], &resumeIndex)) {
2158 return false;
2159 }
2160 if (i == 0) {
2161 *firstResumeIndex = resumeIndex;
2162 }
2163 }
2164
2165 return true;
2166}
2167
2168bool BytecodeEmitter::emitYieldOp(JSOp op) {
2169 // ParseContext::Scope::setOwnStackSlotCount should check the fixed slot
2170 // for the following, and it should prevent using fixed slot if there are
2171 // too many bindings:
2172 // * generator or asyn function
2173 // * module code after top-level await
2174 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"
, 2175); AnnotateMozCrashReason("MOZ_ASSERT" "(" "innermostEmitterScopeNoCheck()->frameSlotEnd() <= ParseContext::Scope::FixedSlotLimit"
")"); do { *((volatile int*)__null) = 2175; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2175 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"
, 2175); AnnotateMozCrashReason("MOZ_ASSERT" "(" "innermostEmitterScopeNoCheck()->frameSlotEnd() <= ParseContext::Scope::FixedSlotLimit"
")"); do { *((volatile int*)__null) = 2175; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2176
2177 if (op == JSOp::FinalYieldRval) {
2178 return emit1(JSOp::FinalYieldRval);
2179 }
2180
2181 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"
, 2182); AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::InitialYield || op == JSOp::Yield || op == JSOp::Await"
")"); do { *((volatile int*)__null) = 2182; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2182 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"
, 2182); AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::InitialYield || op == JSOp::Yield || op == JSOp::Await"
")"); do { *((volatile int*)__null) = 2182; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2183
2184 BytecodeOffset off;
2185 if (!emitN(op, 3, &off)) {
2186 return false;
2187 }
2188
2189 if (op == JSOp::InitialYield || op == JSOp::Yield) {
2190 bytecodeSection().addNumYields();
2191 }
2192
2193 uint32_t resumeIndex;
2194 if (!allocateResumeIndex(bytecodeSection().offset(), &resumeIndex)) {
2195 return false;
2196 }
2197
2198 SET_RESUMEINDEX(bytecodeSection().code(off), resumeIndex);
2199
2200 BytecodeOffset unusedOffset;
2201 return emitJumpTargetOp(JSOp::AfterYield, &unusedOffset);
2202}
2203
2204bool BytecodeEmitter::emitPushResumeKind(GeneratorResumeKind kind) {
2205 return emit2(JSOp::ResumeKind, uint8_t(kind));
2206}
2207
2208bool BytecodeEmitter::emitSetThis(BinaryNode* setThisNode) {
2209 // ParseNodeKind::SetThis is used to update |this| after a super() call
2210 // in a derived class constructor.
2211
2212 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"
, 2212); AnnotateMozCrashReason("MOZ_ASSERT" "(" "setThisNode->isKind(ParseNodeKind::SetThis)"
")"); do { *((volatile int*)__null) = 2212; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2213 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"
, 2213); AnnotateMozCrashReason("MOZ_ASSERT" "(" "setThisNode->left()->isKind(ParseNodeKind::Name)"
")"); do { *((volatile int*)__null) = 2213; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2214
2215 auto name = setThisNode->left()->as<NameNode>().name();
2216
2217 // The 'this' binding is not lexical, but due to super() semantics this
2218 // initialization needs to be treated as a lexical one.
2219 NameLocation loc = lookupName(name);
2220 NameLocation lexicalLoc;
2221 if (loc.kind() == NameLocation::Kind::FrameSlot) {
2222 lexicalLoc = NameLocation::FrameSlot(BindingKind::Let, loc.frameSlot());
2223 } else if (loc.kind() == NameLocation::Kind::EnvironmentCoordinate) {
2224 EnvironmentCoordinate coord = loc.environmentCoordinate();
2225 uint8_t hops = AssertedCast<uint8_t>(coord.hops());
2226 lexicalLoc = NameLocation::EnvironmentCoordinate(BindingKind::Let, hops,
2227 coord.slot());
2228 } else {
2229 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"
, 2229); AnnotateMozCrashReason("MOZ_ASSERT" "(" "loc.kind() == NameLocation::Kind::Dynamic"
")"); do { *((volatile int*)__null) = 2229; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2230 lexicalLoc = loc;
2231 }
2232
2233 NameOpEmitter noe(this, name, lexicalLoc, NameOpEmitter::Kind::Initialize);
2234 if (!noe.prepareForRhs()) {
2235 // [stack]
2236 return false;
2237 }
2238
2239 // Emit the new |this| value.
2240 if (!emitTree(setThisNode->right())) {
2241 // [stack] NEWTHIS
2242 return false;
2243 }
2244
2245 // Get the original |this| and throw if we already initialized
2246 // it. Do *not* use the NameLocation argument, as that's the special
2247 // lexical location below to deal with super() semantics.
2248 if (!emitGetName(name)) {
2249 // [stack] NEWTHIS THIS
2250 return false;
2251 }
2252 if (!emit1(JSOp::CheckThisReinit)) {
2253 // [stack] NEWTHIS THIS
2254 return false;
2255 }
2256 if (!emit1(JSOp::Pop)) {
2257 // [stack] NEWTHIS
2258 return false;
2259 }
2260 if (!noe.emitAssignment()) {
2261 // [stack] NEWTHIS
2262 return false;
2263 }
2264
2265 if (!emitInitializeInstanceMembers(true)) {
2266 return false;
2267 }
2268
2269 return true;
2270}
2271
2272bool BytecodeEmitter::defineHoistedTopLevelFunctions(ParseNode* body) {
2273 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"
, 2273); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inPrologue()"
")"); do { *((volatile int*)__null) = 2273; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2274 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"
, 2274); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isGlobalContext() || (sc->isEvalContext() && !sc->strict())"
")"); do { *((volatile int*)__null) = 2274; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2275 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"
, 2275); AnnotateMozCrashReason("MOZ_ASSERT" "(" "body->is<LexicalScopeNode>() || body->is<ListNode>()"
")"); do { *((volatile int*)__null) = 2275; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2276
2277 if (body->is<LexicalScopeNode>()) {
2278 body = body->as<LexicalScopeNode>().scopeBody();
2279 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"
, 2279); AnnotateMozCrashReason("MOZ_ASSERT" "(" "body->is<ListNode>()"
")"); do { *((volatile int*)__null) = 2279; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2280 }
2281
2282 if (!body->as<ListNode>().hasTopLevelFunctionDeclarations()) {
2283 return true;
2284 }
2285
2286 return emitHoistedFunctionsInList(&body->as<ListNode>());
2287}
2288
2289// For Global and sloppy-Eval scripts, this performs most of the steps of the
2290// spec's [GlobalDeclarationInstantiation] and [EvalDeclarationInstantiation]
2291// operations.
2292//
2293// Note that while strict-Eval is handled in the same part of the spec, it never
2294// fails for global-redeclaration checks so those scripts initialize directly in
2295// their bytecode.
2296bool BytecodeEmitter::emitDeclarationInstantiation(ParseNode* body) {
2297 if (sc->isModuleContext()) {
2298 // ES Modules have dedicated variable and lexial environments and therefore
2299 // do not have to perform redeclaration checks. We initialize their bindings
2300 // elsewhere in bytecode.
2301 return true;
2302 }
2303
2304 if (sc->isEvalContext() && sc->strict()) {
2305 // Strict Eval has a dedicated variables (and lexical) environment and
2306 // therefore does not have to perform redeclaration checks. We initialize
2307 // their bindings elsewhere in the bytecode.
2308 return true;
2309 }
2310
2311 // If we have no variables bindings, then we are done!
2312 if (sc->isGlobalContext()) {
2313 if (!sc->asGlobalContext()->bindings) {
2314 return true;
2315 }
2316 } else {
2317 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"
, 2317); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isEvalContext()"
")"); do { *((volatile int*)__null) = 2317; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2318
2319 if (!sc->asEvalContext()->bindings) {
2320 return true;
2321 }
2322 }
2323
2324#if DEBUG1
2325 // There should be no emitted functions yet.
2326 for (const auto& thing : perScriptData().gcThingList().objects()) {
2327 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"
, 2327); AnnotateMozCrashReason("MOZ_ASSERT" "(" "thing.isEmptyGlobalScope() || thing.isScope()"
")"); do { *((volatile int*)__null) = 2327; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2328 }
2329#endif
2330
2331 // Emit the hoisted functions to gc-things list. There is no bytecode
2332 // generated yet to bind them.
2333 if (!defineHoistedTopLevelFunctions(body)) {
2334 return false;
2335 }
2336
2337 // Save the last GCThingIndex emitted. The hoisted functions are contained in
2338 // the gc-things list up until this point. This set of gc-things also contain
2339 // initial scopes (of which there must be at least one).
2340 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"
, 2340); AnnotateMozCrashReason("MOZ_ASSERT" "(" "perScriptData().gcThingList().length() > 0"
")"); do { *((volatile int*)__null) = 2340; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2341 GCThingIndex lastFun =
2342 GCThingIndex(perScriptData().gcThingList().length() - 1);
2343
2344#if DEBUG1
2345 for (const auto& thing : perScriptData().gcThingList().objects()) {
2346 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"
, 2347); AnnotateMozCrashReason("MOZ_ASSERT" "(" "thing.isEmptyGlobalScope() || thing.isScope() || thing.isFunction()"
")"); do { *((volatile int*)__null) = 2347; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2347 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"
, 2347); AnnotateMozCrashReason("MOZ_ASSERT" "(" "thing.isEmptyGlobalScope() || thing.isScope() || thing.isFunction()"
")"); do { *((volatile int*)__null) = 2347; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2348 }
2349#endif
2350
2351 // Check for declaration conflicts and initialize the bindings.
2352 // NOTE: The self-hosting top-level script should not populate the builtins
2353 // directly on the GlobalObject (and instead uses JSOp::GetIntrinsic for
2354 // lookups).
2355 if (emitterMode == BytecodeEmitter::EmitterMode::Normal) {
2356 if (!emitGCIndexOp(JSOp::GlobalOrEvalDeclInstantiation, lastFun)) {
2357 return false;
2358 }
2359 }
2360
2361 return true;
2362}
2363
2364bool BytecodeEmitter::emitScript(ParseNode* body) {
2365 setScriptStartOffsetIfUnset(body->pn_pos.begin);
2366
2367 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"
, 2367); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inPrologue()"
")"); do { *((volatile int*)__null) = 2367; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2368
2369 TDZCheckCache tdzCache(this);
2370 EmitterScope emitterScope(this);
2371 Maybe<AsyncEmitter> topLevelAwait;
2372 if (sc->isGlobalContext()) {
2373 if (!emitterScope.enterGlobal(this, sc->asGlobalContext())) {
2374 return false;
2375 }
2376 } else if (sc->isEvalContext()) {
2377 if (!emitterScope.enterEval(this, sc->asEvalContext())) {
2378 return false;
2379 }
2380 } else {
2381 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"
, 2381); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isModuleContext()"
")"); do { *((volatile int*)__null) = 2381; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2382 if (!emitterScope.enterModule(this, sc->asModuleContext())) {
2383 return false;
2384 }
2385 if (sc->asModuleContext()->isAsync()) {
2386 topLevelAwait.emplace(this);
2387 }
2388 }
2389
2390 setFunctionBodyEndPos(body->pn_pos.end);
2391
2392 bool isSloppyEval = sc->isEvalContext() && !sc->strict();
2393 if (isSloppyEval && body->is<LexicalScopeNode>() &&
2394 !body->as<LexicalScopeNode>().isEmptyScope()) {
2395 // Sloppy eval scripts may emit hoisted functions bindings with a
2396 // `JSOp::GlobalOrEvalDeclInstantiation` opcode below. If this eval needs a
2397 // top-level lexical environment, we must ensure that environment is created
2398 // before those functions are created and bound.
2399 //
2400 // This differs from the global-script case below because the global-lexical
2401 // environment exists outside the script itself. In the case of strict eval
2402 // scripts, the `emitterScope` above is already sufficient.
2403 EmitterScope lexicalEmitterScope(this);
2404 LexicalScopeNode* scope = &body->as<LexicalScopeNode>();
2405
2406 if (!lexicalEmitterScope.enterLexical(this, ScopeKind::Lexical,
2407 scope->scopeBindings())) {
2408 return false;
2409 }
2410
2411 if (!emitDeclarationInstantiation(scope->scopeBody())) {
2412 return false;
2413 }
2414
2415 switchToMain();
2416
2417 ParseNode* scopeBody = scope->scopeBody();
2418 if (!emitLexicalScopeBody(scopeBody)) {
2419 return false;
2420 }
2421
2422 if (!updateSourceCoordNotes(scopeBody->pn_pos.end)) {
2423 return false;
2424 }
2425
2426 if (!lexicalEmitterScope.leave(this)) {
2427 return false;
2428 }
2429 } else {
2430 if (!emitDeclarationInstantiation(body)) {
2431 return false;
2432 }
2433 if (topLevelAwait) {
2434 if (!topLevelAwait->prepareForModule()) {
2435 return false;
2436 }
2437 }
2438
2439 switchToMain();
2440
2441 if (topLevelAwait) {
2442 if (!topLevelAwait->prepareForBody()) {
2443 return false;
2444 }
2445 }
2446
2447 if (!emitTree(body)) {
2448 // [stack]
2449 return false;
2450 }
2451
2452 if (!updateSourceCoordNotes(body->pn_pos.end)) {
2453 return false;
2454 }
2455 }
2456
2457 if (topLevelAwait) {
2458 if (!topLevelAwait->emitEndModule()) {
2459 return false;
2460 }
2461 }
2462
2463 if (!markSimpleBreakpoint()) {
2464 return false;
2465 }
2466
2467 if (!emitReturnRval()) {
2468 return false;
2469 }
2470
2471 if (!emitterScope.leave(this)) {
2472 return false;
2473 }
2474
2475 if (!NameFunctions(fc, parserAtoms(), body)) {
2476 return false;
2477 }
2478
2479 // Create a Stencil and convert it into a JSScript.
2480 return intoScriptStencil(CompilationStencil::TopLevelIndex);
2481}
2482
2483js::UniquePtr<ImmutableScriptData>
2484BytecodeEmitter::createImmutableScriptData() {
2485 uint32_t nslots;
2486 if (!getNslots(&nslots)) {
2487 return nullptr;
2488 }
2489
2490 bool isFunction = sc->isFunctionBox();
2491 uint16_t funLength = isFunction ? sc->asFunctionBox()->length() : 0;
2492
2493 mozilla::SaturateUint8 propertyCountEstimate = propertyAdditionEstimate;
2494
2495 // Add fields to the property count estimate.
2496 if (isFunction && sc->asFunctionBox()->useMemberInitializers()) {
2497 propertyCountEstimate +=
2498 sc->asFunctionBox()->memberInitializers().numMemberInitializers;
2499 }
2500
2501 return ImmutableScriptData::new_(
2502 fc, mainOffset(), maxFixedSlots, nslots, bodyScopeIndex,
2503 bytecodeSection().numICEntries(), isFunction, funLength,
2504 propertyCountEstimate.value(), bytecodeSection().code(),
2505 bytecodeSection().notes(), bytecodeSection().resumeOffsetList().span(),
2506 bytecodeSection().scopeNoteList().span(),
2507 bytecodeSection().tryNoteList().span());
2508}
2509
2510#ifdef ENABLE_DECORATORS
2511bool BytecodeEmitter::emitCheckIsCallable() {
2512 // This emits code to check if the value at the top of the stack is
2513 // callable. The value is left on the stack.
2514 // [stack] VAL
2515 if (!emitAtomOp(JSOp::GetIntrinsic,
2516 TaggedParserAtomIndex::WellKnown::IsCallable())) {
2517 // [stack] VAL ISCALLABLE
2518 return false;
2519 }
2520 if (!emit1(JSOp::Undefined)) {
2521 // [stack] VAL ISCALLABLE UNDEFINED
2522 return false;
2523 }
2524 if (!emitDupAt(2)) {
2525 // [stack] VAL ISCALLABLE UNDEFINED VAL
2526 return false;
2527 }
2528 return emitCall(JSOp::Call, 1);
2529 // [stack] VAL ISCALLABLE_RESULT
2530}
2531#endif
2532
2533bool BytecodeEmitter::getNslots(uint32_t* nslots) {
2534 uint64_t nslots64 =
2535 maxFixedSlots + static_cast<uint64_t>(bytecodeSection().maxStackDepth());
2536 if (nslots64 > UINT32_MAX(4294967295U)) {
2537 reportError(nullptr, JSMSG_NEED_DIET, "script");
2538 return false;
2539 }
2540 *nslots = nslots64;
2541 return true;
2542}
2543
2544bool BytecodeEmitter::emitFunctionScript(FunctionNode* funNode) {
2545 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"
, 2545); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inPrologue()"
")"); do { *((volatile int*)__null) = 2545; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2546 ParamsBodyNode* paramsBody = funNode->body();
2547 FunctionBox* funbox = sc->asFunctionBox();
2548
2549 setScriptStartOffsetIfUnset(paramsBody->pn_pos.begin);
2550
2551 // [stack]
2552
2553 FunctionScriptEmitter fse(this, funbox, Some(paramsBody->pn_pos.begin),
2554 Some(paramsBody->pn_pos.end));
2555 if (!fse.prepareForParameters()) {
2556 // [stack]
2557 return false;
2558 }
2559
2560 if (!emitFunctionFormalParameters(paramsBody)) {
2561 // [stack]
2562 return false;
2563 }
2564
2565 if (!fse.prepareForBody()) {
2566 // [stack]
2567 return false;
2568 }
2569
2570 if (!emitTree(paramsBody->body())) {
2571 // [stack]
2572 return false;
2573 }
2574
2575 if (!fse.emitEndBody()) {
2576 // [stack]
2577 return false;
2578 }
2579
2580 if (funbox->index() == CompilationStencil::TopLevelIndex) {
2581 if (!NameFunctions(fc, parserAtoms(), funNode)) {
2582 return false;
2583 }
2584 }
2585
2586 return fse.intoStencil();
2587}
2588
2589bool BytecodeEmitter::emitDestructuringLHSRef(ParseNode* target,
2590 size_t* emitted) {
2591#ifdef DEBUG1
2592 int depth = bytecodeSection().stackDepth();
2593#endif
2594
2595 switch (target->getKind()) {
2596 case ParseNodeKind::Name:
2597 case ParseNodeKind::ArrayExpr:
2598 case ParseNodeKind::ObjectExpr:
2599 // No need to recurse into ParseNodeKind::Array and ParseNodeKind::Object
2600 // subpatterns here, since emitSetOrInitializeDestructuring does the
2601 // recursion when setting or initializing the value. Getting reference
2602 // doesn't recurse.
2603 *emitted = 0;
2604 break;
2605
2606 case ParseNodeKind::ArgumentsLength:
2607 case ParseNodeKind::DotExpr: {
2608 PropertyAccess* prop = &target->as<PropertyAccess>();
2609 bool isSuper = prop->isSuper();
2610 PropOpEmitter poe(this, PropOpEmitter::Kind::SimpleAssignment,
2611 isSuper ? PropOpEmitter::ObjKind::Super
2612 : PropOpEmitter::ObjKind::Other);
2613 if (!poe.prepareForObj()) {
2614 return false;
2615 }
2616 if (isSuper) {
2617 UnaryNode* base = &prop->expression().as<UnaryNode>();
2618 if (!emitGetThisForSuperBase(base)) {
2619 // [stack] THIS SUPERBASE
2620 return false;
2621 }
2622 } else {
2623 if (!emitTree(&prop->expression())) {
2624 // [stack] OBJ
2625 return false;
2626 }
2627 }
2628 if (!poe.prepareForRhs()) {
2629 // [stack] # if Super
2630 // [stack] THIS SUPERBASE
2631 // [stack] # otherwise
2632 // [stack] OBJ
2633 return false;
2634 }
2635
2636 // SUPERBASE was pushed onto THIS in poe.prepareForRhs above.
2637 *emitted = 1 + isSuper;
2638 break;
2639 }
2640
2641 case ParseNodeKind::ElemExpr: {
2642 PropertyByValue* elem = &target->as<PropertyByValue>();
2643 bool isSuper = elem->isSuper();
2644 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"
, 2644); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 2644; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2645 ElemOpEmitter eoe(this, ElemOpEmitter::Kind::SimpleAssignment,
2646 isSuper ? ElemOpEmitter::ObjKind::Super
2647 : ElemOpEmitter::ObjKind::Other);
2648 if (!emitElemObjAndKey(elem, isSuper, eoe)) {
2649 // [stack] # if Super
2650 // [stack] THIS KEY
2651 // [stack] # otherwise
2652 // [stack] OBJ KEY
2653 return false;
2654 }
2655 if (!eoe.prepareForRhs()) {
2656 // [stack] # if Super
2657 // [stack] THIS KEY SUPERBASE
2658 // [stack] # otherwise
2659 // [stack] OBJ KEY
2660 return false;
2661 }
2662
2663 // SUPERBASE was pushed onto KEY in eoe.prepareForRhs above.
2664 *emitted = 2 + isSuper;
2665 break;
2666 }
2667
2668 case ParseNodeKind::PrivateMemberExpr: {
2669 PrivateMemberAccess* privateExpr = &target->as<PrivateMemberAccess>();
2670 PrivateOpEmitter xoe(this, PrivateOpEmitter::Kind::SimpleAssignment,
2671 privateExpr->privateName().name());
2672 if (!emitTree(&privateExpr->expression())) {
2673 // [stack] OBJ
2674 return false;
2675 }
2676 if (!xoe.emitReference()) {
2677 // [stack] OBJ NAME
2678 return false;
2679 }
2680 *emitted = xoe.numReferenceSlots();
2681 break;
2682 }
2683
2684 case ParseNodeKind::CallExpr:
2685 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"
, 2688); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget "
"rejects function calls as assignment " "targets in destructuring assignments"
")"); do { *((volatile int*)__null) = 2688; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2686 "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"
, 2688); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget "
"rejects function calls as assignment " "targets in destructuring assignments"
")"); do { *((volatile int*)__null) = 2688; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2687 "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"
, 2688); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget "
"rejects function calls as assignment " "targets in destructuring assignments"
")"); do { *((volatile int*)__null) = 2688; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2688 "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"
, 2688); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget "
"rejects function calls as assignment " "targets in destructuring assignments"
")"); do { *((volatile int*)__null) = 2688; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2689 break;
2690
2691 default:
2692 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"
, 2692); AnnotateMozCrashReason("MOZ_CRASH(" "emitDestructuringLHSRef: bad lhs kind"
")"); do { *((volatile int*)__null) = 2692; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
2693 }
2694
2695 MOZ_ASSERT(bytecodeSection().stackDepth() == depth + int(*emitted))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bytecodeSection().stackDepth() == depth + int(*emitted
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(bytecodeSection().stackDepth() == depth + int(*emitted
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("bytecodeSection().stackDepth() == depth + int(*emitted)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2695); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == depth + int(*emitted)"
")"); do { *((volatile int*)__null) = 2695; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2696
2697 return true;
2698}
2699
2700bool BytecodeEmitter::emitSetOrInitializeDestructuring(
2701 ParseNode* target, DestructuringFlavor flav) {
2702 // Now emit the lvalue opcode sequence. If the lvalue is a nested
2703 // destructuring initialiser-form, call ourselves to handle it, then pop
2704 // the matched value. Otherwise emit an lvalue bytecode sequence followed
2705 // by an assignment op.
2706
2707 switch (target->getKind()) {
2708 case ParseNodeKind::ArrayExpr:
2709 case ParseNodeKind::ObjectExpr:
2710 if (!emitDestructuringOps(&target->as<ListNode>(), flav)) {
2711 return false;
2712 }
2713 // emitDestructuringOps leaves the assigned (to-be-destructured) value on
2714 // top of the stack.
2715 break;
2716
2717 case ParseNodeKind::Name: {
2718 auto name = target->as<NameNode>().name();
2719 NameLocation loc = lookupName(name);
2720 NameOpEmitter::Kind kind;
2721 switch (flav) {
2722 case DestructuringFlavor::Declaration:
2723 kind = NameOpEmitter::Kind::Initialize;
2724 break;
2725
2726 case DestructuringFlavor::Assignment:
2727 kind = NameOpEmitter::Kind::SimpleAssignment;
2728 break;
2729 }
2730
2731 NameOpEmitter noe(this, name, loc, kind);
2732 if (!noe.prepareForRhs()) {
2733 // [stack] V ENV?
2734 return false;
2735 }
2736 if (noe.emittedBindOp()) {
2737 // This is like ordinary assignment, but with one difference.
2738 //
2739 // In `a = b`, we first determine a binding for `a` (using
2740 // JSOp::BindName or JSOp::BindGName), then we evaluate `b`, then
2741 // a JSOp::SetName instruction.
2742 //
2743 // In `[a] = [b]`, per spec, `b` is evaluated first, then we
2744 // determine a binding for `a`. Then we need to do assignment--
2745 // but the operands are on the stack in the wrong order for
2746 // JSOp::SetProp, so we have to add a JSOp::Swap.
2747 //
2748 // In the cases where we are emitting a name op, emit a swap
2749 // because of this.
2750 if (!emit1(JSOp::Swap)) {
2751 // [stack] ENV V
2752 return false;
2753 }
2754 } else {
2755 // In cases of emitting a frame slot or environment slot,
2756 // nothing needs be done.
2757 }
2758 if (!noe.emitAssignment()) {
2759 // [stack] V
2760 return false;
2761 }
2762
2763 break;
2764 }
2765
2766 case ParseNodeKind::ArgumentsLength:
2767 case ParseNodeKind::DotExpr: {
2768 // The reference is already pushed by emitDestructuringLHSRef.
2769 // [stack] # if Super
2770 // [stack] THIS SUPERBASE VAL
2771 // [stack] # otherwise
2772 // [stack] OBJ VAL
2773 PropertyAccess* prop = &target->as<PropertyAccess>();
2774 bool isSuper = prop->isSuper();
2775 PropOpEmitter poe(this, PropOpEmitter::Kind::SimpleAssignment,
2776 isSuper ? PropOpEmitter::ObjKind::Super
2777 : PropOpEmitter::ObjKind::Other);
2778 if (!poe.skipObjAndRhs()) {
2779 return false;
2780 }
2781 // [stack] # VAL
2782 if (!poe.emitAssignment(prop->key().atom())) {
2783 return false;
2784 }
2785 break;
2786 }
2787
2788 case ParseNodeKind::ElemExpr: {
2789 // The reference is already pushed by emitDestructuringLHSRef.
2790 // [stack] # if Super
2791 // [stack] THIS KEY SUPERBASE VAL
2792 // [stack] # otherwise
2793 // [stack] OBJ KEY VAL
2794 PropertyByValue* elem = &target->as<PropertyByValue>();
2795 bool isSuper = elem->isSuper();
2796 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"
, 2796); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 2796; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2797 ElemOpEmitter eoe(this, ElemOpEmitter::Kind::SimpleAssignment,
2798 isSuper ? ElemOpEmitter::ObjKind::Super
2799 : ElemOpEmitter::ObjKind::Other);
2800 if (!eoe.skipObjAndKeyAndRhs()) {
2801 return false;
2802 }
2803 if (!eoe.emitAssignment()) {
2804 // [stack] VAL
2805 return false;
2806 }
2807 break;
2808 }
2809
2810 case ParseNodeKind::PrivateMemberExpr: {
2811 // The reference is already pushed by emitDestructuringLHSRef.
2812 // [stack] OBJ NAME VAL
2813 PrivateMemberAccess* privateExpr = &target->as<PrivateMemberAccess>();
2814 PrivateOpEmitter xoe(this, PrivateOpEmitter::Kind::SimpleAssignment,
2815 privateExpr->privateName().name());
2816 if (!xoe.skipReference()) {
2817 return false;
2818 }
2819 if (!xoe.emitAssignment()) {
2820 // [stack] VAL
2821 return false;
2822 }
2823 break;
2824 }
2825
2826 case ParseNodeKind::CallExpr:
2827 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"
, 2830); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget "
"rejects function calls as assignment " "targets in destructuring assignments"
")"); do { *((volatile int*)__null) = 2830; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2828 "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"
, 2830); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget "
"rejects function calls as assignment " "targets in destructuring assignments"
")"); do { *((volatile int*)__null) = 2830; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2829 "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"
, 2830); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget "
"rejects function calls as assignment " "targets in destructuring assignments"
")"); do { *((volatile int*)__null) = 2830; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2830 "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"
, 2830); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget "
"rejects function calls as assignment " "targets in destructuring assignments"
")"); do { *((volatile int*)__null) = 2830; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2831 break;
2832
2833 default:
2834 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"
, 2834); AnnotateMozCrashReason("MOZ_CRASH(" "emitSetOrInitializeDestructuring: bad lhs kind"
")"); do { *((volatile int*)__null) = 2834; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
2835 }
2836
2837 // Pop the assigned value.
2838 if (!emit1(JSOp::Pop)) {
2839 // [stack] # empty
2840 return false;
2841 }
2842
2843 return true;
2844}
2845
2846JSOp BytecodeEmitter::getIterCallOp(JSOp callOp,
2847 SelfHostedIter selfHostedIter) {
2848 if (emitterMode == BytecodeEmitter::SelfHosting) {
2849 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"
, 2849); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny"
")"); do { *((volatile int*)__null) = 2849; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2850
2851 switch (callOp) {
2852 case JSOp::Call:
2853 return JSOp::CallContent;
2854 case JSOp::CallIter:
2855 return JSOp::CallContentIter;
2856 default:
2857 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"
, 2857); AnnotateMozCrashReason("MOZ_CRASH(" "Unknown iterator call op"
")"); do { *((volatile int*)__null) = 2857; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
2858 }
2859 }
2860
2861 return callOp;
2862}
2863
2864bool BytecodeEmitter::emitIteratorNext(
2865 const Maybe<uint32_t>& callSourceCoordOffset,
2866 IteratorKind iterKind /* = IteratorKind::Sync */,
2867 SelfHostedIter selfHostedIter /* = SelfHostedIter::Deny */) {
2868 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"
, 2871); 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) = 2871; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
2869 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"
, 2871); 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) = 2871; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
2870 ".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"
, 2871); 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) = 2871; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
2871 "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"
, 2871); 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) = 2871; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
2872
2873 // [stack] ... NEXT ITER
2874 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"
, 2874); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() >= 2"
")"); do { *((volatile int*)__null) = 2874; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2875
2876 if (!emitCall(getIterCallOp(JSOp::Call, selfHostedIter), 0,
2877 callSourceCoordOffset)) {
2878 // [stack] ... RESULT
2879 return false;
2880 }
2881
2882 if (iterKind == IteratorKind::Async) {
2883 if (!emitAwaitInInnermostScope()) {
2884 // [stack] ... RESULT
2885 return false;
2886 }
2887 }
2888
2889 if (!emitCheckIsObj(CheckIsObjectKind::IteratorNext)) {
2890 // [stack] ... RESULT
2891 return false;
2892 }
2893 return true;
2894}
2895
2896bool BytecodeEmitter::emitIteratorCloseInScope(
2897 EmitterScope& currentScope,
2898 IteratorKind iterKind /* = IteratorKind::Sync */,
2899 CompletionKind completionKind /* = CompletionKind::Normal */,
2900 SelfHostedIter selfHostedIter /* = SelfHostedIter::Deny */) {
2901 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"
, 2904); 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) = 2904; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
2902 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"
, 2904); 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) = 2904; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
2903 ".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"
, 2904); 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) = 2904; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
2904 "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"
, 2904); 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) = 2904; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
2905
2906 if (iterKind == IteratorKind::Sync) {
2907 return emit2(JSOp::CloseIter, uint8_t(completionKind));
2908 }
2909
2910 // Generate inline logic corresponding to IteratorClose (ES2021 7.4.6) and
2911 // AsyncIteratorClose (ES2021 7.4.7). Steps numbers apply to both operations.
2912 //
2913 // Callers need to ensure that the iterator object is at the top of the
2914 // stack.
2915
2916 // For non-Throw completions, we emit the equivalent of:
2917 //
2918 // var returnMethod = GetMethod(iterator, "return");
2919 // if (returnMethod !== undefined) {
2920 // var innerResult = [Await] Call(returnMethod, iterator);
2921 // CheckIsObj(innerResult);
2922 // }
2923 //
2924 // Whereas for Throw completions, we emit:
2925 //
2926 // try {
2927 // var returnMethod = GetMethod(iterator, "return");
2928 // if (returnMethod !== undefined) {
2929 // [Await] Call(returnMethod, iterator);
2930 // }
2931 // } catch {}
2932
2933 Maybe<TryEmitter> tryCatch;
2934
2935 if (completionKind == CompletionKind::Throw) {
2936 tryCatch.emplace(this, TryEmitter::Kind::TryCatch,
2937 TryEmitter::ControlKind::NonSyntactic);
2938
2939 if (!tryCatch->emitTry()) {
2940 // [stack] ... ITER
2941 return false;
2942 }
2943 }
2944
2945 if (!emit1(JSOp::Dup)) {
2946 // [stack] ... ITER ITER
2947 return false;
2948 }
2949
2950 // Steps 1-2 are assertions, step 3 is implicit.
2951
2952 // Step 4.
2953 //
2954 // Get the "return" method.
2955 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::return_())) {
2956 // [stack] ... ITER RET
2957 return false;
2958 }
2959
2960 // Step 5.
2961 //
2962 // Do nothing if "return" is undefined or null.
2963 InternalIfEmitter ifReturnMethodIsDefined(this);
2964 if (!emit1(JSOp::IsNullOrUndefined)) {
2965 // [stack] ... ITER RET NULL-OR-UNDEF
2966 return false;
2967 }
2968
2969 if (!ifReturnMethodIsDefined.emitThenElse(
2970 IfEmitter::ConditionKind::Negative)) {
2971 // [stack] ... ITER RET
2972 return false;
2973 }
2974
2975 // Steps 5.c, 7.
2976 //
2977 // Call the "return" method.
2978 if (!emit1(JSOp::Swap)) {
2979 // [stack] ... RET ITER
2980 return false;
2981 }
2982
2983 if (!emitCall(getIterCallOp(JSOp::Call, selfHostedIter), 0)) {
2984 // [stack] ... RESULT
2985 return false;
2986 }
2987
2988 // 7.4.7 AsyncIteratorClose, step 5.d.
2989 if (iterKind == IteratorKind::Async) {
2990 if (completionKind != CompletionKind::Throw) {
2991 // Await clobbers rval, so save the current rval.
2992 if (!emit1(JSOp::GetRval)) {
2993 // [stack] ... RESULT RVAL
2994 return false;
2995 }
2996 if (!emit1(JSOp::Swap)) {
2997 // [stack] ... RVAL RESULT
2998 return false;
2999 }
3000 }
3001
3002 if (!emitAwaitInScope(currentScope)) {
3003 // [stack] ... RVAL? RESULT
3004 return false;
3005 }
3006
3007 if (completionKind != CompletionKind::Throw) {
3008 if (!emit1(JSOp::Swap)) {
3009 // [stack] ... RESULT RVAL
3010 return false;
3011 }
3012 if (!emit1(JSOp::SetRval)) {
3013 // [stack] ... RESULT
3014 return false;
3015 }
3016 }
3017 }
3018
3019 // Step 6 (Handled in caller).
3020
3021 // Step 8.
3022 if (completionKind != CompletionKind::Throw) {
3023 // Check that the "return" result is an object.
3024 if (!emitCheckIsObj(CheckIsObjectKind::IteratorReturn)) {
3025 // [stack] ... RESULT
3026 return false;
3027 }
3028 }
3029
3030 if (!ifReturnMethodIsDefined.emitElse()) {
3031 // [stack] ... ITER RET
3032 return false;
3033 }
3034
3035 if (!emit1(JSOp::Pop)) {
3036 // [stack] ... ITER
3037 return false;
3038 }
3039
3040 if (!ifReturnMethodIsDefined.emitEnd()) {
3041 return false;
3042 }
3043
3044 if (completionKind == CompletionKind::Throw) {
3045 if (!tryCatch->emitCatch()) {
3046 // [stack] ... ITER EXC
3047 return false;
3048 }
3049
3050 // Just ignore the exception thrown by call and await.
3051 if (!emit1(JSOp::Pop)) {
3052 // [stack] ... ITER
3053 return false;
3054 }
3055
3056 if (!tryCatch->emitEnd()) {
3057 // [stack] ... ITER
3058 return false;
3059 }
3060 }
3061
3062 // Step 9 (Handled in caller).
3063
3064 return emit1(JSOp::Pop);
3065 // [stack] ...
3066}
3067
3068template <typename InnerEmitter>
3069bool BytecodeEmitter::wrapWithDestructuringTryNote(int32_t iterDepth,
3070 InnerEmitter emitter) {
3071 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"
, 3071); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() >= iterDepth"
")"); do { *((volatile int*)__null) = 3071; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3072
3073 // Pad a nop at the beginning of the bytecode covered by the trynote so
3074 // that when unwinding environments, we may unwind to the scope
3075 // corresponding to the pc *before* the start, in case the first bytecode
3076 // emitted by |emitter| is the start of an inner scope. See comment above
3077 // UnwindEnvironmentToTryPc.
3078 if (!emit1(JSOp::TryDestructuring)) {
3079 return false;
3080 }
3081
3082 BytecodeOffset start = bytecodeSection().offset();
3083 if (!emitter(this)) {
3084 return false;
3085 }
3086 BytecodeOffset end = bytecodeSection().offset();
3087 if (start != end) {
3088 return addTryNote(TryNoteKind::Destructuring, iterDepth, start, end);
3089 }
3090 return true;
3091}
3092
3093bool BytecodeEmitter::emitDefault(ParseNode* defaultExpr, ParseNode* pattern) {
3094 // [stack] VALUE
3095
3096 DefaultEmitter de(this);
3097 if (!de.prepareForDefault()) {
3098 // [stack]
3099 return false;
3100 }
3101 if (!emitInitializer(defaultExpr, pattern)) {
3102 // [stack] DEFAULTVALUE
3103 return false;
3104 }
3105 if (!de.emitEnd()) {
3106 // [stack] VALUE/DEFAULTVALUE
3107 return false;
3108 }
3109 return true;
3110}
3111
3112bool BytecodeEmitter::emitAnonymousFunctionWithName(
3113 ParseNode* node, TaggedParserAtomIndex name) {
3114 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"
, 3114); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isDirectRHSAnonFunction()"
")"); do { *((volatile int*)__null) = 3114; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3115
3116 if (node->is<FunctionNode>()) {
3117 // Function doesn't have 'name' property at this point.
3118 // Set function's name at compile time.
3119 if (!setFunName(node->as<FunctionNode>().funbox(), name)) {
3120 return false;
3121 }
3122
3123 return emitTree(node);
3124 }
3125
3126 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"
, 3126); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->is<ClassNode>()"
")"); do { *((volatile int*)__null) = 3126; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3127
3128 return emitClass(&node->as<ClassNode>(), ClassNameKind::InferredName, name);
3129}
3130
3131bool BytecodeEmitter::emitAnonymousFunctionWithComputedName(
3132 ParseNode* node, FunctionPrefixKind prefixKind) {
3133 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"
, 3133); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isDirectRHSAnonFunction()"
")"); do { *((volatile int*)__null) = 3133; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3134
3135 if (node->is<FunctionNode>()) {
3136 if (!emitTree(node)) {
3137 // [stack] NAME FUN
3138 return false;
3139 }
3140 if (!emitDupAt(1)) {
3141 // [stack] NAME FUN NAME
3142 return false;
3143 }
3144 if (!emit2(JSOp::SetFunName, uint8_t(prefixKind))) {
3145 // [stack] NAME FUN
3146 return false;
3147 }
3148 return true;
3149 }
3150
3151 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"
, 3151); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->is<ClassNode>()"
")"); do { *((volatile int*)__null) = 3151; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3152 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"
, 3152); AnnotateMozCrashReason("MOZ_ASSERT" "(" "prefixKind == FunctionPrefixKind::None"
")"); do { *((volatile int*)__null) = 3152; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3153
3154 return emitClass(&node->as<ClassNode>(), ClassNameKind::ComputedName);
3155}
3156
3157bool BytecodeEmitter::setFunName(FunctionBox* funbox,
3158 TaggedParserAtomIndex name) {
3159 // The inferred name may already be set if this function is an interpreted
3160 // lazy function and we OOM'ed after we set the inferred name the first
3161 // time.
3162 if (funbox->hasInferredName()) {
3163 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"
, 3163); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!funbox->emitBytecode"
")"); do { *((volatile int*)__null) = 3163; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3164 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"
, 3164); AnnotateMozCrashReason("MOZ_ASSERT" "(" "funbox->displayAtom() == name"
")"); do { *((volatile int*)__null) = 3164; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3165
3166 return true;
3167 }
3168
3169 funbox->setInferredName(name);
3170 return true;
3171}
3172
3173bool BytecodeEmitter::emitInitializer(ParseNode* initializer,
3174 ParseNode* pattern) {
3175 if (initializer->isDirectRHSAnonFunction()) {
3176 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"
, 3176); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!pattern->isInParens()"
")"); do { *((volatile int*)__null) = 3176; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3177 auto name = pattern->as<NameNode>().name();
3178 if (!emitAnonymousFunctionWithName(initializer, name)) {
3179 return false;
3180 }
3181 } else {
3182 if (!emitTree(initializer)) {
3183 return false;
3184 }
3185 }
3186
3187 return true;
3188}
3189
3190bool BytecodeEmitter::emitDestructuringOpsArray(ListNode* pattern,
3191 DestructuringFlavor flav) {
3192 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"
, 3194); 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) = 3194; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
3193 "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"
, 3194); 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) = 3194; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
3194 "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"
, 3194); 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) = 3194; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
3195 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"
, 3195); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pattern->isKind(ParseNodeKind::ArrayExpr)"
")"); do { *((volatile int*)__null) = 3195; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3196 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"
, 3196); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() != 0"
")"); do { *((volatile int*)__null) = 3196; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3197
3198 // Here's pseudo code for |let [a, b, , c=y, ...d] = x;|
3199 //
3200 // Lines that are annotated "covered by trynote" mean that upon throwing
3201 // an exception, IteratorClose is called on iter only if done is false.
3202 //
3203 // let x, y;
3204 // let a, b, c, d;
3205 // let iter, next, lref, result, done, value; // stack values
3206 //
3207 // // NOTE: the fast path for this example is not applicable, because of
3208 // // the spread and the assignment |c=y|, but it is documented here for a
3209 // // simpler example, |let [a,b] = x;|
3210 // //
3211 // // if (IsOptimizableArray(x)) {
3212 // // a = x[0];
3213 // // b = x[1];
3214 // // goto end: // (skip everything below)
3215 // // }
3216 //
3217 // iter = x[Symbol.iterator]();
3218 // next = iter.next;
3219 //
3220 // // ==== emitted by loop for a ====
3221 // lref = GetReference(a); // covered by trynote
3222 //
3223 // result = Call(next, iter);
3224 // done = result.done;
3225 //
3226 // if (done)
3227 // value = undefined;
3228 // else
3229 // value = result.value;
3230 //
3231 // SetOrInitialize(lref, value); // covered by trynote
3232 //
3233 // // ==== emitted by loop for b ====
3234 // lref = GetReference(b); // covered by trynote
3235 //
3236 // if (done) {
3237 // value = undefined;
3238 // } else {
3239 // result = Call(next, iter);
3240 // done = result.done;
3241 // if (done)
3242 // value = undefined;
3243 // else
3244 // value = result.value;
3245 // }
3246 //
3247 // SetOrInitialize(lref, value); // covered by trynote
3248 //
3249 // // ==== emitted by loop for elision ====
3250 // if (done) {
3251 // value = undefined;
3252 // } else {
3253 // result = Call(next, iter);
3254 // done = result.done;
3255 // if (done)
3256 // value = undefined;
3257 // else
3258 // value = result.value;
3259 // }
3260 //
3261 // // ==== emitted by loop for c ====
3262 // lref = GetReference(c); // covered by trynote
3263 //
3264 // if (done) {
3265 // value = undefined;
3266 // } else {
3267 // result = Call(next, iter);
3268 // done = result.done;
3269 // if (done)
3270 // value = undefined;
3271 // else
3272 // value = result.value;
3273 // }
3274 //
3275 // if (value === undefined)
3276 // value = y; // covered by trynote
3277 //
3278 // SetOrInitialize(lref, value); // covered by trynote
3279 //
3280 // // ==== emitted by loop for d ====
3281 // lref = GetReference(d); // covered by trynote
3282 //
3283 // if (done)
3284 // value = [];
3285 // else
3286 // value = [...iter];
3287 //
3288 // SetOrInitialize(lref, value); // covered by trynote
3289 //
3290 // // === emitted after loop ===
3291 // if (!done)
3292 // IteratorClose(iter);
3293 //
3294 // end:
3295
3296 bool isEligibleForArrayOptimizations = true;
3297 for (ParseNode* member : pattern->contents()) {
3298 switch (member->getKind()) {
3299 case ParseNodeKind::Elision:
3300 break;
3301 case ParseNodeKind::Name: {
3302 auto name = member->as<NameNode>().name();
3303 NameLocation loc = lookupName(name);
3304 if (loc.kind() != NameLocation::Kind::ArgumentSlot &&
3305 loc.kind() != NameLocation::Kind::FrameSlot &&
3306 loc.kind() != NameLocation::Kind::EnvironmentCoordinate) {
3307 isEligibleForArrayOptimizations = false;
3308 }
3309 break;
3310 }
3311 default:
3312 // Unfortunately we can't handle any recursive destructuring,
3313 // because we can't guarantee that the recursed-into parts
3314 // won't run code which invalidates our constraints. We also
3315 // cannot handle ParseNodeKind::AssignExpr for similar reasons.
3316 isEligibleForArrayOptimizations = false;
3317 break;
3318 }
3319 if (!isEligibleForArrayOptimizations) {
3320 break;
3321 }
3322 }
3323
3324 // Use an iterator to destructure the RHS, instead of index lookup. We
3325 // must leave the *original* value on the stack.
3326 if (!emit1(JSOp::Dup)) {
3327 // [stack] ... OBJ OBJ
3328 return false;
3329 }
3330
3331 Maybe<InternalIfEmitter> ifArrayOptimizable;
3332
3333 if (isEligibleForArrayOptimizations) {
3334 ifArrayOptimizable.emplace(
3335 this, BranchEmitterBase::LexicalKind::MayContainLexicalAccessInBranch);
3336
3337 if (!emit1(JSOp::Dup)) {
3338 // [stack] OBJ OBJ
3339 return false;
3340 }
3341
3342 if (!emit1(JSOp::OptimizeGetIterator)) {
3343 // [stack] OBJ OBJ IS_OPTIMIZABLE
3344 return false;
3345 }
3346
3347 if (!ifArrayOptimizable->emitThenElse()) {
3348 // [stack] OBJ OBJ
3349 return false;
3350 }
3351
3352 if (!emitAtomOp(JSOp::GetProp,
3353 TaggedParserAtomIndex::WellKnown::length())) {
3354 // [stack] OBJ LENGTH
3355 return false;
3356 }
3357
3358 if (!emit1(JSOp::Swap)) {
3359 // [stack] LENGTH OBJ
3360 return false;
3361 }
3362
3363 uint32_t idx = 0;
3364 for (ParseNode* member : pattern->contents()) {
3365 if (member->isKind(ParseNodeKind::Elision)) {
3366 idx += 1;
3367 continue;
3368 }
3369
3370 if (!emit1(JSOp::Dup)) {
3371 // [stack] LENGTH OBJ OBJ
3372 return false;
3373 }
3374
3375 if (!emitNumberOp(idx)) {
3376 // [stack] LENGTH OBJ OBJ IDX
3377 return false;
3378 }
3379
3380 if (!emit1(JSOp::Dup)) {
3381 // [stack] LENGTH OBJ OBJ IDX IDX
3382 return false;
3383 }
3384
3385 if (!emitDupAt(4)) {
3386 // [stack] LENGTH OBJ OBJ IDX IDX LENGTH
3387 return false;
3388 }
3389
3390 if (!emit1(JSOp::Lt)) {
3391 // [stack] LENGTH OBJ OBJ IDX IS_IN_DENSE_BOUNDS
3392 return false;
3393 }
3394
3395 InternalIfEmitter isInDenseBounds(this);
3396 if (!isInDenseBounds.emitThenElse()) {
3397 // [stack] LENGTH OBJ OBJ IDX
3398 return false;
3399 }
3400
3401 if (!emit1(JSOp::GetElem)) {
3402 // [stack] LENGTH OBJ VALUE
3403 return false;
3404 }
3405
3406 if (!isInDenseBounds.emitElse()) {
3407 // [stack] LENGTH OBJ OBJ IDX
3408 return false;
3409 }
3410
3411 if (!emitPopN(2)) {
3412 // [stack] LENGTH OBJ
3413 return false;
3414 }
3415
3416 if (!emit1(JSOp::Undefined)) {
3417 // [stack] LENGTH OBJ UNDEFINED
3418 return false;
3419 }
3420
3421 if (!isInDenseBounds.emitEnd()) {
3422 // [stack] LENGTH OBJ VALUE|UNDEFINED
3423 return false;
3424 }
3425
3426 if (!emitSetOrInitializeDestructuring(member, flav)) {
3427 // [stack] LENGTH OBJ
3428 return false;
3429 }
3430
3431 idx += 1;
3432 }
3433
3434 if (!emit1(JSOp::Swap)) {
3435 // [stack] OBJ LENGTH
3436 return false;
3437 }
3438
3439 if (!emit1(JSOp::Pop)) {
3440 // [stack] OBJ
3441 return false;
3442 }
3443
3444 if (!ifArrayOptimizable->emitElse()) {
3445 // [stack] OBJ OBJ
3446 return false;
3447 }
3448 }
3449
3450 if (!emitIterator(SelfHostedIter::Deny)) {
3451 // [stack] ... OBJ NEXT ITER
3452 return false;
3453 }
3454
3455 // For an empty pattern [], call IteratorClose unconditionally. Nothing
3456 // else needs to be done.
3457 if (!pattern->head()) {
3458 if (!emit1(JSOp::Swap)) {
3459 // [stack] ... OBJ ITER NEXT
3460 return false;
3461 }
3462 if (!emit1(JSOp::Pop)) {
3463 // [stack] ... OBJ ITER
3464 return false;
3465 }
3466
3467 if (!emitIteratorCloseInInnermostScope()) {
3468 // [stack] ... OBJ
3469 return false;
3470 }
3471
3472 if (ifArrayOptimizable.isSome()) {
3473 if (!ifArrayOptimizable->emitEnd()) {
3474 // [stack] OBJ
3475 return false;
3476 }
3477 }
3478
3479 return true;
3480 }
3481
3482 // Push an initial FALSE value for DONE.
3483 if (!emit1(JSOp::False)) {
3484 // [stack] ... OBJ NEXT ITER FALSE
3485 return false;
3486 }
3487
3488 // TryNoteKind::Destructuring expects the iterator and the done value
3489 // to be the second to top and the top of the stack, respectively.
3490 // IteratorClose is called upon exception only if done is false.
3491 int32_t tryNoteDepth = bytecodeSection().stackDepth();
3492
3493 for (ParseNode* member : pattern->contents()) {
3494 bool isFirst = member == pattern->head();
3495 DebugOnly<bool> hasNext = !!member->pn_next;
3496
3497 ParseNode* subpattern;
3498 if (member->isKind(ParseNodeKind::Spread)) {
3499 subpattern = member->as<UnaryNode>().kid();
3500
3501 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"
, 3501); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!subpattern->isKind(ParseNodeKind::AssignExpr)"
")"); do { *((volatile int*)__null) = 3501; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3502 } else {
3503 subpattern = member;
3504 }
3505
3506 ParseNode* lhsPattern = subpattern;
3507 ParseNode* pndefault = nullptr;
3508 if (subpattern->isKind(ParseNodeKind::AssignExpr)) {
3509 lhsPattern = subpattern->as<AssignmentNode>().left();
3510 pndefault = subpattern->as<AssignmentNode>().right();
3511 }
3512
3513 // Number of stack slots emitted for the LHS reference.
3514 size_t emitted = 0;
3515
3516 // Spec requires LHS reference to be evaluated first.
3517 bool isElision = lhsPattern->isKind(ParseNodeKind::Elision);
3518 if (!isElision) {
3519 auto emitLHSRef = [lhsPattern, &emitted](BytecodeEmitter* bce) {
3520 return bce->emitDestructuringLHSRef(lhsPattern, &emitted);
3521 // [stack] ... OBJ NEXT ITER DONE LREF*
3522 };
3523 if (!wrapWithDestructuringTryNote(tryNoteDepth, emitLHSRef)) {
3524 return false;
3525 }
3526 }
3527
3528 // Pick the DONE value to the top of the stack.
3529 if (emitted) {
3530 if (!emitPickN(emitted)) {
3531 // [stack] ... OBJ NEXT ITER LREF* DONE
3532 return false;
3533 }
3534 }
3535
3536 if (isFirst) {
3537 // If this element is the first, DONE is always FALSE, so pop it.
3538 //
3539 // Non-first elements should emit if-else depending on the
3540 // member pattern, below.
3541 if (!emit1(JSOp::Pop)) {
3542 // [stack] ... OBJ NEXT ITER LREF*
3543 return false;
3544 }
3545 }
3546
3547 if (member->isKind(ParseNodeKind::Spread)) {
3548 InternalIfEmitter ifThenElse(this);
3549 if (!isFirst) {
3550 // If spread is not the first element of the pattern,
3551 // iterator can already be completed.
3552 // [stack] ... OBJ NEXT ITER LREF* DONE
3553
3554 if (!ifThenElse.emitThenElse()) {
3555 // [stack] ... OBJ NEXT ITER LREF*
3556 return false;
3557 }
3558
3559 if (!emitUint32Operand(JSOp::NewArray, 0)) {
3560 // [stack] ... OBJ NEXT ITER LREF* ARRAY
3561 return false;
3562 }
3563 if (!ifThenElse.emitElse()) {
3564 // [stack] ... OBJ NEXT ITER LREF*
3565 return false;
3566 }
3567 }
3568
3569 // If iterator is not completed, create a new array with the rest
3570 // of the iterator.
3571 if (!emitDupAt(emitted + 1, 2)) {
3572 // [stack] ... OBJ NEXT ITER LREF* NEXT ITER
3573 return false;
3574 }
3575 if (!emitUint32Operand(JSOp::NewArray, 0)) {
3576 // [stack] ... OBJ NEXT ITER LREF* NEXT ITER ARRAY
3577 return false;
3578 }
3579 if (!emitNumberOp(0)) {
3580 // [stack] ... OBJ NEXT ITER LREF* NEXT ITER ARRAY INDEX
3581 return false;
3582 }
3583 if (!emitSpread(SelfHostedIter::Deny)) {
3584 // [stack] ... OBJ NEXT ITER LREF* ARRAY INDEX
3585 return false;
3586 }
3587 if (!emit1(JSOp::Pop)) {
3588 // [stack] ... OBJ NEXT ITER LREF* ARRAY
3589 return false;
3590 }
3591
3592 if (!isFirst) {
3593 if (!ifThenElse.emitEnd()) {
3594 return false;
3595 }
3596 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"
, 3596); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ifThenElse.pushed() == 1"
")"); do { *((volatile int*)__null) = 3596; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3597 }
3598
3599 // At this point the iterator is done. Unpick a TRUE value for DONE above
3600 // ITER.
3601 if (!emit1(JSOp::True)) {
3602 // [stack] ... OBJ NEXT ITER LREF* ARRAY TRUE
3603 return false;
3604 }
3605 if (!emitUnpickN(emitted + 1)) {
3606 // [stack] ... OBJ NEXT ITER TRUE LREF* ARRAY
3607 return false;
3608 }
3609
3610 auto emitAssignment = [lhsPattern, flav](BytecodeEmitter* bce) {
3611 return bce->emitSetOrInitializeDestructuring(lhsPattern, flav);
3612 // [stack] ... OBJ NEXT ITER TRUE
3613 };
3614 if (!wrapWithDestructuringTryNote(tryNoteDepth, emitAssignment)) {
3615 return false;
3616 }
3617
3618 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"
, 3618); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!hasNext" ")"
); do { *((volatile int*)__null) = 3618; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3619 break;
3620 }
3621
3622 InternalIfEmitter ifAlreadyDone(this);
3623 if (!isFirst) {
3624 // [stack] ... OBJ NEXT ITER LREF* DONE
3625
3626 if (!ifAlreadyDone.emitThenElse()) {
3627 // [stack] ... OBJ NEXT ITER LREF*
3628 return false;
3629 }
3630
3631 if (!emit1(JSOp::Undefined)) {
3632 // [stack] ... OBJ NEXT ITER LREF* UNDEF
3633 return false;
3634 }
3635 if (!emit1(JSOp::NopDestructuring)) {
3636 // [stack] ... OBJ NEXT ITER LREF* UNDEF
3637 return false;
3638 }
3639
3640 // The iterator is done. Unpick a TRUE value for DONE above ITER.
3641 if (!emit1(JSOp::True)) {
3642 // [stack] ... OBJ NEXT ITER LREF* UNDEF TRUE
3643 return false;
3644 }
3645 if (!emitUnpickN(emitted + 1)) {
3646 // [stack] ... OBJ NEXT ITER TRUE LREF* UNDEF
3647 return false;
3648 }
3649
3650 if (!ifAlreadyDone.emitElse()) {
3651 // [stack] ... OBJ NEXT ITER LREF*
3652 return false;
3653 }
3654 }
3655
3656 if (!emitDupAt(emitted + 1, 2)) {
3657 // [stack] ... OBJ NEXT ITER LREF* NEXT
3658 return false;
3659 }
3660 if (!emitIteratorNext(Some(pattern->pn_pos.begin))) {
3661 // [stack] ... OBJ NEXT ITER LREF* RESULT
3662 return false;
3663 }
3664 if (!emit1(JSOp::Dup)) {
3665 // [stack] ... OBJ NEXT ITER LREF* RESULT RESULT
3666 return false;
3667 }
3668 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::done())) {
3669 // [stack] ... OBJ NEXT ITER LREF* RESULT DONE
3670 return false;
3671 }
3672
3673 if (!emit1(JSOp::Dup)) {
3674 // [stack] ... OBJ NEXT ITER LREF* RESULT DONE DONE
3675 return false;
3676 }
3677 if (!emitUnpickN(emitted + 2)) {
3678 // [stack] ... OBJ NEXT ITER DONE LREF* RESULT DONE
3679 return false;
3680 }
3681
3682 InternalIfEmitter ifDone(this);
3683 if (!ifDone.emitThenElse()) {
3684 // [stack] ... OBJ NEXT ITER DONE LREF* RESULT
3685 return false;
3686 }
3687
3688 if (!emit1(JSOp::Pop)) {
3689 // [stack] ... OBJ NEXT ITER DONE LREF*
3690 return false;
3691 }
3692 if (!emit1(JSOp::Undefined)) {
3693 // [stack] ... OBJ NEXT ITER DONE LREF* UNDEF
3694 return false;
3695 }
3696 if (!emit1(JSOp::NopDestructuring)) {
3697 // [stack] ... OBJ NEXT ITER DONE LREF* UNDEF
3698 return false;
3699 }
3700
3701 if (!ifDone.emitElse()) {
3702 // [stack] ... OBJ NEXT ITER DONE LREF* RESULT
3703 return false;
3704 }
3705
3706 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::value())) {
3707 // [stack] ... OBJ NEXT ITER DONE LREF* VALUE
3708 return false;
3709 }
3710
3711 if (!ifDone.emitEnd()) {
3712 return false;
3713 }
3714 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"
, 3714); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ifDone.pushed() == 0"
")"); do { *((volatile int*)__null) = 3714; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3715
3716 if (!isFirst) {
3717 if (!ifAlreadyDone.emitEnd()) {
3718 return false;
3719 }
3720 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"
, 3720); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ifAlreadyDone.pushed() == 2"
")"); do { *((volatile int*)__null) = 3720; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3721 }
3722
3723 if (pndefault) {
3724 auto emitDefault = [pndefault, lhsPattern](BytecodeEmitter* bce) {
3725 return bce->emitDefault(pndefault, lhsPattern);
3726 // [stack] ... OBJ NEXT ITER DONE LREF* VALUE
3727 };
3728
3729 if (!wrapWithDestructuringTryNote(tryNoteDepth, emitDefault)) {
3730 return false;
3731 }
3732 }
3733
3734 if (!isElision) {
3735 auto emitAssignment = [lhsPattern, flav](BytecodeEmitter* bce) {
3736 return bce->emitSetOrInitializeDestructuring(lhsPattern, flav);
3737 // [stack] ... OBJ NEXT ITER DONE
3738 };
3739
3740 if (!wrapWithDestructuringTryNote(tryNoteDepth, emitAssignment)) {
3741 return false;
3742 }
3743 } else {
3744 if (!emit1(JSOp::Pop)) {
3745 // [stack] ... OBJ NEXT ITER DONE
3746 return false;
3747 }
3748 }
3749 }
3750
3751 // The last DONE value is on top of the stack. If not DONE, call
3752 // IteratorClose.
3753 // [stack] ... OBJ NEXT ITER DONE
3754
3755 InternalIfEmitter ifDone(this);
3756 if (!ifDone.emitThenElse()) {
3757 // [stack] ... OBJ NEXT ITER
3758 return false;
3759 }
3760 if (!emitPopN(2)) {
3761 // [stack] ... OBJ
3762 return false;
3763 }
3764 if (!ifDone.emitElse()) {
3765 // [stack] ... OBJ NEXT ITER
3766 return false;
3767 }
3768 if (!emit1(JSOp::Swap)) {
3769 // [stack] ... OBJ ITER NEXT
3770 return false;
3771 }
3772 if (!emit1(JSOp::Pop)) {
3773 // [stack] ... OBJ ITER
3774 return false;
3775 }
3776 if (!emitIteratorCloseInInnermostScope()) {
3777 // [stack] ... OBJ
3778 return false;
3779 }
3780 if (!ifDone.emitEnd()) {
3781 return false;
3782 }
3783
3784 if (ifArrayOptimizable.isSome()) {
3785 if (!ifArrayOptimizable->emitEnd()) {
3786 // [stack] OBJ
3787 return false;
3788 }
3789 }
3790
3791 return true;
3792}
3793
3794bool BytecodeEmitter::emitComputedPropertyName(UnaryNode* computedPropName) {
3795 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"
, 3795); AnnotateMozCrashReason("MOZ_ASSERT" "(" "computedPropName->isKind(ParseNodeKind::ComputedName)"
")"); do { *((volatile int*)__null) = 3795; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3796 return emitTree(computedPropName->kid()) && emit1(JSOp::ToPropertyKey);
3797}
3798
3799bool BytecodeEmitter::emitDestructuringOpsObject(ListNode* pattern,
3800 DestructuringFlavor flav) {
3801 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"
, 3801); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pattern->isKind(ParseNodeKind::ObjectExpr)"
")"); do { *((volatile int*)__null) = 3801; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3802
3803 // [stack] ... RHS
3804 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"
, 3804); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() > 0"
")"); do { *((volatile int*)__null) = 3804; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3805
3806 if (!emit1(JSOp::CheckObjCoercible)) {
3807 // [stack] ... RHS
3808 return false;
3809 }
3810
3811 bool needsRestPropertyExcludedSet =
3812 pattern->count() > 1 && pattern->last()->isKind(ParseNodeKind::Spread);
3813 if (needsRestPropertyExcludedSet) {
3814 if (!emitDestructuringObjRestExclusionSet(pattern)) {
3815 // [stack] ... RHS SET
3816 return false;
3817 }
3818
3819 if (!emit1(JSOp::Swap)) {
3820 // [stack] ... SET RHS
3821 return false;
3822 }
3823 }
3824
3825 for (ParseNode* member : pattern->contents()) {
3826 ParseNode* subpattern;
3827 if (member->isKind(ParseNodeKind::MutateProto) ||
3828 member->isKind(ParseNodeKind::Spread)) {
3829 subpattern = member->as<UnaryNode>().kid();
3830
3831 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"
, 3832); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!subpattern->isKind(ParseNodeKind::AssignExpr)"
")"); do { *((volatile int*)__null) = 3832; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3832 !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"
, 3832); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!subpattern->isKind(ParseNodeKind::AssignExpr)"
")"); do { *((volatile int*)__null) = 3832; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
3833 } else {
3834 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"
, 3835); AnnotateMozCrashReason("MOZ_ASSERT" "(" "member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)"
")"); do { *((volatile int*)__null) = 3835; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3835 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"
, 3835); AnnotateMozCrashReason("MOZ_ASSERT" "(" "member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)"
")"); do { *((volatile int*)__null) = 3835; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3836 subpattern = member->as<BinaryNode>().right();
3837 }
3838
3839 ParseNode* lhs = subpattern;
3840 ParseNode* pndefault = nullptr;
3841 if (subpattern->isKind(ParseNodeKind::AssignExpr)) {
3842 lhs = subpattern->as<AssignmentNode>().left();
3843 pndefault = subpattern->as<AssignmentNode>().right();
3844 }
3845
3846 // Number of stack slots emitted for the LHS reference.
3847 size_t emitted = 0;
3848
3849 // Spec requires LHS reference to be evaluated first.
3850 if (!emitDestructuringLHSRef(lhs, &emitted)) {
3851 // [stack] ... SET? RHS LREF*
3852 return false;
3853 }
3854
3855 // Duplicate the value being destructured to use as a reference base.
3856 if (!emitDupAt(emitted)) {
3857 // [stack] ... SET? RHS LREF* RHS
3858 return false;
3859 }
3860
3861 if (member->isKind(ParseNodeKind::Spread)) {
3862 if (!updateSourceCoordNotes(member->pn_pos.begin)) {
3863 return false;
3864 }
3865
3866 if (!emit1(JSOp::NewInit)) {
3867 // [stack] ... SET? RHS LREF* RHS TARGET
3868 return false;
3869 }
3870 if (!emit1(JSOp::Dup)) {
3871 // [stack] ... SET? RHS LREF* RHS TARGET TARGET
3872 return false;
3873 }
3874 if (!emit2(JSOp::Pick, 2)) {
3875 // [stack] ... SET? RHS LREF* TARGET TARGET RHS
3876 return false;
3877 }
3878
3879 if (needsRestPropertyExcludedSet) {
3880 if (!emit2(JSOp::Pick, emitted + 4)) {
3881 // [stack] ... RHS LREF* TARGET TARGET RHS SET
3882 return false;
3883 }
3884 }
3885
3886 CopyOption option = needsRestPropertyExcludedSet ? CopyOption::Filtered
3887 : CopyOption::Unfiltered;
3888 if (!emitCopyDataProperties(option)) {
3889 // [stack] ... RHS LREF* TARGET
3890 return false;
3891 }
3892
3893 // Destructure TARGET per this member's lhs.
3894 if (!emitSetOrInitializeDestructuring(lhs, flav)) {
3895 // [stack] ... RHS
3896 return false;
3897 }
3898
3899 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"
, 3899); AnnotateMozCrashReason("MOZ_ASSERT" "(" "member == pattern->last()"
") (" "Rest property is always last" ")"); do { *((volatile int
*)__null) = 3899; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
3900 break;
3901 }
3902
3903 // Now push the property value currently being matched, which is the value
3904 // of the current property name "label" on the left of a colon in the object
3905 // initialiser.
3906 if (member->isKind(ParseNodeKind::MutateProto)) {
3907 if (!emitAtomOp(JSOp::GetProp,
3908 TaggedParserAtomIndex::WellKnown::proto_())) {
3909 // [stack] ... SET? RHS LREF* PROP
3910 return false;
3911 }
3912 } else {
3913 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"
, 3914); AnnotateMozCrashReason("MOZ_ASSERT" "(" "member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)"
")"); do { *((volatile int*)__null) = 3914; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3914 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"
, 3914); AnnotateMozCrashReason("MOZ_ASSERT" "(" "member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)"
")"); do { *((volatile int*)__null) = 3914; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3915
3916 ParseNode* key = member->as<BinaryNode>().left();
3917 if (key->isKind(ParseNodeKind::ObjectPropertyName) ||
3918 key->isKind(ParseNodeKind::StringExpr)) {
3919 if (!emitAtomOp(JSOp::GetProp, key->as<NameNode>().atom())) {
3920 // [stack] ... SET? RHS LREF* PROP
3921 return false;
3922 }
3923 } else {
3924 if (key->isKind(ParseNodeKind::NumberExpr)) {
3925 if (!emitNumberOp(key->as<NumericLiteral>().value())) {
3926 // [stack]... SET? RHS LREF* RHS KEY
3927 return false;
3928 }
3929 } else {
3930 // Otherwise this is a computed property name. BigInt keys are parsed
3931 // as (synthetic) computed property names, too.
3932 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"
, 3932); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::ComputedName)"
")"); do { *((volatile int*)__null) = 3932; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3933
3934 if (!emitComputedPropertyName(&key->as<UnaryNode>())) {
3935 // [stack] ... SET? RHS LREF* RHS KEY
3936 return false;
3937 }
3938
3939 // Add the computed property key to the exclusion set.
3940 if (needsRestPropertyExcludedSet) {
3941 if (!emitDupAt(emitted + 3)) {
3942 // [stack] ... SET RHS LREF* RHS KEY SET
3943 return false;
3944 }
3945 if (!emitDupAt(1)) {
3946 // [stack] ... SET RHS LREF* RHS KEY SET KEY
3947 return false;
3948 }
3949 if (!emit1(JSOp::Undefined)) {
3950 // [stack] ... SET RHS LREF* RHS KEY SET KEY UNDEFINED
3951 return false;
3952 }
3953 if (!emit1(JSOp::InitElem)) {
3954 // [stack] ... SET RHS LREF* RHS KEY SET
3955 return false;
3956 }
3957 if (!emit1(JSOp::Pop)) {
3958 // [stack] ... SET RHS LREF* RHS KEY
3959 return false;
3960 }
3961 }
3962 }
3963
3964 // Get the property value.
3965 if (!emitElemOpBase(JSOp::GetElem)) {
3966 // [stack] ... SET? RHS LREF* PROP
3967 return false;
3968 }
3969 }
3970 }
3971
3972 if (pndefault) {
3973 if (!emitDefault(pndefault, lhs)) {
3974 // [stack] ... SET? RHS LREF* VALUE
3975 return false;
3976 }
3977 }
3978
3979 // Destructure PROP per this member's lhs.
3980 if (!emitSetOrInitializeDestructuring(lhs, flav)) {
3981 // [stack] ... SET? RHS
3982 return false;
3983 }
3984 }
3985
3986 return true;
3987}
3988
3989static bool IsDestructuringRestExclusionSetObjLiteralCompatible(
3990 ListNode* pattern) {
3991 uint32_t propCount = 0;
3992 for (ParseNode* member : pattern->contents()) {
3993 if (member->isKind(ParseNodeKind::Spread)) {
3994 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"
, 3994); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!member->pn_next"
") (" "unexpected trailing element after spread" ")"); do { *
((volatile int*)__null) = 3994; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
3995 break;
3996 }
3997
3998 propCount++;
3999
4000 if (member->isKind(ParseNodeKind::MutateProto)) {
4001 continue;
4002 }
4003
4004 ParseNode* key = member->as<BinaryNode>().left();
4005 if (key->isKind(ParseNodeKind::ObjectPropertyName) ||
4006 key->isKind(ParseNodeKind::StringExpr)) {
4007 continue;
4008 }
4009
4010 // Number and BigInt keys aren't yet supported. Computed property names need
4011 // to be added dynamically.
4012 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"
, 4014); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr) || key->isKind(ParseNodeKind::ComputedName)"
")"); do { *((volatile int*)__null) = 4014; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4013 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"
, 4014); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr) || key->isKind(ParseNodeKind::ComputedName)"
")"); do { *((volatile int*)__null) = 4014; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4014 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"
, 4014); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr) || key->isKind(ParseNodeKind::ComputedName)"
")"); do { *((volatile int*)__null) = 4014; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4015 return false;
4016 }
4017
4018 if (propCount > SharedPropMap::MaxPropsForNonDictionary) {
4019 // JSOp::NewObject cannot accept dictionary-mode objects.
4020 return false;
4021 }
4022
4023 return true;
4024}
4025
4026bool BytecodeEmitter::emitDestructuringObjRestExclusionSet(ListNode* pattern) {
4027 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"
, 4027); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pattern->isKind(ParseNodeKind::ObjectExpr)"
")"); do { *((volatile int*)__null) = 4027; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4028 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"
, 4028); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pattern->last()->isKind(ParseNodeKind::Spread)"
")"); do { *((volatile int*)__null) = 4028; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4029
4030 // See if we can use ObjLiteral to construct the exclusion set object.
4031 if (IsDestructuringRestExclusionSetObjLiteralCompatible(pattern)) {
4032 if (!emitDestructuringRestExclusionSetObjLiteral(pattern)) {
4033 // [stack] OBJ
4034 return false;
4035 }
4036 } else {
4037 // Take the slow but sure way and start off with a blank object.
4038 if (!emit1(JSOp::NewInit)) {
4039 // [stack] OBJ
4040 return false;
4041 }
4042 }
4043
4044 for (ParseNode* member : pattern->contents()) {
4045 if (member->isKind(ParseNodeKind::Spread)) {
4046 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"
, 4046); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!member->pn_next"
") (" "unexpected trailing element after spread" ")"); do { *
((volatile int*)__null) = 4046; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
4047 break;
4048 }
4049
4050 TaggedParserAtomIndex pnatom;
4051 if (member->isKind(ParseNodeKind::MutateProto)) {
4052 pnatom = TaggedParserAtomIndex::WellKnown::proto_();
4053 } else {
4054 ParseNode* key = member->as<BinaryNode>().left();
4055 if (key->isKind(ParseNodeKind::ObjectPropertyName) ||
4056 key->isKind(ParseNodeKind::StringExpr)) {
4057 pnatom = key->as<NameNode>().atom();
4058 } else if (key->isKind(ParseNodeKind::NumberExpr)) {
4059 if (!emitNumberOp(key->as<NumericLiteral>().value())) {
4060 return false;
4061 }
4062 } else {
4063 // Otherwise this is a computed property name which needs to be added
4064 // dynamically. BigInt keys are parsed as (synthetic) computed property
4065 // names, too.
4066 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"
, 4066); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::ComputedName)"
")"); do { *((volatile int*)__null) = 4066; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4067 continue;
4068 }
4069 }
4070
4071 // Initialize elements with |undefined|.
4072 if (!emit1(JSOp::Undefined)) {
4073 return false;
4074 }
4075
4076 if (!pnatom) {
4077 if (!emit1(JSOp::InitElem)) {
4078 return false;
4079 }
4080 } else {
4081 if (!emitAtomOp(JSOp::InitProp, pnatom)) {
4082 return false;
4083 }
4084 }
4085 }
4086
4087 return true;
4088}
4089
4090bool BytecodeEmitter::emitDestructuringOps(ListNode* pattern,
4091 DestructuringFlavor flav) {
4092 if (pattern->isKind(ParseNodeKind::ArrayExpr)) {
4093 return emitDestructuringOpsArray(pattern, flav);
4094 }
4095 return emitDestructuringOpsObject(pattern, flav);
4096}
4097
4098bool BytecodeEmitter::emitTemplateString(ListNode* templateString) {
4099 bool pushedString = false;
4100
4101 for (ParseNode* item : templateString->contents()) {
4102 bool isString = (item->getKind() == ParseNodeKind::StringExpr ||
4103 item->getKind() == ParseNodeKind::TemplateStringExpr);
4104
4105 // Skip empty strings. These are very common: a template string like
4106 // `${a}${b}` has three empty strings and without this optimization
4107 // we'd emit four JSOp::Add operations instead of just one.
4108 if (isString && item->as<NameNode>().atom() ==
4109 TaggedParserAtomIndex::WellKnown::empty()) {
4110 continue;
4111 }
4112
4113 if (!isString) {
4114 // We update source notes before emitting the expression
4115 if (!updateSourceCoordNotes(item->pn_pos.begin)) {
4116 return false;
4117 }
4118 }
4119
4120 if (!emitTree(item)) {
4121 return false;
4122 }
4123
4124 if (!isString) {
4125 // We need to convert the expression to a string
4126 if (!emit1(JSOp::ToString)) {
4127 return false;
4128 }
4129 }
4130
4131 if (pushedString) {
4132 // We've pushed two strings onto the stack. Add them together, leaving
4133 // just one.
4134 if (!emit1(JSOp::Add)) {
4135 return false;
4136 }
4137 } else {
4138 pushedString = true;
4139 }
4140 }
4141
4142 if (!pushedString) {
4143 // All strings were empty, this can happen for something like `${""}`.
4144 // Just push an empty string.
4145 if (!emitStringOp(JSOp::String,
4146 TaggedParserAtomIndex::WellKnown::empty())) {
4147 return false;
4148 }
4149 }
4150
4151 return true;
4152}
4153
4154bool BytecodeEmitter::emitDeclarationList(ListNode* declList) {
4155 for (ParseNode* decl : declList->contents()) {
4156 ParseNode* pattern;
4157 ParseNode* initializer;
4158 if (decl->isKind(ParseNodeKind::Name)) {
4159 pattern = decl;
4160 initializer = nullptr;
4161 } else {
4162 AssignmentNode* assignNode = &decl->as<AssignmentNode>();
4163 pattern = assignNode->left();
4164 initializer = assignNode->right();
4165 }
4166
4167 if (pattern->isKind(ParseNodeKind::Name)) {
4168 // initializer can be null here.
4169 if (!emitSingleDeclaration(declList, &pattern->as<NameNode>(),
4170 initializer)) {
4171 return false;
4172 }
4173 } else {
4174 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"
, 4175); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pattern->isKind(ParseNodeKind::ArrayExpr) || pattern->isKind(ParseNodeKind::ObjectExpr)"
")"); do { *((volatile int*)__null) = 4175; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4175 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"
, 4175); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pattern->isKind(ParseNodeKind::ArrayExpr) || pattern->isKind(ParseNodeKind::ObjectExpr)"
")"); do { *((volatile int*)__null) = 4175; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4176 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"
, 4176); AnnotateMozCrashReason("MOZ_ASSERT" "(" "initializer != nullptr"
")"); do { *((volatile int*)__null) = 4176; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4177
4178 if (!updateSourceCoordNotes(initializer->pn_pos.begin)) {
4179 return false;
4180 }
4181 if (!markStepBreakpoint()) {
4182 return false;
4183 }
4184 if (!emitTree(initializer)) {
4185 return false;
4186 }
4187
4188 if (!emitDestructuringOps(&pattern->as<ListNode>(),
4189 DestructuringFlavor::Declaration)) {
4190 return false;
4191 }
4192
4193 if (!emit1(JSOp::Pop)) {
4194 return false;
4195 }
4196 }
4197 }
4198 return true;
4199}
4200
4201bool BytecodeEmitter::emitSingleDeclaration(ListNode* declList, NameNode* decl,
4202 ParseNode* initializer) {
4203 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"
, 4203); AnnotateMozCrashReason("MOZ_ASSERT" "(" "decl->isKind(ParseNodeKind::Name)"
")"); do { *((volatile int*)__null) = 4203; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4204
4205 // Nothing to do for initializer-less 'var' declarations, as there's no TDZ.
4206 if (!initializer && declList->isKind(ParseNodeKind::VarStmt)) {
4207 return true;
4208 }
4209
4210 auto nameAtom = decl->name();
4211 NameOpEmitter noe(this, nameAtom, NameOpEmitter::Kind::Initialize);
4212 if (!noe.prepareForRhs()) {
4213 // [stack] ENV?
4214 return false;
4215 }
4216 if (!initializer) {
4217 // Lexical declarations are initialized to undefined without an
4218 // initializer.
4219 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"
, 4221); AnnotateMozCrashReason("MOZ_ASSERT" "(" "declList->isKind(ParseNodeKind::LetDecl)"
") (" "var declarations without initializers handled above, "
"and const declarations must have initializers" ")"); do { *
((volatile int*)__null) = 4221; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
4220 "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"
, 4221); AnnotateMozCrashReason("MOZ_ASSERT" "(" "declList->isKind(ParseNodeKind::LetDecl)"
") (" "var declarations without initializers handled above, "
"and const declarations must have initializers" ")"); do { *
((volatile int*)__null) = 4221; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
4221 "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"
, 4221); AnnotateMozCrashReason("MOZ_ASSERT" "(" "declList->isKind(ParseNodeKind::LetDecl)"
") (" "var declarations without initializers handled above, "
"and const declarations must have initializers" ")"); do { *
((volatile int*)__null) = 4221; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
4222 if (!emit1(JSOp::Undefined)) {
4223 // [stack] ENV? UNDEF
4224 return false;
4225 }
4226 } else {
4227 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"
, 4227); AnnotateMozCrashReason("MOZ_ASSERT" "(" "initializer"
")"); do { *((volatile int*)__null) = 4227; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4228
4229 if (!updateSourceCoordNotes(initializer->pn_pos.begin)) {
4230 return false;
4231 }
4232 if (!markStepBreakpoint()) {
4233 return false;
4234 }
4235 if (!emitInitializer(initializer, decl)) {
4236 // [stack] ENV? V
4237 return false;
4238 }
4239 }
4240 if (!noe.emitAssignment()) {
4241 // [stack] V
4242 return false;
4243 }
4244 if (!emit1(JSOp::Pop)) {
4245 // [stack]
4246 return false;
4247 }
4248
4249 return true;
4250}
4251
4252bool BytecodeEmitter::emitAssignmentRhs(
4253 ParseNode* rhs, TaggedParserAtomIndex anonFunctionName) {
4254 if (rhs->isDirectRHSAnonFunction()) {
4255 if (anonFunctionName) {
4256 return emitAnonymousFunctionWithName(rhs, anonFunctionName);
4257 }
4258 return emitAnonymousFunctionWithComputedName(rhs, FunctionPrefixKind::None);
4259 }
4260 return emitTree(rhs);
4261}
4262
4263// The RHS value to assign is already on the stack, i.e., the next enumeration
4264// value in a for-in or for-of loop. Offset is the location in the stack of the
4265// already-emitted rhs. If we emitted a JSOp::BindName or JSOp::BindGName, then
4266// the scope is on the top of the stack and we need to dig one deeper to get
4267// the right RHS value.
4268bool BytecodeEmitter::emitAssignmentRhs(uint8_t offset) {
4269 if (offset != 1) {
4270 return emitPickN(offset - 1);
4271 }
4272
4273 return true;
4274}
4275
4276static inline JSOp CompoundAssignmentParseNodeKindToJSOp(ParseNodeKind pnk) {
4277 switch (pnk) {
4278 case ParseNodeKind::InitExpr:
4279 return JSOp::Nop;
4280 case ParseNodeKind::AssignExpr:
4281 return JSOp::Nop;
4282 case ParseNodeKind::AddAssignExpr:
4283 return JSOp::Add;
4284 case ParseNodeKind::SubAssignExpr:
4285 return JSOp::Sub;
4286 case ParseNodeKind::BitOrAssignExpr:
4287 return JSOp::BitOr;
4288 case ParseNodeKind::BitXorAssignExpr:
4289 return JSOp::BitXor;
4290 case ParseNodeKind::BitAndAssignExpr:
4291 return JSOp::BitAnd;
4292 case ParseNodeKind::LshAssignExpr:
4293 return JSOp::Lsh;
4294 case ParseNodeKind::RshAssignExpr:
4295 return JSOp::Rsh;
4296 case ParseNodeKind::UrshAssignExpr:
4297 return JSOp::Ursh;
4298 case ParseNodeKind::MulAssignExpr:
4299 return JSOp::Mul;
4300 case ParseNodeKind::DivAssignExpr:
4301 return JSOp::Div;
4302 case ParseNodeKind::ModAssignExpr:
4303 return JSOp::Mod;
4304 case ParseNodeKind::PowAssignExpr:
4305 return JSOp::Pow;
4306 case ParseNodeKind::CoalesceAssignExpr:
4307 case ParseNodeKind::OrAssignExpr:
4308 case ParseNodeKind::AndAssignExpr:
4309 // Short-circuit assignment operators are handled elsewhere.
4310 [[fallthrough]];
4311 default:
4312 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"
, 4312); AnnotateMozCrashReason("MOZ_CRASH(" "unexpected compound assignment op"
")"); do { *((volatile int*)__null) = 4312; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
4313 }
4314}
4315
4316bool BytecodeEmitter::emitAssignmentOrInit(ParseNodeKind kind, ParseNode* lhs,
4317 ParseNode* rhs) {
4318 JSOp compoundOp = CompoundAssignmentParseNodeKindToJSOp(kind);
4319 bool isCompound = compoundOp != JSOp::Nop;
4320 bool isInit = kind == ParseNodeKind::InitExpr;
4321
4322 // We estimate the number of properties this could create
4323 // if used as constructor merely by counting this.foo = assignment
4324 // or init expressions;
4325 //
4326 // This currently doesn't handle this[x] = foo;
4327 if (isInit || kind == ParseNodeKind::AssignExpr) {
4328 if (lhs->isKind(ParseNodeKind::DotExpr)) {
4329 if (lhs->as<PropertyAccess>().expression().isKind(
4330 ParseNodeKind::ThisExpr)) {
4331 propertyAdditionEstimate++;
4332 }
4333 }
4334 }
4335
4336 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"
, 4338); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lhs->isKind(ParseNodeKind::DotExpr) || lhs->isKind(ParseNodeKind::ElemExpr) || lhs->isKind(ParseNodeKind::PrivateMemberExpr)"
")"); do { *((volatile int*)__null) = 4338; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4337 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"
, 4338); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lhs->isKind(ParseNodeKind::DotExpr) || lhs->isKind(ParseNodeKind::ElemExpr) || lhs->isKind(ParseNodeKind::PrivateMemberExpr)"
")"); do { *((volatile int*)__null) = 4338; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4338 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"
, 4338); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lhs->isKind(ParseNodeKind::DotExpr) || lhs->isKind(ParseNodeKind::ElemExpr) || lhs->isKind(ParseNodeKind::PrivateMemberExpr)"
")"); do { *((volatile int*)__null) = 4338; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4339
4340 // |name| is used within NameOpEmitter, so its lifetime must surpass |noe|.
4341 TaggedParserAtomIndex name;
4342
4343 Maybe<NameOpEmitter> noe;
4344 Maybe<PropOpEmitter> poe;
4345 Maybe<ElemOpEmitter> eoe;
4346 Maybe<PrivateOpEmitter> xoe;
4347
4348 // Deal with non-name assignments.
4349 uint8_t offset = 1;
4350
4351 // Purpose of anonFunctionName:
4352 //
4353 // In normal name assignments (`f = function(){}`), an anonymous function gets
4354 // an inferred name based on the left-hand side name node.
4355 //
4356 // In normal property assignments (`obj.x = function(){}`), the anonymous
4357 // function does not have a computed name, and rhs->isDirectRHSAnonFunction()
4358 // will be false (and anonFunctionName will not be used). However, in field
4359 // initializers (`class C { x = function(){} }`), field initialization is
4360 // implemented via a property or elem assignment (where we are now), and
4361 // rhs->isDirectRHSAnonFunction() is set - so we'll assign the name of the
4362 // function.
4363 TaggedParserAtomIndex anonFunctionName;
4364
4365 switch (lhs->getKind()) {
4366 case ParseNodeKind::Name: {
4367 name = lhs->as<NameNode>().name();
4368 anonFunctionName = name;
4369 noe.emplace(this, name,
4370 isCompound ? NameOpEmitter::Kind::CompoundAssignment
4371 : NameOpEmitter::Kind::SimpleAssignment);
4372 break;
4373 }
4374 case ParseNodeKind::ArgumentsLength:
4375 case ParseNodeKind::DotExpr: {
4376 PropertyAccess* prop = &lhs->as<PropertyAccess>();
4377 bool isSuper = prop->isSuper();
4378 poe.emplace(this,
4379 isCompound ? PropOpEmitter::Kind::CompoundAssignment
4380 : isInit ? PropOpEmitter::Kind::PropInit
4381 : PropOpEmitter::Kind::SimpleAssignment,
4382 isSuper ? PropOpEmitter::ObjKind::Super
4383 : PropOpEmitter::ObjKind::Other);
4384 if (!poe->prepareForObj()) {
4385 return false;
4386 }
4387 anonFunctionName = prop->name();
4388 if (isSuper) {
4389 UnaryNode* base = &prop->expression().as<UnaryNode>();
4390 if (!emitGetThisForSuperBase(base)) {
4391 // [stack] THIS SUPERBASE
4392 return false;
4393 }
4394 // SUPERBASE is pushed onto THIS later in poe->emitGet below.
4395 offset += 2;
4396 } else {
4397 if (!emitTree(&prop->expression())) {
4398 // [stack] OBJ
4399 return false;
4400 }
4401 offset += 1;
4402 }
4403 break;
4404 }
4405 case ParseNodeKind::ElemExpr: {
4406 PropertyByValue* elem = &lhs->as<PropertyByValue>();
4407 bool isSuper = elem->isSuper();
4408 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"
, 4408); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 4408; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4409 eoe.emplace(this,
4410 isCompound ? ElemOpEmitter::Kind::CompoundAssignment
4411 : isInit ? ElemOpEmitter::Kind::PropInit
4412 : ElemOpEmitter::Kind::SimpleAssignment,
4413 isSuper ? ElemOpEmitter::ObjKind::Super
4414 : ElemOpEmitter::ObjKind::Other);
4415 if (!emitElemObjAndKey(elem, isSuper, *eoe)) {
4416 // [stack] # if Super
4417 // [stack] THIS KEY
4418 // [stack] # otherwise
4419 // [stack] OBJ KEY
4420 return false;
4421 }
4422 if (isSuper) {
4423 // SUPERBASE is pushed onto KEY in eoe->emitGet below.
4424 offset += 3;
4425 } else {
4426 offset += 2;
4427 }
4428 break;
4429 }
4430 case ParseNodeKind::PrivateMemberExpr: {
4431 PrivateMemberAccess* privateExpr = &lhs->as<PrivateMemberAccess>();
4432 xoe.emplace(this,
4433 isCompound ? PrivateOpEmitter::Kind::CompoundAssignment
4434 : isInit ? PrivateOpEmitter::Kind::PropInit
4435 : PrivateOpEmitter::Kind::SimpleAssignment,
4436 privateExpr->privateName().name());
4437 if (!emitTree(&privateExpr->expression())) {
4438 // [stack] OBJ
4439 return false;
4440 }
4441 if (!xoe->emitReference()) {
4442 // [stack] OBJ KEY
4443 return false;
4444 }
4445 offset += xoe->numReferenceSlots();
4446 break;
4447 }
4448 case ParseNodeKind::ArrayExpr:
4449 case ParseNodeKind::ObjectExpr:
4450 break;
4451 case ParseNodeKind::CallExpr:
4452 if (!emitTree(lhs)) {
4453 return false;
4454 }
4455
4456 // Assignment to function calls is forbidden, but we have to make the
4457 // call first. Now we can throw.
4458 if (!emit2(JSOp::ThrowMsg, uint8_t(ThrowMsgKind::AssignToCall))) {
4459 return false;
4460 }
4461
4462 // Rebalance the stack to placate stack-depth assertions.
4463 if (!emit1(JSOp::Pop)) {
4464 return false;
4465 }
4466 break;
4467 default:
4468 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"
, 4468); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0" ")"); do
{ *((volatile int*)__null) = 4468; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
4469 }
4470
4471 if (isCompound) {
4472 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"
, 4472); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rhs" ")"); do
{ *((volatile int*)__null) = 4472; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
4473 switch (lhs->getKind()) {
4474 case ParseNodeKind::ArgumentsLength:
4475 case ParseNodeKind::DotExpr: {
4476 PropertyAccess* prop = &lhs->as<PropertyAccess>();
4477 if (!poe->emitGet(prop->key().atom())) {
4478 // [stack] # if Super
4479 // [stack] THIS SUPERBASE PROP
4480 // [stack] # otherwise
4481 // [stack] OBJ PROP
4482 return false;
4483 }
4484 break;
4485 }
4486 case ParseNodeKind::ElemExpr: {
4487 if (!eoe->emitGet()) {
4488 // [stack] KEY THIS OBJ ELEM
4489 return false;
4490 }
4491 break;
4492 }
4493 case ParseNodeKind::PrivateMemberExpr: {
4494 if (!xoe->emitGet()) {
4495 // [stack] OBJ KEY VALUE
4496 return false;
4497 }
4498 break;
4499 }
4500 case ParseNodeKind::CallExpr:
4501 // We just emitted a JSOp::ThrowMsg and popped the call's return
4502 // value. Push a random value to make sure the stack depth is
4503 // correct.
4504 if (!emit1(JSOp::Null)) {
4505 // [stack] NULL
4506 return false;
4507 }
4508 break;
4509 default:;
4510 }
4511 }
4512
4513 switch (lhs->getKind()) {
4514 case ParseNodeKind::Name:
4515 if (!noe->prepareForRhs()) {
4516 // [stack] ENV? VAL?
4517 return false;
4518 }
4519 offset += noe->emittedBindOp();
4520 break;
4521 case ParseNodeKind::ArgumentsLength:
4522 case ParseNodeKind::DotExpr:
4523 if (!poe->prepareForRhs()) {
4524 // [stack] # if Simple Assignment with Super
4525 // [stack] THIS SUPERBASE
4526 // [stack] # if Simple Assignment with other
4527 // [stack] OBJ
4528 // [stack] # if Compound Assignment with Super
4529 // [stack] THIS SUPERBASE PROP
4530 // [stack] # if Compound Assignment with other
4531 // [stack] OBJ PROP
4532 return false;
4533 }
4534 break;
4535 case ParseNodeKind::ElemExpr:
4536 if (!eoe->prepareForRhs()) {
4537 // [stack] # if Simple Assignment with Super
4538 // [stack] THIS KEY SUPERBASE
4539 // [stack] # if Simple Assignment with other
4540 // [stack] OBJ KEY
4541 // [stack] # if Compound Assignment with Super
4542 // [stack] THIS KEY SUPERBASE ELEM
4543 // [stack] # if Compound Assignment with other
4544 // [stack] OBJ KEY ELEM
4545 return false;
4546 }
4547 break;
4548 case ParseNodeKind::PrivateMemberExpr:
4549 // no stack adjustment needed
4550 break;
4551 default:
4552 break;
4553 }
4554
4555 if (rhs) {
4556 if (!emitAssignmentRhs(rhs, anonFunctionName)) {
4557 // [stack] ... VAL? RHS
4558 return false;
4559 }
4560 } else {
4561 // Assumption: Things with pre-emitted RHS values never need to be named.
4562 if (!emitAssignmentRhs(offset)) {
4563 // [stack] ... VAL? RHS
4564 return false;
4565 }
4566 }
4567
4568 /* If += etc., emit the binary operator with a hint for the decompiler. */
4569 if (isCompound) {
4570 if (!emit1(compoundOp)) {
4571 // [stack] ... VAL
4572 return false;
4573 }
4574 if (!emit1(JSOp::NopIsAssignOp)) {
4575 // [stack] ... VAL
4576 return false;
4577 }
4578 }
4579
4580 /* Finally, emit the specialized assignment bytecode. */
4581 switch (lhs->getKind()) {
4582 case ParseNodeKind::Name: {
4583 if (!noe->emitAssignment()) {
4584 // [stack] VAL
4585 return false;
4586 }
4587 break;
4588 }
4589 case ParseNodeKind::ArgumentsLength:
4590 case ParseNodeKind::DotExpr: {
4591 PropertyAccess* prop = &lhs->as<PropertyAccess>();
4592 if (!poe->emitAssignment(prop->key().atom())) {
4593 // [stack] VAL
4594 return false;
4595 }
4596 break;
4597 }
4598 case ParseNodeKind::CallExpr:
4599 // We threw above, so nothing to do here.
4600 break;
4601 case ParseNodeKind::ElemExpr: {
4602 if (!eoe->emitAssignment()) {
4603 // [stack] VAL
4604 return false;
4605 }
4606 break;
4607 }
4608 case ParseNodeKind::PrivateMemberExpr:
4609 if (!xoe->emitAssignment()) {
4610 // [stack] VAL
4611 return false;
4612 }
4613 break;
4614 case ParseNodeKind::ArrayExpr:
4615 case ParseNodeKind::ObjectExpr:
4616 if (!emitDestructuringOps(&lhs->as<ListNode>(),
4617 DestructuringFlavor::Assignment)) {
4618 return false;
4619 }
4620 break;
4621 default:
4622 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"
, 4622); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0" ")"); do
{ *((volatile int*)__null) = 4622; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
4623 }
4624 return true;
4625}
4626
4627bool BytecodeEmitter::emitShortCircuitAssignment(AssignmentNode* node) {
4628 TDZCheckCache tdzCache(this);
4629
4630 JSOp op;
4631 switch (node->getKind()) {
4632 case ParseNodeKind::CoalesceAssignExpr:
4633 op = JSOp::Coalesce;
4634 break;
4635 case ParseNodeKind::OrAssignExpr:
4636 op = JSOp::Or;
4637 break;
4638 case ParseNodeKind::AndAssignExpr:
4639 op = JSOp::And;
4640 break;
4641 default:
4642 MOZ_CRASH("Unexpected ParseNodeKind")do { do { } while (false); MOZ_ReportCrash("" "Unexpected ParseNodeKind"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4642); AnnotateMozCrashReason("MOZ_CRASH(" "Unexpected ParseNodeKind"
")"); do { *((volatile int*)__null) = 4642; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
4643 }
4644
4645 ParseNode* lhs = node->left();
4646 ParseNode* rhs = node->right();
4647
4648 // |name| is used within NameOpEmitter, so its lifetime must surpass |noe|.
4649 TaggedParserAtomIndex name;
4650
4651 // Select the appropriate emitter based on the left-hand side.
4652 Maybe<NameOpEmitter> noe;
4653 Maybe<PropOpEmitter> poe;
4654 Maybe<ElemOpEmitter> eoe;
4655 Maybe<PrivateOpEmitter> xoe;
4656
4657 int32_t depth = bytecodeSection().stackDepth();
4658
4659 // Number of values pushed onto the stack in addition to the lhs value.
4660 int32_t numPushed;
4661
4662 // Evaluate the left-hand side expression and compute any stack values needed
4663 // for the assignment.
4664 switch (lhs->getKind()) {
4665 case ParseNodeKind::Name: {
4666 name = lhs->as<NameNode>().name();
4667 noe.emplace(this, name, NameOpEmitter::Kind::CompoundAssignment);
4668
4669 if (!noe->prepareForRhs()) {
4670 // [stack] ENV? LHS
4671 return false;
4672 }
4673
4674 numPushed = noe->emittedBindOp();
4675 break;
4676 }
4677 case ParseNodeKind::ArgumentsLength:
4678 case ParseNodeKind::DotExpr: {
4679 PropertyAccess* prop = &lhs->as<PropertyAccess>();
4680 bool isSuper = prop->isSuper();
4681
4682 poe.emplace(this, PropOpEmitter::Kind::CompoundAssignment,
4683 isSuper ? PropOpEmitter::ObjKind::Super
4684 : PropOpEmitter::ObjKind::Other);
4685
4686 if (!poe->prepareForObj()) {
4687 return false;
4688 }
4689
4690 if (isSuper) {
4691 UnaryNode* base = &prop->expression().as<UnaryNode>();
4692 if (!emitGetThisForSuperBase(base)) {
4693 // [stack] THIS SUPERBASE
4694 return false;
4695 }
4696 } else {
4697 if (!emitTree(&prop->expression())) {
4698 // [stack] OBJ
4699 return false;
4700 }
4701 }
4702
4703 if (!poe->emitGet(prop->key().atom())) {
4704 // [stack] # if Super
4705 // [stack] THIS SUPERBASE LHS
4706 // [stack] # otherwise
4707 // [stack] OBJ LHS
4708 return false;
4709 }
4710
4711 if (!poe->prepareForRhs()) {
4712 // [stack] # if Super
4713 // [stack] THIS SUPERBASE LHS
4714 // [stack] # otherwise
4715 // [stack] OBJ LHS
4716 return false;
4717 }
4718
4719 numPushed = 1 + isSuper;
4720 break;
4721 }
4722
4723 case ParseNodeKind::ElemExpr: {
4724 PropertyByValue* elem = &lhs->as<PropertyByValue>();
4725 bool isSuper = elem->isSuper();
4726 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"
, 4726); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 4726; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4727 eoe.emplace(this, ElemOpEmitter::Kind::CompoundAssignment,
4728 isSuper ? ElemOpEmitter::ObjKind::Super
4729 : ElemOpEmitter::ObjKind::Other);
4730
4731 if (!emitElemObjAndKey(elem, isSuper, *eoe)) {
4732 // [stack] # if Super
4733 // [stack] THIS KEY
4734 // [stack] # otherwise
4735 // [stack] OBJ KEY
4736 return false;
4737 }
4738
4739 if (!eoe->emitGet()) {
4740 // [stack] # if Super
4741 // [stack] THIS KEY SUPERBASE LHS
4742 // [stack] # otherwise
4743 // [stack] OBJ KEY LHS
4744 return false;
4745 }
4746
4747 if (!eoe->prepareForRhs()) {
4748 // [stack] # if Super
4749 // [stack] THIS KEY SUPERBASE LHS
4750 // [stack] # otherwise
4751 // [stack] OBJ KEY LHS
4752 return false;
4753 }
4754
4755 numPushed = 2 + isSuper;
4756 break;
4757 }
4758
4759 case ParseNodeKind::PrivateMemberExpr: {
4760 PrivateMemberAccess* privateExpr = &lhs->as<PrivateMemberAccess>();
4761 xoe.emplace(this, PrivateOpEmitter::Kind::CompoundAssignment,
4762 privateExpr->privateName().name());
4763 if (!emitTree(&privateExpr->expression())) {
4764 // [stack] OBJ
4765 return false;
4766 }
4767 if (!xoe->emitReference()) {
4768 // [stack] OBJ NAME
4769 return false;
4770 }
4771 if (!xoe->emitGet()) {
4772 // [stack] OBJ NAME LHS
4773 return false;
4774 }
4775 numPushed = xoe->numReferenceSlots();
4776 break;
4777 }
4778
4779 default:
4780 MOZ_CRASH()do { do { } while (false); MOZ_ReportCrash("" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4780); AnnotateMozCrashReason("MOZ_CRASH(" ")"); do { *((volatile
int*)__null) = 4780; __attribute__((nomerge)) ::abort(); } while
(false); } while (false)
;
4781 }
4782
4783 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"
, 4783); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == depth + numPushed + 1"
")"); do { *((volatile int*)__null) = 4783; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4784
4785 // Test for the short-circuit condition.
4786 JumpList jump;
4787 if (!emitJump(op, &jump)) {
4788 // [stack] ... LHS
4789 return false;
4790 }
4791
4792 // The short-circuit condition wasn't fulfilled, pop the left-hand side value
4793 // which was kept on the stack.
4794 if (!emit1(JSOp::Pop)) {
4795 // [stack] ...
4796 return false;
4797 }
4798
4799 if (!emitAssignmentRhs(rhs, name)) {
4800 // [stack] ... RHS
4801 return false;
4802 }
4803
4804 // Perform the actual assignment.
4805 switch (lhs->getKind()) {
4806 case ParseNodeKind::Name: {
4807 if (!noe->emitAssignment()) {
4808 // [stack] RHS
4809 return false;
4810 }
4811 break;
4812 }
4813 case ParseNodeKind::ArgumentsLength:
4814 case ParseNodeKind::DotExpr: {
4815 PropertyAccess* prop = &lhs->as<PropertyAccess>();
4816
4817 if (!poe->emitAssignment(prop->key().atom())) {
4818 // [stack] RHS
4819 return false;
4820 }
4821 break;
4822 }
4823
4824 case ParseNodeKind::ElemExpr: {
4825 if (!eoe->emitAssignment()) {
4826 // [stack] RHS
4827 return false;
4828 }
4829 break;
4830 }
4831
4832 case ParseNodeKind::PrivateMemberExpr:
4833 if (!xoe->emitAssignment()) {
4834 // [stack] RHS
4835 return false;
4836 }
4837 break;
4838
4839 default:
4840 MOZ_CRASH()do { do { } while (false); MOZ_ReportCrash("" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4840); AnnotateMozCrashReason("MOZ_CRASH(" ")"); do { *((volatile
int*)__null) = 4840; __attribute__((nomerge)) ::abort(); } while
(false); } while (false)
;
4841 }
4842
4843 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"
, 4843); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == depth + 1"
")"); do { *((volatile int*)__null) = 4843; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4844
4845 // Join with the short-circuit jump and pop anything left on the stack.
4846 if (numPushed > 0) {
4847 JumpList jumpAroundPop;
4848 if (!emitJump(JSOp::Goto, &jumpAroundPop)) {
4849 // [stack] RHS
4850 return false;
4851 }
4852
4853 if (!emitJumpTargetAndPatch(jump)) {
4854 // [stack] ... LHS
4855 return false;
4856 }
4857
4858 // Reconstruct the stack depth after the jump.
4859 bytecodeSection().setStackDepth(depth + 1 + numPushed);
4860
4861 // Move the left-hand side value to the bottom and pop the rest.
4862 if (!emitUnpickN(numPushed)) {
4863 // [stack] LHS ...
4864 return false;
4865 }
4866 if (!emitPopN(numPushed)) {
4867 // [stack] LHS
4868 return false;
4869 }
4870
4871 if (!emitJumpTargetAndPatch(jumpAroundPop)) {
4872 // [stack] LHS | RHS
4873 return false;
4874 }
4875 } else {
4876 if (!emitJumpTargetAndPatch(jump)) {
4877 // [stack] LHS | RHS
4878 return false;
4879 }
4880 }
4881
4882 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"
, 4882); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == depth + 1"
")"); do { *((volatile int*)__null) = 4882; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4883
4884 return true;
4885}
4886
4887bool BytecodeEmitter::emitCallSiteObjectArray(ObjLiteralWriter& writer,
4888 ListNode* cookedOrRaw,
4889 ParseNode* head, uint32_t count) {
4890 DebugOnly<size_t> idx = 0;
4891 for (ParseNode* pn : cookedOrRaw->contentsFrom(head)) {
4892 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"
, 4893); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->isKind(ParseNodeKind::TemplateStringExpr) || pn->isKind(ParseNodeKind::RawUndefinedExpr)"
")"); do { *((volatile int*)__null) = 4893; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4893 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"
, 4893); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->isKind(ParseNodeKind::TemplateStringExpr) || pn->isKind(ParseNodeKind::RawUndefinedExpr)"
")"); do { *((volatile int*)__null) = 4893; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4894
4895 if (!emitObjLiteralValue(writer, pn)) {
4896 return false;
4897 }
4898 idx++;
4899 }
4900 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"
, 4900); AnnotateMozCrashReason("MOZ_ASSERT" "(" "idx == count"
")"); do { *((volatile int*)__null) = 4900; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4901
4902 return true;
4903}
4904
4905bool BytecodeEmitter::emitCallSiteObject(CallSiteNode* callSiteObj) {
4906 constexpr JSOp op = JSOp::CallSiteObj;
4907
4908 // The first element of a call-site node is the raw-values list. Skip over it.
4909 ListNode* raw = callSiteObj->rawNodes();
4910 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"
, 4910); AnnotateMozCrashReason("MOZ_ASSERT" "(" "raw->isKind(ParseNodeKind::ArrayExpr)"
")"); do { *((volatile int*)__null) = 4910; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4911 ParseNode* head = callSiteObj->head()->pn_next;
4912
4913 uint32_t count = callSiteObj->count() - 1;
4914 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"
, 4914); AnnotateMozCrashReason("MOZ_ASSERT" "(" "count == raw->count()"
")"); do { *((volatile int*)__null) = 4914; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4915
4916 ObjLiteralWriter writer;
4917 writer.beginCallSiteObj(op);
4918 writer.beginDenseArrayElements();
4919
4920 // Write elements of the two arrays: the 'cooked' values followed by the
4921 // 'raw' values.
4922 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"
, 4923); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "count < (4294967295U) / 2"
") (" "Number of elements for both arrays must fit in uint32_t"
")"); do { *((volatile int*)__null) = 4923; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4923 "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"
, 4923); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "count < (4294967295U) / 2"
") (" "Number of elements for both arrays must fit in uint32_t"
")"); do { *((volatile int*)__null) = 4923; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4924 if (!emitCallSiteObjectArray(writer, callSiteObj, head, count)) {
4925 return false;
4926 }
4927 if (!emitCallSiteObjectArray(writer, raw, raw->head(), count)) {
4928 return false;
4929 }
4930
4931 GCThingIndex cookedIndex;
4932 if (!addObjLiteralData(writer, &cookedIndex)) {
4933 return false;
4934 }
4935
4936 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"
, 4936); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->hasCallSiteObj()"
")"); do { *((volatile int*)__null) = 4936; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4937
4938 return emitInternedObjectOp(cookedIndex, op);
4939}
4940
4941bool BytecodeEmitter::emitCatch(BinaryNode* catchClause) {
4942 // We must be nested under a try-finally statement.
4943 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"
, 4943); AnnotateMozCrashReason("MOZ_ASSERT" "(" "innermostNestableControl->is<TryFinallyControl>()"
")"); do { *((volatile int*)__null) = 4943; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4944
4945 ParseNode* param = catchClause->left();
4946 if (!param) {
4947 // Catch parameter was omitted; just discard the exception.
4948 if (!emit1(JSOp::Pop)) {
4949 return false;
4950 }
4951 } else {
4952 switch (param->getKind()) {
4953 case ParseNodeKind::ArrayExpr:
4954 case ParseNodeKind::ObjectExpr:
4955 if (!emitDestructuringOps(&param->as<ListNode>(),
4956 DestructuringFlavor::Declaration)) {
4957 return false;
4958 }
4959 if (!emit1(JSOp::Pop)) {
4960 return false;
4961 }
4962 break;
4963
4964 case ParseNodeKind::Name:
4965 if (!emitLexicalInitialization(&param->as<NameNode>())) {
4966 return false;
4967 }
4968 if (!emit1(JSOp::Pop)) {
4969 return false;
4970 }
4971 break;
4972
4973 default:
4974 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"
, 4974); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0" ")"); do
{ *((volatile int*)__null) = 4974; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
4975 }
4976 }
4977
4978 /* Emit the catch body. */
4979 return emitTree(catchClause->right());
4980}
4981
4982// Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See the
4983// comment on EmitSwitch.
4984MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitTry(TryNode* tryNode) {
4985 LexicalScopeNode* catchScope = tryNode->catchScope();
4986 ParseNode* finallyNode = tryNode->finallyBlock();
4987
4988 TryEmitter::Kind kind;
4989 if (catchScope) {
4990 if (finallyNode) {
4991 kind = TryEmitter::Kind::TryCatchFinally;
4992 } else {
4993 kind = TryEmitter::Kind::TryCatch;
4994 }
4995 } else {
4996 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"
, 4996); AnnotateMozCrashReason("MOZ_ASSERT" "(" "finallyNode"
")"); do { *((volatile int*)__null) = 4996; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4997 kind = TryEmitter::Kind::TryFinally;
4998 }
4999 TryEmitter tryCatch(this, kind, TryEmitter::ControlKind::Syntactic);
5000
5001 if (!tryCatch.emitTry()) {
5002 return false;
5003 }
5004
5005 if (!emitTree(tryNode->body())) {
5006 return false;
5007 }
5008
5009 // If this try has a catch block, emit it.
5010 if (catchScope) {
5011 // The emitted code for a catch block looks like:
5012 //
5013 // [pushlexicalenv] only if any local aliased
5014 // exception
5015 // setlocal 0; pop assign or possibly destructure exception
5016 // < catch block contents >
5017 // debugleaveblock
5018 // [poplexicalenv] only if any local aliased
5019 // if there is a finally block:
5020 // goto <finally>
5021 // [jump target for returning from finally]
5022 // goto <after finally>
5023 if (!tryCatch.emitCatch()) {
5024 return false;
5025 }
5026
5027 // Emit the lexical scope and catch body.
5028 if (!emitTree(catchScope)) {
5029 return false;
5030 }
5031 }
5032
5033 // Emit the finally handler, if there is one.
5034 if (finallyNode) {
5035 if (!tryCatch.emitFinally(Some(finallyNode->pn_pos.begin))) {
5036 return false;
5037 }
5038
5039 if (!emitTree(finallyNode)) {
5040 return false;
5041 }
5042 }
5043
5044 if (!tryCatch.emitEnd()) {
5045 return false;
5046 }
5047
5048 return true;
5049}
5050
5051[[nodiscard]] bool BytecodeEmitter::emitJumpToFinally(JumpList* jump,
5052 uint32_t idx) {
5053 // Push the continuation index.
5054 if (!emitNumberOp(idx)) {
5055 return false;
5056 }
5057
5058 // Push |exception_stack|.
5059 if (!emit1(JSOp::Null)) {
5060 return false;
5061 }
5062
5063 // Push |throwing|.
5064 if (!emit1(JSOp::False)) {
5065 return false;
5066 }
5067
5068 // Jump to the finally block.
5069 if (!emitJumpNoFallthrough(JSOp::Goto, jump)) {
5070 return false;
5071 }
5072
5073 return true;
5074}
5075
5076bool BytecodeEmitter::emitIf(TernaryNode* ifNode) {
5077 IfEmitter ifThenElse(this);
5078
5079 if (!ifThenElse.emitIf(Some(ifNode->kid1()->pn_pos.begin))) {
5080 return false;
5081 }
5082
5083if_again:
5084 ParseNode* testNode = ifNode->kid1();
5085 auto conditionKind = IfEmitter::ConditionKind::Positive;
5086 if (testNode->isKind(ParseNodeKind::NotExpr)) {
5087 testNode = testNode->as<UnaryNode>().kid();
5088 conditionKind = IfEmitter::ConditionKind::Negative;
5089 }
5090
5091 if (!markStepBreakpoint()) {
5092 return false;
5093 }
5094
5095 // Emit code for the condition before pushing stmtInfo.
5096 // NOTE: NotExpr of testNode may be unwrapped, and in that case the negation
5097 // is handled by conditionKind.
5098 if (!emitTree(testNode)) {
5099 return false;
5100 }
5101
5102 ParseNode* elseNode = ifNode->kid3();
5103 if (elseNode) {
5104 if (!ifThenElse.emitThenElse(conditionKind)) {
5105 return false;
5106 }
5107 } else {
5108 if (!ifThenElse.emitThen(conditionKind)) {
5109 return false;
5110 }
5111 }
5112
5113 /* Emit code for the then part. */
5114 if (!emitTree(ifNode->kid2())) {
5115 return false;
5116 }
5117
5118 if (elseNode) {
5119 if (elseNode->isKind(ParseNodeKind::IfStmt)) {
5120 ifNode = &elseNode->as<TernaryNode>();
5121
5122 if (!ifThenElse.emitElseIf(Some(ifNode->kid1()->pn_pos.begin))) {
5123 return false;
5124 }
5125
5126 goto if_again;
5127 }
5128
5129 if (!ifThenElse.emitElse()) {
5130 return false;
5131 }
5132
5133 /* Emit code for the else part. */
5134 if (!emitTree(elseNode)) {
5135 return false;
5136 }
5137 }
5138
5139 if (!ifThenElse.emitEnd()) {
5140 return false;
5141 }
5142
5143 return true;
5144}
5145
5146bool BytecodeEmitter::emitHoistedFunctionsInList(ListNode* stmtList) {
5147 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"
, 5147); AnnotateMozCrashReason("MOZ_ASSERT" "(" "stmtList->hasTopLevelFunctionDeclarations()"
")"); do { *((volatile int*)__null) = 5147; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5148
5149 // We can call this multiple times for sloppy eval scopes.
5150 if (stmtList->emittedTopLevelFunctionDeclarations()) {
5151 return true;
5152 }
5153
5154 stmtList->setEmittedTopLevelFunctionDeclarations();
5155
5156 for (ParseNode* stmt : stmtList->contents()) {
5157 ParseNode* maybeFun = stmt;
5158
5159 if (!sc->strict()) {
5160 while (maybeFun->isKind(ParseNodeKind::LabelStmt)) {
5161 maybeFun = maybeFun->as<LabeledStatement>().statement();
5162 }
5163 }
5164
5165 if (maybeFun->is<FunctionNode>() &&
5166 maybeFun->as<FunctionNode>().functionIsHoisted()) {
5167 if (!emitTree(maybeFun)) {
5168 return false;
5169 }
5170 }
5171 }
5172
5173 return true;
5174}
5175
5176bool BytecodeEmitter::emitLexicalScopeBody(
5177 ParseNode* body, EmitLineNumberNote emitLineNote /* = EMIT_LINENOTE */) {
5178 if (body->isKind(ParseNodeKind::StatementList) &&
5179 body->as<ListNode>().hasTopLevelFunctionDeclarations()) {
5180 // This block contains function statements whose definitions are
5181 // hoisted to the top of the block. Emit these as a separate pass
5182 // before the rest of the block.
5183 if (!emitHoistedFunctionsInList(&body->as<ListNode>())) {
5184 return false;
5185 }
5186 }
5187
5188 // Line notes were updated by emitLexicalScope or emitScript.
5189 return emitTree(body, ValueUsage::WantValue, emitLineNote);
5190}
5191
5192// Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See
5193// the comment on emitSwitch.
5194MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitLexicalScope(
5195 LexicalScopeNode* lexicalScope) {
5196 LexicalScopeEmitter lse(this);
5197
5198 ParseNode* body = lexicalScope->scopeBody();
5199 if (lexicalScope->isEmptyScope()) {
5200 if (!lse.emitEmptyScope()) {
5201 return false;
5202 }
5203
5204 if (!emitLexicalScopeBody(body)) {
5205 return false;
5206 }
5207
5208 if (!lse.emitEnd()) {
5209 return false;
5210 }
5211
5212 return true;
5213 }
5214
5215 // We are about to emit some bytecode for what the spec calls "declaration
5216 // instantiation". Assign these instructions to the opening `{` of the
5217 // block. (Using the location of each declaration we're instantiating is
5218 // too weird when stepping in the debugger.)
5219 if (!ParseNodeRequiresSpecialLineNumberNotes(body)) {
5220 if (!updateSourceCoordNotes(lexicalScope->pn_pos.begin)) {
5221 return false;
5222 }
5223 }
5224
5225 ScopeKind kind;
5226 if (body->isKind(ParseNodeKind::Catch)) {
5227 BinaryNode* catchNode = &body->as<BinaryNode>();
5228 kind =
5229 (!catchNode->left() || catchNode->left()->isKind(ParseNodeKind::Name))
5230 ? ScopeKind::SimpleCatch
5231 : ScopeKind::Catch;
5232 } else {
5233 kind = lexicalScope->kind();
5234 }
5235
5236 if (!lse.emitScope(kind, lexicalScope->scopeBindings())) {
5237 return false;
5238 }
5239
5240 if (body->isKind(ParseNodeKind::ForStmt)) {
5241 // for loops need to emit JSOp::FreshenLexicalEnv/JSOp::RecreateLexicalEnv
5242 // if there are lexical declarations in the head. Signal this by passing a
5243 // non-nullptr lexical scope.
5244 if (!emitFor(&body->as<ForNode>(), &lse.emitterScope())) {
5245 return false;
5246 }
5247 } else {
5248 if (!emitLexicalScopeBody(body, SUPPRESS_LINENOTE)) {
5249 return false;
5250 }
5251 }
5252
5253 if (!lse.emitEnd()) {
5254 return false;
5255 }
5256 return true;
5257}
5258
5259bool BytecodeEmitter::emitWith(BinaryNode* withNode) {
5260 // Ensure that the column of the 'with' is set properly.
5261 if (!updateSourceCoordNotes(withNode->left()->pn_pos.begin)) {
5262 return false;
5263 }
5264
5265 if (!markStepBreakpoint()) {
5266 return false;
5267 }
5268
5269 if (!emitTree(withNode->left())) {
5270 return false;
5271 }
5272
5273 EmitterScope emitterScope(this);
5274 if (!emitterScope.enterWith(this)) {
5275 return false;
5276 }
5277
5278 if (!emitTree(withNode->right())) {
5279 return