Bug Summary

File:var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp
Warning:line 821, column 3
Value stored to 'pc' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name Unified_cpp_js_src_frontend0.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/js/src/frontend -fcoverage-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/js/src/frontend -resource-dir /usr/lib/llvm-20/lib/clang/20 -include /var/lib/jenkins/workspace/firefox-scan-build/config/gcc_hidden.h -include /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D _GLIBCXX_ASSERTIONS -D DEBUG=1 -D WASM_SUPPORTS_HUGE_MEMORY -D JS_CACHEIR_SPEW -D JS_STRUCTURED_SPEW -D JS_HAS_CTYPES -D FFI_BUILDING -D EXPORT_JS_API -D MOZ_HAS_MOZGLUE -D MOZ_SUPPORT_LEAKCHECKING -I /var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/js/src/frontend -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/js/src -I /var/lib/jenkins/workspace/firefox-scan-build/js/src -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/backward -internal-isystem /usr/lib/llvm-20/lib/clang/20/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-deprecated-this-capture -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -fdeprecated-macro -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2025-01-20-090804-167946-1 -x c++ Unified_cpp_js_src_frontend0.cpp
1/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=8 sts=2 et sw=2 tw=80:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7/*
8 * JS bytecode generation.
9 */
10
11#include "frontend/BytecodeEmitter.h"
12
13#include "mozilla/Casting.h" // mozilla::AssertedCast
14#include "mozilla/DebugOnly.h" // mozilla::DebugOnly
15#include "mozilla/FloatingPoint.h" // mozilla::NumberEqualsInt32, mozilla::NumberIsInt32
16#include "mozilla/HashTable.h" // mozilla::HashSet
17#include "mozilla/Maybe.h" // mozilla::{Maybe,Nothing,Some}
18#include "mozilla/Saturate.h"
19#include "mozilla/Variant.h" // mozilla::AsVariant
20
21#include <algorithm>
22#include <iterator>
23#include <string.h>
24
25#include "jstypes.h" // JS_BIT
26
27#include "frontend/AbstractScopePtr.h" // ScopeIndex
28#include "frontend/BytecodeControlStructures.h" // NestableControl, BreakableControl, LabelControl, LoopControl, TryFinallyControl
29#include "frontend/CallOrNewEmitter.h" // CallOrNewEmitter
30#include "frontend/CForEmitter.h" // CForEmitter
31#include "frontend/DecoratorEmitter.h" // DecoratorEmitter
32#include "frontend/DefaultEmitter.h" // DefaultEmitter
33#include "frontend/DoWhileEmitter.h" // DoWhileEmitter
34#include "frontend/ElemOpEmitter.h" // ElemOpEmitter
35#include "frontend/EmitterScope.h" // EmitterScope
36#include "frontend/ExpressionStatementEmitter.h" // ExpressionStatementEmitter
37#include "frontend/ForInEmitter.h" // ForInEmitter
38#include "frontend/ForOfEmitter.h" // ForOfEmitter
39#include "frontend/FunctionEmitter.h" // FunctionEmitter, FunctionScriptEmitter, FunctionParamsEmitter
40#include "frontend/IfEmitter.h" // IfEmitter, InternalIfEmitter, CondEmitter
41#include "frontend/LabelEmitter.h" // LabelEmitter
42#include "frontend/LexicalScopeEmitter.h" // LexicalScopeEmitter
43#include "frontend/ModuleSharedContext.h" // ModuleSharedContext
44#include "frontend/NameAnalysisTypes.h" // PrivateNameKind
45#include "frontend/NameFunctions.h" // NameFunctions
46#include "frontend/NameOpEmitter.h" // NameOpEmitter
47#include "frontend/ObjectEmitter.h" // PropertyEmitter, ObjectEmitter, ClassEmitter
48#include "frontend/OptionalEmitter.h" // OptionalEmitter
49#include "frontend/ParseContext.h" // ParseContext::Scope
50#include "frontend/ParseNode.h" // ParseNodeKind, ParseNode and subclasses
51#include "frontend/Parser.h" // Parser
52#include "frontend/ParserAtom.h" // ParserAtomsTable, ParserAtom
53#include "frontend/PrivateOpEmitter.h" // PrivateOpEmitter
54#include "frontend/PropOpEmitter.h" // PropOpEmitter
55#include "frontend/SourceNotes.h" // SrcNote, SrcNoteType, SrcNoteWriter
56#include "frontend/SwitchEmitter.h" // SwitchEmitter
57#include "frontend/TaggedParserAtomIndexHasher.h" // TaggedParserAtomIndexHasher
58#include "frontend/TDZCheckCache.h" // TDZCheckCache
59#include "frontend/TryEmitter.h" // TryEmitter
60#include "frontend/UsingEmitter.h" // UsingEmitter
61#include "frontend/WhileEmitter.h" // WhileEmitter
62#include "js/ColumnNumber.h" // JS::LimitedColumnNumberOneOrigin, JS::ColumnNumberOffset
63#include "js/friend/ErrorMessages.h" // JSMSG_*
64#include "js/friend/StackLimits.h" // AutoCheckRecursionLimit
65#include "util/StringBuilder.h" // StringBuilder
66#include "vm/BytecodeUtil.h" // JOF_*, IsArgOp, IsLocalOp, SET_UINT24, SET_ICINDEX, BytecodeFallsThrough, BytecodeIsJumpTarget
67#include "vm/CompletionKind.h" // CompletionKind
68#include "vm/FunctionPrefixKind.h" // FunctionPrefixKind
69#include "vm/GeneratorObject.h" // AbstractGeneratorObject
70#include "vm/Opcodes.h" // JSOp, JSOpLength_*
71#include "vm/PropMap.h" // SharedPropMap::MaxPropsForNonDictionary
72#include "vm/Scope.h" // GetScopeDataTrailingNames
73#include "vm/SharedStencil.h" // ScopeNote
74#include "vm/ThrowMsgKind.h" // ThrowMsgKind
75#include "vm/TypeofEqOperand.h" // TypeofEqOperand
76
77using namespace js;
78using namespace js::frontend;
79
80using mozilla::AssertedCast;
81using mozilla::AsVariant;
82using mozilla::DebugOnly;
83using mozilla::Maybe;
84using mozilla::Nothing;
85using mozilla::NumberEqualsInt32;
86using mozilla::NumberIsInt32;
87using mozilla::Some;
88
89static bool ParseNodeRequiresSpecialLineNumberNotes(ParseNode* pn) {
90 // The few node types listed below are exceptions to the usual
91 // location-source-note-emitting code in BytecodeEmitter::emitTree().
92 // Single-line `while` loops and C-style `for` loops require careful
93 // handling to avoid strange stepping behavior.
94 // Functions usually shouldn't have location information (bug 1431202).
95
96 ParseNodeKind kind = pn->getKind();
97 return kind == ParseNodeKind::WhileStmt || kind == ParseNodeKind::ForStmt ||
98 kind == ParseNodeKind::Function;
99}
100
101static bool NeedsFieldInitializer(ParseNode* member, bool inStaticContext) {
102 // For the purposes of bytecode emission, StaticClassBlocks are treated as if
103 // they were static initializers.
104 return (member->is<StaticClassBlock>() && inStaticContext) ||
105 (member->is<ClassField>() &&
106 member->as<ClassField>().isStatic() == inStaticContext);
107}
108
109static bool NeedsAccessorInitializer(ParseNode* member, bool isStatic) {
110 if (isStatic) {
111 return false;
112 }
113 return member->is<ClassMethod>() &&
114 member->as<ClassMethod>().name().isKind(ParseNodeKind::PrivateName) &&
115 !member->as<ClassMethod>().isStatic() &&
116 member->as<ClassMethod>().accessorType() != AccessorType::None;
117}
118
119static bool ShouldSuppressBreakpointsAndSourceNotes(
120 SharedContext* sc, BytecodeEmitter::EmitterMode emitterMode) {
121 // Suppress for all self-hosting code.
122 if (emitterMode == BytecodeEmitter::EmitterMode::SelfHosting) {
123 return true;
124 }
125
126 // Suppress for synthesized class constructors.
127 if (sc->isFunctionBox()) {
128 FunctionBox* funbox = sc->asFunctionBox();
129 return funbox->isSyntheticFunction() && funbox->isClassConstructor();
130 }
131
132 return false;
133}
134
135BytecodeEmitter::BytecodeEmitter(BytecodeEmitter* parent, FrontendContext* fc,
136 SharedContext* sc,
137 const ErrorReporter& errorReporter,
138 CompilationState& compilationState,
139 EmitterMode emitterMode)
140 : sc(sc),
141 fc(fc),
142 parent(parent),
143 bytecodeSection_(fc, sc->extent().lineno,
144 JS::LimitedColumnNumberOneOrigin(sc->extent().column)),
145 perScriptData_(fc, compilationState),
146 errorReporter_(errorReporter),
147 compilationState(compilationState),
148 suppressBreakpointsAndSourceNotes(
149 ShouldSuppressBreakpointsAndSourceNotes(sc, emitterMode)),
150 emitterMode(emitterMode) {
151 MOZ_ASSERT_IF(parent, fc == parent->fc)do { if (parent) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(fc == parent->fc)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(fc == parent->fc))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("fc == parent->fc"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 151); AnnotateMozCrashReason("MOZ_ASSERT" "(" "fc == parent->fc"
")"); do { *((volatile int*)__null) = 151; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
152}
153
154BytecodeEmitter::BytecodeEmitter(BytecodeEmitter* parent, SharedContext* sc)
155 : BytecodeEmitter(parent, parent->fc, sc, parent->errorReporter_,
156 parent->compilationState, parent->emitterMode) {}
157
158BytecodeEmitter::BytecodeEmitter(FrontendContext* fc,
159 const EitherParser& parser, SharedContext* sc,
160 CompilationState& compilationState,
161 EmitterMode emitterMode)
162 : BytecodeEmitter(nullptr, fc, sc, parser.errorReporter(), compilationState,
163 emitterMode) {
164 ep_.emplace(parser);
165}
166
167void BytecodeEmitter::initFromBodyPosition(TokenPos bodyPosition) {
168 setScriptStartOffsetIfUnset(bodyPosition.begin);
169 setFunctionBodyEndPos(bodyPosition.end);
170}
171
172bool BytecodeEmitter::init() {
173 if (!parent) {
174 if (!compilationState.prepareSharedDataStorage(fc)) {
175 return false;
176 }
177 }
178 return perScriptData_.init(fc);
179}
180
181bool BytecodeEmitter::init(TokenPos bodyPosition) {
182 initFromBodyPosition(bodyPosition);
183 return init();
184}
185
186template <typename T>
187T* BytecodeEmitter::findInnermostNestableControl() const {
188 return NestableControl::findNearest<T>(innermostNestableControl);
189}
190
191template <typename T, typename Predicate /* (T*) -> bool */>
192T* BytecodeEmitter::findInnermostNestableControl(Predicate predicate) const {
193 return NestableControl::findNearest<T>(innermostNestableControl, predicate);
194}
195
196NameLocation BytecodeEmitter::lookupName(TaggedParserAtomIndex name) {
197 return innermostEmitterScope()->lookup(this, name);
198}
199
200void BytecodeEmitter::lookupPrivate(TaggedParserAtomIndex name,
201 NameLocation& loc,
202 Maybe<NameLocation>& brandLoc) {
203 innermostEmitterScope()->lookupPrivate(this, name, loc, brandLoc);
204}
205
206Maybe<NameLocation> BytecodeEmitter::locationOfNameBoundInScope(
207 TaggedParserAtomIndex name, EmitterScope* target) {
208 return innermostEmitterScope()->locationBoundInScope(name, target);
209}
210
211template <typename T>
212Maybe<NameLocation> BytecodeEmitter::locationOfNameBoundInScopeType(
213 TaggedParserAtomIndex name, EmitterScope* source) {
214 EmitterScope* aScope = source;
215 while (!aScope->scope(this).is<T>()) {
216 aScope = aScope->enclosingInFrame();
217 }
218 return source->locationBoundInScope(name, aScope);
219}
220
221bool BytecodeEmitter::markStepBreakpoint() {
222 if (skipBreakpointSrcNotes()) {
223 return true;
224 }
225
226 if (!newSrcNote(SrcNoteType::BreakpointStepSep)) {
227 return false;
228 }
229
230 // We track the location of the most recent separator for use in
231 // markSimpleBreakpoint. Note that this means that the position must already
232 // be set before markStepBreakpoint is called.
233 bytecodeSection().updateSeparatorPosition();
234
235 return true;
236}
237
238bool BytecodeEmitter::markSimpleBreakpoint() {
239 if (skipBreakpointSrcNotes()) {
240 return true;
241 }
242
243 // If a breakable call ends up being the same location as the most recent
244 // expression start, we need to skip marking it breakable in order to avoid
245 // having two breakpoints with the same line/column position.
246 // Note: This assumes that the position for the call has already been set.
247 if (!bytecodeSection().isDuplicateLocation()) {
248 if (!newSrcNote(SrcNoteType::Breakpoint)) {
249 return false;
250 }
251 }
252
253 return true;
254}
255
256bool BytecodeEmitter::emitCheck(JSOp op, ptrdiff_t delta,
257 BytecodeOffset* offset) {
258 size_t oldLength = bytecodeSection().code().length();
259 *offset = BytecodeOffset(oldLength);
260
261 size_t newLength = oldLength + size_t(delta);
262 if (MOZ_UNLIKELY(newLength > MaxBytecodeLength)(__builtin_expect(!!(newLength > MaxBytecodeLength), 0))) {
263 ReportAllocationOverflow(fc);
264 return false;
265 }
266
267 if (!bytecodeSection().code().growByUninitialized(delta)) {
268 return false;
269 }
270
271 if (BytecodeOpHasIC(op)) {
272 // Even if every bytecode op is a JOF_IC op and the function has ARGC_LIMIT
273 // arguments, numICEntries cannot overflow.
274 static_assert(MaxBytecodeLength + 1 /* this */ + ARGC_LIMIT <= UINT32_MAX(4294967295U),
275 "numICEntries must not overflow");
276 bytecodeSection().incrementNumICEntries();
277 }
278
279 return true;
280}
281
282#ifdef DEBUG1
283bool BytecodeEmitter::checkStrictOrSloppy(JSOp op) const {
284 if (IsCheckStrictOp(op) && !sc->strict()) {
285 return false;
286 }
287 if (IsCheckSloppyOp(op) && sc->strict()) {
288 return false;
289 }
290 return true;
291}
292#endif
293
294bool BytecodeEmitter::emit1(JSOp op) {
295 MOZ_ASSERT(checkStrictOrSloppy(op))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(checkStrictOrSloppy(op))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(checkStrictOrSloppy(op)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("checkStrictOrSloppy(op)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 295); AnnotateMozCrashReason("MOZ_ASSERT" "(" "checkStrictOrSloppy(op)"
")"); do { *((volatile int*)__null) = 295; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
296
297 BytecodeOffset offset;
298 if (!emitCheck(op, 1, &offset)) {
299 return false;
300 }
301
302 jsbytecode* code = bytecodeSection().code(offset);
303 code[0] = jsbytecode(op);
304 bytecodeSection().updateDepth(op, offset);
305 return true;
306}
307
308bool BytecodeEmitter::emit2(JSOp op, uint8_t op1) {
309 MOZ_ASSERT(checkStrictOrSloppy(op))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(checkStrictOrSloppy(op))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(checkStrictOrSloppy(op)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("checkStrictOrSloppy(op)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 309); AnnotateMozCrashReason("MOZ_ASSERT" "(" "checkStrictOrSloppy(op)"
")"); do { *((volatile int*)__null) = 309; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
310
311 BytecodeOffset offset;
312 if (!emitCheck(op, 2, &offset)) {
313 return false;
314 }
315
316 jsbytecode* code = bytecodeSection().code(offset);
317 code[0] = jsbytecode(op);
318 code[1] = jsbytecode(op1);
319 bytecodeSection().updateDepth(op, offset);
320 return true;
321}
322
323bool BytecodeEmitter::emit3(JSOp op, jsbytecode op1, jsbytecode op2) {
324 MOZ_ASSERT(checkStrictOrSloppy(op))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(checkStrictOrSloppy(op))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(checkStrictOrSloppy(op)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("checkStrictOrSloppy(op)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 324); AnnotateMozCrashReason("MOZ_ASSERT" "(" "checkStrictOrSloppy(op)"
")"); do { *((volatile int*)__null) = 324; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
325
326 /* These should filter through emitVarOp. */
327 MOZ_ASSERT(!IsArgOp(op))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsArgOp(op))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!IsArgOp(op)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!IsArgOp(op)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 327); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsArgOp(op)"
")"); do { *((volatile int*)__null) = 327; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
328 MOZ_ASSERT(!IsLocalOp(op))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsLocalOp(op))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!IsLocalOp(op)))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("!IsLocalOp(op)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 328); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsLocalOp(op)"
")"); do { *((volatile int*)__null) = 328; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
329
330 BytecodeOffset offset;
331 if (!emitCheck(op, 3, &offset)) {
332 return false;
333 }
334
335 jsbytecode* code = bytecodeSection().code(offset);
336 code[0] = jsbytecode(op);
337 code[1] = op1;
338 code[2] = op2;
339 bytecodeSection().updateDepth(op, offset);
340 return true;
341}
342
343bool BytecodeEmitter::emitN(JSOp op, size_t extra, BytecodeOffset* offset) {
344 MOZ_ASSERT(checkStrictOrSloppy(op))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(checkStrictOrSloppy(op))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(checkStrictOrSloppy(op)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("checkStrictOrSloppy(op)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 344); AnnotateMozCrashReason("MOZ_ASSERT" "(" "checkStrictOrSloppy(op)"
")"); do { *((volatile int*)__null) = 344; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
345 ptrdiff_t length = 1 + ptrdiff_t(extra);
346
347 BytecodeOffset off;
348 if (!emitCheck(op, length, &off)) {
349 return false;
350 }
351
352 jsbytecode* code = bytecodeSection().code(off);
353 code[0] = jsbytecode(op);
354 /* The remaining |extra| bytes are set by the caller */
355
356 /*
357 * Don't updateDepth if op's use-count comes from the immediate
358 * operand yet to be stored in the extra bytes after op.
359 */
360 if (CodeSpec(op).nuses >= 0) {
361 bytecodeSection().updateDepth(op, off);
362 }
363
364 if (offset) {
365 *offset = off;
366 }
367 return true;
368}
369
370bool BytecodeEmitter::emitJumpTargetOp(JSOp op, BytecodeOffset* off) {
371 MOZ_ASSERT(BytecodeIsJumpTarget(op))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(BytecodeIsJumpTarget(op))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(BytecodeIsJumpTarget(op)))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("BytecodeIsJumpTarget(op)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 371); AnnotateMozCrashReason("MOZ_ASSERT" "(" "BytecodeIsJumpTarget(op)"
")"); do { *((volatile int*)__null) = 371; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
372
373 // Record the current IC-entry index at start of this op.
374 uint32_t numEntries = bytecodeSection().numICEntries();
375
376 size_t n = GetOpLength(op) - 1;
377 MOZ_ASSERT(GetOpLength(op) >= 1 + ICINDEX_LEN)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(GetOpLength(op) >= 1 + ICINDEX_LEN)>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(GetOpLength(op) >= 1 + ICINDEX_LEN))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("GetOpLength(op) >= 1 + ICINDEX_LEN"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 377); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetOpLength(op) >= 1 + ICINDEX_LEN"
")"); do { *((volatile int*)__null) = 377; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
378
379 if (!emitN(op, n, off)) {
380 return false;
381 }
382
383 SET_ICINDEX(bytecodeSection().code(*off), numEntries);
384 return true;
385}
386
387bool BytecodeEmitter::emitJumpTarget(JumpTarget* target) {
388 BytecodeOffset off = bytecodeSection().offset();
389
390 // Alias consecutive jump targets.
391 if (bytecodeSection().lastTargetOffset().valid() &&
392 off == bytecodeSection().lastTargetOffset() +
393 BytecodeOffsetDiff(JSOpLength_JumpTarget)) {
394 target->offset = bytecodeSection().lastTargetOffset();
395 return true;
396 }
397
398 target->offset = off;
399 bytecodeSection().setLastTargetOffset(off);
400
401 BytecodeOffset opOff;
402 return emitJumpTargetOp(JSOp::JumpTarget, &opOff);
403}
404
405bool BytecodeEmitter::emitJumpNoFallthrough(JSOp op, JumpList* jump) {
406 BytecodeOffset offset;
407 if (!emitCheck(op, 5, &offset)) {
408 return false;
409 }
410
411 jsbytecode* code = bytecodeSection().code(offset);
412 code[0] = jsbytecode(op);
413 MOZ_ASSERT(!jump->offset.valid() ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!jump->offset.valid() || (0 <= jump->offset
.value() && jump->offset < offset))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!jump->offset.valid() || (0 <= jump->offset.value
() && jump->offset < offset)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!jump->offset.valid() || (0 <= jump->offset.value() && jump->offset < offset)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 414); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!jump->offset.valid() || (0 <= jump->offset.value() && jump->offset < offset)"
")"); do { *((volatile int*)__null) = 414; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
414 (0 <= jump->offset.value() && jump->offset < offset))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!jump->offset.valid() || (0 <= jump->offset
.value() && jump->offset < offset))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!jump->offset.valid() || (0 <= jump->offset.value
() && jump->offset < offset)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!jump->offset.valid() || (0 <= jump->offset.value() && jump->offset < offset)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 414); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!jump->offset.valid() || (0 <= jump->offset.value() && jump->offset < offset)"
")"); do { *((volatile int*)__null) = 414; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
415 jump->push(bytecodeSection().code(BytecodeOffset(0)), offset);
416 bytecodeSection().updateDepth(op, offset);
417 return true;
418}
419
420bool BytecodeEmitter::emitJump(JSOp op, JumpList* jump) {
421 if (!emitJumpNoFallthrough(op, jump)) {
422 return false;
423 }
424 if (BytecodeFallsThrough(op)) {
425 JumpTarget fallthrough;
426 if (!emitJumpTarget(&fallthrough)) {
427 return false;
428 }
429 }
430 return true;
431}
432
433void BytecodeEmitter::patchJumpsToTarget(JumpList jump, JumpTarget target) {
434 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!jump.offset.valid() || (0 <= jump.offset.value()
&& jump.offset <= bytecodeSection().offset()))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!jump.offset.valid() || (0 <= jump.offset.value()
&& jump.offset <= bytecodeSection().offset())))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset())"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 436); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset())"
")"); do { *((volatile int*)__null) = 436; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
435 !jump.offset.valid() ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!jump.offset.valid() || (0 <= jump.offset.value()
&& jump.offset <= bytecodeSection().offset()))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!jump.offset.valid() || (0 <= jump.offset.value()
&& jump.offset <= bytecodeSection().offset())))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset())"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 436); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset())"
")"); do { *((volatile int*)__null) = 436; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
436 (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset()))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!jump.offset.valid() || (0 <= jump.offset.value()
&& jump.offset <= bytecodeSection().offset()))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!jump.offset.valid() || (0 <= jump.offset.value()
&& jump.offset <= bytecodeSection().offset())))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset())"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 436); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset())"
")"); do { *((volatile int*)__null) = 436; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
437 MOZ_ASSERT(0 <= target.offset.value() &&do { static_assert( mozilla::detail::AssertionConditionType<
decltype(0 <= target.offset.value() && target.offset
<= bytecodeSection().offset())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(0 <= target.offset.value(
) && target.offset <= bytecodeSection().offset()))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("0 <= target.offset.value() && target.offset <= bytecodeSection().offset()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 438); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0 <= target.offset.value() && target.offset <= bytecodeSection().offset()"
")"); do { *((volatile int*)__null) = 438; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
438 target.offset <= bytecodeSection().offset())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(0 <= target.offset.value() && target.offset
<= bytecodeSection().offset())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(0 <= target.offset.value(
) && target.offset <= bytecodeSection().offset()))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("0 <= target.offset.value() && target.offset <= bytecodeSection().offset()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 438); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0 <= target.offset.value() && target.offset <= bytecodeSection().offset()"
")"); do { *((volatile int*)__null) = 438; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
439 MOZ_ASSERT_IF(do { if (jump.offset.valid() && target.offset + BytecodeOffsetDiff
(4) <= bytecodeSection().offset()) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(BytecodeIsJumpTarget
(JSOp(*bytecodeSection().code(target.offset))))>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset
)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 442); AnnotateMozCrashReason("MOZ_ASSERT" "(" "BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))"
")"); do { *((volatile int*)__null) = 442; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
440 jump.offset.valid() &&do { if (jump.offset.valid() && target.offset + BytecodeOffsetDiff
(4) <= bytecodeSection().offset()) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(BytecodeIsJumpTarget
(JSOp(*bytecodeSection().code(target.offset))))>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset
)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 442); AnnotateMozCrashReason("MOZ_ASSERT" "(" "BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))"
")"); do { *((volatile int*)__null) = 442; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
441 target.offset + BytecodeOffsetDiff(4) <= bytecodeSection().offset(),do { if (jump.offset.valid() && target.offset + BytecodeOffsetDiff
(4) <= bytecodeSection().offset()) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(BytecodeIsJumpTarget
(JSOp(*bytecodeSection().code(target.offset))))>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset
)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 442); AnnotateMozCrashReason("MOZ_ASSERT" "(" "BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))"
")"); do { *((volatile int*)__null) = 442; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
442 BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset))))do { if (jump.offset.valid() && target.offset + BytecodeOffsetDiff
(4) <= bytecodeSection().offset()) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(BytecodeIsJumpTarget
(JSOp(*bytecodeSection().code(target.offset))))>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset
)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 442); AnnotateMozCrashReason("MOZ_ASSERT" "(" "BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))"
")"); do { *((volatile int*)__null) = 442; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
443 jump.patchAll(bytecodeSection().code(BytecodeOffset(0)), target);
444}
445
446bool BytecodeEmitter::emitJumpTargetAndPatch(JumpList jump) {
447 if (!jump.offset.valid()) {
448 return true;
449 }
450 JumpTarget target;
451 if (!emitJumpTarget(&target)) {
452 return false;
453 }
454 patchJumpsToTarget(jump, target);
455 return true;
456}
457
458bool BytecodeEmitter::emitCall(JSOp op, uint16_t argc,
459 const Maybe<uint32_t>& sourceCoordOffset) {
460 if (sourceCoordOffset.isSome()) {
461 if (!updateSourceCoordNotes(*sourceCoordOffset)) {
462 return false;
463 }
464 }
465 return emit3(op, ARGC_LO(argc), ARGC_HI(argc));
466}
467
468bool BytecodeEmitter::emitCall(JSOp op, uint16_t argc, ParseNode* pn) {
469 return emitCall(op, argc, pn ? Some(pn->pn_pos.begin) : Nothing());
470}
471
472bool BytecodeEmitter::emitDupAt(unsigned slotFromTop, unsigned count) {
473 MOZ_ASSERT(slotFromTop < unsigned(bytecodeSection().stackDepth()))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(slotFromTop < unsigned(bytecodeSection().stackDepth
()))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(slotFromTop < unsigned(bytecodeSection().stackDepth
())))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("slotFromTop < unsigned(bytecodeSection().stackDepth())",
"/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 473); AnnotateMozCrashReason("MOZ_ASSERT" "(" "slotFromTop < unsigned(bytecodeSection().stackDepth())"
")"); do { *((volatile int*)__null) = 473; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
474 MOZ_ASSERT(slotFromTop + 1 >= count)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(slotFromTop + 1 >= count)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(slotFromTop + 1 >= count)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("slotFromTop + 1 >= count"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 474); AnnotateMozCrashReason("MOZ_ASSERT" "(" "slotFromTop + 1 >= count"
")"); do { *((volatile int*)__null) = 474; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
475
476 if (slotFromTop == 0 && count == 1) {
477 return emit1(JSOp::Dup);
478 }
479
480 if (slotFromTop == 1 && count == 2) {
481 return emit1(JSOp::Dup2);
482 }
483
484 if (slotFromTop >= Bit(24)) {
485 reportError(nullptr, JSMSG_TOO_MANY_LOCALS);
486 return false;
487 }
488
489 for (unsigned i = 0; i < count; i++) {
490 BytecodeOffset off;
491 if (!emitN(JSOp::DupAt, 3, &off)) {
492 return false;
493 }
494
495 jsbytecode* pc = bytecodeSection().code(off);
496 SET_UINT24(pc, slotFromTop);
497 }
498
499 return true;
500}
501
502bool BytecodeEmitter::emitPopN(unsigned n) {
503 MOZ_ASSERT(n != 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(n != 0)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(n != 0))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("n != 0", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 503); AnnotateMozCrashReason("MOZ_ASSERT" "(" "n != 0" ")")
; do { *((volatile int*)__null) = 503; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
504
505 if (n == 1) {
506 return emit1(JSOp::Pop);
507 }
508
509 // 2 JSOp::Pop instructions (2 bytes) are shorter than JSOp::PopN (3 bytes).
510 if (n == 2) {
511 return emit1(JSOp::Pop) && emit1(JSOp::Pop);
512 }
513
514 return emitUint16Operand(JSOp::PopN, n);
515}
516
517bool BytecodeEmitter::emitPickN(uint8_t n) {
518 MOZ_ASSERT(n != 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(n != 0)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(n != 0))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("n != 0", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 518); AnnotateMozCrashReason("MOZ_ASSERT" "(" "n != 0" ")")
; do { *((volatile int*)__null) = 518; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
519
520 if (n == 1) {
521 return emit1(JSOp::Swap);
522 }
523
524 return emit2(JSOp::Pick, n);
525}
526
527bool BytecodeEmitter::emitUnpickN(uint8_t n) {
528 MOZ_ASSERT(n != 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(n != 0)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(n != 0))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("n != 0", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 528); AnnotateMozCrashReason("MOZ_ASSERT" "(" "n != 0" ")")
; do { *((volatile int*)__null) = 528; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
529
530 if (n == 1) {
531 return emit1(JSOp::Swap);
532 }
533
534 return emit2(JSOp::Unpick, n);
535}
536
537bool BytecodeEmitter::emitCheckIsObj(CheckIsObjectKind kind) {
538 return emit2(JSOp::CheckIsObj, uint8_t(kind));
539}
540
541bool BytecodeEmitter::emitBuiltinObject(BuiltinObjectKind kind) {
542 return emit2(JSOp::BuiltinObject, uint8_t(kind));
543}
544
545/* Updates line number notes, not column notes. */
546bool BytecodeEmitter::updateLineNumberNotes(uint32_t offset) {
547 if (skipLocationSrcNotes()) {
548 return true;
549 }
550
551 const ErrorReporter& er = errorReporter();
552 std::optional<bool> onThisLineStatus =
553 er.isOnThisLine(offset, bytecodeSection().currentLine());
554 if (!onThisLineStatus.has_value()) {
555 er.errorNoOffset(JSMSG_OUT_OF_MEMORY);
556 return false;
557 }
558
559 bool onThisLine = *onThisLineStatus;
560
561 if (!onThisLine) {
562 unsigned line = er.lineAt(offset);
563 unsigned delta = line - bytecodeSection().currentLine();
564
565 // If we use a `SetLine` note below, we want it to be relative to the
566 // scripts initial line number for better chance of sharing.
567 unsigned initialLine = sc->extent().lineno;
568 MOZ_ASSERT(line >= initialLine)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(line >= initialLine)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(line >= initialLine))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("line >= initialLine"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 568); AnnotateMozCrashReason("MOZ_ASSERT" "(" "line >= initialLine"
")"); do { *((volatile int*)__null) = 568; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
569
570 /*
571 * Encode any change in the current source line number by using
572 * either several SrcNoteType::NewLine notes or just one
573 * SrcNoteType::SetLine note, whichever consumes less space.
574 *
575 * NB: We handle backward line number deltas (possible with for
576 * loops where the update part is emitted after the body, but its
577 * line number is <= any line number in the body) here by letting
578 * unsigned delta_ wrap to a very large number, which triggers a
579 * SrcNoteType::SetLine.
580 */
581 bytecodeSection().setCurrentLine(line, offset);
582 if (delta >= SrcNote::SetLine::lengthFor(line, initialLine)) {
583 if (!newSrcNote2(SrcNoteType::SetLine,
584 SrcNote::SetLine::toOperand(line, initialLine))) {
585 return false;
586 }
587 } else {
588 do {
589 if (!newSrcNote(SrcNoteType::NewLine)) {
590 return false;
591 }
592 } while (--delta != 0);
593 }
594
595 bytecodeSection().updateSeparatorPositionIfPresent();
596 }
597 return true;
598}
599
600/* Updates the line number and column number information in the source notes. */
601bool BytecodeEmitter::updateSourceCoordNotes(uint32_t offset) {
602 if (skipLocationSrcNotes()) {
603 return true;
604 }
605
606 if (!updateLineNumberNotes(offset)) {
607 return false;
608 }
609
610 JS::LimitedColumnNumberOneOrigin columnIndex =
611 errorReporter().columnAt(offset);
612
613 // Assert colspan is always representable.
614 static_assert((0 - ptrdiff_t(JS::LimitedColumnNumberOneOrigin::Limit)) >=
615 SrcNote::ColSpan::MinColSpan);
616 static_assert((ptrdiff_t(JS::LimitedColumnNumberOneOrigin::Limit) - 0) <=
617 SrcNote::ColSpan::MaxColSpan);
618
619 JS::ColumnNumberOffset colspan = columnIndex - bytecodeSection().lastColumn();
620
621 if (colspan != JS::ColumnNumberOffset::zero()) {
622 if (lastLineOnlySrcNoteIndex != LastSrcNoteIsNotLineOnly) {
623 MOZ_ASSERT(bytecodeSection().lastColumn() ==do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bytecodeSection().lastColumn() == JS::LimitedColumnNumberOneOrigin
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(bytecodeSection().lastColumn() == JS::LimitedColumnNumberOneOrigin
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("bytecodeSection().lastColumn() == JS::LimitedColumnNumberOneOrigin()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 624); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().lastColumn() == JS::LimitedColumnNumberOneOrigin()"
")"); do { *((volatile int*)__null) = 624; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
624 JS::LimitedColumnNumberOneOrigin())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bytecodeSection().lastColumn() == JS::LimitedColumnNumberOneOrigin
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(bytecodeSection().lastColumn() == JS::LimitedColumnNumberOneOrigin
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("bytecodeSection().lastColumn() == JS::LimitedColumnNumberOneOrigin()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 624); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().lastColumn() == JS::LimitedColumnNumberOneOrigin()"
")"); do { *((volatile int*)__null) = 624; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
625
626 const SrcNotesVector& notes = bytecodeSection().notes();
627 SrcNoteType type = notes[lastLineOnlySrcNoteIndex].type();
628 if (type == SrcNoteType::NewLine) {
629 if (!convertLastNewLineToNewLineColumn(columnIndex)) {
630 return false;
631 }
632 } else {
633 MOZ_ASSERT(type == SrcNoteType::SetLine)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(type == SrcNoteType::SetLine)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(type == SrcNoteType::SetLine
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"type == SrcNoteType::SetLine", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 633); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == SrcNoteType::SetLine"
")"); do { *((volatile int*)__null) = 633; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
634 if (!convertLastSetLineToSetLineColumn(columnIndex)) {
635 return false;
636 }
637 }
638 } else {
639 if (!newSrcNote2(SrcNoteType::ColSpan,
640 SrcNote::ColSpan::toOperand(colspan))) {
641 return false;
642 }
643 }
644 bytecodeSection().setLastColumn(columnIndex, offset);
645 bytecodeSection().updateSeparatorPositionIfPresent();
646 }
647 return true;
648}
649
650bool BytecodeEmitter::updateSourceCoordNotesIfNonLiteral(ParseNode* node) {
651 if (node->isLiteral()) {
652 return true;
653 }
654 return updateSourceCoordNotes(node->pn_pos.begin);
655}
656
657uint32_t BytecodeEmitter::getOffsetForLoop(ParseNode* nextpn) const {
658 // Try to give the JSOp::LoopHead the same line number as the next
659 // instruction. nextpn is often a block, in which case the next instruction
660 // typically comes from the first statement inside.
661 if (nextpn->is<LexicalScopeNode>()) {
662 nextpn = nextpn->as<LexicalScopeNode>().scopeBody();
663 }
664 if (nextpn->isKind(ParseNodeKind::StatementList)) {
665 if (ParseNode* firstStatement = nextpn->as<ListNode>().head()) {
666 nextpn = firstStatement;
667 }
668 }
669
670 return nextpn->pn_pos.begin;
671}
672
673bool BytecodeEmitter::emitUint16Operand(JSOp op, uint32_t operand) {
674 MOZ_ASSERT(operand <= UINT16_MAX)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(operand <= (65535))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(operand <= (65535)))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("operand <= (65535)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 674); AnnotateMozCrashReason("MOZ_ASSERT" "(" "operand <= (65535)"
")"); do { *((volatile int*)__null) = 674; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
675 if (!emit3(op, UINT16_LO(operand), UINT16_HI(operand))) {
676 return false;
677 }
678 return true;
679}
680
681bool BytecodeEmitter::emitUint32Operand(JSOp op, uint32_t operand) {
682 BytecodeOffset off;
683 if (!emitN(op, 4, &off)) {
684 return false;
685 }
686 SET_UINT32(bytecodeSection().code(off), operand);
687 return true;
688}
689
690bool BytecodeEmitter::emitGoto(NestableControl* target, GotoKind kind) {
691 NonLocalExitControl nle(this, kind == GotoKind::Continue
692 ? NonLocalExitKind::Continue
693 : NonLocalExitKind::Break);
694 return nle.emitNonLocalJump(target);
695}
696
697AbstractScopePtr BytecodeEmitter::innermostScope() const {
698 return innermostEmitterScope()->scope(this);
699}
700
701ScopeIndex BytecodeEmitter::innermostScopeIndex() const {
702 return *innermostEmitterScope()->scopeIndex(this);
703}
704
705bool BytecodeEmitter::emitGCIndexOp(JSOp op, GCThingIndex index) {
706 MOZ_ASSERT(checkStrictOrSloppy(op))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(checkStrictOrSloppy(op))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(checkStrictOrSloppy(op)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("checkStrictOrSloppy(op)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 706); AnnotateMozCrashReason("MOZ_ASSERT" "(" "checkStrictOrSloppy(op)"
")"); do { *((volatile int*)__null) = 706; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
707
708 constexpr size_t OpLength = 1 + GCTHING_INDEX_LEN;
709 MOZ_ASSERT(GetOpLength(op) == OpLength)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(GetOpLength(op) == OpLength)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(GetOpLength(op) == OpLength)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("GetOpLength(op) == OpLength"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 709); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetOpLength(op) == OpLength"
")"); do { *((volatile int*)__null) = 709; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
710
711 BytecodeOffset offset;
712 if (!emitCheck(op, OpLength, &offset)) {
713 return false;
714 }
715
716 jsbytecode* code = bytecodeSection().code(offset);
717 code[0] = jsbytecode(op);
718 SET_GCTHING_INDEX(code, index);
719 bytecodeSection().updateDepth(op, offset);
720 return true;
721}
722
723bool BytecodeEmitter::emitAtomOp(JSOp op, TaggedParserAtomIndex atom) {
724 MOZ_ASSERT(atom)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(atom)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(atom))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("atom", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 724); AnnotateMozCrashReason("MOZ_ASSERT" "(" "atom" ")"); do
{ *((volatile int*)__null) = 724; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
725
726 // .generator lookups should be emitted as JSOp::GetAliasedVar instead of
727 // JSOp::GetName etc, to bypass |with| objects on the scope chain.
728 // It's safe to emit .this lookups though because |with| objects skip
729 // those.
730 MOZ_ASSERT_IF(op == JSOp::GetName || op == JSOp::GetGName,do { if (op == JSOp::GetName || op == JSOp::GetGName) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(atom !=
TaggedParserAtomIndex::WellKnown::dot_generator_())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(atom != TaggedParserAtomIndex::WellKnown::dot_generator_()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"atom != TaggedParserAtomIndex::WellKnown::dot_generator_()",
"/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 731); AnnotateMozCrashReason("MOZ_ASSERT" "(" "atom != TaggedParserAtomIndex::WellKnown::dot_generator_()"
")"); do { *((volatile int*)__null) = 731; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
731 atom != TaggedParserAtomIndex::WellKnown::dot_generator_())do { if (op == JSOp::GetName || op == JSOp::GetGName) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(atom !=
TaggedParserAtomIndex::WellKnown::dot_generator_())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(atom != TaggedParserAtomIndex::WellKnown::dot_generator_()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"atom != TaggedParserAtomIndex::WellKnown::dot_generator_()",
"/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 731); AnnotateMozCrashReason("MOZ_ASSERT" "(" "atom != TaggedParserAtomIndex::WellKnown::dot_generator_()"
")"); do { *((volatile int*)__null) = 731; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
732
733 GCThingIndex index;
734 if (!makeAtomIndex(atom, ParserAtom::Atomize::Yes, &index)) {
735 return false;
736 }
737
738 return emitAtomOp(op, index);
739}
740
741bool BytecodeEmitter::emitAtomOp(JSOp op, GCThingIndex atomIndex) {
742 MOZ_ASSERT(JOF_OPTYPE(op) == JOF_ATOM)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(JOF_OPTYPE(op) == JOF_ATOM)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(JOF_OPTYPE(op) == JOF_ATOM))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("JOF_OPTYPE(op) == JOF_ATOM"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 742); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JOF_OPTYPE(op) == JOF_ATOM"
")"); do { *((volatile int*)__null) = 742; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
743#ifdef DEBUG1
744 auto atom = perScriptData().gcThingList().getAtom(atomIndex);
745 MOZ_ASSERT(compilationState.parserAtoms.isInstantiatedAsJSAtom(atom))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(compilationState.parserAtoms.isInstantiatedAsJSAtom(
atom))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(compilationState.parserAtoms.isInstantiatedAsJSAtom(
atom)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("compilationState.parserAtoms.isInstantiatedAsJSAtom(atom)",
"/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 745); AnnotateMozCrashReason("MOZ_ASSERT" "(" "compilationState.parserAtoms.isInstantiatedAsJSAtom(atom)"
")"); do { *((volatile int*)__null) = 745; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
746#endif
747 return emitGCIndexOp(op, atomIndex);
748}
749
750bool BytecodeEmitter::emitStringOp(JSOp op, TaggedParserAtomIndex atom) {
751 MOZ_ASSERT(atom)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(atom)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(atom))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("atom", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 751); AnnotateMozCrashReason("MOZ_ASSERT" "(" "atom" ")"); do
{ *((volatile int*)__null) = 751; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
752 GCThingIndex index;
753 if (!makeAtomIndex(atom, ParserAtom::Atomize::No, &index)) {
754 return false;
755 }
756
757 return emitStringOp(op, index);
758}
759
760bool BytecodeEmitter::emitStringOp(JSOp op, GCThingIndex atomIndex) {
761 MOZ_ASSERT(JOF_OPTYPE(op) == JOF_STRING)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(JOF_OPTYPE(op) == JOF_STRING)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(JOF_OPTYPE(op) == JOF_STRING
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"JOF_OPTYPE(op) == JOF_STRING", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 761); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JOF_OPTYPE(op) == JOF_STRING"
")"); do { *((volatile int*)__null) = 761; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
762 return emitGCIndexOp(op, atomIndex);
763}
764
765bool BytecodeEmitter::emitInternedScopeOp(GCThingIndex index, JSOp op) {
766 MOZ_ASSERT(JOF_OPTYPE(op) == JOF_SCOPE)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(JOF_OPTYPE(op) == JOF_SCOPE)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(JOF_OPTYPE(op) == JOF_SCOPE)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("JOF_OPTYPE(op) == JOF_SCOPE"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 766); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JOF_OPTYPE(op) == JOF_SCOPE"
")"); do { *((volatile int*)__null) = 766; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
767 MOZ_ASSERT(index < perScriptData().gcThingList().length())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(index < perScriptData().gcThingList().length())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(index < perScriptData().gcThingList().length())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("index < perScriptData().gcThingList().length()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 767); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index < perScriptData().gcThingList().length()"
")"); do { *((volatile int*)__null) = 767; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
768 return emitGCIndexOp(op, index);
769}
770
771bool BytecodeEmitter::emitInternedObjectOp(GCThingIndex index, JSOp op) {
772 MOZ_ASSERT(JOF_OPTYPE(op) == JOF_OBJECT)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(JOF_OPTYPE(op) == JOF_OBJECT)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(JOF_OPTYPE(op) == JOF_OBJECT
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"JOF_OPTYPE(op) == JOF_OBJECT", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 772); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JOF_OPTYPE(op) == JOF_OBJECT"
")"); do { *((volatile int*)__null) = 772; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
773 MOZ_ASSERT(index < perScriptData().gcThingList().length())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(index < perScriptData().gcThingList().length())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(index < perScriptData().gcThingList().length())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("index < perScriptData().gcThingList().length()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 773); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index < perScriptData().gcThingList().length()"
")"); do { *((volatile int*)__null) = 773; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
774 return emitGCIndexOp(op, index);
775}
776
777bool BytecodeEmitter::emitRegExp(GCThingIndex index) {
778 return emitGCIndexOp(JSOp::RegExp, index);
779}
780
781bool BytecodeEmitter::emitLocalOp(JSOp op, uint32_t slot) {
782 MOZ_ASSERT(JOF_OPTYPE(op) != JOF_ENVCOORD)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(JOF_OPTYPE(op) != JOF_ENVCOORD)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(JOF_OPTYPE(op) != JOF_ENVCOORD
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"JOF_OPTYPE(op) != JOF_ENVCOORD", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 782); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JOF_OPTYPE(op) != JOF_ENVCOORD"
")"); do { *((volatile int*)__null) = 782; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
783 MOZ_ASSERT(IsLocalOp(op))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsLocalOp(op))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsLocalOp(op)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("IsLocalOp(op)",
"/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 783); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsLocalOp(op)"
")"); do { *((volatile int*)__null) = 783; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
784
785 BytecodeOffset off;
786 if (!emitN(op, LOCALNO_LEN, &off)) {
787 return false;
788 }
789
790 SET_LOCALNO(bytecodeSection().code(off), slot);
791 return true;
792}
793
794bool BytecodeEmitter::emitArgOp(JSOp op, uint16_t slot) {
795 MOZ_ASSERT(IsArgOp(op))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsArgOp(op))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsArgOp(op)))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("IsArgOp(op)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 795); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsArgOp(op)"
")"); do { *((volatile int*)__null) = 795; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
796 BytecodeOffset off;
797 if (!emitN(op, ARGNO_LEN, &off)) {
798 return false;
799 }
800
801 SET_ARGNO(bytecodeSection().code(off), slot);
802 return true;
803}
804
805bool BytecodeEmitter::emitEnvCoordOp(JSOp op, EnvironmentCoordinate ec) {
806 MOZ_ASSERT(JOF_OPTYPE(op) == JOF_ENVCOORD ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(JOF_OPTYPE(op) == JOF_ENVCOORD || JOF_OPTYPE(op) == JOF_DEBUGCOORD
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(JOF_OPTYPE(op) == JOF_ENVCOORD || JOF_OPTYPE(op) == JOF_DEBUGCOORD
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"JOF_OPTYPE(op) == JOF_ENVCOORD || JOF_OPTYPE(op) == JOF_DEBUGCOORD"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 807); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JOF_OPTYPE(op) == JOF_ENVCOORD || JOF_OPTYPE(op) == JOF_DEBUGCOORD"
")"); do { *((volatile int*)__null) = 807; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
807 JOF_OPTYPE(op) == JOF_DEBUGCOORD)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(JOF_OPTYPE(op) == JOF_ENVCOORD || JOF_OPTYPE(op) == JOF_DEBUGCOORD
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(JOF_OPTYPE(op) == JOF_ENVCOORD || JOF_OPTYPE(op) == JOF_DEBUGCOORD
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"JOF_OPTYPE(op) == JOF_ENVCOORD || JOF_OPTYPE(op) == JOF_DEBUGCOORD"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 807); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JOF_OPTYPE(op) == JOF_ENVCOORD || JOF_OPTYPE(op) == JOF_DEBUGCOORD"
")"); do { *((volatile int*)__null) = 807; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
808
809 constexpr size_t N = ENVCOORD_HOPS_LEN + ENVCOORD_SLOT_LEN;
810 MOZ_ASSERT(GetOpLength(op) == 1 + N)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(GetOpLength(op) == 1 + N)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(GetOpLength(op) == 1 + N))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("GetOpLength(op) == 1 + N"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 810); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetOpLength(op) == 1 + N"
")"); do { *((volatile int*)__null) = 810; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
811
812 BytecodeOffset off;
813 if (!emitN(op, N, &off)) {
814 return false;
815 }
816
817 jsbytecode* pc = bytecodeSection().code(off);
818 SET_ENVCOORD_HOPS(pc, ec.hops());
819 pc += ENVCOORD_HOPS_LEN;
820 SET_ENVCOORD_SLOT(pc, ec.slot());
821 pc += ENVCOORD_SLOT_LEN;
Value stored to 'pc' is never read
822 return true;
823}
824
825bool BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer) const {
826 AutoCheckRecursionLimit recursion(fc);
827 if (!recursion.check(fc)) {
828 return false;
829 }
830
831restart:
832
833 switch (pn->getKind()) {
834 // Trivial cases with no side effects.
835 case ParseNodeKind::EmptyStmt:
836 case ParseNodeKind::TrueExpr:
837 case ParseNodeKind::FalseExpr:
838 case ParseNodeKind::NullExpr:
839 case ParseNodeKind::RawUndefinedExpr:
840 case ParseNodeKind::Elision:
841 case ParseNodeKind::Generator:
842 MOZ_ASSERT(pn->is<NullaryNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<NullaryNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<NullaryNode>
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("pn->is<NullaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 842); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<NullaryNode>()"
")"); do { *((volatile int*)__null) = 842; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
843 *answer = false;
844 return true;
845
846 case ParseNodeKind::ObjectPropertyName:
847 case ParseNodeKind::PrivateName: // no side effects, unlike
848 // ParseNodeKind::Name
849 case ParseNodeKind::StringExpr:
850 case ParseNodeKind::TemplateStringExpr:
851 MOZ_ASSERT(pn->is<NameNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<NameNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<NameNode>())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("pn->is<NameNode>()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 851); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<NameNode>()"
")"); do { *((volatile int*)__null) = 851; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
852 *answer = false;
853 return true;
854
855 case ParseNodeKind::RegExpExpr:
856 MOZ_ASSERT(pn->is<RegExpLiteral>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<RegExpLiteral>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<RegExpLiteral>
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("pn->is<RegExpLiteral>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 856); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<RegExpLiteral>()"
")"); do { *((volatile int*)__null) = 856; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
857 *answer = false;
858 return true;
859
860 case ParseNodeKind::NumberExpr:
861 MOZ_ASSERT(pn->is<NumericLiteral>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<NumericLiteral>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<NumericLiteral>
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("pn->is<NumericLiteral>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 861); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<NumericLiteral>()"
")"); do { *((volatile int*)__null) = 861; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
862 *answer = false;
863 return true;
864
865 case ParseNodeKind::BigIntExpr:
866 MOZ_ASSERT(pn->is<BigIntLiteral>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<BigIntLiteral>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<BigIntLiteral>
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("pn->is<BigIntLiteral>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 866); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BigIntLiteral>()"
")"); do { *((volatile int*)__null) = 866; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
867 *answer = false;
868 return true;
869
870 // |this| can throw in derived class constructors, including nested arrow
871 // functions or eval.
872 case ParseNodeKind::ThisExpr:
873 MOZ_ASSERT(pn->is<UnaryNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<UnaryNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<UnaryNode>()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"pn->is<UnaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 873); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { *((volatile int*)__null) = 873; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
874 *answer = sc->needsThisTDZChecks();
875 return true;
876
877 // |new.target| doesn't have any side-effects.
878 case ParseNodeKind::NewTargetExpr: {
879 MOZ_ASSERT(pn->is<NewTargetNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<NewTargetNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<NewTargetNode>
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("pn->is<NewTargetNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 879); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<NewTargetNode>()"
")"); do { *((volatile int*)__null) = 879; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
880 *answer = false;
881 return true;
882 }
883
884 // Trivial binary nodes with more token pos holders.
885 case ParseNodeKind::ImportMetaExpr: {
886 MOZ_ASSERT(pn->as<BinaryNode>().left()->isKind(ParseNodeKind::PosHolder))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->as<BinaryNode>().left()->isKind(ParseNodeKind
::PosHolder))>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(pn->as<BinaryNode>().left
()->isKind(ParseNodeKind::PosHolder)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("pn->as<BinaryNode>().left()->isKind(ParseNodeKind::PosHolder)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 886); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->as<BinaryNode>().left()->isKind(ParseNodeKind::PosHolder)"
")"); do { *((volatile int*)__null) = 886; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
887 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->as<BinaryNode>().right()->isKind(ParseNodeKind
::PosHolder))>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(pn->as<BinaryNode>().right
()->isKind(ParseNodeKind::PosHolder)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("pn->as<BinaryNode>().right()->isKind(ParseNodeKind::PosHolder)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 888); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->as<BinaryNode>().right()->isKind(ParseNodeKind::PosHolder)"
")"); do { *((volatile int*)__null) = 888; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
888 pn->as<BinaryNode>().right()->isKind(ParseNodeKind::PosHolder))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->as<BinaryNode>().right()->isKind(ParseNodeKind
::PosHolder))>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(pn->as<BinaryNode>().right
()->isKind(ParseNodeKind::PosHolder)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("pn->as<BinaryNode>().right()->isKind(ParseNodeKind::PosHolder)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 888); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->as<BinaryNode>().right()->isKind(ParseNodeKind::PosHolder)"
")"); do { *((volatile int*)__null) = 888; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
889 *answer = false;
890 return true;
891 }
892
893 case ParseNodeKind::BreakStmt:
894 MOZ_ASSERT(pn->is<BreakStatement>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<BreakStatement>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<BreakStatement>
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("pn->is<BreakStatement>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 894); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BreakStatement>()"
")"); do { *((volatile int*)__null) = 894; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
895 *answer = true;
896 return true;
897
898 case ParseNodeKind::ContinueStmt:
899 MOZ_ASSERT(pn->is<ContinueStatement>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<ContinueStatement>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<ContinueStatement
>()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("pn->is<ContinueStatement>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 899); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<ContinueStatement>()"
")"); do { *((volatile int*)__null) = 899; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
900 *answer = true;
901 return true;
902
903 case ParseNodeKind::DebuggerStmt:
904 MOZ_ASSERT(pn->is<DebuggerStatement>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<DebuggerStatement>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<DebuggerStatement
>()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("pn->is<DebuggerStatement>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 904); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<DebuggerStatement>()"
")"); do { *((volatile int*)__null) = 904; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
905 *answer = true;
906 return true;
907
908 // Watch out for getters!
909 case ParseNodeKind::OptionalDotExpr:
910 case ParseNodeKind::DotExpr:
911 case ParseNodeKind::ArgumentsLength:
912 MOZ_ASSERT(pn->is<BinaryNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<BinaryNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<BinaryNode>(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("pn->is<BinaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 912); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { *((volatile int*)__null) = 912; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
913 *answer = true;
914 return true;
915
916 // Unary cases with side effects only if the child has them.
917 case ParseNodeKind::TypeOfExpr:
918 case ParseNodeKind::VoidExpr:
919 case ParseNodeKind::NotExpr:
920 return checkSideEffects(pn->as<UnaryNode>().kid(), answer);
921
922 // Even if the name expression is effect-free, performing ToPropertyKey on
923 // it might not be effect-free:
924 //
925 // RegExp.prototype.toString = () => { throw 42; };
926 // ({ [/regex/]: 0 }); // ToPropertyKey(/regex/) throws 42
927 //
928 // function Q() {
929 // ({ [new.target]: 0 });
930 // }
931 // Q.toString = () => { throw 17; };
932 // new Q; // new.target will be Q, ToPropertyKey(Q) throws 17
933 case ParseNodeKind::ComputedName:
934 MOZ_ASSERT(pn->is<UnaryNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<UnaryNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<UnaryNode>()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"pn->is<UnaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 934); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { *((volatile int*)__null) = 934; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
935 *answer = true;
936 return true;
937
938 // Looking up or evaluating the associated name could throw.
939 case ParseNodeKind::TypeOfNameExpr:
940 MOZ_ASSERT(pn->is<UnaryNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<UnaryNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<UnaryNode>()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"pn->is<UnaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 940); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { *((volatile int*)__null) = 940; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
941 *answer = true;
942 return true;
943
944 // This unary case has side effects on the enclosing object, sure. But
945 // that's not the question this function answers: it's whether the
946 // operation may have a side effect on something *other* than the result
947 // of the overall operation in which it's embedded. The answer to that
948 // is no, because an object literal having a mutated prototype only
949 // produces a value, without affecting anything else.
950 case ParseNodeKind::MutateProto:
951 return checkSideEffects(pn->as<UnaryNode>().kid(), answer);
952
953 // Unary cases with obvious side effects.
954 case ParseNodeKind::PreIncrementExpr:
955 case ParseNodeKind::PostIncrementExpr:
956 case ParseNodeKind::PreDecrementExpr:
957 case ParseNodeKind::PostDecrementExpr:
958 case ParseNodeKind::ThrowStmt:
959 MOZ_ASSERT(pn->is<UnaryNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<UnaryNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<UnaryNode>()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"pn->is<UnaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 959); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { *((volatile int*)__null) = 959; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
960 *answer = true;
961 return true;
962
963 // These might invoke valueOf/toString, even with a subexpression without
964 // side effects! Consider |+{ valueOf: null, toString: null }|.
965 case ParseNodeKind::BitNotExpr:
966 case ParseNodeKind::PosExpr:
967 case ParseNodeKind::NegExpr:
968 MOZ_ASSERT(pn->is<UnaryNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<UnaryNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<UnaryNode>()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"pn->is<UnaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 968); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { *((volatile int*)__null) = 968; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
969 *answer = true;
970 return true;
971
972 // This invokes the (user-controllable) iterator protocol.
973 case ParseNodeKind::Spread:
974 MOZ_ASSERT(pn->is<UnaryNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<UnaryNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<UnaryNode>()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"pn->is<UnaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 974); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { *((volatile int*)__null) = 974; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
975 *answer = true;
976 return true;
977
978 case ParseNodeKind::InitialYield:
979 case ParseNodeKind::YieldStarExpr:
980 case ParseNodeKind::YieldExpr:
981 case ParseNodeKind::AwaitExpr:
982 MOZ_ASSERT(pn->is<UnaryNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<UnaryNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<UnaryNode>()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"pn->is<UnaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 982); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { *((volatile int*)__null) = 982; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
983 *answer = true;
984 return true;
985
986 // Deletion generally has side effects, even if isolated cases have none.
987 case ParseNodeKind::DeleteNameExpr:
988 case ParseNodeKind::DeletePropExpr:
989 case ParseNodeKind::DeleteElemExpr:
990 case ParseNodeKind::DeleteOptionalChainExpr:
991 MOZ_ASSERT(pn->is<UnaryNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<UnaryNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<UnaryNode>()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"pn->is<UnaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 991); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { *((volatile int*)__null) = 991; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
992 *answer = true;
993 return true;
994
995 // Deletion of a non-Reference expression has side effects only through
996 // evaluating the expression.
997 case ParseNodeKind::DeleteExpr: {
998 ParseNode* expr = pn->as<UnaryNode>().kid();
999 return checkSideEffects(expr, answer);
1000 }
1001
1002 case ParseNodeKind::ExpressionStmt:
1003 return checkSideEffects(pn->as<UnaryNode>().kid(), answer);
1004
1005 // Binary cases with obvious side effects.
1006 case ParseNodeKind::InitExpr:
1007 *answer = true;
1008 return true;
1009
1010 case ParseNodeKind::AssignExpr:
1011 case ParseNodeKind::AddAssignExpr:
1012 case ParseNodeKind::SubAssignExpr:
1013 case ParseNodeKind::CoalesceAssignExpr:
1014 case ParseNodeKind::OrAssignExpr:
1015 case ParseNodeKind::AndAssignExpr:
1016 case ParseNodeKind::BitOrAssignExpr:
1017 case ParseNodeKind::BitXorAssignExpr:
1018 case ParseNodeKind::BitAndAssignExpr:
1019 case ParseNodeKind::LshAssignExpr:
1020 case ParseNodeKind::RshAssignExpr:
1021 case ParseNodeKind::UrshAssignExpr:
1022 case ParseNodeKind::MulAssignExpr:
1023 case ParseNodeKind::DivAssignExpr:
1024 case ParseNodeKind::ModAssignExpr:
1025 case ParseNodeKind::PowAssignExpr:
1026 MOZ_ASSERT(pn->is<AssignmentNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<AssignmentNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<AssignmentNode>
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("pn->is<AssignmentNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1026); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<AssignmentNode>()"
")"); do { *((volatile int*)__null) = 1026; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1027 *answer = true;
1028 return true;
1029
1030 case ParseNodeKind::SetThis:
1031 MOZ_ASSERT(pn->is<BinaryNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<BinaryNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<BinaryNode>(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("pn->is<BinaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1031); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { *((volatile int*)__null) = 1031; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1032 *answer = true;
1033 return true;
1034
1035 case ParseNodeKind::StatementList:
1036 // Strict equality operations and short circuit operators are well-behaved
1037 // and perform no conversions.
1038 case ParseNodeKind::CoalesceExpr:
1039 case ParseNodeKind::OrExpr:
1040 case ParseNodeKind::AndExpr:
1041 case ParseNodeKind::StrictEqExpr:
1042 case ParseNodeKind::StrictNeExpr:
1043 // Any subexpression of a comma expression could be effectful.
1044 case ParseNodeKind::CommaExpr:
1045 MOZ_ASSERT(!pn->as<ListNode>().empty())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!pn->as<ListNode>().empty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!pn->as<ListNode>()
.empty()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!pn->as<ListNode>().empty()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1045); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!pn->as<ListNode>().empty()"
")"); do { *((volatile int*)__null) = 1045; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1046 [[fallthrough]];
1047 // Subcomponents of a literal may be effectful.
1048 case ParseNodeKind::ArrayExpr:
1049 case ParseNodeKind::ObjectExpr:
1050 for (ParseNode* item : pn->as<ListNode>().contents()) {
1051 if (!checkSideEffects(item, answer)) {
1052 return false;
1053 }
1054 if (*answer) {
1055 return true;
1056 }
1057 }
1058 return true;
1059
1060#ifdef ENABLE_RECORD_TUPLE
1061 case ParseNodeKind::RecordExpr:
1062 case ParseNodeKind::TupleExpr:
1063 MOZ_CRASH("Record and Tuple are not supported yet")do { do { } while (false); MOZ_ReportCrash("" "Record and Tuple are not supported yet"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1063); AnnotateMozCrashReason("MOZ_CRASH(" "Record and Tuple are not supported yet"
")"); do { *((volatile int*)__null) = 1063; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
1064#endif
1065
1066#ifdef ENABLE_DECORATORS
1067 case ParseNodeKind::DecoratorList:
1068 MOZ_CRASH("Decorators are not supported yet")do { do { } while (false); MOZ_ReportCrash("" "Decorators are not supported yet"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1068); AnnotateMozCrashReason("MOZ_CRASH(" "Decorators are not supported yet"
")"); do { *((volatile int*)__null) = 1068; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
1069#endif
1070
1071#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT1
1072 case ParseNodeKind::UsingDecl:
1073 case ParseNodeKind::AwaitUsingDecl:
1074 MOZ_CRASH("Using declarations are not supported yet")do { do { } while (false); MOZ_ReportCrash("" "Using declarations are not supported yet"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1074); AnnotateMozCrashReason("MOZ_CRASH(" "Using declarations are not supported yet"
")"); do { *((volatile int*)__null) = 1074; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
1075#endif
1076
1077 // Most other binary operations (parsed as lists in SpiderMonkey) may
1078 // perform conversions triggering side effects. Math operations perform
1079 // ToNumber and may fail invoking invalid user-defined toString/valueOf:
1080 // |5 < { toString: null }|. |instanceof| throws if provided a
1081 // non-object constructor: |null instanceof null|. |in| throws if given
1082 // a non-object RHS: |5 in null|.
1083 case ParseNodeKind::BitOrExpr:
1084 case ParseNodeKind::BitXorExpr:
1085 case ParseNodeKind::BitAndExpr:
1086 case ParseNodeKind::EqExpr:
1087 case ParseNodeKind::NeExpr:
1088 case ParseNodeKind::LtExpr:
1089 case ParseNodeKind::LeExpr:
1090 case ParseNodeKind::GtExpr:
1091 case ParseNodeKind::GeExpr:
1092 case ParseNodeKind::InstanceOfExpr:
1093 case ParseNodeKind::InExpr:
1094 case ParseNodeKind::PrivateInExpr:
1095 case ParseNodeKind::LshExpr:
1096 case ParseNodeKind::RshExpr:
1097 case ParseNodeKind::UrshExpr:
1098 case ParseNodeKind::AddExpr:
1099 case ParseNodeKind::SubExpr:
1100 case ParseNodeKind::MulExpr:
1101 case ParseNodeKind::DivExpr:
1102 case ParseNodeKind::ModExpr:
1103 case ParseNodeKind::PowExpr:
1104 MOZ_ASSERT(pn->as<ListNode>().count() >= 2)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->as<ListNode>().count() >= 2)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(pn->as<ListNode>().count() >= 2))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("pn->as<ListNode>().count() >= 2"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1104); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->as<ListNode>().count() >= 2"
")"); do { *((volatile int*)__null) = 1104; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1105 *answer = true;
1106 return true;
1107
1108 case ParseNodeKind::PropertyDefinition:
1109 case ParseNodeKind::Case: {
1110 BinaryNode* node = &pn->as<BinaryNode>();
1111 if (!checkSideEffects(node->left(), answer)) {
1112 return false;
1113 }
1114 if (*answer) {
1115 return true;
1116 }
1117 return checkSideEffects(node->right(), answer);
1118 }
1119
1120 // More getters.
1121 case ParseNodeKind::ElemExpr:
1122 case ParseNodeKind::OptionalElemExpr:
1123 MOZ_ASSERT(pn->is<BinaryNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<BinaryNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<BinaryNode>(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("pn->is<BinaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1123); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { *((volatile int*)__null) = 1123; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1124 *answer = true;
1125 return true;
1126
1127 // Throws if the operand is not of the right class. Can also call a private
1128 // getter.
1129 case ParseNodeKind::PrivateMemberExpr:
1130 case ParseNodeKind::OptionalPrivateMemberExpr:
1131 *answer = true;
1132 return true;
1133
1134 // These affect visible names in this code, or in other code.
1135 case ParseNodeKind::ImportDecl:
1136 case ParseNodeKind::ExportFromStmt:
1137 case ParseNodeKind::ExportDefaultStmt:
1138 MOZ_ASSERT(pn->is<BinaryNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<BinaryNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<BinaryNode>(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("pn->is<BinaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1138); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { *((volatile int*)__null) = 1138; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1139 *answer = true;
1140 return true;
1141
1142 // Likewise.
1143 case ParseNodeKind::ExportStmt:
1144 MOZ_ASSERT(pn->is<UnaryNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<UnaryNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<UnaryNode>()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"pn->is<UnaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1144); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { *((volatile int*)__null) = 1144; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1145 *answer = true;
1146 return true;
1147
1148 case ParseNodeKind::CallImportExpr:
1149 case ParseNodeKind::CallImportSpec:
1150 MOZ_ASSERT(pn->is<BinaryNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<BinaryNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<BinaryNode>(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("pn->is<BinaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1150); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { *((volatile int*)__null) = 1150; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1151 *answer = true;
1152 return true;
1153
1154 // Every part of a loop might be effect-free, but looping infinitely *is*
1155 // an effect. (Language lawyer trivia: C++ says threads can be assumed
1156 // to exit or have side effects, C++14 [intro.multithread]p27, so a C++
1157 // implementation's equivalent of the below could set |*answer = false;|
1158 // if all loop sub-nodes set |*answer = false|!)
1159 case ParseNodeKind::DoWhileStmt:
1160 case ParseNodeKind::WhileStmt:
1161 case ParseNodeKind::ForStmt:
1162 MOZ_ASSERT(pn->is<BinaryNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<BinaryNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<BinaryNode>(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("pn->is<BinaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1162); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { *((volatile int*)__null) = 1162; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1163 *answer = true;
1164 return true;
1165
1166 // Declarations affect the name set of the relevant scope.
1167 case ParseNodeKind::VarStmt:
1168 case ParseNodeKind::ConstDecl:
1169 case ParseNodeKind::LetDecl:
1170 MOZ_ASSERT(pn->is<ListNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<ListNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<ListNode>())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("pn->is<ListNode>()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1170); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<ListNode>()"
")"); do { *((volatile int*)__null) = 1170; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1171 *answer = true;
1172 return true;
1173
1174 case ParseNodeKind::IfStmt:
1175 case ParseNodeKind::ConditionalExpr: {
1176 TernaryNode* node = &pn->as<TernaryNode>();
1177 if (!checkSideEffects(node->kid1(), answer)) {
1178 return false;
1179 }
1180 if (*answer) {
1181 return true;
1182 }
1183 if (!checkSideEffects(node->kid2(), answer)) {
1184 return false;
1185 }
1186 if (*answer) {
1187 return true;
1188 }
1189 if ((pn = node->kid3())) {
1190 goto restart;
1191 }
1192 return true;
1193 }
1194
1195 // Function calls can invoke non-local code.
1196 case ParseNodeKind::NewExpr:
1197 case ParseNodeKind::CallExpr:
1198 case ParseNodeKind::OptionalCallExpr:
1199 case ParseNodeKind::TaggedTemplateExpr:
1200 case ParseNodeKind::SuperCallExpr:
1201 MOZ_ASSERT(pn->is<BinaryNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<BinaryNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<BinaryNode>(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("pn->is<BinaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1201); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { *((volatile int*)__null) = 1201; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1202 *answer = true;
1203 return true;
1204
1205 // Function arg lists can contain arbitrary expressions. Technically
1206 // this only causes side-effects if one of the arguments does, but since
1207 // the call being made will always trigger side-effects, it isn't needed.
1208 case ParseNodeKind::Arguments:
1209 MOZ_ASSERT(pn->is<ListNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<ListNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<ListNode>())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("pn->is<ListNode>()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1209); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<ListNode>()"
")"); do { *((volatile int*)__null) = 1209; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1210 *answer = true;
1211 return true;
1212
1213 case ParseNodeKind::OptionalChain:
1214 MOZ_ASSERT(pn->is<UnaryNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<UnaryNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<UnaryNode>()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"pn->is<UnaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1214); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { *((volatile int*)__null) = 1214; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1215 *answer = true;
1216 return true;
1217
1218 // Classes typically introduce names. Even if no name is introduced,
1219 // the heritage and/or class body (through computed property names)
1220 // usually have effects.
1221 case ParseNodeKind::ClassDecl:
1222 MOZ_ASSERT(pn->is<ClassNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<ClassNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<ClassNode>()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"pn->is<ClassNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1222); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<ClassNode>()"
")"); do { *((volatile int*)__null) = 1222; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1223 *answer = true;
1224 return true;
1225
1226 // |with| calls |ToObject| on its expression and so throws if that value
1227 // is null/undefined.
1228 case ParseNodeKind::WithStmt:
1229 MOZ_ASSERT(pn->is<BinaryNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<BinaryNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<BinaryNode>(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("pn->is<BinaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1229); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { *((volatile int*)__null) = 1229; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1230 *answer = true;
1231 return true;
1232
1233 case ParseNodeKind::ReturnStmt:
1234 MOZ_ASSERT(pn->is<BinaryNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<BinaryNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<BinaryNode>(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("pn->is<BinaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1234); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { *((volatile int*)__null) = 1234; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1235 *answer = true;
1236 return true;
1237
1238 case ParseNodeKind::Name:
1239 MOZ_ASSERT(pn->is<NameNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<NameNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<NameNode>())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("pn->is<NameNode>()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1239); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<NameNode>()"
")"); do { *((volatile int*)__null) = 1239; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1240 *answer = true;
1241 return true;
1242
1243 // Shorthands could trigger getters: the |x| in the object literal in
1244 // |with ({ get x() { throw 42; } }) ({ x });|, for example, triggers
1245 // one. (Of course, it isn't necessary to use |with| for a shorthand to
1246 // trigger a getter.)
1247 case ParseNodeKind::Shorthand:
1248 MOZ_ASSERT(pn->is<BinaryNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<BinaryNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<BinaryNode>(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("pn->is<BinaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1248); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { *((volatile int*)__null) = 1248; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1249 *answer = true;
1250 return true;
1251
1252 case ParseNodeKind::Function:
1253 MOZ_ASSERT(pn->is<FunctionNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<FunctionNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<FunctionNode>
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("pn->is<FunctionNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1253); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<FunctionNode>()"
")"); do { *((volatile int*)__null) = 1253; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1254 /*
1255 * A named function, contrary to ES3, is no longer effectful, because
1256 * we bind its name lexically (using JSOp::Callee) instead of creating
1257 * an Object instance and binding a readonly, permanent property in it
1258 * (the object and binding can be detected and hijacked or captured).
1259 * This is a bug fix to ES3; it is fixed in ES3.1 drafts.
1260 */
1261 *answer = false;
1262 return true;
1263
1264 case ParseNodeKind::Module:
1265 *answer = false;
1266 return true;
1267
1268 case ParseNodeKind::TryStmt: {
1269 TryNode* tryNode = &pn->as<TryNode>();
1270 if (!checkSideEffects(tryNode->body(), answer)) {
1271 return false;
1272 }
1273 if (*answer) {
1274 return true;
1275 }
1276 if (LexicalScopeNode* catchScope = tryNode->catchScope()) {
1277 if (!checkSideEffects(catchScope, answer)) {
1278 return false;
1279 }
1280 if (*answer) {
1281 return true;
1282 }
1283 }
1284 if (ParseNode* finallyBlock = tryNode->finallyBlock()) {
1285 if (!checkSideEffects(finallyBlock, answer)) {
1286 return false;
1287 }
1288 }
1289 return true;
1290 }
1291
1292 case ParseNodeKind::Catch: {
1293 BinaryNode* catchClause = &pn->as<BinaryNode>();
1294 if (ParseNode* name = catchClause->left()) {
1295 if (!checkSideEffects(name, answer)) {
1296 return false;
1297 }
1298 if (*answer) {
1299 return true;
1300 }
1301 }
1302 return checkSideEffects(catchClause->right(), answer);
1303 }
1304
1305 case ParseNodeKind::SwitchStmt: {
1306 SwitchStatement* switchStmt = &pn->as<SwitchStatement>();
1307 if (!checkSideEffects(&switchStmt->discriminant(), answer)) {
1308 return false;
1309 }
1310 return *answer ||
1311 checkSideEffects(&switchStmt->lexicalForCaseList(), answer);
1312 }
1313
1314 case ParseNodeKind::LabelStmt:
1315 return checkSideEffects(pn->as<LabeledStatement>().statement(), answer);
1316
1317 case ParseNodeKind::LexicalScope:
1318 return checkSideEffects(pn->as<LexicalScopeNode>().scopeBody(), answer);
1319
1320 // We could methodically check every interpolated expression, but it's
1321 // probably not worth the trouble. Treat template strings as effect-free
1322 // only if they don't contain any substitutions.
1323 case ParseNodeKind::TemplateStringListExpr: {
1324 ListNode* list = &pn->as<ListNode>();
1325 MOZ_ASSERT(!list->empty())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!list->empty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!list->empty()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!list->empty()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1325); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!list->empty()"
")"); do { *((volatile int*)__null) = 1325; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1326 MOZ_ASSERT((list->count() % 2) == 1,do { static_assert( mozilla::detail::AssertionConditionType<
decltype((list->count() % 2) == 1)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!((list->count() % 2) == 1)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("(list->count() % 2) == 1"
" (" "template strings must alternate template and substitution "
"parts" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1328); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(list->count() % 2) == 1"
") (" "template strings must alternate template and substitution "
"parts" ")"); do { *((volatile int*)__null) = 1328; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
1327 "template strings must alternate template and substitution "do { static_assert( mozilla::detail::AssertionConditionType<
decltype((list->count() % 2) == 1)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!((list->count() % 2) == 1)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("(list->count() % 2) == 1"
" (" "template strings must alternate template and substitution "
"parts" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1328); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(list->count() % 2) == 1"
") (" "template strings must alternate template and substitution "
"parts" ")"); do { *((volatile int*)__null) = 1328; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
1328 "parts")do { static_assert( mozilla::detail::AssertionConditionType<
decltype((list->count() % 2) == 1)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!((list->count() % 2) == 1)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("(list->count() % 2) == 1"
" (" "template strings must alternate template and substitution "
"parts" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1328); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(list->count() % 2) == 1"
") (" "template strings must alternate template and substitution "
"parts" ")"); do { *((volatile int*)__null) = 1328; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
1329 *answer = list->count() > 1;
1330 return true;
1331 }
1332
1333 // This should be unreachable but is left as-is for now.
1334 case ParseNodeKind::ParamsBody:
1335 *answer = true;
1336 return true;
1337
1338 case ParseNodeKind::ForIn: // by ParseNodeKind::For
1339 case ParseNodeKind::ForOf: // by ParseNodeKind::For
1340 case ParseNodeKind::ForHead: // by ParseNodeKind::For
1341 case ParseNodeKind::DefaultConstructor: // by ParseNodeKind::ClassDecl
1342 case ParseNodeKind::ClassBodyScope: // by ParseNodeKind::ClassDecl
1343 case ParseNodeKind::ClassMethod: // by ParseNodeKind::ClassDecl
1344 case ParseNodeKind::ClassField: // by ParseNodeKind::ClassDecl
1345 case ParseNodeKind::ClassNames: // by ParseNodeKind::ClassDecl
1346 case ParseNodeKind::StaticClassBlock: // by ParseNodeKind::ClassDecl
1347 case ParseNodeKind::ClassMemberList: // by ParseNodeKind::ClassDecl
1348 case ParseNodeKind::ImportSpecList: // by ParseNodeKind::Import
1349 case ParseNodeKind::ImportSpec: // by ParseNodeKind::Import
1350 case ParseNodeKind::ImportNamespaceSpec: // by ParseNodeKind::Import
1351 case ParseNodeKind::ImportAttribute: // by ParseNodeKind::Import
1352 case ParseNodeKind::ImportAttributeList: // by ParseNodeKind::Import
1353 case ParseNodeKind::ImportModuleRequest: // by ParseNodeKind::Import
1354 case ParseNodeKind::ExportBatchSpecStmt: // by ParseNodeKind::Export
1355 case ParseNodeKind::ExportSpecList: // by ParseNodeKind::Export
1356 case ParseNodeKind::ExportSpec: // by ParseNodeKind::Export
1357 case ParseNodeKind::ExportNamespaceSpec: // by ParseNodeKind::Export
1358 case ParseNodeKind::CallSiteObj: // by ParseNodeKind::TaggedTemplate
1359 case ParseNodeKind::PosHolder: // by ParseNodeKind::NewTarget
1360 case ParseNodeKind::SuperBase: // by ParseNodeKind::Elem and others
1361 case ParseNodeKind::PropertyNameExpr: // by ParseNodeKind::Dot
1362 MOZ_CRASH("handled by parent nodes")do { do { } while (false); MOZ_ReportCrash("" "handled by parent nodes"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1362); AnnotateMozCrashReason("MOZ_CRASH(" "handled by parent nodes"
")"); do { *((volatile int*)__null) = 1362; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
1363
1364 case ParseNodeKind::LastUnused:
1365 case ParseNodeKind::Limit:
1366 MOZ_CRASH("invalid node kind")do { do { } while (false); MOZ_ReportCrash("" "invalid node kind"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1366); AnnotateMozCrashReason("MOZ_CRASH(" "invalid node kind"
")"); do { *((volatile int*)__null) = 1366; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
1367 }
1368
1369 MOZ_CRASH(do { do { } while (false); MOZ_ReportCrash("" "invalid, unenumerated ParseNodeKind value encountered in "
"BytecodeEmitter::checkSideEffects", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1371); AnnotateMozCrashReason("MOZ_CRASH(" "invalid, unenumerated ParseNodeKind value encountered in "
"BytecodeEmitter::checkSideEffects" ")"); do { *((volatile int
*)__null) = 1371; __attribute__((nomerge)) ::abort(); } while
(false); } while (false)
1370 "invalid, unenumerated ParseNodeKind value encountered in "do { do { } while (false); MOZ_ReportCrash("" "invalid, unenumerated ParseNodeKind value encountered in "
"BytecodeEmitter::checkSideEffects", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1371); AnnotateMozCrashReason("MOZ_CRASH(" "invalid, unenumerated ParseNodeKind value encountered in "
"BytecodeEmitter::checkSideEffects" ")"); do { *((volatile int
*)__null) = 1371; __attribute__((nomerge)) ::abort(); } while
(false); } while (false)
1371 "BytecodeEmitter::checkSideEffects")do { do { } while (false); MOZ_ReportCrash("" "invalid, unenumerated ParseNodeKind value encountered in "
"BytecodeEmitter::checkSideEffects", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1371); AnnotateMozCrashReason("MOZ_CRASH(" "invalid, unenumerated ParseNodeKind value encountered in "
"BytecodeEmitter::checkSideEffects" ")"); do { *((volatile int
*)__null) = 1371; __attribute__((nomerge)) ::abort(); } while
(false); } while (false)
;
1372}
1373
1374bool BytecodeEmitter::isInLoop() const {
1375 return findInnermostNestableControl<LoopControl>();
1376}
1377
1378bool BytecodeEmitter::checkSingletonContext() const {
1379 MOZ_ASSERT_IF(sc->treatAsRunOnce(), sc->isTopLevelContext())do { if (sc->treatAsRunOnce()) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(sc->isTopLevelContext
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(sc->isTopLevelContext()))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("sc->isTopLevelContext()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1379); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isTopLevelContext()"
")"); do { *((volatile int*)__null) = 1379; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
1380 return sc->treatAsRunOnce() && !isInLoop();
1381}
1382
1383bool BytecodeEmitter::needsImplicitThis() const {
1384 // Short-circuit if there is an enclosing 'with' scope.
1385 if (sc->inWith()) {
1386 return true;
1387 }
1388
1389 // Otherwise see if the current point is under a 'with'.
1390 for (EmitterScope* es = innermostEmitterScope(); es;
1391 es = es->enclosingInFrame()) {
1392 if (es->scope(this).kind() == ScopeKind::With) {
1393 return true;
1394 }
1395 }
1396
1397 return false;
1398}
1399
1400size_t BytecodeEmitter::countThisEnvironmentHops() const {
1401 unsigned numHops = 0;
1402
1403 for (const auto* current = this; current; current = current->parent) {
1404 for (EmitterScope* es = current->innermostEmitterScope(); es;
1405 es = es->enclosingInFrame()) {
1406 if (es->scope(current).is<FunctionScope>()) {
1407 if (!es->scope(current).isArrow()) {
1408 // The Parser is responsible for marking the environment as either
1409 // closed-over or used-by-eval which ensure that is must exist.
1410 MOZ_ASSERT(es->scope(current).hasEnvironment())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(es->scope(current).hasEnvironment())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(es->scope(current).hasEnvironment()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("es->scope(current).hasEnvironment()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1410); AnnotateMozCrashReason("MOZ_ASSERT" "(" "es->scope(current).hasEnvironment()"
")"); do { *((volatile int*)__null) = 1410; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1411 return numHops;
1412 }
1413 }
1414 if (es->scope(current).hasEnvironment()) {
1415 numHops++;
1416 }
1417 }
1418 }
1419
1420 // The "this" environment exists outside of the compilation, but the
1421 // `ScopeContext` recorded the number of additional hops needed, so add
1422 // those in now.
1423 MOZ_ASSERT(sc->allowSuperProperty())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sc->allowSuperProperty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sc->allowSuperProperty())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("sc->allowSuperProperty()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1423); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->allowSuperProperty()"
")"); do { *((volatile int*)__null) = 1423; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1424 numHops += compilationState.scopeContext.enclosingThisEnvironmentHops;
1425 return numHops;
1426}
1427
1428bool BytecodeEmitter::emitThisEnvironmentCallee() {
1429 // Get the innermost enclosing function that has a |this| binding.
1430
1431 // Directly load callee from the frame if possible.
1432 if (sc->isFunctionBox() && !sc->asFunctionBox()->isArrow()) {
1433 return emit1(JSOp::Callee);
1434 }
1435
1436 // We have to load the callee from the environment chain.
1437 size_t numHops = countThisEnvironmentHops();
1438
1439 static_assert(
1440 ENVCOORD_HOPS_LIMIT - 1 <= UINT8_MAX(255),
1441 "JSOp::EnvCallee operand size should match ENVCOORD_HOPS_LIMIT");
1442
1443 MOZ_ASSERT(numHops < ENVCOORD_HOPS_LIMIT - 1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(numHops < ENVCOORD_HOPS_LIMIT - 1)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(numHops < ENVCOORD_HOPS_LIMIT
- 1))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("numHops < ENVCOORD_HOPS_LIMIT - 1", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1443); AnnotateMozCrashReason("MOZ_ASSERT" "(" "numHops < ENVCOORD_HOPS_LIMIT - 1"
")"); do { *((volatile int*)__null) = 1443; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1444
1445 return emit2(JSOp::EnvCallee, numHops);
1446}
1447
1448bool BytecodeEmitter::emitSuperBase() {
1449 if (!emitThisEnvironmentCallee()) {
1450 return false;
1451 }
1452
1453 return emit1(JSOp::SuperBase);
1454}
1455
1456void BytecodeEmitter::reportError(ParseNode* pn, unsigned errorNumber,
1457 ...) const {
1458 uint32_t offset = pn ? pn->pn_pos.begin : *scriptStartOffset;
1459
1460 va_list args;
1461 va_start(args, errorNumber)__builtin_va_start(args, errorNumber);
1462
1463 errorReporter().errorWithNotesAtVA(nullptr, AsVariant(offset), errorNumber,
1464 &args);
1465
1466 va_end(args)__builtin_va_end(args);
1467}
1468
1469void BytecodeEmitter::reportError(uint32_t offset, unsigned errorNumber,
1470 ...) const {
1471 va_list args;
1472 va_start(args, errorNumber)__builtin_va_start(args, errorNumber);
1473
1474 errorReporter().errorWithNotesAtVA(nullptr, AsVariant(offset), errorNumber,
1475 &args);
1476
1477 va_end(args)__builtin_va_end(args);
1478}
1479
1480bool BytecodeEmitter::addObjLiteralData(ObjLiteralWriter& writer,
1481 GCThingIndex* outIndex) {
1482 if (!writer.checkForDuplicatedNames(fc)) {
1483 return false;
1484 }
1485
1486 size_t len = writer.getCode().size();
1487 auto* code = compilationState.alloc.newArrayUninitialized<uint8_t>(len);
1488 if (!code) {
1489 js::ReportOutOfMemory(fc);
1490 return false;
1491 }
1492 memcpy(code, writer.getCode().data(), len);
1493
1494 ObjLiteralIndex objIndex(compilationState.objLiteralData.length());
1495 if (uint32_t(objIndex) >= TaggedScriptThingIndex::IndexLimit) {
1496 ReportAllocationOverflow(fc);
1497 return false;
1498 }
1499 if (!compilationState.objLiteralData.emplaceBack(code, len, writer.getKind(),
1500 writer.getFlags(),
1501 writer.getPropertyCount())) {
1502 js::ReportOutOfMemory(fc);
1503 return false;
1504 }
1505
1506 return perScriptData().gcThingList().append(objIndex, outIndex);
1507}
1508
1509bool BytecodeEmitter::emitPrepareIteratorResult() {
1510 constexpr JSOp op = JSOp::NewObject;
1511
1512 ObjLiteralWriter writer;
1513 writer.beginShape(op);
1514
1515 writer.setPropNameNoDuplicateCheck(parserAtoms(),
1516 TaggedParserAtomIndex::WellKnown::value());
1517 if (!writer.propWithUndefinedValue(fc)) {
1518 return false;
1519 }
1520 writer.setPropNameNoDuplicateCheck(parserAtoms(),
1521 TaggedParserAtomIndex::WellKnown::done());
1522 if (!writer.propWithUndefinedValue(fc)) {
1523 return false;
1524 }
1525
1526 GCThingIndex shape;
1527 if (!addObjLiteralData(writer, &shape)) {
1528 return false;
1529 }
1530
1531 return emitGCIndexOp(op, shape);
1532}
1533
1534bool BytecodeEmitter::emitFinishIteratorResult(bool done) {
1535 if (!emitAtomOp(JSOp::InitProp, TaggedParserAtomIndex::WellKnown::value())) {
1536 return false;
1537 }
1538 if (!emit1(done ? JSOp::True : JSOp::False)) {
1539 return false;
1540 }
1541 if (!emitAtomOp(JSOp::InitProp, TaggedParserAtomIndex::WellKnown::done())) {
1542 return false;
1543 }
1544 return true;
1545}
1546
1547bool BytecodeEmitter::emitGetNameAtLocation(TaggedParserAtomIndex name,
1548 const NameLocation& loc) {
1549 NameOpEmitter noe(this, name, loc, NameOpEmitter::Kind::Get);
1550 if (!noe.emitGet()) {
1551 return false;
1552 }
1553
1554 return true;
1555}
1556
1557bool BytecodeEmitter::emitGetName(NameNode* name) {
1558 MOZ_ASSERT(name->isKind(ParseNodeKind::Name))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(name->isKind(ParseNodeKind::Name))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(name->isKind(ParseNodeKind
::Name)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("name->isKind(ParseNodeKind::Name)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1558); AnnotateMozCrashReason("MOZ_ASSERT" "(" "name->isKind(ParseNodeKind::Name)"
")"); do { *((volatile int*)__null) = 1558; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1559
1560 return emitGetName(name->name());
1561}
1562
1563bool BytecodeEmitter::emitGetPrivateName(NameNode* name) {
1564 MOZ_ASSERT(name->isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(name->isKind(ParseNodeKind::PrivateName))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(name->isKind(ParseNodeKind::PrivateName)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("name->isKind(ParseNodeKind::PrivateName)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1564); AnnotateMozCrashReason("MOZ_ASSERT" "(" "name->isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 1564; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1565 return emitGetPrivateName(name->name());
1566}
1567
1568bool BytecodeEmitter::emitGetPrivateName(TaggedParserAtomIndex nameAtom) {
1569 // The parser ensures the private name is present on the environment chain,
1570 // but its location can be Dynamic or Global when emitting debugger
1571 // eval-in-frame code.
1572 NameLocation location = lookupName(nameAtom);
1573 MOZ_ASSERT(location.kind() == NameLocation::Kind::FrameSlot ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(location.kind() == NameLocation::Kind::FrameSlot || location
.kind() == NameLocation::Kind::EnvironmentCoordinate || location
.kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation
::Kind::Global)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(location.kind() == NameLocation
::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate
|| location.kind() == NameLocation::Kind::Dynamic || location
.kind() == NameLocation::Kind::Global))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("location.kind() == NameLocation::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate || location.kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation::Kind::Global"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1576); AnnotateMozCrashReason("MOZ_ASSERT" "(" "location.kind() == NameLocation::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate || location.kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation::Kind::Global"
")"); do { *((volatile int*)__null) = 1576; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1574 location.kind() == NameLocation::Kind::EnvironmentCoordinate ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(location.kind() == NameLocation::Kind::FrameSlot || location
.kind() == NameLocation::Kind::EnvironmentCoordinate || location
.kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation
::Kind::Global)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(location.kind() == NameLocation
::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate
|| location.kind() == NameLocation::Kind::Dynamic || location
.kind() == NameLocation::Kind::Global))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("location.kind() == NameLocation::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate || location.kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation::Kind::Global"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1576); AnnotateMozCrashReason("MOZ_ASSERT" "(" "location.kind() == NameLocation::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate || location.kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation::Kind::Global"
")"); do { *((volatile int*)__null) = 1576; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1575 location.kind() == NameLocation::Kind::Dynamic ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(location.kind() == NameLocation::Kind::FrameSlot || location
.kind() == NameLocation::Kind::EnvironmentCoordinate || location
.kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation
::Kind::Global)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(location.kind() == NameLocation
::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate
|| location.kind() == NameLocation::Kind::Dynamic || location
.kind() == NameLocation::Kind::Global))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("location.kind() == NameLocation::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate || location.kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation::Kind::Global"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1576); AnnotateMozCrashReason("MOZ_ASSERT" "(" "location.kind() == NameLocation::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate || location.kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation::Kind::Global"
")"); do { *((volatile int*)__null) = 1576; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1576 location.kind() == NameLocation::Kind::Global)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(location.kind() == NameLocation::Kind::FrameSlot || location
.kind() == NameLocation::Kind::EnvironmentCoordinate || location
.kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation
::Kind::Global)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(location.kind() == NameLocation
::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate
|| location.kind() == NameLocation::Kind::Dynamic || location
.kind() == NameLocation::Kind::Global))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("location.kind() == NameLocation::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate || location.kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation::Kind::Global"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1576); AnnotateMozCrashReason("MOZ_ASSERT" "(" "location.kind() == NameLocation::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate || location.kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation::Kind::Global"
")"); do { *((volatile int*)__null) = 1576; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1577
1578 return emitGetNameAtLocation(nameAtom, location);
1579}
1580
1581bool BytecodeEmitter::emitTDZCheckIfNeeded(TaggedParserAtomIndex name,
1582 const NameLocation& loc,
1583 ValueIsOnStack isOnStack) {
1584 // Dynamic accesses have TDZ checks built into their VM code and should
1585 // never emit explicit TDZ checks.
1586 MOZ_ASSERT(loc.hasKnownSlot())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(loc.hasKnownSlot())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(loc.hasKnownSlot()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("loc.hasKnownSlot()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1586); AnnotateMozCrashReason("MOZ_ASSERT" "(" "loc.hasKnownSlot()"
")"); do { *((volatile int*)__null) = 1586; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1587 MOZ_ASSERT(loc.isLexical() || loc.isPrivateMethod() || loc.isSynthetic())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(loc.isLexical() || loc.isPrivateMethod() || loc.isSynthetic
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(loc.isLexical() || loc.isPrivateMethod() || loc.isSynthetic
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("loc.isLexical() || loc.isPrivateMethod() || loc.isSynthetic()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1587); AnnotateMozCrashReason("MOZ_ASSERT" "(" "loc.isLexical() || loc.isPrivateMethod() || loc.isSynthetic()"
")"); do { *((volatile int*)__null) = 1587; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1588
1589 // Private names are implemented as lexical bindings, but it's just an
1590 // implementation detail. Per spec there's no TDZ check when using them.
1591 if (parserAtoms().isPrivateName(name)) {
1592 return true;
1593 }
1594
1595 Maybe<MaybeCheckTDZ> check =
1596 innermostTDZCheckCache->needsTDZCheck(this, name);
1597 if (!check) {
1598 return false;
1599 }
1600
1601 // We've already emitted a check in this basic block.
1602 if (*check == DontCheckTDZ) {
1603 return true;
1604 }
1605
1606 // If the value is not on the stack, we have to load it first.
1607 if (isOnStack == ValueIsOnStack::No) {
1608 if (loc.kind() == NameLocation::Kind::FrameSlot) {
1609 if (!emitLocalOp(JSOp::GetLocal, loc.frameSlot())) {
1610 return false;
1611 }
1612 } else {
1613 if (!emitEnvCoordOp(JSOp::GetAliasedVar, loc.environmentCoordinate())) {
1614 return false;
1615 }
1616 }
1617 }
1618
1619 // Emit the lexical check.
1620 if (loc.kind() == NameLocation::Kind::FrameSlot) {
1621 if (!emitLocalOp(JSOp::CheckLexical, loc.frameSlot())) {
1622 return false;
1623 }
1624 } else {
1625 if (!emitEnvCoordOp(JSOp::CheckAliasedLexical,
1626 loc.environmentCoordinate())) {
1627 return false;
1628 }
1629 }
1630
1631 // Pop the value if needed.
1632 if (isOnStack == ValueIsOnStack::No) {
1633 if (!emit1(JSOp::Pop)) {
1634 return false;
1635 }
1636 }
1637
1638 return innermostTDZCheckCache->noteTDZCheck(this, name, DontCheckTDZ);
1639}
1640
1641bool BytecodeEmitter::emitPropLHS(PropertyAccess* prop) {
1642 MOZ_ASSERT(!prop->isSuper())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!prop->isSuper())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!prop->isSuper()))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("!prop->isSuper()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1642); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!prop->isSuper()"
")"); do { *((volatile int*)__null) = 1642; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1643
1644 ParseNode* expr = &prop->expression();
1645
1646 if (!expr->is<PropertyAccess>() || expr->as<PropertyAccess>().isSuper()) {
1647 // The non-optimized case.
1648 return emitTree(expr);
1649 }
1650
1651 // If the object operand is also a dotted property reference, reverse the
1652 // list linked via expression() temporarily so we can iterate over it from
1653 // the bottom up (reversing again as we go), to avoid excessive recursion.
1654 PropertyAccess* pndot = &expr->as<PropertyAccess>();
1655 ParseNode* pnup = nullptr;
1656 ParseNode* pndown;
1657 for (;;) {
1658 // Reverse pndot->expression() to point up, not down.
1659 pndown = &pndot->expression();
1660 pndot->setExpression(pnup);
1661 if (!pndown->is<PropertyAccess>() ||
1662 pndown->as<PropertyAccess>().isSuper()) {
1663 break;
1664 }
1665 pnup = pndot;
1666 pndot = &pndown->as<PropertyAccess>();
1667 }
1668
1669 // pndown is a primary expression, not a dotted property reference.
1670 if (!emitTree(pndown)) {
1671 return false;
1672 }
1673
1674 while (true) {
1675 // Walk back up the list, emitting annotated name ops.
1676 if (!emitAtomOp(JSOp::GetProp, pndot->key().atom())) {
1677 return false;
1678 }
1679
1680 // Reverse the pndot->expression() link again.
1681 pnup = pndot->maybeExpression();
1682 pndot->setExpression(pndown);
1683 pndown = pndot;
1684 if (!pnup) {
1685 break;
1686 }
1687 pndot = &pnup->as<PropertyAccess>();
1688 }
1689 return true;
1690}
1691
1692bool BytecodeEmitter::emitPropIncDec(UnaryNode* incDec, ValueUsage valueUsage) {
1693 PropertyAccess* prop = &incDec->kid()->as<PropertyAccess>();
1694 bool isSuper = prop->isSuper();
1695 ParseNodeKind kind = incDec->getKind();
1696 PropOpEmitter poe(
1697 this,
1698 kind == ParseNodeKind::PostIncrementExpr
1699 ? PropOpEmitter::Kind::PostIncrement
1700 : kind == ParseNodeKind::PreIncrementExpr
1701 ? PropOpEmitter::Kind::PreIncrement
1702 : kind == ParseNodeKind::PostDecrementExpr
1703 ? PropOpEmitter::Kind::PostDecrement
1704 : PropOpEmitter::Kind::PreDecrement,
1705 isSuper ? PropOpEmitter::ObjKind::Super : PropOpEmitter::ObjKind::Other);
1706 if (!poe.prepareForObj()) {
1707 return false;
1708 }
1709 if (isSuper) {
1710 UnaryNode* base = &prop->expression().as<UnaryNode>();
1711 if (!emitGetThisForSuperBase(base)) {
1712 // [stack] THIS
1713 return false;
1714 }
1715 } else {
1716 if (!emitPropLHS(prop)) {
1717 // [stack] OBJ
1718 return false;
1719 }
1720 }
1721 if (!poe.emitIncDec(prop->key().atom(), valueUsage)) {
1722 // [stack] RESULT
1723 return false;
1724 }
1725
1726 return true;
1727}
1728
1729bool BytecodeEmitter::emitNameIncDec(UnaryNode* incDec, ValueUsage valueUsage) {
1730 MOZ_ASSERT(incDec->kid()->isKind(ParseNodeKind::Name))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(incDec->kid()->isKind(ParseNodeKind::Name))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(incDec->kid()->isKind(ParseNodeKind::Name)))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("incDec->kid()->isKind(ParseNodeKind::Name)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1730); AnnotateMozCrashReason("MOZ_ASSERT" "(" "incDec->kid()->isKind(ParseNodeKind::Name)"
")"); do { *((volatile int*)__null) = 1730; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1731
1732 ParseNodeKind kind = incDec->getKind();
1733 NameNode* name = &incDec->kid()->as<NameNode>();
1734 NameOpEmitter noe(this, name->atom(),
1735 kind == ParseNodeKind::PostIncrementExpr
1736 ? NameOpEmitter::Kind::PostIncrement
1737 : kind == ParseNodeKind::PreIncrementExpr
1738 ? NameOpEmitter::Kind::PreIncrement
1739 : kind == ParseNodeKind::PostDecrementExpr
1740 ? NameOpEmitter::Kind::PostDecrement
1741 : NameOpEmitter::Kind::PreDecrement);
1742 if (!noe.emitIncDec(valueUsage)) {
1743 return false;
1744 }
1745
1746 return true;
1747}
1748
1749bool BytecodeEmitter::emitElemObjAndKey(PropertyByValue* elem,
1750 ElemOpEmitter& eoe) {
1751 ParseNode* exprOrSuper = &elem->expression();
1752 ParseNode* key = &elem->key();
1753
1754 if (!eoe.prepareForObj()) {
1755 // [stack]
1756 return false;
1757 }
1758
1759 if (elem->isSuper()) {
1760 auto* base = &exprOrSuper->as<UnaryNode>();
1761 if (!emitGetThisForSuperBase(base)) {
1762 // [stack] THIS
1763 return false;
1764 }
1765 } else {
1766 if (!emitTree(exprOrSuper)) {
1767 // [stack] OBJ
1768 return false;
1769 }
1770 }
1771
1772 if (!eoe.prepareForKey()) {
1773 // [stack] # if Super
1774 // [stack] THIS? THIS
1775 // [stack] # otherwise
1776 // [stack] OBJ? OBJ
1777 return false;
1778 }
1779
1780 if (!emitTree(key)) {
1781 // [stack] # if Super
1782 // [stack] THIS? THIS KEY
1783 // [stack] # otherwise
1784 // [stack] OBJ? OBJ KEY
1785 return false;
1786 }
1787
1788 return true;
1789}
1790
1791bool BytecodeEmitter::emitElemOpBase(JSOp op) {
1792 if (!emit1(op)) {
1793 return false;
1794 }
1795
1796 return true;
1797}
1798
1799static ElemOpEmitter::Kind ConvertIncDecKind(ParseNodeKind kind) {
1800 switch (kind) {
1801 case ParseNodeKind::PostIncrementExpr:
1802 return ElemOpEmitter::Kind::PostIncrement;
1803 case ParseNodeKind::PreIncrementExpr:
1804 return ElemOpEmitter::Kind::PreIncrement;
1805 case ParseNodeKind::PostDecrementExpr:
1806 return ElemOpEmitter::Kind::PostDecrement;
1807 case ParseNodeKind::PreDecrementExpr:
1808 return ElemOpEmitter::Kind::PreDecrement;
1809 default:
1810 MOZ_CRASH("unexpected inc/dec node kind")do { do { } while (false); MOZ_ReportCrash("" "unexpected inc/dec node kind"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1810); AnnotateMozCrashReason("MOZ_CRASH(" "unexpected inc/dec node kind"
")"); do { *((volatile int*)__null) = 1810; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
1811 }
1812}
1813
1814static PrivateOpEmitter::Kind PrivateConvertIncDecKind(ParseNodeKind kind) {
1815 switch (kind) {
1816 case ParseNodeKind::PostIncrementExpr:
1817 return PrivateOpEmitter::Kind::PostIncrement;
1818 case ParseNodeKind::PreIncrementExpr:
1819 return PrivateOpEmitter::Kind::PreIncrement;
1820 case ParseNodeKind::PostDecrementExpr:
1821 return PrivateOpEmitter::Kind::PostDecrement;
1822 case ParseNodeKind::PreDecrementExpr:
1823 return PrivateOpEmitter::Kind::PreDecrement;
1824 default:
1825 MOZ_CRASH("unexpected inc/dec node kind")do { do { } while (false); MOZ_ReportCrash("" "unexpected inc/dec node kind"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1825); AnnotateMozCrashReason("MOZ_CRASH(" "unexpected inc/dec node kind"
")"); do { *((volatile int*)__null) = 1825; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
1826 }
1827}
1828
1829bool BytecodeEmitter::emitElemIncDec(UnaryNode* incDec, ValueUsage valueUsage) {
1830 PropertyByValue* elemExpr = &incDec->kid()->as<PropertyByValue>();
1831 bool isSuper = elemExpr->isSuper();
1832 MOZ_ASSERT(!elemExpr->key().isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!elemExpr->key().isKind(ParseNodeKind::PrivateName
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!elemExpr->key().isKind(ParseNodeKind::PrivateName
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!elemExpr->key().isKind(ParseNodeKind::PrivateName)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1832); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elemExpr->key().isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 1832; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1833 ParseNodeKind kind = incDec->getKind();
1834 ElemOpEmitter eoe(
1835 this, ConvertIncDecKind(kind),
1836 isSuper ? ElemOpEmitter::ObjKind::Super : ElemOpEmitter::ObjKind::Other);
1837 if (!emitElemObjAndKey(elemExpr, eoe)) {
1838 // [stack] # if Super
1839 // [stack] THIS KEY
1840 // [stack] # otherwise
1841 // [stack] OBJ KEY
1842 return false;
1843 }
1844 if (!eoe.emitIncDec(valueUsage)) {
1845 // [stack] RESULT
1846 return false;
1847 }
1848
1849 return true;
1850}
1851
1852bool BytecodeEmitter::emitCallIncDec(UnaryNode* incDec) {
1853 MOZ_ASSERT(incDec->isKind(ParseNodeKind::PreIncrementExpr) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(incDec->isKind(ParseNodeKind::PreIncrementExpr) ||
incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec
->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind
(ParseNodeKind::PostDecrementExpr))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(incDec->isKind(ParseNodeKind
::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr
) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec
->isKind(ParseNodeKind::PostDecrementExpr)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind(ParseNodeKind::PostDecrementExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1856); AnnotateMozCrashReason("MOZ_ASSERT" "(" "incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind(ParseNodeKind::PostDecrementExpr)"
")"); do { *((volatile int*)__null) = 1856; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1854 incDec->isKind(ParseNodeKind::PostIncrementExpr) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(incDec->isKind(ParseNodeKind::PreIncrementExpr) ||
incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec
->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind
(ParseNodeKind::PostDecrementExpr))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(incDec->isKind(ParseNodeKind
::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr
) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec
->isKind(ParseNodeKind::PostDecrementExpr)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind(ParseNodeKind::PostDecrementExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1856); AnnotateMozCrashReason("MOZ_ASSERT" "(" "incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind(ParseNodeKind::PostDecrementExpr)"
")"); do { *((volatile int*)__null) = 1856; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1855 incDec->isKind(ParseNodeKind::PreDecrementExpr) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(incDec->isKind(ParseNodeKind::PreIncrementExpr) ||
incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec
->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind
(ParseNodeKind::PostDecrementExpr))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(incDec->isKind(ParseNodeKind
::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr
) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec
->isKind(ParseNodeKind::PostDecrementExpr)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind(ParseNodeKind::PostDecrementExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1856); AnnotateMozCrashReason("MOZ_ASSERT" "(" "incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind(ParseNodeKind::PostDecrementExpr)"
")"); do { *((volatile int*)__null) = 1856; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1856 incDec->isKind(ParseNodeKind::PostDecrementExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(incDec->isKind(ParseNodeKind::PreIncrementExpr) ||
incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec
->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind
(ParseNodeKind::PostDecrementExpr))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(incDec->isKind(ParseNodeKind
::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr
) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec
->isKind(ParseNodeKind::PostDecrementExpr)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind(ParseNodeKind::PostDecrementExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1856); AnnotateMozCrashReason("MOZ_ASSERT" "(" "incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind(ParseNodeKind::PostDecrementExpr)"
")"); do { *((volatile int*)__null) = 1856; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1857
1858 ParseNode* call = incDec->kid();
1859 MOZ_ASSERT(call->isKind(ParseNodeKind::CallExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(call->isKind(ParseNodeKind::CallExpr))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(call->isKind(ParseNodeKind::CallExpr)))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("call->isKind(ParseNodeKind::CallExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1859); AnnotateMozCrashReason("MOZ_ASSERT" "(" "call->isKind(ParseNodeKind::CallExpr)"
")"); do { *((volatile int*)__null) = 1859; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1860 if (!emitTree(call)) {
1861 // [stack] CALLRESULT
1862 return false;
1863 }
1864 if (!emit1(JSOp::ToNumeric)) {
1865 // [stack] N
1866 return false;
1867 }
1868
1869 // The increment/decrement has no side effects, so proceed to throw for
1870 // invalid assignment target.
1871 return emit2(JSOp::ThrowMsg, uint8_t(ThrowMsgKind::AssignToCall));
1872}
1873
1874bool BytecodeEmitter::emitPrivateIncDec(UnaryNode* incDec,
1875 ValueUsage valueUsage) {
1876 PrivateMemberAccess* privateExpr = &incDec->kid()->as<PrivateMemberAccess>();
1877 ParseNodeKind kind = incDec->getKind();
1878 PrivateOpEmitter xoe(this, PrivateConvertIncDecKind(kind),
1879 privateExpr->privateName().name());
1880 if (!emitTree(&privateExpr->expression())) {
1881 // [stack] OBJ
1882 return false;
1883 }
1884 if (!xoe.emitReference()) {
1885 // [stack] OBJ NAME
1886 return false;
1887 }
1888 if (!xoe.emitIncDec(valueUsage)) {
1889 // [stack] RESULT
1890 return false;
1891 }
1892
1893 return true;
1894}
1895
1896bool BytecodeEmitter::emitDouble(double d) {
1897 BytecodeOffset offset;
1898 if (!emitCheck(JSOp::Double, 9, &offset)) {
1899 return false;
1900 }
1901
1902 jsbytecode* code = bytecodeSection().code(offset);
1903 code[0] = jsbytecode(JSOp::Double);
1904 SET_INLINE_VALUE(code, DoubleValue(d));
1905 bytecodeSection().updateDepth(JSOp::Double, offset);
1906 return true;
1907}
1908
1909bool BytecodeEmitter::emitNumberOp(double dval) {
1910 int32_t ival;
1911 if (NumberIsInt32(dval, &ival)) {
1912 if (ival == 0) {
1913 return emit1(JSOp::Zero);
1914 }
1915 if (ival == 1) {
1916 return emit1(JSOp::One);
1917 }
1918 if ((int)(int8_t)ival == ival) {
1919 return emit2(JSOp::Int8, uint8_t(int8_t(ival)));
1920 }
1921
1922 uint32_t u = uint32_t(ival);
1923 if (u < Bit(16)) {
1924 if (!emitUint16Operand(JSOp::Uint16, u)) {
1925 return false;
1926 }
1927 } else if (u < Bit(24)) {
1928 BytecodeOffset off;
1929 if (!emitN(JSOp::Uint24, 3, &off)) {
1930 return false;
1931 }
1932 SET_UINT24(bytecodeSection().code(off), u);
1933 } else {
1934 BytecodeOffset off;
1935 if (!emitN(JSOp::Int32, 4, &off)) {
1936 return false;
1937 }
1938 SET_INT32(bytecodeSection().code(off), ival);
1939 }
1940 return true;
1941 }
1942
1943 return emitDouble(dval);
1944}
1945
1946/*
1947 * Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047.
1948 * LLVM is deciding to inline this function which uses a lot of stack space
1949 * into emitTree which is recursive and uses relatively little stack space.
1950 */
1951MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitSwitch(SwitchStatement* switchStmt) {
1952 LexicalScopeNode& lexical = switchStmt->lexicalForCaseList();
1953 MOZ_ASSERT(lexical.isKind(ParseNodeKind::LexicalScope))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(lexical.isKind(ParseNodeKind::LexicalScope))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(lexical.isKind(ParseNodeKind::LexicalScope)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("lexical.isKind(ParseNodeKind::LexicalScope)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1953); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lexical.isKind(ParseNodeKind::LexicalScope)"
")"); do { *((volatile int*)__null) = 1953; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1954 ListNode* cases = &lexical.scopeBody()->as<ListNode>();
1955 MOZ_ASSERT(cases->isKind(ParseNodeKind::StatementList))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(cases->isKind(ParseNodeKind::StatementList))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(cases->isKind(ParseNodeKind::StatementList)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("cases->isKind(ParseNodeKind::StatementList)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1955); AnnotateMozCrashReason("MOZ_ASSERT" "(" "cases->isKind(ParseNodeKind::StatementList)"
")"); do { *((volatile int*)__null) = 1955; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1956
1957 SwitchEmitter se(this);
1958 if (!se.emitDiscriminant(switchStmt->discriminant().pn_pos.begin)) {
1959 return false;
1960 }
1961
1962 if (!markStepBreakpoint()) {
1963 return false;
1964 }
1965 if (!emitTree(&switchStmt->discriminant())) {
1966 return false;
1967 }
1968
1969 // Enter the scope before pushing the switch BreakableControl since all
1970 // breaks are under this scope.
1971
1972 if (!lexical.isEmptyScope()) {
1973 if (!se.emitLexical(lexical.scopeBindings())) {
1974 return false;
1975 }
1976
1977 // A switch statement may contain hoisted functions inside its
1978 // cases. The hasTopLevelFunctionDeclarations flag is propagated from the
1979 // StatementList bodies of the cases to the case list.
1980 if (cases->hasTopLevelFunctionDeclarations()) {
1981 for (ParseNode* item : cases->contents()) {
1982 CaseClause* caseClause = &item->as<CaseClause>();
1983 ListNode* statements = caseClause->statementList();
1984 if (statements->hasTopLevelFunctionDeclarations()) {
1985 if (!emitHoistedFunctionsInList(statements)) {
1986 return false;
1987 }
1988 }
1989 }
1990 }
1991 } else {
1992 MOZ_ASSERT(!cases->hasTopLevelFunctionDeclarations())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!cases->hasTopLevelFunctionDeclarations())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!cases->hasTopLevelFunctionDeclarations()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("!cases->hasTopLevelFunctionDeclarations()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1992); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!cases->hasTopLevelFunctionDeclarations()"
")"); do { *((volatile int*)__null) = 1992; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1993 }
1994
1995 SwitchEmitter::TableGenerator tableGen(this);
1996 uint32_t caseCount = cases->count() - (switchStmt->hasDefault() ? 1 : 0);
1997 if (caseCount == 0) {
1998 tableGen.finish(0);
1999 } else {
2000 for (ParseNode* item : cases->contents()) {
2001 CaseClause* caseClause = &item->as<CaseClause>();
2002 if (caseClause->isDefault()) {
2003 continue;
2004 }
2005
2006 ParseNode* caseValue = caseClause->caseExpression();
2007
2008 if (caseValue->getKind() != ParseNodeKind::NumberExpr) {
2009 tableGen.setInvalid();
2010 break;
2011 }
2012
2013 int32_t i;
2014 if (!NumberEqualsInt32(caseValue->as<NumericLiteral>().value(), &i)) {
2015 tableGen.setInvalid();
2016 break;
2017 }
2018
2019 if (!tableGen.addNumber(i)) {
2020 return false;
2021 }
2022 }
2023
2024 tableGen.finish(caseCount);
2025 }
2026
2027 if (!se.validateCaseCount(caseCount)) {
2028 return false;
2029 }
2030
2031 bool isTableSwitch = tableGen.isValid();
2032 if (isTableSwitch) {
2033 if (!se.emitTable(tableGen)) {
2034 return false;
2035 }
2036 } else {
2037 if (!se.emitCond()) {
2038 return false;
2039 }
2040
2041 // Emit code for evaluating cases and jumping to case statements.
2042 for (ParseNode* item : cases->contents()) {
2043 CaseClause* caseClause = &item->as<CaseClause>();
2044 if (caseClause->isDefault()) {
2045 continue;
2046 }
2047
2048 if (!se.prepareForCaseValue()) {
2049 return false;
2050 }
2051
2052 ParseNode* caseValue = caseClause->caseExpression();
2053 // If the expression is a literal, suppress line number emission so
2054 // that debugging works more naturally.
2055 if (!emitTree(
2056 caseValue, ValueUsage::WantValue,
2057 caseValue->isLiteral() ? SUPPRESS_LINENOTE : EMIT_LINENOTE)) {
2058 return false;
2059 }
2060
2061 if (!se.emitCaseJump()) {
2062 return false;
2063 }
2064 }
2065 }
2066
2067 // Emit code for each case's statements.
2068 for (ParseNode* item : cases->contents()) {
2069 CaseClause* caseClause = &item->as<CaseClause>();
2070 if (caseClause->isDefault()) {
2071 if (!se.emitDefaultBody()) {
2072 return false;
2073 }
2074 } else {
2075 if (isTableSwitch) {
2076 ParseNode* caseValue = caseClause->caseExpression();
2077 MOZ_ASSERT(caseValue->isKind(ParseNodeKind::NumberExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(caseValue->isKind(ParseNodeKind::NumberExpr))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(caseValue->isKind(ParseNodeKind::NumberExpr)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("caseValue->isKind(ParseNodeKind::NumberExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2077); AnnotateMozCrashReason("MOZ_ASSERT" "(" "caseValue->isKind(ParseNodeKind::NumberExpr)"
")"); do { *((volatile int*)__null) = 2077; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2078
2079 NumericLiteral* literal = &caseValue->as<NumericLiteral>();
2080#ifdef DEBUG1
2081 // Use NumberEqualsInt32 here because switches compare using
2082 // strict equality, which will equate -0 and +0. In contrast
2083 // NumberIsInt32 would return false for -0.
2084 int32_t v;
2085 MOZ_ASSERT(mozilla::NumberEqualsInt32(literal->value(), &v))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mozilla::NumberEqualsInt32(literal->value(), &
v))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(mozilla::NumberEqualsInt32(literal->value(), &
v)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mozilla::NumberEqualsInt32(literal->value(), &v)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2085); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mozilla::NumberEqualsInt32(literal->value(), &v)"
")"); do { *((volatile int*)__null) = 2085; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2086#endif
2087 int32_t i = int32_t(literal->value());
2088
2089 if (!se.emitCaseBody(i, tableGen)) {
2090 return false;
2091 }
2092 } else {
2093 if (!se.emitCaseBody()) {
2094 return false;
2095 }
2096 }
2097 }
2098
2099 if (!emitTree(caseClause->statementList())) {
2100 return false;
2101 }
2102 }
2103
2104 if (!se.emitEnd()) {
2105 return false;
2106 }
2107
2108 return true;
2109}
2110
2111bool BytecodeEmitter::allocateResumeIndex(BytecodeOffset offset,
2112 uint32_t* resumeIndex) {
2113 static constexpr uint32_t MaxResumeIndex = BitMask(24);
2114
2115 static_assert(
2116 MaxResumeIndex < uint32_t(AbstractGeneratorObject::RESUME_INDEX_RUNNING),
2117 "resumeIndex should not include magic AbstractGeneratorObject "
2118 "resumeIndex values");
2119 static_assert(
2120 MaxResumeIndex <= INT32_MAX(2147483647) / sizeof(uintptr_t),
2121 "resumeIndex * sizeof(uintptr_t) must fit in an int32. JIT code relies "
2122 "on this when loading resume entries from BaselineScript");
2123
2124 *resumeIndex = bytecodeSection().resumeOffsetList().length();
2125 if (*resumeIndex > MaxResumeIndex) {
2126 reportError(nullptr, JSMSG_TOO_MANY_RESUME_INDEXES);
2127 return false;
2128 }
2129
2130 return bytecodeSection().resumeOffsetList().append(offset.value());
2131}
2132
2133bool BytecodeEmitter::allocateResumeIndexRange(
2134 mozilla::Span<BytecodeOffset> offsets, uint32_t* firstResumeIndex) {
2135 *firstResumeIndex = 0;
2136
2137 for (size_t i = 0, len = offsets.size(); i < len; i++) {
2138 uint32_t resumeIndex;
2139 if (!allocateResumeIndex(offsets[i], &resumeIndex)) {
2140 return false;
2141 }
2142 if (i == 0) {
2143 *firstResumeIndex = resumeIndex;
2144 }
2145 }
2146
2147 return true;
2148}
2149
2150bool BytecodeEmitter::emitYieldOp(JSOp op) {
2151 // ParseContext::Scope::setOwnStackSlotCount should check the fixed slot
2152 // for the following, and it should prevent using fixed slot if there are
2153 // too many bindings:
2154 // * generator or asyn function
2155 // * module code after top-level await
2156 MOZ_ASSERT(innermostEmitterScopeNoCheck()->frameSlotEnd() <=do { static_assert( mozilla::detail::AssertionConditionType<
decltype(innermostEmitterScopeNoCheck()->frameSlotEnd() <=
ParseContext::Scope::FixedSlotLimit)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(innermostEmitterScopeNoCheck
()->frameSlotEnd() <= ParseContext::Scope::FixedSlotLimit
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"innermostEmitterScopeNoCheck()->frameSlotEnd() <= ParseContext::Scope::FixedSlotLimit"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2157); AnnotateMozCrashReason("MOZ_ASSERT" "(" "innermostEmitterScopeNoCheck()->frameSlotEnd() <= ParseContext::Scope::FixedSlotLimit"
")"); do { *((volatile int*)__null) = 2157; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2157 ParseContext::Scope::FixedSlotLimit)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(innermostEmitterScopeNoCheck()->frameSlotEnd() <=
ParseContext::Scope::FixedSlotLimit)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(innermostEmitterScopeNoCheck
()->frameSlotEnd() <= ParseContext::Scope::FixedSlotLimit
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"innermostEmitterScopeNoCheck()->frameSlotEnd() <= ParseContext::Scope::FixedSlotLimit"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2157); AnnotateMozCrashReason("MOZ_ASSERT" "(" "innermostEmitterScopeNoCheck()->frameSlotEnd() <= ParseContext::Scope::FixedSlotLimit"
")"); do { *((volatile int*)__null) = 2157; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2158
2159 if (op == JSOp::FinalYieldRval) {
2160 return emit1(JSOp::FinalYieldRval);
2161 }
2162
2163 MOZ_ASSERT(op == JSOp::InitialYield || op == JSOp::Yield ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(op == JSOp::InitialYield || op == JSOp::Yield || op ==
JSOp::Await)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(op == JSOp::InitialYield || op ==
JSOp::Yield || op == JSOp::Await))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("op == JSOp::InitialYield || op == JSOp::Yield || op == JSOp::Await"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2164); AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::InitialYield || op == JSOp::Yield || op == JSOp::Await"
")"); do { *((volatile int*)__null) = 2164; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2164 op == JSOp::Await)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(op == JSOp::InitialYield || op == JSOp::Yield || op ==
JSOp::Await)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(op == JSOp::InitialYield || op ==
JSOp::Yield || op == JSOp::Await))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("op == JSOp::InitialYield || op == JSOp::Yield || op == JSOp::Await"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2164); AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::InitialYield || op == JSOp::Yield || op == JSOp::Await"
")"); do { *((volatile int*)__null) = 2164; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2165
2166 BytecodeOffset off;
2167 if (!emitN(op, 3, &off)) {
2168 return false;
2169 }
2170
2171 if (op == JSOp::InitialYield || op == JSOp::Yield) {
2172 bytecodeSection().addNumYields();
2173 }
2174
2175 uint32_t resumeIndex;
2176 if (!allocateResumeIndex(bytecodeSection().offset(), &resumeIndex)) {
2177 return false;
2178 }
2179
2180 SET_RESUMEINDEX(bytecodeSection().code(off), resumeIndex);
2181
2182 BytecodeOffset unusedOffset;
2183 return emitJumpTargetOp(JSOp::AfterYield, &unusedOffset);
2184}
2185
2186bool BytecodeEmitter::emitPushResumeKind(GeneratorResumeKind kind) {
2187 return emit2(JSOp::ResumeKind, uint8_t(kind));
2188}
2189
2190bool BytecodeEmitter::emitSetThis(BinaryNode* setThisNode) {
2191 // ParseNodeKind::SetThis is used to update |this| after a super() call
2192 // in a derived class constructor.
2193
2194 MOZ_ASSERT(setThisNode->isKind(ParseNodeKind::SetThis))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(setThisNode->isKind(ParseNodeKind::SetThis))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(setThisNode->isKind(ParseNodeKind::SetThis)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("setThisNode->isKind(ParseNodeKind::SetThis)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2194); AnnotateMozCrashReason("MOZ_ASSERT" "(" "setThisNode->isKind(ParseNodeKind::SetThis)"
")"); do { *((volatile int*)__null) = 2194; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2195 MOZ_ASSERT(setThisNode->left()->isKind(ParseNodeKind::Name))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(setThisNode->left()->isKind(ParseNodeKind::Name
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(setThisNode->left()->isKind(ParseNodeKind::Name
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("setThisNode->left()->isKind(ParseNodeKind::Name)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2195); AnnotateMozCrashReason("MOZ_ASSERT" "(" "setThisNode->left()->isKind(ParseNodeKind::Name)"
")"); do { *((volatile int*)__null) = 2195; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2196
2197 auto name = setThisNode->left()->as<NameNode>().name();
2198
2199 // The 'this' binding is not lexical, but due to super() semantics this
2200 // initialization needs to be treated as a lexical one.
2201 NameLocation loc = lookupName(name);
2202 NameLocation lexicalLoc;
2203 if (loc.kind() == NameLocation::Kind::FrameSlot) {
2204 lexicalLoc = NameLocation::FrameSlot(BindingKind::Let, loc.frameSlot());
2205 } else if (loc.kind() == NameLocation::Kind::EnvironmentCoordinate) {
2206 EnvironmentCoordinate coord = loc.environmentCoordinate();
2207 uint8_t hops = AssertedCast<uint8_t>(coord.hops());
2208 lexicalLoc = NameLocation::EnvironmentCoordinate(BindingKind::Let, hops,
2209 coord.slot());
2210 } else {
2211 MOZ_ASSERT(loc.kind() == NameLocation::Kind::Dynamic)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(loc.kind() == NameLocation::Kind::Dynamic)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(loc.kind() == NameLocation::Kind::Dynamic))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("loc.kind() == NameLocation::Kind::Dynamic"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2211); AnnotateMozCrashReason("MOZ_ASSERT" "(" "loc.kind() == NameLocation::Kind::Dynamic"
")"); do { *((volatile int*)__null) = 2211; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2212 lexicalLoc = loc;
2213 }
2214
2215 NameOpEmitter noe(this, name, lexicalLoc, NameOpEmitter::Kind::Initialize);
2216 if (!noe.prepareForRhs()) {
2217 // [stack]
2218 return false;
2219 }
2220
2221 // Emit the new |this| value.
2222 if (!emitTree(setThisNode->right())) {
2223 // [stack] NEWTHIS
2224 return false;
2225 }
2226
2227 // Get the original |this| and throw if we already initialized
2228 // it. Do *not* use the NameLocation argument, as that's the special
2229 // lexical location below to deal with super() semantics.
2230 if (!emitGetName(name)) {
2231 // [stack] NEWTHIS THIS
2232 return false;
2233 }
2234 if (!emit1(JSOp::CheckThisReinit)) {
2235 // [stack] NEWTHIS THIS
2236 return false;
2237 }
2238 if (!emit1(JSOp::Pop)) {
2239 // [stack] NEWTHIS
2240 return false;
2241 }
2242 if (!noe.emitAssignment()) {
2243 // [stack] NEWTHIS
2244 return false;
2245 }
2246
2247 if (!emitInitializeInstanceMembers(true)) {
2248 return false;
2249 }
2250
2251 return true;
2252}
2253
2254bool BytecodeEmitter::defineHoistedTopLevelFunctions(ParseNode* body) {
2255 MOZ_ASSERT(inPrologue())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(inPrologue())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(inPrologue()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("inPrologue()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2255); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inPrologue()"
")"); do { *((volatile int*)__null) = 2255; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2256 MOZ_ASSERT(sc->isGlobalContext() || (sc->isEvalContext() && !sc->strict()))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sc->isGlobalContext() || (sc->isEvalContext() &&
!sc->strict()))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sc->isGlobalContext() || (
sc->isEvalContext() && !sc->strict())))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("sc->isGlobalContext() || (sc->isEvalContext() && !sc->strict())"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2256); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isGlobalContext() || (sc->isEvalContext() && !sc->strict())"
")"); do { *((volatile int*)__null) = 2256; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2257 MOZ_ASSERT(body->is<LexicalScopeNode>() || body->is<ListNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(body->is<LexicalScopeNode>() || body->is
<ListNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(body->is<LexicalScopeNode
>() || body->is<ListNode>()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("body->is<LexicalScopeNode>() || body->is<ListNode>()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2257); AnnotateMozCrashReason("MOZ_ASSERT" "(" "body->is<LexicalScopeNode>() || body->is<ListNode>()"
")"); do { *((volatile int*)__null) = 2257; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2258
2259 if (body->is<LexicalScopeNode>()) {
2260 body = body->as<LexicalScopeNode>().scopeBody();
2261 MOZ_ASSERT(body->is<ListNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(body->is<ListNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(body->is<ListNode>(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("body->is<ListNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2261); AnnotateMozCrashReason("MOZ_ASSERT" "(" "body->is<ListNode>()"
")"); do { *((volatile int*)__null) = 2261; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2262 }
2263
2264 if (!body->as<ListNode>().hasTopLevelFunctionDeclarations()) {
2265 return true;
2266 }
2267
2268 return emitHoistedFunctionsInList(&body->as<ListNode>());
2269}
2270
2271// For Global and sloppy-Eval scripts, this performs most of the steps of the
2272// spec's [GlobalDeclarationInstantiation] and [EvalDeclarationInstantiation]
2273// operations.
2274//
2275// Note that while strict-Eval is handled in the same part of the spec, it never
2276// fails for global-redeclaration checks so those scripts initialize directly in
2277// their bytecode.
2278bool BytecodeEmitter::emitDeclarationInstantiation(ParseNode* body) {
2279 if (sc->isModuleContext()) {
2280 // ES Modules have dedicated variable and lexial environments and therefore
2281 // do not have to perform redeclaration checks. We initialize their bindings
2282 // elsewhere in bytecode.
2283 return true;
2284 }
2285
2286 if (sc->isEvalContext() && sc->strict()) {
2287 // Strict Eval has a dedicated variables (and lexical) environment and
2288 // therefore does not have to perform redeclaration checks. We initialize
2289 // their bindings elsewhere in the bytecode.
2290 return true;
2291 }
2292
2293 // If we have no variables bindings, then we are done!
2294 if (sc->isGlobalContext()) {
2295 if (!sc->asGlobalContext()->bindings) {
2296 return true;
2297 }
2298 } else {
2299 MOZ_ASSERT(sc->isEvalContext())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sc->isEvalContext())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sc->isEvalContext()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("sc->isEvalContext()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2299); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isEvalContext()"
")"); do { *((volatile int*)__null) = 2299; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2300
2301 if (!sc->asEvalContext()->bindings) {
2302 return true;
2303 }
2304 }
2305
2306#if DEBUG1
2307 // There should be no emitted functions yet.
2308 for (const auto& thing : perScriptData().gcThingList().objects()) {
2309 MOZ_ASSERT(thing.isEmptyGlobalScope() || thing.isScope())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(thing.isEmptyGlobalScope() || thing.isScope())>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(thing.isEmptyGlobalScope() || thing.isScope()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("thing.isEmptyGlobalScope() || thing.isScope()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2309); AnnotateMozCrashReason("MOZ_ASSERT" "(" "thing.isEmptyGlobalScope() || thing.isScope()"
")"); do { *((volatile int*)__null) = 2309; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2310 }
2311#endif
2312
2313 // Emit the hoisted functions to gc-things list. There is no bytecode
2314 // generated yet to bind them.
2315 if (!defineHoistedTopLevelFunctions(body)) {
2316 return false;
2317 }
2318
2319 // Save the last GCThingIndex emitted. The hoisted functions are contained in
2320 // the gc-things list up until this point. This set of gc-things also contain
2321 // initial scopes (of which there must be at least one).
2322 MOZ_ASSERT(perScriptData().gcThingList().length() > 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(perScriptData().gcThingList().length() > 0)>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(perScriptData().gcThingList().length() > 0))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("perScriptData().gcThingList().length() > 0"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2322); AnnotateMozCrashReason("MOZ_ASSERT" "(" "perScriptData().gcThingList().length() > 0"
")"); do { *((volatile int*)__null) = 2322; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2323 GCThingIndex lastFun =
2324 GCThingIndex(perScriptData().gcThingList().length() - 1);
2325
2326#if DEBUG1
2327 for (const auto& thing : perScriptData().gcThingList().objects()) {
2328 MOZ_ASSERT(thing.isEmptyGlobalScope() || thing.isScope() ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(thing.isEmptyGlobalScope() || thing.isScope() || thing
.isFunction())>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(thing.isEmptyGlobalScope() || thing
.isScope() || thing.isFunction()))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("thing.isEmptyGlobalScope() || thing.isScope() || thing.isFunction()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2329); AnnotateMozCrashReason("MOZ_ASSERT" "(" "thing.isEmptyGlobalScope() || thing.isScope() || thing.isFunction()"
")"); do { *((volatile int*)__null) = 2329; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2329 thing.isFunction())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(thing.isEmptyGlobalScope() || thing.isScope() || thing
.isFunction())>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(thing.isEmptyGlobalScope() || thing
.isScope() || thing.isFunction()))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("thing.isEmptyGlobalScope() || thing.isScope() || thing.isFunction()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2329); AnnotateMozCrashReason("MOZ_ASSERT" "(" "thing.isEmptyGlobalScope() || thing.isScope() || thing.isFunction()"
")"); do { *((volatile int*)__null) = 2329; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2330 }
2331#endif
2332
2333 // Check for declaration conflicts and initialize the bindings.
2334 // NOTE: The self-hosting top-level script should not populate the builtins
2335 // directly on the GlobalObject (and instead uses JSOp::GetIntrinsic for
2336 // lookups).
2337 if (emitterMode == BytecodeEmitter::EmitterMode::Normal) {
2338 if (!emitGCIndexOp(JSOp::GlobalOrEvalDeclInstantiation, lastFun)) {
2339 return false;
2340 }
2341 }
2342
2343 return true;
2344}
2345
2346bool BytecodeEmitter::emitScript(ParseNode* body) {
2347 setScriptStartOffsetIfUnset(body->pn_pos.begin);
2348
2349 MOZ_ASSERT(inPrologue())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(inPrologue())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(inPrologue()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("inPrologue()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2349); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inPrologue()"
")"); do { *((volatile int*)__null) = 2349; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2350
2351 TDZCheckCache tdzCache(this);
2352 EmitterScope emitterScope(this);
2353 Maybe<AsyncEmitter> topLevelAwait;
2354 if (sc->isGlobalContext()) {
2355 if (!emitterScope.enterGlobal(this, sc->asGlobalContext())) {
2356 return false;
2357 }
2358 } else if (sc->isEvalContext()) {
2359 if (!emitterScope.enterEval(this, sc->asEvalContext())) {
2360 return false;
2361 }
2362 } else {
2363 MOZ_ASSERT(sc->isModuleContext())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sc->isModuleContext())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sc->isModuleContext()))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("sc->isModuleContext()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2363); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isModuleContext()"
")"); do { *((volatile int*)__null) = 2363; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2364 if (!emitterScope.enterModule(this, sc->asModuleContext())) {
2365 return false;
2366 }
2367 if (sc->asModuleContext()->isAsync()) {
2368 topLevelAwait.emplace(this);
2369 }
2370 }
2371
2372 setFunctionBodyEndPos(body->pn_pos.end);
2373
2374 bool isSloppyEval = sc->isEvalContext() && !sc->strict();
2375 if (isSloppyEval && body->is<LexicalScopeNode>() &&
2376 !body->as<LexicalScopeNode>().isEmptyScope()) {
2377 // Sloppy eval scripts may emit hoisted functions bindings with a
2378 // `JSOp::GlobalOrEvalDeclInstantiation` opcode below. If this eval needs a
2379 // top-level lexical environment, we must ensure that environment is created
2380 // before those functions are created and bound.
2381 //
2382 // This differs from the global-script case below because the global-lexical
2383 // environment exists outside the script itself. In the case of strict eval
2384 // scripts, the `emitterScope` above is already sufficient.
2385 EmitterScope lexicalEmitterScope(this);
2386 LexicalScopeNode* scope = &body->as<LexicalScopeNode>();
2387
2388 if (!lexicalEmitterScope.enterLexical(this, ScopeKind::Lexical,
2389 scope->scopeBindings())) {
2390 return false;
2391 }
2392
2393 if (!emitDeclarationInstantiation(scope->scopeBody())) {
2394 return false;
2395 }
2396
2397 switchToMain();
2398
2399 ParseNode* scopeBody = scope->scopeBody();
2400 if (!emitLexicalScopeBody(scopeBody)) {
2401 return false;
2402 }
2403
2404 if (!updateSourceCoordNotes(scopeBody->pn_pos.end)) {
2405 return false;
2406 }
2407
2408 if (!lexicalEmitterScope.leave(this)) {
2409 return false;
2410 }
2411 } else {
2412 if (!emitDeclarationInstantiation(body)) {
2413 return false;
2414 }
2415 if (topLevelAwait) {
2416 if (!topLevelAwait->prepareForModule()) {
2417 return false;
2418 }
2419 }
2420
2421 switchToMain();
2422
2423#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT1
2424 if (!emitterScope.prepareForModuleDisposableScopeBody(this)) {
2425 return false;
2426 }
2427#endif
2428
2429 if (topLevelAwait) {
2430 if (!topLevelAwait->prepareForBody()) {
2431 return false;
2432 }
2433 }
2434
2435 if (!emitTree(body)) {
2436 // [stack]
2437 return false;
2438 }
2439
2440 if (!updateSourceCoordNotes(body->pn_pos.end)) {
2441 return false;
2442 }
2443 }
2444
2445#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT1
2446 if (!emitterScope.emitModuleDisposableScopeBodyEnd(this)) {
2447 return false;
2448 }
2449#endif
2450
2451 if (topLevelAwait) {
2452 if (!topLevelAwait->emitEndModule()) {
2453 return false;
2454 }
2455 }
2456
2457 if (!markSimpleBreakpoint()) {
2458 return false;
2459 }
2460
2461 if (!emitReturnRval()) {
2462 return false;
2463 }
2464
2465 if (!emitterScope.leave(this)) {
2466 return false;
2467 }
2468
2469 if (!NameFunctions(fc, parserAtoms(), body)) {
2470 return false;
2471 }
2472
2473 // Create a Stencil and convert it into a JSScript.
2474 return intoScriptStencil(CompilationStencil::TopLevelIndex);
2475}
2476
2477js::UniquePtr<ImmutableScriptData>
2478BytecodeEmitter::createImmutableScriptData() {
2479 uint32_t nslots;
2480 if (!getNslots(&nslots)) {
2481 return nullptr;
2482 }
2483
2484 bool isFunction = sc->isFunctionBox();
2485 uint16_t funLength = isFunction ? sc->asFunctionBox()->length() : 0;
2486
2487 mozilla::SaturateUint8 propertyCountEstimate = propertyAdditionEstimate;
2488
2489 // Add fields to the property count estimate.
2490 if (isFunction && sc->asFunctionBox()->useMemberInitializers()) {
2491 propertyCountEstimate +=
2492 sc->asFunctionBox()->memberInitializers().numMemberInitializers;
2493 }
2494
2495 return ImmutableScriptData::new_(
2496 fc, mainOffset(), maxFixedSlots, nslots, bodyScopeIndex,
2497 bytecodeSection().numICEntries(), isFunction, funLength,
2498 propertyCountEstimate.value(), bytecodeSection().code(),
2499 bytecodeSection().notes(), bytecodeSection().resumeOffsetList().span(),
2500 bytecodeSection().scopeNoteList().span(),
2501 bytecodeSection().tryNoteList().span());
2502}
2503
2504#if defined(ENABLE_DECORATORS) || defined(ENABLE_EXPLICIT_RESOURCE_MANAGEMENT1)
2505bool BytecodeEmitter::emitCheckIsCallable() {
2506 // This emits code to check if the value at the top of the stack is
2507 // callable. The value is left on the stack.
2508 // [stack] VAL
2509 if (!emitAtomOp(JSOp::GetIntrinsic,
2510 TaggedParserAtomIndex::WellKnown::IsCallable())) {
2511 // [stack] VAL ISCALLABLE
2512 return false;
2513 }
2514 if (!emit1(JSOp::Undefined)) {
2515 // [stack] VAL ISCALLABLE UNDEFINED
2516 return false;
2517 }
2518 if (!emitDupAt(2)) {
2519 // [stack] VAL ISCALLABLE UNDEFINED VAL
2520 return false;
2521 }
2522 return emitCall(JSOp::Call, 1);
2523 // [stack] VAL ISCALLABLE_RESULT
2524}
2525#endif
2526
2527bool BytecodeEmitter::getNslots(uint32_t* nslots) const {
2528 uint64_t nslots64 =
2529 maxFixedSlots + static_cast<uint64_t>(bytecodeSection().maxStackDepth());
2530 if (nslots64 > UINT32_MAX(4294967295U)) {
2531 reportError(nullptr, JSMSG_NEED_DIET, "script");
2532 return false;
2533 }
2534 *nslots = nslots64;
2535 return true;
2536}
2537
2538bool BytecodeEmitter::emitFunctionScript(FunctionNode* funNode) {
2539 MOZ_ASSERT(inPrologue())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(inPrologue())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(inPrologue()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("inPrologue()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2539); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inPrologue()"
")"); do { *((volatile int*)__null) = 2539; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2540 ParamsBodyNode* paramsBody = funNode->body();
2541 FunctionBox* funbox = sc->asFunctionBox();
2542
2543 setScriptStartOffsetIfUnset(paramsBody->pn_pos.begin);
2544
2545 // [stack]
2546
2547 FunctionScriptEmitter fse(this, funbox, Some(paramsBody->pn_pos.begin),
2548 Some(paramsBody->pn_pos.end));
2549 if (!fse.prepareForParameters()) {
2550 // [stack]
2551 return false;
2552 }
2553
2554 if (!emitFunctionFormalParameters(paramsBody)) {
2555 // [stack]
2556 return false;
2557 }
2558
2559 if (!fse.prepareForBody()) {
2560 // [stack]
2561 return false;
2562 }
2563
2564 if (!emitTree(paramsBody->body())) {
2565 // [stack]
2566 return false;
2567 }
2568
2569 if (!fse.emitEndBody()) {
2570 // [stack]
2571 return false;
2572 }
2573
2574 if (funbox->index() == CompilationStencil::TopLevelIndex) {
2575 if (!NameFunctions(fc, parserAtoms(), funNode)) {
2576 return false;
2577 }
2578 }
2579
2580 return fse.intoStencil();
2581}
2582
2583class js::frontend::DestructuringLHSRef {
2584 struct None {
2585 size_t numReferenceSlots() const { return 0; }
2586 };
2587
2588 mozilla::Variant<None, NameOpEmitter, PropOpEmitter, ElemOpEmitter,
2589 PrivateOpEmitter>
2590 emitter_ = AsVariant(None{});
2591
2592 public:
2593 template <typename T>
2594 void from(T&& emitter) {
2595 emitter_.emplace<T>(std::forward<T>(emitter));
2596 }
2597
2598 template <typename T>
2599 T& emitter() {
2600 return emitter_.as<T>();
2601 }
2602
2603 /**
2604 * Return the number of values pushed onto the stack.
2605 */
2606 size_t numReferenceSlots() const {
2607 return emitter_.match([](auto& e) { return e.numReferenceSlots(); });
2608 }
2609};
2610
2611bool BytecodeEmitter::emitDestructuringLHSRef(ParseNode* target,
2612 DestructuringFlavor flav,
2613 DestructuringLHSRef& lref) {
2614#ifdef DEBUG1
2615 int depth = bytecodeSection().stackDepth();
2616#endif
2617
2618 switch (target->getKind()) {
2619 case ParseNodeKind::ArrayExpr:
2620 case ParseNodeKind::ObjectExpr:
2621 // No need to recurse into ParseNodeKind::Array and ParseNodeKind::Object
2622 // subpatterns here, since emitSetOrInitializeDestructuring does the
2623 // recursion when setting or initializing the value.
2624 break;
2625
2626 case ParseNodeKind::Name: {
2627 auto* name = &target->as<NameNode>();
2628 NameOpEmitter noe(this, name->atom(),
2629 flav == DestructuringFlavor::Assignment
2630 ? NameOpEmitter::Kind::SimpleAssignment
2631 : NameOpEmitter::Kind::Initialize);
2632 if (!noe.prepareForRhs()) {
2633 return false;
2634 }
2635
2636 lref.from(std::move(noe));
2637 return true;
2638 }
2639
2640 case ParseNodeKind::ArgumentsLength:
2641 case ParseNodeKind::DotExpr: {
2642 PropertyAccess* prop = &target->as<PropertyAccess>();
2643 bool isSuper = prop->isSuper();
2644 PropOpEmitter poe(this, PropOpEmitter::Kind::SimpleAssignment,
2645 isSuper ? PropOpEmitter::ObjKind::Super
2646 : PropOpEmitter::ObjKind::Other);
2647 if (!poe.prepareForObj()) {
2648 return false;
2649 }
2650 if (isSuper) {
2651 UnaryNode* base = &prop->expression().as<UnaryNode>();
2652 if (!emitGetThisForSuperBase(base)) {
2653 // [stack] THIS SUPERBASE
2654 return false;
2655 }
2656 } else {
2657 if (!emitTree(&prop->expression())) {
2658 // [stack] OBJ
2659 return false;
2660 }
2661 }
2662 if (!poe.prepareForRhs()) {
2663 // [stack] # if Super
2664 // [stack] THIS SUPERBASE
2665 // [stack] # otherwise
2666 // [stack] OBJ
2667 return false;
2668 }
2669
2670 lref.from(std::move(poe));
2671 break;
2672 }
2673
2674 case ParseNodeKind::ElemExpr: {
2675 PropertyByValue* elem = &target->as<PropertyByValue>();
2676 bool isSuper = elem->isSuper();
2677 MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!elem->key().isKind(ParseNodeKind::PrivateName))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!elem->key().isKind(ParseNodeKind::PrivateName)))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!elem->key().isKind(ParseNodeKind::PrivateName)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2677); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 2677; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2678 ElemOpEmitter eoe(this, ElemOpEmitter::Kind::SimpleAssignment,
2679 isSuper ? ElemOpEmitter::ObjKind::Super
2680 : ElemOpEmitter::ObjKind::Other);
2681 if (!emitElemObjAndKey(elem, eoe)) {
2682 // [stack] # if Super
2683 // [stack] THIS KEY
2684 // [stack] # otherwise
2685 // [stack] OBJ KEY
2686 return false;
2687 }
2688 if (!eoe.prepareForRhs()) {
2689 // [stack] # if Super
2690 // [stack] THIS KEY SUPERBASE
2691 // [stack] # otherwise
2692 // [stack] OBJ KEY
2693 return false;
2694 }
2695
2696 lref.from(std::move(eoe));
2697 break;
2698 }
2699
2700 case ParseNodeKind::PrivateMemberExpr: {
2701 PrivateMemberAccess* privateExpr = &target->as<PrivateMemberAccess>();
2702 PrivateOpEmitter xoe(this, PrivateOpEmitter::Kind::SimpleAssignment,
2703 privateExpr->privateName().name());
2704 if (!emitTree(&privateExpr->expression())) {
2705 // [stack] OBJ
2706 return false;
2707 }
2708 if (!xoe.emitReference()) {
2709 // [stack] OBJ NAME
2710 return false;
2711 }
2712
2713 lref.from(std::move(xoe));
2714 break;
2715 }
2716
2717 case ParseNodeKind::CallExpr:
2718 MOZ_ASSERT_UNREACHABLE(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"Parser::reportIfNotValidSimpleAssignmentTarget " "rejects function calls as assignment "
"targets in destructuring assignments" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2721); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget "
"rejects function calls as assignment " "targets in destructuring assignments"
")"); do { *((volatile int*)__null) = 2721; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2719 "Parser::reportIfNotValidSimpleAssignmentTarget "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"Parser::reportIfNotValidSimpleAssignmentTarget " "rejects function calls as assignment "
"targets in destructuring assignments" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2721); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget "
"rejects function calls as assignment " "targets in destructuring assignments"
")"); do { *((volatile int*)__null) = 2721; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2720 "rejects function calls as assignment "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"Parser::reportIfNotValidSimpleAssignmentTarget " "rejects function calls as assignment "
"targets in destructuring assignments" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2721); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget "
"rejects function calls as assignment " "targets in destructuring assignments"
")"); do { *((volatile int*)__null) = 2721; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2721 "targets in destructuring assignments")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"Parser::reportIfNotValidSimpleAssignmentTarget " "rejects function calls as assignment "
"targets in destructuring assignments" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2721); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget "
"rejects function calls as assignment " "targets in destructuring assignments"
")"); do { *((volatile int*)__null) = 2721; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2722 break;
2723
2724 default:
2725 MOZ_CRASH("emitDestructuringLHSRef: bad lhs kind")do { do { } while (false); MOZ_ReportCrash("" "emitDestructuringLHSRef: bad lhs kind"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2725); AnnotateMozCrashReason("MOZ_CRASH(" "emitDestructuringLHSRef: bad lhs kind"
")"); do { *((volatile int*)__null) = 2725; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
2726 }
2727
2728 MOZ_ASSERT(bytecodeSection().stackDepth() ==do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bytecodeSection().stackDepth() == depth + int(lref.numReferenceSlots
()))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(bytecodeSection().stackDepth() == depth + int(lref.numReferenceSlots
())))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("bytecodeSection().stackDepth() == depth + int(lref.numReferenceSlots())"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2729); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == depth + int(lref.numReferenceSlots())"
")"); do { *((volatile int*)__null) = 2729; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2729 depth + int(lref.numReferenceSlots()))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bytecodeSection().stackDepth() == depth + int(lref.numReferenceSlots
()))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(bytecodeSection().stackDepth() == depth + int(lref.numReferenceSlots
())))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("bytecodeSection().stackDepth() == depth + int(lref.numReferenceSlots())"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2729); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == depth + int(lref.numReferenceSlots())"
")"); do { *((volatile int*)__null) = 2729; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2730
2731 return true;
2732}
2733
2734bool BytecodeEmitter::emitSetOrInitializeDestructuring(
2735 ParseNode* target, DestructuringFlavor flav, DestructuringLHSRef& lref) {
2736 // Now emit the lvalue opcode sequence. If the lvalue is a nested
2737 // destructuring initialiser-form, call ourselves to handle it, then pop
2738 // the matched value. Otherwise emit an lvalue bytecode sequence followed
2739 // by an assignment op.
2740
2741 switch (target->getKind()) {
2742 case ParseNodeKind::ArrayExpr:
2743 case ParseNodeKind::ObjectExpr:
2744 if (!emitDestructuringOps(&target->as<ListNode>(), flav)) {
2745 return false;
2746 }
2747 // emitDestructuringOps leaves the assigned (to-be-destructured) value on
2748 // top of the stack.
2749 break;
2750
2751 case ParseNodeKind::Name: {
2752 // The environment is already pushed by emitDestructuringLHSRef.
2753 // [stack] ENV? VAL
2754 auto& noe = lref.emitter<NameOpEmitter>();
2755
2756 if (!noe.emitAssignment()) {
2757 // [stack] VAL
2758 return false;
2759 }
2760 break;
2761 }
2762
2763 case ParseNodeKind::ArgumentsLength:
2764 case ParseNodeKind::DotExpr: {
2765 // The reference is already pushed by emitDestructuringLHSRef.
2766 // [stack] # if Super
2767 // [stack] THIS SUPERBASE VAL
2768 // [stack] # otherwise
2769 // [stack] OBJ VAL
2770 auto& poe = lref.emitter<PropOpEmitter>();
2771 auto* prop = &target->as<PropertyAccess>();
2772
2773 if (!poe.emitAssignment(prop->key().atom())) {
2774 // [stack] # VAL
2775 return false;
2776 }
2777 break;
2778 }
2779
2780 case ParseNodeKind::ElemExpr: {
2781 // The reference is already pushed by emitDestructuringLHSRef.
2782 // [stack] # if Super
2783 // [stack] THIS KEY SUPERBASE VAL
2784 // [stack] # otherwise
2785 // [stack] OBJ KEY VAL
2786 auto& eoe = lref.emitter<ElemOpEmitter>();
2787
2788 if (!eoe.emitAssignment()) {
2789 // [stack] VAL
2790 return false;
2791 }
2792 break;
2793 }
2794
2795 case ParseNodeKind::PrivateMemberExpr: {
2796 // The reference is already pushed by emitDestructuringLHSRef.
2797 // [stack] OBJ NAME VAL
2798 auto& xoe = lref.emitter<PrivateOpEmitter>();
2799
2800 if (!xoe.emitAssignment()) {
2801 // [stack] VAL
2802 return false;
2803 }
2804 break;
2805 }
2806
2807 case ParseNodeKind::CallExpr:
2808 MOZ_ASSERT_UNREACHABLE(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"Parser::reportIfNotValidSimpleAssignmentTarget " "rejects function calls as assignment "
"targets in destructuring assignments" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2811); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget "
"rejects function calls as assignment " "targets in destructuring assignments"
")"); do { *((volatile int*)__null) = 2811; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2809 "Parser::reportIfNotValidSimpleAssignmentTarget "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"Parser::reportIfNotValidSimpleAssignmentTarget " "rejects function calls as assignment "
"targets in destructuring assignments" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2811); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget "
"rejects function calls as assignment " "targets in destructuring assignments"
")"); do { *((volatile int*)__null) = 2811; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2810 "rejects function calls as assignment "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"Parser::reportIfNotValidSimpleAssignmentTarget " "rejects function calls as assignment "
"targets in destructuring assignments" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2811); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget "
"rejects function calls as assignment " "targets in destructuring assignments"
")"); do { *((volatile int*)__null) = 2811; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2811 "targets in destructuring assignments")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"Parser::reportIfNotValidSimpleAssignmentTarget " "rejects function calls as assignment "
"targets in destructuring assignments" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2811); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget "
"rejects function calls as assignment " "targets in destructuring assignments"
")"); do { *((volatile int*)__null) = 2811; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2812 break;
2813
2814 default:
2815 MOZ_CRASH("emitSetOrInitializeDestructuring: bad lhs kind")do { do { } while (false); MOZ_ReportCrash("" "emitSetOrInitializeDestructuring: bad lhs kind"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2815); AnnotateMozCrashReason("MOZ_CRASH(" "emitSetOrInitializeDestructuring: bad lhs kind"
")"); do { *((volatile int*)__null) = 2815; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
2816 }
2817
2818 // Pop the assigned value.
2819 if (!emit1(JSOp::Pop)) {
2820 // [stack] # empty
2821 return false;
2822 }
2823
2824 return true;
2825}
2826
2827JSOp BytecodeEmitter::getIterCallOp(JSOp callOp,
2828 SelfHostedIter selfHostedIter) const {
2829 if (emitterMode == BytecodeEmitter::SelfHosting) {
2830 MOZ_ASSERT(selfHostedIter != SelfHostedIter::Deny)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(selfHostedIter != SelfHostedIter::Deny)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(selfHostedIter != SelfHostedIter::Deny))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2830); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny"
")"); do { *((volatile int*)__null) = 2830; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2831
2832 switch (callOp) {
2833 case JSOp::Call:
2834 return JSOp::CallContent;
2835 case JSOp::CallIter:
2836 return JSOp::CallContentIter;
2837 default:
2838 MOZ_CRASH("Unknown iterator call op")do { do { } while (false); MOZ_ReportCrash("" "Unknown iterator call op"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2838); AnnotateMozCrashReason("MOZ_CRASH(" "Unknown iterator call op"
")"); do { *((volatile int*)__null) = 2838; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
2839 }
2840 }
2841
2842 return callOp;
2843}
2844
2845bool BytecodeEmitter::emitIteratorNext(
2846 const Maybe<uint32_t>& callSourceCoordOffset,
2847 IteratorKind iterKind /* = IteratorKind::Sync */,
2848 SelfHostedIter selfHostedIter /* = SelfHostedIter::Deny */) {
2849 MOZ_ASSERT(selfHostedIter != SelfHostedIter::Deny ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode
!= BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter
::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
" (" ".next() iteration is prohibited in self-hosted code because it"
"can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2852); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
") (" ".next() iteration is prohibited in self-hosted code because it"
"can run user-modifiable iteration code" ")"); do { *((volatile
int*)__null) = 2852; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
2850 emitterMode != BytecodeEmitter::SelfHosting,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode
!= BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter
::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
" (" ".next() iteration is prohibited in self-hosted code because it"
"can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2852); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
") (" ".next() iteration is prohibited in self-hosted code because it"
"can run user-modifiable iteration code" ")"); do { *((volatile
int*)__null) = 2852; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
2851 ".next() iteration is prohibited in self-hosted code because it"do { static_assert( mozilla::detail::AssertionConditionType<
decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode
!= BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter
::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
" (" ".next() iteration is prohibited in self-hosted code because it"
"can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2852); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
") (" ".next() iteration is prohibited in self-hosted code because it"
"can run user-modifiable iteration code" ")"); do { *((volatile
int*)__null) = 2852; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
2852 "can run user-modifiable iteration code")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode
!= BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter
::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
" (" ".next() iteration is prohibited in self-hosted code because it"
"can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2852); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
") (" ".next() iteration is prohibited in self-hosted code because it"
"can run user-modifiable iteration code" ")"); do { *((volatile
int*)__null) = 2852; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
2853
2854 // [stack] ... NEXT ITER
2855 MOZ_ASSERT(bytecodeSection().stackDepth() >= 2)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bytecodeSection().stackDepth() >= 2)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(bytecodeSection().stackDepth() >= 2))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("bytecodeSection().stackDepth() >= 2"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2855); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() >= 2"
")"); do { *((volatile int*)__null) = 2855; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2856
2857 if (!emitCall(getIterCallOp(JSOp::Call, selfHostedIter), 0,
2858 callSourceCoordOffset)) {
2859 // [stack] ... RESULT
2860 return false;
2861 }
2862
2863 if (iterKind == IteratorKind::Async) {
2864 if (!emitAwaitInInnermostScope()) {
2865 // [stack] ... RESULT
2866 return false;
2867 }
2868 }
2869
2870 if (!emitCheckIsObj(CheckIsObjectKind::IteratorNext)) {
2871 // [stack] ... RESULT
2872 return false;
2873 }
2874 return true;
2875}
2876
2877bool BytecodeEmitter::emitIteratorCloseInScope(
2878 EmitterScope& currentScope,
2879 IteratorKind iterKind /* = IteratorKind::Sync */,
2880 CompletionKind completionKind /* = CompletionKind::Normal */,
2881 SelfHostedIter selfHostedIter /* = SelfHostedIter::Deny */) {
2882 MOZ_ASSERT(selfHostedIter != SelfHostedIter::Deny ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode
!= BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter
::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
" (" ".close() on iterators is prohibited in self-hosted code because "
"it can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2885); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
") (" ".close() on iterators is prohibited in self-hosted code because "
"it can run user-modifiable iteration code" ")"); do { *((volatile
int*)__null) = 2885; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
2883 emitterMode != BytecodeEmitter::SelfHosting,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode
!= BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter
::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
" (" ".close() on iterators is prohibited in self-hosted code because "
"it can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2885); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
") (" ".close() on iterators is prohibited in self-hosted code because "
"it can run user-modifiable iteration code" ")"); do { *((volatile
int*)__null) = 2885; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
2884 ".close() on iterators is prohibited in self-hosted code because "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode
!= BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter
::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
" (" ".close() on iterators is prohibited in self-hosted code because "
"it can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2885); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
") (" ".close() on iterators is prohibited in self-hosted code because "
"it can run user-modifiable iteration code" ")"); do { *((volatile
int*)__null) = 2885; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
2885 "it can run user-modifiable iteration code")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode
!= BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter
::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
" (" ".close() on iterators is prohibited in self-hosted code because "
"it can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2885); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
") (" ".close() on iterators is prohibited in self-hosted code because "
"it can run user-modifiable iteration code" ")"); do { *((volatile
int*)__null) = 2885; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
2886
2887 if (iterKind == IteratorKind::Sync) {
2888 return emit2(JSOp::CloseIter, uint8_t(completionKind));
2889 }
2890
2891 // Generate inline logic corresponding to IteratorClose (ES2021 7.4.6) and
2892 // AsyncIteratorClose (ES2021 7.4.7). Steps numbers apply to both operations.
2893 //
2894 // Callers need to ensure that the iterator object is at the top of the
2895 // stack.
2896
2897 // For non-Throw completions, we emit the equivalent of:
2898 //
2899 // var returnMethod = GetMethod(iterator, "return");
2900 // if (returnMethod !== undefined) {
2901 // var innerResult = [Await] Call(returnMethod, iterator);
2902 // CheckIsObj(innerResult);
2903 // }
2904 //
2905 // Whereas for Throw completions, we emit:
2906 //
2907 // try {
2908 // var returnMethod = GetMethod(iterator, "return");
2909 // if (returnMethod !== undefined) {
2910 // [Await] Call(returnMethod, iterator);
2911 // }
2912 // } catch {}
2913
2914 Maybe<TryEmitter> tryCatch;
2915
2916 if (completionKind == CompletionKind::Throw) {
2917 tryCatch.emplace(this, TryEmitter::Kind::TryCatch,
2918 TryEmitter::ControlKind::NonSyntactic);
2919
2920 if (!tryCatch->emitTry()) {
2921 // [stack] ... ITER
2922 return false;
2923 }
2924 }
2925
2926 if (!emit1(JSOp::Dup)) {
2927 // [stack] ... ITER ITER
2928 return false;
2929 }
2930
2931 // Steps 1-2 are assertions, step 3 is implicit.
2932
2933 // Step 4.
2934 //
2935 // Get the "return" method.
2936 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::return_())) {
2937 // [stack] ... ITER RET
2938 return false;
2939 }
2940
2941 // Step 5.
2942 //
2943 // Do nothing if "return" is undefined or null.
2944 InternalIfEmitter ifReturnMethodIsDefined(this);
2945 if (!emit1(JSOp::IsNullOrUndefined)) {
2946 // [stack] ... ITER RET NULL-OR-UNDEF
2947 return false;
2948 }
2949
2950 if (!ifReturnMethodIsDefined.emitThenElse(
2951 IfEmitter::ConditionKind::Negative)) {
2952 // [stack] ... ITER RET
2953 return false;
2954 }
2955
2956 // Steps 5.c, 7.
2957 //
2958 // Call the "return" method.
2959 if (!emit1(JSOp::Swap)) {
2960 // [stack] ... RET ITER
2961 return false;
2962 }
2963
2964 if (!emitCall(getIterCallOp(JSOp::Call, selfHostedIter), 0)) {
2965 // [stack] ... RESULT
2966 return false;
2967 }
2968
2969 // 7.4.7 AsyncIteratorClose, step 5.d.
2970 if (iterKind == IteratorKind::Async) {
2971 if (completionKind != CompletionKind::Throw) {
2972 // Await clobbers rval, so save the current rval.
2973 if (!emit1(JSOp::GetRval)) {
2974 // [stack] ... RESULT RVAL
2975 return false;
2976 }
2977 if (!emit1(JSOp::Swap)) {
2978 // [stack] ... RVAL RESULT
2979 return false;
2980 }
2981 }
2982
2983 if (!emitAwaitInScope(currentScope)) {
2984 // [stack] ... RVAL? RESULT
2985 return false;
2986 }
2987
2988 if (completionKind != CompletionKind::Throw) {
2989 if (!emit1(JSOp::Swap)) {
2990 // [stack] ... RESULT RVAL
2991 return false;
2992 }
2993 if (!emit1(JSOp::SetRval)) {
2994 // [stack] ... RESULT
2995 return false;
2996 }
2997 }
2998 }
2999
3000 // Step 6 (Handled in caller).
3001
3002 // Step 8.
3003 if (completionKind != CompletionKind::Throw) {
3004 // Check that the "return" result is an object.
3005 if (!emitCheckIsObj(CheckIsObjectKind::IteratorReturn)) {
3006 // [stack] ... RESULT
3007 return false;
3008 }
3009 }
3010
3011 if (!ifReturnMethodIsDefined.emitElse()) {
3012 // [stack] ... ITER RET
3013 return false;
3014 }
3015
3016 if (!emit1(JSOp::Pop)) {
3017 // [stack] ... ITER
3018 return false;
3019 }
3020
3021 if (!ifReturnMethodIsDefined.emitEnd()) {
3022 return false;
3023 }
3024
3025 if (completionKind == CompletionKind::Throw) {
3026 if (!tryCatch->emitCatch()) {
3027 // [stack] ... ITER EXC
3028 return false;
3029 }
3030
3031 // Just ignore the exception thrown by call and await.
3032 if (!emit1(JSOp::Pop)) {
3033 // [stack] ... ITER
3034 return false;
3035 }
3036
3037 if (!tryCatch->emitEnd()) {
3038 // [stack] ... ITER
3039 return false;
3040 }
3041 }
3042
3043 // Step 9 (Handled in caller).
3044
3045 return emit1(JSOp::Pop);
3046 // [stack] ...
3047}
3048
3049template <typename InnerEmitter>
3050bool BytecodeEmitter::wrapWithDestructuringTryNote(int32_t iterDepth,
3051 InnerEmitter emitter) {
3052 MOZ_ASSERT(bytecodeSection().stackDepth() >= iterDepth)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bytecodeSection().stackDepth() >= iterDepth)>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(bytecodeSection().stackDepth() >= iterDepth))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("bytecodeSection().stackDepth() >= iterDepth"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3052); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() >= iterDepth"
")"); do { *((volatile int*)__null) = 3052; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3053
3054 // Pad a nop at the beginning of the bytecode covered by the trynote so
3055 // that when unwinding environments, we may unwind to the scope
3056 // corresponding to the pc *before* the start, in case the first bytecode
3057 // emitted by |emitter| is the start of an inner scope. See comment above
3058 // UnwindEnvironmentToTryPc.
3059 if (!emit1(JSOp::TryDestructuring)) {
3060 return false;
3061 }
3062
3063 BytecodeOffset start = bytecodeSection().offset();
3064 if (!emitter(this)) {
3065 return false;
3066 }
3067 BytecodeOffset end = bytecodeSection().offset();
3068 if (start != end) {
3069 return addTryNote(TryNoteKind::Destructuring, iterDepth, start, end);
3070 }
3071 return true;
3072}
3073
3074bool BytecodeEmitter::emitDefault(ParseNode* defaultExpr, ParseNode* pattern) {
3075 // [stack] VALUE
3076
3077 DefaultEmitter de(this);
3078 if (!de.prepareForDefault()) {
3079 // [stack]
3080 return false;
3081 }
3082 if (!emitInitializer(defaultExpr, pattern)) {
3083 // [stack] DEFAULTVALUE
3084 return false;
3085 }
3086 if (!de.emitEnd()) {
3087 // [stack] VALUE/DEFAULTVALUE
3088 return false;
3089 }
3090 return true;
3091}
3092
3093bool BytecodeEmitter::emitAnonymousFunctionWithName(
3094 ParseNode* node, TaggedParserAtomIndex name) {
3095 MOZ_ASSERT(node->isDirectRHSAnonFunction())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(node->isDirectRHSAnonFunction())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(node->isDirectRHSAnonFunction
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("node->isDirectRHSAnonFunction()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3095); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isDirectRHSAnonFunction()"
")"); do { *((volatile int*)__null) = 3095; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3096
3097 if (node->is<FunctionNode>()) {
3098 // Function doesn't have 'name' property at this point.
3099 // Set function's name at compile time.
3100 setFunName(node->as<FunctionNode>().funbox(), name);
3101
3102 return emitTree(node);
3103 }
3104
3105 MOZ_ASSERT(node->is<ClassNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(node->is<ClassNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(node->is<ClassNode>
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("node->is<ClassNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3105); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->is<ClassNode>()"
")"); do { *((volatile int*)__null) = 3105; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3106
3107 return emitClass(&node->as<ClassNode>(), ClassNameKind::InferredName, name);
3108}
3109
3110bool BytecodeEmitter::emitAnonymousFunctionWithComputedName(
3111 ParseNode* node, FunctionPrefixKind prefixKind) {
3112 MOZ_ASSERT(node->isDirectRHSAnonFunction())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(node->isDirectRHSAnonFunction())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(node->isDirectRHSAnonFunction
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("node->isDirectRHSAnonFunction()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3112); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isDirectRHSAnonFunction()"
")"); do { *((volatile int*)__null) = 3112; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3113
3114 if (node->is<FunctionNode>()) {
3115 if (!emitTree(node)) {
3116 // [stack] NAME FUN
3117 return false;
3118 }
3119 if (!emitDupAt(1)) {
3120 // [stack] NAME FUN NAME
3121 return false;
3122 }
3123 if (!emit2(JSOp::SetFunName, uint8_t(prefixKind))) {
3124 // [stack] NAME FUN
3125 return false;
3126 }
3127 return true;
3128 }
3129
3130 MOZ_ASSERT(node->is<ClassNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(node->is<ClassNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(node->is<ClassNode>
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("node->is<ClassNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3130); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->is<ClassNode>()"
")"); do { *((volatile int*)__null) = 3130; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3131 MOZ_ASSERT(prefixKind == FunctionPrefixKind::None)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(prefixKind == FunctionPrefixKind::None)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(prefixKind == FunctionPrefixKind::None))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("prefixKind == FunctionPrefixKind::None"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3131); AnnotateMozCrashReason("MOZ_ASSERT" "(" "prefixKind == FunctionPrefixKind::None"
")"); do { *((volatile int*)__null) = 3131; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3132
3133 return emitClass(&node->as<ClassNode>(), ClassNameKind::ComputedName);
3134}
3135
3136void BytecodeEmitter::setFunName(FunctionBox* funbox,
3137 TaggedParserAtomIndex name) const {
3138 // The inferred name may already be set if this function is an interpreted
3139 // lazy function and we OOM'ed after we set the inferred name the first
3140 // time.
3141 if (funbox->hasInferredName()) {
3142 MOZ_ASSERT(!funbox->emitBytecode)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!funbox->emitBytecode)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!funbox->emitBytecode))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("!funbox->emitBytecode"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3142); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!funbox->emitBytecode"
")"); do { *((volatile int*)__null) = 3142; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3143 MOZ_ASSERT(funbox->displayAtom() == name)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(funbox->displayAtom() == name)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(funbox->displayAtom() == name
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"funbox->displayAtom() == name", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3143); AnnotateMozCrashReason("MOZ_ASSERT" "(" "funbox->displayAtom() == name"
")"); do { *((volatile int*)__null) = 3143; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3144 } else {
3145 funbox->setInferredName(name);
3146 }
3147}
3148
3149bool BytecodeEmitter::emitInitializer(ParseNode* initializer,
3150 ParseNode* pattern) {
3151 if (initializer->isDirectRHSAnonFunction()) {
3152 MOZ_ASSERT(!pattern->isInParens())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!pattern->isInParens())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!pattern->isInParens())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("!pattern->isInParens()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3152); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!pattern->isInParens()"
")"); do { *((volatile int*)__null) = 3152; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3153 auto name = pattern->as<NameNode>().name();
3154 if (!emitAnonymousFunctionWithName(initializer, name)) {
3155 return false;
3156 }
3157 } else {
3158 if (!emitTree(initializer)) {
3159 return false;
3160 }
3161 }
3162
3163 return true;
3164}
3165
3166bool BytecodeEmitter::emitDestructuringOpsArray(ListNode* pattern,
3167 DestructuringFlavor flav) {
3168 MOZ_ASSERT(getSelfHostedIterFor(pattern) == SelfHostedIter::Deny,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(getSelfHostedIterFor(pattern) == SelfHostedIter::Deny
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(getSelfHostedIterFor(pattern) == SelfHostedIter::Deny
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"getSelfHostedIterFor(pattern) == SelfHostedIter::Deny" " (" "array destructuring is prohibited in self-hosted code because it"
"can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3170); AnnotateMozCrashReason("MOZ_ASSERT" "(" "getSelfHostedIterFor(pattern) == SelfHostedIter::Deny"
") (" "array destructuring is prohibited in self-hosted code because it"
"can run user-modifiable iteration code" ")"); do { *((volatile
int*)__null) = 3170; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
3169 "array destructuring is prohibited in self-hosted code because it"do { static_assert( mozilla::detail::AssertionConditionType<
decltype(getSelfHostedIterFor(pattern) == SelfHostedIter::Deny
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(getSelfHostedIterFor(pattern) == SelfHostedIter::Deny
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"getSelfHostedIterFor(pattern) == SelfHostedIter::Deny" " (" "array destructuring is prohibited in self-hosted code because it"
"can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3170); AnnotateMozCrashReason("MOZ_ASSERT" "(" "getSelfHostedIterFor(pattern) == SelfHostedIter::Deny"
") (" "array destructuring is prohibited in self-hosted code because it"
"can run user-modifiable iteration code" ")"); do { *((volatile
int*)__null) = 3170; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
3170 "can run user-modifiable iteration code")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(getSelfHostedIterFor(pattern) == SelfHostedIter::Deny
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(getSelfHostedIterFor(pattern) == SelfHostedIter::Deny
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"getSelfHostedIterFor(pattern) == SelfHostedIter::Deny" " (" "array destructuring is prohibited in self-hosted code because it"
"can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3170); AnnotateMozCrashReason("MOZ_ASSERT" "(" "getSelfHostedIterFor(pattern) == SelfHostedIter::Deny"
") (" "array destructuring is prohibited in self-hosted code because it"
"can run user-modifiable iteration code" ")"); do { *((volatile
int*)__null) = 3170; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
3171 MOZ_ASSERT(pattern->isKind(ParseNodeKind::ArrayExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pattern->isKind(ParseNodeKind::ArrayExpr))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(pattern->isKind(ParseNodeKind::ArrayExpr)))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("pattern->isKind(ParseNodeKind::ArrayExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3171); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pattern->isKind(ParseNodeKind::ArrayExpr)"
")"); do { *((volatile int*)__null) = 3171; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3172 MOZ_ASSERT(bytecodeSection().stackDepth() != 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bytecodeSection().stackDepth() != 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(bytecodeSection().stackDepth
() != 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("bytecodeSection().stackDepth() != 0", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3172); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() != 0"
")"); do { *((volatile int*)__null) = 3172; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3173
3174 // Here's pseudo code for |let [a, b, , c=y, ...d] = x;|
3175 //
3176 // Lines that are annotated "covered by trynote" mean that upon throwing
3177 // an exception, IteratorClose is called on iter only if done is false.
3178 //
3179 // let x, y;
3180 // let a, b, c, d;
3181 // let iter, next, lref, result, done, value; // stack values
3182 //
3183 // // NOTE: the fast path for this example is not applicable, because of
3184 // // the spread and the assignment |c=y|, but it is documented here for a
3185 // // simpler example, |let [a,b] = x;|
3186 // //
3187 // // if (IsOptimizableArray(x)) {
3188 // // a = x[0];
3189 // // b = x[1];
3190 // // goto end: // (skip everything below)
3191 // // }
3192 //
3193 // iter = x[Symbol.iterator]();
3194 // next = iter.next;
3195 //
3196 // // ==== emitted by loop for a ====
3197 // lref = GetReference(a); // covered by trynote
3198 //
3199 // result = Call(next, iter);
3200 // done = result.done;
3201 //
3202 // if (done)
3203 // value = undefined;
3204 // else
3205 // value = result.value;
3206 //
3207 // SetOrInitialize(lref, value); // covered by trynote
3208 //
3209 // // ==== emitted by loop for b ====
3210 // lref = GetReference(b); // covered by trynote
3211 //
3212 // if (done) {
3213 // value = undefined;
3214 // } else {
3215 // result = Call(next, iter);
3216 // done = result.done;
3217 // if (done)
3218 // value = undefined;
3219 // else
3220 // value = result.value;
3221 // }
3222 //
3223 // SetOrInitialize(lref, value); // covered by trynote
3224 //
3225 // // ==== emitted by loop for elision ====
3226 // if (done) {
3227 // value = undefined;
3228 // } else {
3229 // result = Call(next, iter);
3230 // done = result.done;
3231 // if (done)
3232 // value = undefined;
3233 // else
3234 // value = result.value;
3235 // }
3236 //
3237 // // ==== emitted by loop for c ====
3238 // lref = GetReference(c); // covered by trynote
3239 //
3240 // if (done) {
3241 // value = undefined;
3242 // } else {
3243 // result = Call(next, iter);
3244 // done = result.done;
3245 // if (done)
3246 // value = undefined;
3247 // else
3248 // value = result.value;
3249 // }
3250 //
3251 // if (value === undefined)
3252 // value = y; // covered by trynote
3253 //
3254 // SetOrInitialize(lref, value); // covered by trynote
3255 //
3256 // // ==== emitted by loop for d ====
3257 // lref = GetReference(d); // covered by trynote
3258 //
3259 // if (done)
3260 // value = [];
3261 // else
3262 // value = [...iter];
3263 //
3264 // SetOrInitialize(lref, value); // covered by trynote
3265 //
3266 // // === emitted after loop ===
3267 // if (!done)
3268 // IteratorClose(iter);
3269 //
3270 // end:
3271
3272 bool isEligibleForArrayOptimizations = true;
3273 for (ParseNode* member : pattern->contents()) {
3274 switch (member->getKind()) {
3275 case ParseNodeKind::Elision:
3276 break;
3277 case ParseNodeKind::Name: {
3278 auto name = member->as<NameNode>().name();
3279 NameLocation loc = lookupName(name);
3280 if (loc.kind() != NameLocation::Kind::ArgumentSlot &&
3281 loc.kind() != NameLocation::Kind::FrameSlot &&
3282 loc.kind() != NameLocation::Kind::EnvironmentCoordinate) {
3283 isEligibleForArrayOptimizations = false;
3284 }
3285 break;
3286 }
3287 default:
3288 // Unfortunately we can't handle any recursive destructuring,
3289 // because we can't guarantee that the recursed-into parts
3290 // won't run code which invalidates our constraints. We also
3291 // cannot handle ParseNodeKind::AssignExpr for similar reasons.
3292 isEligibleForArrayOptimizations = false;
3293 break;
3294 }
3295 if (!isEligibleForArrayOptimizations) {
3296 break;
3297 }
3298 }
3299
3300 // Use an iterator to destructure the RHS, instead of index lookup. We
3301 // must leave the *original* value on the stack.
3302 if (!emit1(JSOp::Dup)) {
3303 // [stack] ... OBJ OBJ
3304 return false;
3305 }
3306
3307 Maybe<InternalIfEmitter> ifArrayOptimizable;
3308
3309 if (isEligibleForArrayOptimizations) {
3310 ifArrayOptimizable.emplace(
3311 this, BranchEmitterBase::LexicalKind::MayContainLexicalAccessInBranch);
3312
3313 if (!emit1(JSOp::Dup)) {
3314 // [stack] OBJ OBJ
3315 return false;
3316 }
3317
3318 if (!emit1(JSOp::OptimizeGetIterator)) {
3319 // [stack] OBJ OBJ IS_OPTIMIZABLE
3320 return false;
3321 }
3322
3323 if (!ifArrayOptimizable->emitThenElse()) {
3324 // [stack] OBJ OBJ
3325 return false;
3326 }
3327
3328 if (!emitAtomOp(JSOp::GetProp,
3329 TaggedParserAtomIndex::WellKnown::length())) {
3330 // [stack] OBJ LENGTH
3331 return false;
3332 }
3333
3334 if (!emit1(JSOp::Swap)) {
3335 // [stack] LENGTH OBJ
3336 return false;
3337 }
3338
3339 uint32_t idx = 0;
3340 for (ParseNode* member : pattern->contents()) {
3341 if (member->isKind(ParseNodeKind::Elision)) {
3342 idx += 1;
3343 continue;
3344 }
3345 MOZ_ASSERT(member->isKind(ParseNodeKind::Name))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(member->isKind(ParseNodeKind::Name))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(member->isKind(ParseNodeKind::Name)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("member->isKind(ParseNodeKind::Name)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3345); AnnotateMozCrashReason("MOZ_ASSERT" "(" "member->isKind(ParseNodeKind::Name)"
")"); do { *((volatile int*)__null) = 3345; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3346
3347 if (!emit1(JSOp::Dup)) {
3348 // [stack] LENGTH OBJ OBJ
3349 return false;
3350 }
3351
3352 if (!emitNumberOp(idx)) {
3353 // [stack] LENGTH OBJ OBJ IDX
3354 return false;
3355 }
3356
3357 if (!emit1(JSOp::Dup)) {
3358 // [stack] LENGTH OBJ OBJ IDX IDX
3359 return false;
3360 }
3361
3362 if (!emitDupAt(4)) {
3363 // [stack] LENGTH OBJ OBJ IDX IDX LENGTH
3364 return false;
3365 }
3366
3367 if (!emit1(JSOp::Lt)) {
3368 // [stack] LENGTH OBJ OBJ IDX IS_IN_DENSE_BOUNDS
3369 return false;
3370 }
3371
3372 InternalIfEmitter isInDenseBounds(this);
3373 if (!isInDenseBounds.emitThenElse()) {
3374 // [stack] LENGTH OBJ OBJ IDX
3375 return false;
3376 }
3377
3378 if (!emit1(JSOp::GetElem)) {
3379 // [stack] LENGTH OBJ VALUE
3380 return false;
3381 }
3382
3383 if (!isInDenseBounds.emitElse()) {
3384 // [stack] LENGTH OBJ OBJ IDX
3385 return false;
3386 }
3387
3388 if (!emitPopN(2)) {
3389 // [stack] LENGTH OBJ
3390 return false;
3391 }
3392
3393 if (!emit1(JSOp::Undefined)) {
3394 // [stack] LENGTH OBJ UNDEFINED
3395 return false;
3396 }
3397
3398 if (!isInDenseBounds.emitEnd()) {
3399 // [stack] LENGTH OBJ VALUE|UNDEFINED
3400 return false;
3401 }
3402
3403 DestructuringLHSRef lref;
3404 if (!emitDestructuringLHSRef(member, flav, lref)) {
3405 // [stack] LENGTH OBJ
3406 return false;
3407 }
3408
3409 if (!emitSetOrInitializeDestructuring(member, flav, lref)) {
3410 // [stack] LENGTH OBJ
3411 return false;
3412 }
3413
3414 idx += 1;
3415 }
3416
3417 if (!emit1(JSOp::Swap)) {
3418 // [stack] OBJ LENGTH
3419 return false;
3420 }
3421
3422 if (!emit1(JSOp::Pop)) {
3423 // [stack] OBJ
3424 return false;
3425 }
3426
3427 if (!ifArrayOptimizable->emitElse()) {
3428 // [stack] OBJ OBJ
3429 return false;
3430 }
3431 }
3432
3433 if (!emitIterator(SelfHostedIter::Deny)) {
3434 // [stack] ... OBJ NEXT ITER
3435 return false;
3436 }
3437
3438 // For an empty pattern [], call IteratorClose unconditionally. Nothing
3439 // else needs to be done.
3440 if (!pattern->head()) {
3441 if (!emit1(JSOp::Swap)) {
3442 // [stack] ... OBJ ITER NEXT
3443 return false;
3444 }
3445 if (!emit1(JSOp::Pop)) {
3446 // [stack] ... OBJ ITER
3447 return false;
3448 }
3449
3450 if (!emitIteratorCloseInInnermostScope()) {
3451 // [stack] ... OBJ
3452 return false;
3453 }
3454
3455 if (ifArrayOptimizable.isSome()) {
3456 if (!ifArrayOptimizable->emitEnd()) {
3457 // [stack] OBJ
3458 return false;
3459 }
3460 }
3461
3462 return true;
3463 }
3464
3465 // Push an initial FALSE value for DONE.
3466 if (!emit1(JSOp::False)) {
3467 // [stack] ... OBJ NEXT ITER FALSE
3468 return false;
3469 }
3470
3471 // TryNoteKind::Destructuring expects the iterator and the done value
3472 // to be the second to top and the top of the stack, respectively.
3473 // IteratorClose is called upon exception only if done is false.
3474 int32_t tryNoteDepth = bytecodeSection().stackDepth();
3475
3476 for (ParseNode* member : pattern->contents()) {
3477 bool isFirst = member == pattern->head();
3478 DebugOnly<bool> hasNext = !!member->pn_next;
3479
3480 ParseNode* subpattern;
3481 if (member->isKind(ParseNodeKind::Spread)) {
3482 subpattern = member->as<UnaryNode>().kid();
3483
3484 MOZ_ASSERT(!subpattern->isKind(ParseNodeKind::AssignExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!subpattern->isKind(ParseNodeKind::AssignExpr))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!subpattern->isKind(ParseNodeKind::AssignExpr))))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("!subpattern->isKind(ParseNodeKind::AssignExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3484); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!subpattern->isKind(ParseNodeKind::AssignExpr)"
")"); do { *((volatile int*)__null) = 3484; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3485 } else {
3486 subpattern = member;
3487 }
3488
3489 ParseNode* lhsPattern = subpattern;
3490 ParseNode* pndefault = nullptr;
3491 if (subpattern->isKind(ParseNodeKind::AssignExpr)) {
3492 lhsPattern = subpattern->as<AssignmentNode>().left();
3493 pndefault = subpattern->as<AssignmentNode>().right();
3494 }
3495
3496 // Spec requires LHS reference to be evaluated first.
3497 DestructuringLHSRef lref;
3498 bool isElision = lhsPattern->isKind(ParseNodeKind::Elision);
3499 if (!isElision) {
3500 auto emitLHSRef = [lhsPattern, flav, &lref](BytecodeEmitter* bce) {
3501 return bce->emitDestructuringLHSRef(lhsPattern, flav, lref);
3502 // [stack] ... OBJ NEXT ITER DONE LREF*
3503 };
3504 if (!wrapWithDestructuringTryNote(tryNoteDepth, emitLHSRef)) {
3505 return false;
3506 }
3507 }
3508
3509 // Number of stack slots emitted for the LHS reference.
3510 size_t emitted = lref.numReferenceSlots();
3511
3512 // Pick the DONE value to the top of the stack.
3513 if (emitted) {
3514 if (!emitPickN(emitted)) {
3515 // [stack] ... OBJ NEXT ITER LREF* DONE
3516 return false;
3517 }
3518 }
3519
3520 if (isFirst) {
3521 // If this element is the first, DONE is always FALSE, so pop it.
3522 //
3523 // Non-first elements should emit if-else depending on the
3524 // member pattern, below.
3525 if (!emit1(JSOp::Pop)) {
3526 // [stack] ... OBJ NEXT ITER LREF*
3527 return false;
3528 }
3529 }
3530
3531 if (member->isKind(ParseNodeKind::Spread)) {
3532 InternalIfEmitter ifThenElse(this);
3533 if (!isFirst) {
3534 // If spread is not the first element of the pattern,
3535 // iterator can already be completed.
3536 // [stack] ... OBJ NEXT ITER LREF* DONE
3537
3538 if (!ifThenElse.emitThenElse()) {
3539 // [stack] ... OBJ NEXT ITER LREF*
3540 return false;
3541 }
3542
3543 if (!emitUint32Operand(JSOp::NewArray, 0)) {
3544 // [stack] ... OBJ NEXT ITER LREF* ARRAY
3545 return false;
3546 }
3547 if (!ifThenElse.emitElse()) {
3548 // [stack] ... OBJ NEXT ITER LREF*
3549 return false;
3550 }
3551 }
3552
3553 // If iterator is not completed, create a new array with the rest
3554 // of the iterator.
3555 if (!emitDupAt(emitted + 1, 2)) {
3556 // [stack] ... OBJ NEXT ITER LREF* NEXT ITER
3557 return false;
3558 }
3559 if (!emitUint32Operand(JSOp::NewArray, 0)) {
3560 // [stack] ... OBJ NEXT ITER LREF* NEXT ITER ARRAY
3561 return false;
3562 }
3563 if (!emitNumberOp(0)) {
3564 // [stack] ... OBJ NEXT ITER LREF* NEXT ITER ARRAY INDEX
3565 return false;
3566 }
3567 if (!emitSpread(SelfHostedIter::Deny)) {
3568 // [stack] ... OBJ NEXT ITER LREF* ARRAY INDEX
3569 return false;
3570 }
3571 if (!emit1(JSOp::Pop)) {
3572 // [stack] ... OBJ NEXT ITER LREF* ARRAY
3573 return false;
3574 }
3575
3576 if (!isFirst) {
3577 if (!ifThenElse.emitEnd()) {
3578 return false;
3579 }
3580 MOZ_ASSERT(ifThenElse.pushed() == 1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(ifThenElse.pushed() == 1)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(ifThenElse.pushed() == 1))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("ifThenElse.pushed() == 1"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3580); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ifThenElse.pushed() == 1"
")"); do { *((volatile int*)__null) = 3580; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3581 }
3582
3583 // At this point the iterator is done. Unpick a TRUE value for DONE above
3584 // ITER.
3585 if (!emit1(JSOp::True)) {
3586 // [stack] ... OBJ NEXT ITER LREF* ARRAY TRUE
3587 return false;
3588 }
3589 if (!emitUnpickN(emitted + 1)) {
3590 // [stack] ... OBJ NEXT ITER TRUE LREF* ARRAY
3591 return false;
3592 }
3593
3594 auto emitAssignment = [lhsPattern, flav, &lref](BytecodeEmitter* bce) {
3595 return bce->emitSetOrInitializeDestructuring(lhsPattern, flav, lref);
3596 // [stack] ... OBJ NEXT ITER TRUE
3597 };
3598 if (!wrapWithDestructuringTryNote(tryNoteDepth, emitAssignment)) {
3599 return false;
3600 }
3601
3602 MOZ_ASSERT(!hasNext)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!hasNext)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!hasNext))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!hasNext", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3602); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!hasNext" ")"
); do { *((volatile int*)__null) = 3602; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3603 break;
3604 }
3605
3606 InternalIfEmitter ifAlreadyDone(this);
3607 if (!isFirst) {
3608 // [stack] ... OBJ NEXT ITER LREF* DONE
3609
3610 if (!ifAlreadyDone.emitThenElse()) {
3611 // [stack] ... OBJ NEXT ITER LREF*
3612 return false;
3613 }
3614
3615 if (!emit1(JSOp::Undefined)) {
3616 // [stack] ... OBJ NEXT ITER LREF* UNDEF
3617 return false;
3618 }
3619 if (!emit1(JSOp::NopDestructuring)) {
3620 // [stack] ... OBJ NEXT ITER LREF* UNDEF
3621 return false;
3622 }
3623
3624 // The iterator is done. Unpick a TRUE value for DONE above ITER.
3625 if (!emit1(JSOp::True)) {
3626 // [stack] ... OBJ NEXT ITER LREF* UNDEF TRUE
3627 return false;
3628 }
3629 if (!emitUnpickN(emitted + 1)) {
3630 // [stack] ... OBJ NEXT ITER TRUE LREF* UNDEF
3631 return false;
3632 }
3633
3634 if (!ifAlreadyDone.emitElse()) {
3635 // [stack] ... OBJ NEXT ITER LREF*
3636 return false;
3637 }
3638 }
3639
3640 if (!emitDupAt(emitted + 1, 2)) {
3641 // [stack] ... OBJ NEXT ITER LREF* NEXT
3642 return false;
3643 }
3644 if (!emitIteratorNext(Some(pattern->pn_pos.begin))) {
3645 // [stack] ... OBJ NEXT ITER LREF* RESULT
3646 return false;
3647 }
3648 if (!emit1(JSOp::Dup)) {
3649 // [stack] ... OBJ NEXT ITER LREF* RESULT RESULT
3650 return false;
3651 }
3652 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::done())) {
3653 // [stack] ... OBJ NEXT ITER LREF* RESULT DONE
3654 return false;
3655 }
3656
3657 if (!emit1(JSOp::Dup)) {
3658 // [stack] ... OBJ NEXT ITER LREF* RESULT DONE DONE
3659 return false;
3660 }
3661 if (!emitUnpickN(emitted + 2)) {
3662 // [stack] ... OBJ NEXT ITER DONE LREF* RESULT DONE
3663 return false;
3664 }
3665
3666 InternalIfEmitter ifDone(this);
3667 if (!ifDone.emitThenElse()) {
3668 // [stack] ... OBJ NEXT ITER DONE LREF* RESULT
3669 return false;
3670 }
3671
3672 if (!emit1(JSOp::Pop)) {
3673 // [stack] ... OBJ NEXT ITER DONE LREF*
3674 return false;
3675 }
3676 if (!emit1(JSOp::Undefined)) {
3677 // [stack] ... OBJ NEXT ITER DONE LREF* UNDEF
3678 return false;
3679 }
3680 if (!emit1(JSOp::NopDestructuring)) {
3681 // [stack] ... OBJ NEXT ITER DONE LREF* UNDEF
3682 return false;
3683 }
3684
3685 if (!ifDone.emitElse()) {
3686 // [stack] ... OBJ NEXT ITER DONE LREF* RESULT
3687 return false;
3688 }
3689
3690 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::value())) {
3691 // [stack] ... OBJ NEXT ITER DONE LREF* VALUE
3692 return false;
3693 }
3694
3695 if (!ifDone.emitEnd()) {
3696 return false;
3697 }
3698 MOZ_ASSERT(ifDone.pushed() == 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(ifDone.pushed() == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(ifDone.pushed() == 0))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("ifDone.pushed() == 0"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3698); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ifDone.pushed() == 0"
")"); do { *((volatile int*)__null) = 3698; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3699
3700 if (!isFirst) {
3701 if (!ifAlreadyDone.emitEnd()) {
3702 return false;
3703 }
3704 MOZ_ASSERT(ifAlreadyDone.pushed() == 2)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(ifAlreadyDone.pushed() == 2)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(ifAlreadyDone.pushed() == 2)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("ifAlreadyDone.pushed() == 2"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3704); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ifAlreadyDone.pushed() == 2"
")"); do { *((volatile int*)__null) = 3704; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3705 }
3706
3707 if (pndefault) {
3708 auto emitDefault = [pndefault, lhsPattern](BytecodeEmitter* bce) {
3709 return bce->emitDefault(pndefault, lhsPattern);
3710 // [stack] ... OBJ NEXT ITER DONE LREF* VALUE
3711 };
3712
3713 if (!wrapWithDestructuringTryNote(tryNoteDepth, emitDefault)) {
3714 return false;
3715 }
3716 }
3717
3718 if (!isElision) {
3719 auto emitAssignment = [lhsPattern, flav, &lref](BytecodeEmitter* bce) {
3720 return bce->emitSetOrInitializeDestructuring(lhsPattern, flav, lref);
3721 // [stack] ... OBJ NEXT ITER DONE
3722 };
3723
3724 if (!wrapWithDestructuringTryNote(tryNoteDepth, emitAssignment)) {
3725 return false;
3726 }
3727 } else {
3728 if (!emit1(JSOp::Pop)) {
3729 // [stack] ... OBJ NEXT ITER DONE
3730 return false;
3731 }
3732 }
3733 }
3734
3735 // The last DONE value is on top of the stack. If not DONE, call
3736 // IteratorClose.
3737 // [stack] ... OBJ NEXT ITER DONE
3738
3739 InternalIfEmitter ifDone(this);
3740 if (!ifDone.emitThenElse()) {
3741 // [stack] ... OBJ NEXT ITER
3742 return false;
3743 }
3744 if (!emitPopN(2)) {
3745 // [stack] ... OBJ
3746 return false;
3747 }
3748 if (!ifDone.emitElse()) {
3749 // [stack] ... OBJ NEXT ITER
3750 return false;
3751 }
3752 if (!emit1(JSOp::Swap)) {
3753 // [stack] ... OBJ ITER NEXT
3754 return false;
3755 }
3756 if (!emit1(JSOp::Pop)) {
3757 // [stack] ... OBJ ITER
3758 return false;
3759 }
3760 if (!emitIteratorCloseInInnermostScope()) {
3761 // [stack] ... OBJ
3762 return false;
3763 }
3764 if (!ifDone.emitEnd()) {
3765 return false;
3766 }
3767
3768 if (ifArrayOptimizable.isSome()) {
3769 if (!ifArrayOptimizable->emitEnd()) {
3770 // [stack] OBJ
3771 return false;
3772 }
3773 }
3774
3775 return true;
3776}
3777
3778bool BytecodeEmitter::emitComputedPropertyName(UnaryNode* computedPropName) {
3779 MOZ_ASSERT(computedPropName->isKind(ParseNodeKind::ComputedName))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(computedPropName->isKind(ParseNodeKind::ComputedName
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(computedPropName->isKind(ParseNodeKind::ComputedName
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("computedPropName->isKind(ParseNodeKind::ComputedName)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3779); AnnotateMozCrashReason("MOZ_ASSERT" "(" "computedPropName->isKind(ParseNodeKind::ComputedName)"
")"); do { *((volatile int*)__null) = 3779; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3780 return emitTree(computedPropName->kid()) && emit1(JSOp::ToPropertyKey);
3781}
3782
3783bool BytecodeEmitter::emitDestructuringOpsObject(ListNode* pattern,
3784 DestructuringFlavor flav) {
3785 MOZ_ASSERT(pattern->isKind(ParseNodeKind::ObjectExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pattern->isKind(ParseNodeKind::ObjectExpr))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(pattern->isKind(ParseNodeKind::ObjectExpr)))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("pattern->isKind(ParseNodeKind::ObjectExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3785); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pattern->isKind(ParseNodeKind::ObjectExpr)"
")"); do { *((volatile int*)__null) = 3785; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3786
3787 // [stack] ... RHS
3788 MOZ_ASSERT(bytecodeSection().stackDepth() > 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bytecodeSection().stackDepth() > 0)>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(bytecodeSection().stackDepth() > 0))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("bytecodeSection().stackDepth() > 0"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3788); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() > 0"
")"); do { *((volatile int*)__null) = 3788; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3789
3790 if (!emit1(JSOp::CheckObjCoercible)) {
3791 // [stack] ... RHS
3792 return false;
3793 }
3794
3795 bool needsRestPropertyExcludedSet =
3796 pattern->count() > 1 && pattern->last()->isKind(ParseNodeKind::Spread);
3797 if (needsRestPropertyExcludedSet) {
3798 if (!emitDestructuringObjRestExclusionSet(pattern)) {
3799 // [stack] ... RHS SET
3800 return false;
3801 }
3802
3803 if (!emit1(JSOp::Swap)) {
3804 // [stack] ... SET RHS
3805 return false;
3806 }
3807 }
3808
3809 for (ParseNode* member : pattern->contents()) {
3810 ParseNode* subpattern;
3811 bool hasKeyOnStack = false;
3812 if (member->isKind(ParseNodeKind::MutateProto) ||
3813 member->isKind(ParseNodeKind::Spread)) {
3814 subpattern = member->as<UnaryNode>().kid();
3815
3816 MOZ_ASSERT_IF(member->isKind(ParseNodeKind::Spread),do { if (member->isKind(ParseNodeKind::Spread)) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(!subpattern
->isKind(ParseNodeKind::AssignExpr))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!subpattern->isKind(ParseNodeKind
::AssignExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!subpattern->isKind(ParseNodeKind::AssignExpr)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3817); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!subpattern->isKind(ParseNodeKind::AssignExpr)"
")"); do { *((volatile int*)__null) = 3817; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3817 !subpattern->isKind(ParseNodeKind::AssignExpr))do { if (member->isKind(ParseNodeKind::Spread)) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(!subpattern
->isKind(ParseNodeKind::AssignExpr))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!subpattern->isKind(ParseNodeKind
::AssignExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!subpattern->isKind(ParseNodeKind::AssignExpr)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3817); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!subpattern->isKind(ParseNodeKind::AssignExpr)"
")"); do { *((volatile int*)__null) = 3817; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
3818 } else {
3819 MOZ_ASSERT(member->isKind(ParseNodeKind::PropertyDefinition) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(member->isKind(ParseNodeKind::PropertyDefinition)
|| member->isKind(ParseNodeKind::Shorthand))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(member->isKind(ParseNodeKind::PropertyDefinition) || member
->isKind(ParseNodeKind::Shorthand)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3820); AnnotateMozCrashReason("MOZ_ASSERT" "(" "member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)"
")"); do { *((volatile int*)__null) = 3820; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3820 member->isKind(ParseNodeKind::Shorthand))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(member->isKind(ParseNodeKind::PropertyDefinition)
|| member->isKind(ParseNodeKind::Shorthand))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(member->isKind(ParseNodeKind::PropertyDefinition) || member
->isKind(ParseNodeKind::Shorthand)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3820); AnnotateMozCrashReason("MOZ_ASSERT" "(" "member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)"
")"); do { *((volatile int*)__null) = 3820; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3821 subpattern = member->as<BinaryNode>().right();
3822
3823 // Computed property names are evaluated before the subpattern.
3824 ParseNode* key = member->as<BinaryNode>().left();
3825 if (key->isKind(ParseNodeKind::ComputedName)) {
3826 if (!emitComputedPropertyName(&key->as<UnaryNode>())) {
3827 // [stack] ... SET? RHS KEY
3828 return false;
3829 }
3830 hasKeyOnStack = true;
3831 }
3832 }
3833
3834 ParseNode* lhs = subpattern;
3835 ParseNode* pndefault = nullptr;
3836 if (subpattern->isKind(ParseNodeKind::AssignExpr)) {
3837 lhs = subpattern->as<AssignmentNode>().left();
3838 pndefault = subpattern->as<AssignmentNode>().right();
3839 }
3840
3841 // Spec requires LHS reference to be evaluated first.
3842 DestructuringLHSRef lref;
3843 if (!emitDestructuringLHSRef(lhs, flav, lref)) {
3844 // [stack] ... SET? RHS KEY? LREF*
3845 return false;
3846 }
3847
3848 // Number of stack slots emitted for the LHS reference.
3849 size_t emitted = lref.numReferenceSlots();
3850
3851 // Duplicate the value being destructured to use as a reference base.
3852 if (!emitDupAt(emitted + hasKeyOnStack)) {
3853 // [stack] ... SET? RHS KEY? LREF* RHS
3854 return false;
3855 }
3856
3857 if (member->isKind(ParseNodeKind::Spread)) {
3858 if (!updateSourceCoordNotes(member->pn_pos.begin)) {
3859 return false;
3860 }
3861
3862 if (!emit1(JSOp::NewInit)) {
3863 // [stack] ... SET? RHS LREF* RHS TARGET
3864 return false;
3865 }
3866 if (!emit1(JSOp::Dup)) {
3867 // [stack] ... SET? RHS LREF* RHS TARGET TARGET
3868 return false;
3869 }
3870 if (!emit2(JSOp::Pick, 2)) {
3871 // [stack] ... SET? RHS LREF* TARGET TARGET RHS
3872 return false;
3873 }
3874
3875 if (needsRestPropertyExcludedSet) {
3876 if (!emit2(JSOp::Pick, emitted + 4)) {
3877 // [stack] ... RHS LREF* TARGET TARGET RHS SET
3878 return false;
3879 }
3880 }
3881
3882 CopyOption option = needsRestPropertyExcludedSet ? CopyOption::Filtered
3883 : CopyOption::Unfiltered;
3884 if (!emitCopyDataProperties(option)) {
3885 // [stack] ... RHS LREF* TARGET
3886 return false;
3887 }
3888
3889 // Destructure TARGET per this member's lhs.
3890 if (!emitSetOrInitializeDestructuring(lhs, flav, lref)) {
3891 // [stack] ... RHS
3892 return false;
3893 }
3894
3895 MOZ_ASSERT(member == pattern->last(), "Rest property is always last")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(member == pattern->last())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(member == pattern->last()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"member == pattern->last()" " (" "Rest property is always last"
")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3895); AnnotateMozCrashReason("MOZ_ASSERT" "(" "member == pattern->last()"
") (" "Rest property is always last" ")"); do { *((volatile int
*)__null) = 3895; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
3896 break;
3897 }
3898
3899 // Now push the property value currently being matched, which is the value
3900 // of the current property name "label" on the left of a colon in the object
3901 // initialiser.
3902 if (member->isKind(ParseNodeKind::MutateProto)) {
3903 if (!emitAtomOp(JSOp::GetProp,
3904 TaggedParserAtomIndex::WellKnown::proto_())) {
3905 // [stack] ... SET? RHS LREF* PROP
3906 return false;
3907 }
3908 } else {
3909 MOZ_ASSERT(member->isKind(ParseNodeKind::PropertyDefinition) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(member->isKind(ParseNodeKind::PropertyDefinition)
|| member->isKind(ParseNodeKind::Shorthand))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(member->isKind(ParseNodeKind::PropertyDefinition) || member
->isKind(ParseNodeKind::Shorthand)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3910); AnnotateMozCrashReason("MOZ_ASSERT" "(" "member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)"
")"); do { *((volatile int*)__null) = 3910; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3910 member->isKind(ParseNodeKind::Shorthand))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(member->isKind(ParseNodeKind::PropertyDefinition)
|| member->isKind(ParseNodeKind::Shorthand))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(member->isKind(ParseNodeKind::PropertyDefinition) || member
->isKind(ParseNodeKind::Shorthand)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3910); AnnotateMozCrashReason("MOZ_ASSERT" "(" "member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)"
")"); do { *((volatile int*)__null) = 3910; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3911
3912 ParseNode* key = member->as<BinaryNode>().left();
3913 if (key->isKind(ParseNodeKind::ObjectPropertyName) ||
3914 key->isKind(ParseNodeKind::StringExpr)) {
3915 if (!emitAtomOp(JSOp::GetProp, key->as<NameNode>().atom())) {
3916 // [stack] ... SET? RHS LREF* PROP
3917 return false;
3918 }
3919 } else {
3920 if (key->isKind(ParseNodeKind::NumberExpr)) {
3921 if (!emitNumberOp(key->as<NumericLiteral>().value())) {
3922 // [stack]... SET? RHS LREF* RHS KEY
3923 return false;
3924 }
3925 } else {
3926 // Otherwise this is a computed property name. BigInt keys are parsed
3927 // as (synthetic) computed property names, too.
3928 MOZ_ASSERT(key->isKind(ParseNodeKind::ComputedName))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(key->isKind(ParseNodeKind::ComputedName))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(key->isKind(ParseNodeKind::ComputedName)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("key->isKind(ParseNodeKind::ComputedName)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3928); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::ComputedName)"
")"); do { *((volatile int*)__null) = 3928; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3929 MOZ_ASSERT(hasKeyOnStack)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(hasKeyOnStack)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(hasKeyOnStack))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("hasKeyOnStack",
"/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3929); AnnotateMozCrashReason("MOZ_ASSERT" "(" "hasKeyOnStack"
")"); do { *((volatile int*)__null) = 3929; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3930
3931 if (!emit2(JSOp::Pick, emitted + 1)) {
3932 // [stack] ... SET? RHS LREF* RHS KEY
3933 return false;
3934 }
3935
3936 // Add the computed property key to the exclusion set.
3937 if (needsRestPropertyExcludedSet) {
3938 if (!emitDupAt(emitted + 3)) {
3939 // [stack] ... SET RHS LREF* RHS KEY SET
3940 return false;
3941 }
3942 if (!emitDupAt(1)) {
3943 // [stack] ... SET RHS LREF* RHS KEY SET KEY
3944 return false;
3945 }
3946 if (!emit1(JSOp::Undefined)) {
3947 // [stack] ... SET RHS LREF* RHS KEY SET KEY UNDEFINED
3948 return false;
3949 }
3950 if (!emit1(JSOp::InitElem)) {
3951 // [stack] ... SET RHS LREF* RHS KEY SET
3952 return false;
3953 }
3954 if (!emit1(JSOp::Pop)) {
3955 // [stack] ... SET RHS LREF* RHS KEY
3956 return false;
3957 }
3958 }
3959 }
3960
3961 // Get the property value.
3962 if (!emitElemOpBase(JSOp::GetElem)) {
3963 // [stack] ... SET? RHS LREF* PROP
3964 return false;
3965 }
3966 }
3967 }
3968
3969 if (pndefault) {
3970 if (!emitDefault(pndefault, lhs)) {
3971 // [stack] ... SET? RHS LREF* VALUE
3972 return false;
3973 }
3974 }
3975
3976 // Destructure PROP per this member's lhs.
3977 if (!emitSetOrInitializeDestructuring(lhs, flav, lref)) {
3978 // [stack] ... SET? RHS
3979 return false;
3980 }
3981 }
3982
3983 return true;
3984}
3985
3986static bool IsDestructuringRestExclusionSetObjLiteralCompatible(
3987 ListNode* pattern) {
3988 uint32_t propCount = 0;
3989 for (ParseNode* member : pattern->contents()) {
3990 if (member->isKind(ParseNodeKind::Spread)) {
3991 MOZ_ASSERT(!member->pn_next, "unexpected trailing element after spread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!member->pn_next)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!member->pn_next))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("!member->pn_next"
" (" "unexpected trailing element after spread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3991); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!member->pn_next"
") (" "unexpected trailing element after spread" ")"); do { *
((volatile int*)__null) = 3991; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
3992 break;
3993 }
3994
3995 propCount++;
3996
3997 if (member->isKind(ParseNodeKind::MutateProto)) {
3998 continue;
3999 }
4000
4001 ParseNode* key = member->as<BinaryNode>().left();
4002 if (key->isKind(ParseNodeKind::ObjectPropertyName) ||
4003 key->isKind(ParseNodeKind::StringExpr)) {
4004 continue;
4005 }
4006
4007 // Number and BigInt keys aren't yet supported. Computed property names need
4008 // to be added dynamically.
4009 MOZ_ASSERT(key->isKind(ParseNodeKind::NumberExpr) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(key->isKind(ParseNodeKind::NumberExpr) || key->
isKind(ParseNodeKind::BigIntExpr) || key->isKind(ParseNodeKind
::ComputedName))>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(key->isKind(ParseNodeKind::
NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr) || key
->isKind(ParseNodeKind::ComputedName)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr) || key->isKind(ParseNodeKind::ComputedName)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4011); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr) || key->isKind(ParseNodeKind::ComputedName)"
")"); do { *((volatile int*)__null) = 4011; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4010 key->isKind(ParseNodeKind::BigIntExpr) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(key->isKind(ParseNodeKind::NumberExpr) || key->
isKind(ParseNodeKind::BigIntExpr) || key->isKind(ParseNodeKind
::ComputedName))>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(key->isKind(ParseNodeKind::
NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr) || key
->isKind(ParseNodeKind::ComputedName)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr) || key->isKind(ParseNodeKind::ComputedName)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4011); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr) || key->isKind(ParseNodeKind::ComputedName)"
")"); do { *((volatile int*)__null) = 4011; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4011 key->isKind(ParseNodeKind::ComputedName))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(key->isKind(ParseNodeKind::NumberExpr) || key->
isKind(ParseNodeKind::BigIntExpr) || key->isKind(ParseNodeKind
::ComputedName))>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(key->isKind(ParseNodeKind::
NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr) || key
->isKind(ParseNodeKind::ComputedName)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr) || key->isKind(ParseNodeKind::ComputedName)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4011); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr) || key->isKind(ParseNodeKind::ComputedName)"
")"); do { *((volatile int*)__null) = 4011; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4012 return false;
4013 }
4014
4015 if (propCount > SharedPropMap::MaxPropsForNonDictionary) {
4016 // JSOp::NewObject cannot accept dictionary-mode objects.
4017 return false;
4018 }
4019
4020 return true;
4021}
4022
4023bool BytecodeEmitter::emitDestructuringObjRestExclusionSet(ListNode* pattern) {
4024 MOZ_ASSERT(pattern->isKind(ParseNodeKind::ObjectExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pattern->isKind(ParseNodeKind::ObjectExpr))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(pattern->isKind(ParseNodeKind::ObjectExpr)))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("pattern->isKind(ParseNodeKind::ObjectExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4024); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pattern->isKind(ParseNodeKind::ObjectExpr)"
")"); do { *((volatile int*)__null) = 4024; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4025 MOZ_ASSERT(pattern->last()->isKind(ParseNodeKind::Spread))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pattern->last()->isKind(ParseNodeKind::Spread)
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(pattern->last()->isKind(ParseNodeKind::Spread)
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"pattern->last()->isKind(ParseNodeKind::Spread)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4025); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pattern->last()->isKind(ParseNodeKind::Spread)"
")"); do { *((volatile int*)__null) = 4025; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4026
4027 // See if we can use ObjLiteral to construct the exclusion set object.
4028 if (IsDestructuringRestExclusionSetObjLiteralCompatible(pattern)) {
4029 if (!emitDestructuringRestExclusionSetObjLiteral(pattern)) {
4030 // [stack] OBJ
4031 return false;
4032 }
4033 } else {
4034 // Take the slow but sure way and start off with a blank object.
4035 if (!emit1(JSOp::NewInit)) {
4036 // [stack] OBJ
4037 return false;
4038 }
4039 }
4040
4041 for (ParseNode* member : pattern->contents()) {
4042 if (member->isKind(ParseNodeKind::Spread)) {
4043 MOZ_ASSERT(!member->pn_next, "unexpected trailing element after spread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!member->pn_next)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!member->pn_next))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("!member->pn_next"
" (" "unexpected trailing element after spread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4043); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!member->pn_next"
") (" "unexpected trailing element after spread" ")"); do { *
((volatile int*)__null) = 4043; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
4044 break;
4045 }
4046
4047 TaggedParserAtomIndex pnatom;
4048 if (member->isKind(ParseNodeKind::MutateProto)) {
4049 pnatom = TaggedParserAtomIndex::WellKnown::proto_();
4050 } else {
4051 ParseNode* key = member->as<BinaryNode>().left();
4052 if (key->isKind(ParseNodeKind::ObjectPropertyName) ||
4053 key->isKind(ParseNodeKind::StringExpr)) {
4054 pnatom = key->as<NameNode>().atom();
4055 } else if (key->isKind(ParseNodeKind::NumberExpr)) {
4056 if (!emitNumberOp(key->as<NumericLiteral>().value())) {
4057 return false;
4058 }
4059 } else {
4060 // Otherwise this is a computed property name which needs to be added
4061 // dynamically. BigInt keys are parsed as (synthetic) computed property
4062 // names, too.
4063 MOZ_ASSERT(key->isKind(ParseNodeKind::ComputedName))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(key->isKind(ParseNodeKind::ComputedName))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(key->isKind(ParseNodeKind::ComputedName)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("key->isKind(ParseNodeKind::ComputedName)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4063); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::ComputedName)"
")"); do { *((volatile int*)__null) = 4063; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4064 continue;
4065 }
4066 }
4067
4068 // Initialize elements with |undefined|.
4069 if (!emit1(JSOp::Undefined)) {
4070 return false;
4071 }
4072
4073 if (!pnatom) {
4074 if (!emit1(JSOp::InitElem)) {
4075 return false;
4076 }
4077 } else {
4078 if (!emitAtomOp(JSOp::InitProp, pnatom)) {
4079 return false;
4080 }
4081 }
4082 }
4083
4084 return true;
4085}
4086
4087bool BytecodeEmitter::emitDestructuringOps(ListNode* pattern,
4088 DestructuringFlavor flav) {
4089 if (pattern->isKind(ParseNodeKind::ArrayExpr)) {
4090 return emitDestructuringOpsArray(pattern, flav);
4091 }
4092 return emitDestructuringOpsObject(pattern, flav);
4093}
4094
4095bool BytecodeEmitter::emitTemplateString(ListNode* templateString) {
4096 bool pushedString = false;
4097
4098 for (ParseNode* item : templateString->contents()) {
4099 bool isString = (item->getKind() == ParseNodeKind::StringExpr ||
4100 item->getKind() == ParseNodeKind::TemplateStringExpr);
4101
4102 // Skip empty strings. These are very common: a template string like
4103 // `${a}${b}` has three empty strings and without this optimization
4104 // we'd emit four JSOp::Add operations instead of just one.
4105 if (isString && item->as<NameNode>().atom() ==
4106 TaggedParserAtomIndex::WellKnown::empty()) {
4107 continue;
4108 }
4109
4110 if (!isString) {
4111 // We update source notes before emitting the expression
4112 if (!updateSourceCoordNotes(item->pn_pos.begin)) {
4113 return false;
4114 }
4115 }
4116
4117 if (!emitTree(item)) {
4118 return false;
4119 }
4120
4121 if (!isString) {
4122 // We need to convert the expression to a string
4123 if (!emit1(JSOp::ToString)) {
4124 return false;
4125 }
4126 }
4127
4128 if (pushedString) {
4129 // We've pushed two strings onto the stack. Add them together, leaving
4130 // just one.
4131 if (!emit1(JSOp::Add)) {
4132 return false;
4133 }
4134 } else {
4135 pushedString = true;
4136 }
4137 }
4138
4139 if (!pushedString) {
4140 // All strings were empty, this can happen for something like `${""}`.
4141 // Just push an empty string.
4142 if (!emitStringOp(JSOp::String,
4143 TaggedParserAtomIndex::WellKnown::empty())) {
4144 return false;
4145 }
4146 }
4147
4148 return true;
4149}
4150
4151bool BytecodeEmitter::emitDeclarationList(ListNode* declList) {
4152 for (ParseNode* decl : declList->contents()) {
4153 ParseNode* pattern;
4154 ParseNode* initializer;
4155 if (decl->isKind(ParseNodeKind::Name)) {
4156 pattern = decl;
4157 initializer = nullptr;
4158 } else {
4159 AssignmentNode* assignNode = &decl->as<AssignmentNode>();
4160 pattern = assignNode->left();
4161 initializer = assignNode->right();
4162 }
4163
4164 if (pattern->isKind(ParseNodeKind::Name)) {
4165 // initializer can be null here.
4166 if (!emitSingleDeclaration(declList, &pattern->as<NameNode>(),
4167 initializer)) {
4168 return false;
4169 }
4170 } else {
4171 MOZ_ASSERT(pattern->isKind(ParseNodeKind::ArrayExpr) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pattern->isKind(ParseNodeKind::ArrayExpr) || pattern
->isKind(ParseNodeKind::ObjectExpr))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pattern->isKind(ParseNodeKind
::ArrayExpr) || pattern->isKind(ParseNodeKind::ObjectExpr)
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"pattern->isKind(ParseNodeKind::ArrayExpr) || pattern->isKind(ParseNodeKind::ObjectExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4172); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pattern->isKind(ParseNodeKind::ArrayExpr) || pattern->isKind(ParseNodeKind::ObjectExpr)"
")"); do { *((volatile int*)__null) = 4172; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4172 pattern->isKind(ParseNodeKind::ObjectExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pattern->isKind(ParseNodeKind::ArrayExpr) || pattern
->isKind(ParseNodeKind::ObjectExpr))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pattern->isKind(ParseNodeKind
::ArrayExpr) || pattern->isKind(ParseNodeKind::ObjectExpr)
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"pattern->isKind(ParseNodeKind::ArrayExpr) || pattern->isKind(ParseNodeKind::ObjectExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4172); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pattern->isKind(ParseNodeKind::ArrayExpr) || pattern->isKind(ParseNodeKind::ObjectExpr)"
")"); do { *((volatile int*)__null) = 4172; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4173 MOZ_ASSERT(initializer != nullptr)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(initializer != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(initializer != nullptr))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("initializer != nullptr"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4173); AnnotateMozCrashReason("MOZ_ASSERT" "(" "initializer != nullptr"
")"); do { *((volatile int*)__null) = 4173; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4174
4175 if (!updateSourceCoordNotes(initializer->pn_pos.begin)) {
4176 return false;
4177 }
4178 if (!markStepBreakpoint()) {
4179 return false;
4180 }
4181 if (!emitTree(initializer)) {
4182 return false;
4183 }
4184
4185 if (!emitDestructuringOps(&pattern->as<ListNode>(),
4186 DestructuringFlavor::Declaration)) {
4187 return false;
4188 }
4189
4190 if (!emit1(JSOp::Pop)) {
4191 return false;
4192 }
4193 }
4194 }
4195 return true;
4196}
4197
4198bool BytecodeEmitter::emitSingleDeclaration(ListNode* declList, NameNode* decl,
4199 ParseNode* initializer) {
4200 MOZ_ASSERT(decl->isKind(ParseNodeKind::Name))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(decl->isKind(ParseNodeKind::Name))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(decl->isKind(ParseNodeKind
::Name)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("decl->isKind(ParseNodeKind::Name)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4200); AnnotateMozCrashReason("MOZ_ASSERT" "(" "decl->isKind(ParseNodeKind::Name)"
")"); do { *((volatile int*)__null) = 4200; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4201
4202 // Nothing to do for initializer-less 'var' declarations, as there's no TDZ.
4203 if (!initializer && declList->isKind(ParseNodeKind::VarStmt)) {
4204 return true;
4205 }
4206
4207 auto nameAtom = decl->name();
4208 NameOpEmitter noe(this, nameAtom, NameOpEmitter::Kind::Initialize);
4209 if (!noe.prepareForRhs()) {
4210 // [stack] ENV?
4211 return false;
4212 }
4213 if (!initializer) {
4214 // Lexical declarations are initialized to undefined without an
4215 // initializer.
4216 MOZ_ASSERT(declList->isKind(ParseNodeKind::LetDecl),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(declList->isKind(ParseNodeKind::LetDecl))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(declList->isKind(ParseNodeKind::LetDecl)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("declList->isKind(ParseNodeKind::LetDecl)"
" (" "var declarations without initializers handled above, "
"and const declarations must have initializers" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4218); AnnotateMozCrashReason("MOZ_ASSERT" "(" "declList->isKind(ParseNodeKind::LetDecl)"
") (" "var declarations without initializers handled above, "
"and const declarations must have initializers" ")"); do { *
((volatile int*)__null) = 4218; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
4217 "var declarations without initializers handled above, "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(declList->isKind(ParseNodeKind::LetDecl))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(declList->isKind(ParseNodeKind::LetDecl)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("declList->isKind(ParseNodeKind::LetDecl)"
" (" "var declarations without initializers handled above, "
"and const declarations must have initializers" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4218); AnnotateMozCrashReason("MOZ_ASSERT" "(" "declList->isKind(ParseNodeKind::LetDecl)"
") (" "var declarations without initializers handled above, "
"and const declarations must have initializers" ")"); do { *
((volatile int*)__null) = 4218; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
4218 "and const declarations must have initializers")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(declList->isKind(ParseNodeKind::LetDecl))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(declList->isKind(ParseNodeKind::LetDecl)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("declList->isKind(ParseNodeKind::LetDecl)"
" (" "var declarations without initializers handled above, "
"and const declarations must have initializers" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4218); AnnotateMozCrashReason("MOZ_ASSERT" "(" "declList->isKind(ParseNodeKind::LetDecl)"
") (" "var declarations without initializers handled above, "
"and const declarations must have initializers" ")"); do { *
((volatile int*)__null) = 4218; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
4219 if (!emit1(JSOp::Undefined)) {
4220 // [stack] ENV? UNDEF
4221 return false;
4222 }
4223 } else {
4224 MOZ_ASSERT(initializer)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(initializer)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(initializer))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("initializer", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4224); AnnotateMozCrashReason("MOZ_ASSERT" "(" "initializer"
")"); do { *((volatile int*)__null) = 4224; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4225
4226 if (!updateSourceCoordNotes(initializer->pn_pos.begin)) {
4227 return false;
4228 }
4229 if (!markStepBreakpoint()) {
4230 return false;
4231 }
4232 if (!emitInitializer(initializer, decl)) {
4233 // [stack] ENV? V
4234 return false;
4235 }
4236 }
4237
4238#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT1
4239 if (declList->isKind(ParseNodeKind::UsingDecl)) {
4240 if (!innermostEmitterScope()->prepareForDisposableAssignment(
4241 UsingHint::Sync)) {
4242 // [stack] ENV? V
4243 return false;
4244 }
4245 } else if (declList->isKind(ParseNodeKind::AwaitUsingDecl)) {
4246 if (!innermostEmitterScope()->prepareForDisposableAssignment(
4247 UsingHint::Async)) {
4248 // [stack] ENV? V
4249 return false;
4250 }
4251 }
4252#endif
4253
4254 if (!noe.emitAssignment()) {
4255 // [stack] V
4256 return false;
4257 }
4258
4259 if (!emit1(JSOp::Pop)) {
4260 // [stack]
4261 return false;
4262 }
4263
4264 return true;
4265}
4266
4267bool BytecodeEmitter::emitAssignmentRhs(
4268 ParseNode* rhs, TaggedParserAtomIndex anonFunctionName) {
4269 if (rhs->isDirectRHSAnonFunction()) {
4270 if (anonFunctionName) {
4271 return emitAnonymousFunctionWithName(rhs, anonFunctionName);
4272 }
4273 return emitAnonymousFunctionWithComputedName(rhs, FunctionPrefixKind::None);
4274 }
4275 return emitTree(rhs);
4276}
4277
4278// The RHS value to assign is already on the stack, i.e., the next enumeration
4279// value in a for-in or for-of loop. Offset is the location in the stack of the
4280// already-emitted rhs. If we emitted a JSOp::BindUnqualifiedName or
4281// JSOp::BindUnqualifiedGName, then the scope is on the top of the stack and we
4282// need to dig one deeper to get the right RHS value.
4283bool BytecodeEmitter::emitAssignmentRhs(uint8_t offset) {
4284 if (offset != 1) {
4285 return emitPickN(offset - 1);
4286 }
4287
4288 return true;
4289}
4290
4291static inline JSOp CompoundAssignmentParseNodeKindToJSOp(ParseNodeKind pnk) {
4292 switch (pnk) {
4293 case ParseNodeKind::InitExpr:
4294 return JSOp::Nop;
4295 case ParseNodeKind::AssignExpr:
4296 return JSOp::Nop;
4297 case ParseNodeKind::AddAssignExpr:
4298 return JSOp::Add;
4299 case ParseNodeKind::SubAssignExpr:
4300 return JSOp::Sub;
4301 case ParseNodeKind::BitOrAssignExpr:
4302 return JSOp::BitOr;
4303 case ParseNodeKind::BitXorAssignExpr:
4304 return JSOp::BitXor;
4305 case ParseNodeKind::BitAndAssignExpr:
4306 return JSOp::BitAnd;
4307 case ParseNodeKind::LshAssignExpr:
4308 return JSOp::Lsh;
4309 case ParseNodeKind::RshAssignExpr:
4310 return JSOp::Rsh;
4311 case ParseNodeKind::UrshAssignExpr:
4312 return JSOp::Ursh;
4313 case ParseNodeKind::MulAssignExpr:
4314 return JSOp::Mul;
4315 case ParseNodeKind::DivAssignExpr:
4316 return JSOp::Div;
4317 case ParseNodeKind::ModAssignExpr:
4318 return JSOp::Mod;
4319 case ParseNodeKind::PowAssignExpr:
4320 return JSOp::Pow;
4321 case ParseNodeKind::CoalesceAssignExpr:
4322 case ParseNodeKind::OrAssignExpr:
4323 case ParseNodeKind::AndAssignExpr:
4324 // Short-circuit assignment operators are handled elsewhere.
4325 [[fallthrough]];
4326 default:
4327 MOZ_CRASH("unexpected compound assignment op")do { do { } while (false); MOZ_ReportCrash("" "unexpected compound assignment op"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4327); AnnotateMozCrashReason("MOZ_CRASH(" "unexpected compound assignment op"
")"); do { *((volatile int*)__null) = 4327; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
4328 }
4329}
4330
4331bool BytecodeEmitter::emitAssignmentOrInit(ParseNodeKind kind, ParseNode* lhs,
4332 ParseNode* rhs) {
4333 JSOp compoundOp = CompoundAssignmentParseNodeKindToJSOp(kind);
4334 bool isCompound = compoundOp != JSOp::Nop;
4335 bool isInit = kind == ParseNodeKind::InitExpr;
4336
4337 // We estimate the number of properties this could create
4338 // if used as constructor merely by counting this.foo = assignment
4339 // or init expressions;
4340 //
4341 // This currently doesn't handle this[x] = foo;
4342 if (isInit || kind == ParseNodeKind::AssignExpr) {
4343 if (lhs->isKind(ParseNodeKind::DotExpr)) {
4344 if (lhs->as<PropertyAccess>().expression().isKind(
4345 ParseNodeKind::ThisExpr)) {
4346 propertyAdditionEstimate++;
4347 }
4348 }
4349 }
4350
4351 MOZ_ASSERT_IF(isInit, lhs->isKind(ParseNodeKind::DotExpr) ||do { if (isInit) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(lhs->isKind(ParseNodeKind::DotExpr) || lhs->
isKind(ParseNodeKind::ElemExpr) || lhs->isKind(ParseNodeKind
::PrivateMemberExpr))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(lhs->isKind(ParseNodeKind
::DotExpr) || lhs->isKind(ParseNodeKind::ElemExpr) || lhs->
isKind(ParseNodeKind::PrivateMemberExpr)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("lhs->isKind(ParseNodeKind::DotExpr) || lhs->isKind(ParseNodeKind::ElemExpr) || lhs->isKind(ParseNodeKind::PrivateMemberExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4353); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lhs->isKind(ParseNodeKind::DotExpr) || lhs->isKind(ParseNodeKind::ElemExpr) || lhs->isKind(ParseNodeKind::PrivateMemberExpr)"
")"); do { *((volatile int*)__null) = 4353; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4352 lhs->isKind(ParseNodeKind::ElemExpr) ||do { if (isInit) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(lhs->isKind(ParseNodeKind::DotExpr) || lhs->
isKind(ParseNodeKind::ElemExpr) || lhs->isKind(ParseNodeKind
::PrivateMemberExpr))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(lhs->isKind(ParseNodeKind
::DotExpr) || lhs->isKind(ParseNodeKind::ElemExpr) || lhs->
isKind(ParseNodeKind::PrivateMemberExpr)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("lhs->isKind(ParseNodeKind::DotExpr) || lhs->isKind(ParseNodeKind::ElemExpr) || lhs->isKind(ParseNodeKind::PrivateMemberExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4353); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lhs->isKind(ParseNodeKind::DotExpr) || lhs->isKind(ParseNodeKind::ElemExpr) || lhs->isKind(ParseNodeKind::PrivateMemberExpr)"
")"); do { *((volatile int*)__null) = 4353; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4353 lhs->isKind(ParseNodeKind::PrivateMemberExpr))do { if (isInit) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(lhs->isKind(ParseNodeKind::DotExpr) || lhs->
isKind(ParseNodeKind::ElemExpr) || lhs->isKind(ParseNodeKind
::PrivateMemberExpr))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(lhs->isKind(ParseNodeKind
::DotExpr) || lhs->isKind(ParseNodeKind::ElemExpr) || lhs->
isKind(ParseNodeKind::PrivateMemberExpr)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("lhs->isKind(ParseNodeKind::DotExpr) || lhs->isKind(ParseNodeKind::ElemExpr) || lhs->isKind(ParseNodeKind::PrivateMemberExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4353); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lhs->isKind(ParseNodeKind::DotExpr) || lhs->isKind(ParseNodeKind::ElemExpr) || lhs->isKind(ParseNodeKind::PrivateMemberExpr)"
")"); do { *((volatile int*)__null) = 4353; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4354
4355 // |name| is used within NameOpEmitter, so its lifetime must surpass |noe|.
4356 TaggedParserAtomIndex name;
4357
4358 Maybe<NameOpEmitter> noe;
4359 Maybe<PropOpEmitter> poe;
4360 Maybe<ElemOpEmitter> eoe;
4361 Maybe<PrivateOpEmitter> xoe;
4362
4363 // Deal with non-name assignments.
4364 uint8_t offset = 1;
4365
4366 // Purpose of anonFunctionName:
4367 //
4368 // In normal name assignments (`f = function(){}`), an anonymous function gets
4369 // an inferred name based on the left-hand side name node.
4370 //
4371 // In normal property assignments (`obj.x = function(){}`), the anonymous
4372 // function does not have a computed name, and rhs->isDirectRHSAnonFunction()
4373 // will be false (and anonFunctionName will not be used). However, in field
4374 // initializers (`class C { x = function(){} }`), field initialization is
4375 // implemented via a property or elem assignment (where we are now), and
4376 // rhs->isDirectRHSAnonFunction() is set - so we'll assign the name of the
4377 // function.
4378 TaggedParserAtomIndex anonFunctionName;
4379
4380 switch (lhs->getKind()) {
4381 case ParseNodeKind::Name: {
4382 name = lhs->as<NameNode>().name();
4383 anonFunctionName = name;
4384 noe.emplace(this, name,
4385 isCompound ? NameOpEmitter::Kind::CompoundAssignment
4386 : NameOpEmitter::Kind::SimpleAssignment);
4387 break;
4388 }
4389 case ParseNodeKind::ArgumentsLength:
4390 case ParseNodeKind::DotExpr: {
4391 PropertyAccess* prop = &lhs->as<PropertyAccess>();
4392 bool isSuper = prop->isSuper();
4393 poe.emplace(this,
4394 isCompound ? PropOpEmitter::Kind::CompoundAssignment
4395 : isInit ? PropOpEmitter::Kind::PropInit
4396 : PropOpEmitter::Kind::SimpleAssignment,
4397 isSuper ? PropOpEmitter::ObjKind::Super
4398 : PropOpEmitter::ObjKind::Other);
4399 if (!poe->prepareForObj()) {
4400 return false;
4401 }
4402 anonFunctionName = prop->name();
4403 if (isSuper) {
4404 UnaryNode* base = &prop->expression().as<UnaryNode>();
4405 if (!emitGetThisForSuperBase(base)) {
4406 // [stack] THIS SUPERBASE
4407 return false;
4408 }
4409 // SUPERBASE is pushed onto THIS later in poe->emitGet below.
4410 offset += 2;
4411 } else {
4412 if (!emitTree(&prop->expression())) {
4413 // [stack] OBJ
4414 return false;
4415 }
4416 offset += 1;
4417 }
4418 break;
4419 }
4420 case ParseNodeKind::ElemExpr: {
4421 PropertyByValue* elem = &lhs->as<PropertyByValue>();
4422 bool isSuper = elem->isSuper();
4423 MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!elem->key().isKind(ParseNodeKind::PrivateName))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!elem->key().isKind(ParseNodeKind::PrivateName)))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!elem->key().isKind(ParseNodeKind::PrivateName)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4423); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 4423; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4424 eoe.emplace(this,
4425 isCompound ? ElemOpEmitter::Kind::CompoundAssignment
4426 : isInit ? ElemOpEmitter::Kind::PropInit
4427 : ElemOpEmitter::Kind::SimpleAssignment,
4428 isSuper ? ElemOpEmitter::ObjKind::Super
4429 : ElemOpEmitter::ObjKind::Other);
4430 if (!emitElemObjAndKey(elem, *eoe)) {
4431 // [stack] # if Super
4432 // [stack] THIS KEY
4433 // [stack] # otherwise
4434 // [stack] OBJ KEY
4435 return false;
4436 }
4437 if (isSuper) {
4438 // SUPERBASE is pushed onto KEY in eoe->emitGet below.
4439 offset += 3;
4440 } else {
4441 offset += 2;
4442 }
4443 break;
4444 }
4445 case ParseNodeKind::PrivateMemberExpr: {
4446 PrivateMemberAccess* privateExpr = &lhs->as<PrivateMemberAccess>();
4447 xoe.emplace(this,
4448 isCompound ? PrivateOpEmitter::Kind::CompoundAssignment
4449 : isInit ? PrivateOpEmitter::Kind::PropInit
4450 : PrivateOpEmitter::Kind::SimpleAssignment,
4451 privateExpr->privateName().name());
4452 if (!emitTree(&privateExpr->expression())) {
4453 // [stack] OBJ
4454 return false;
4455 }
4456 if (!xoe->emitReference()) {
4457 // [stack] OBJ KEY
4458 return false;
4459 }
4460 offset += xoe->numReferenceSlots();
4461 break;
4462 }
4463 case ParseNodeKind::ArrayExpr:
4464 case ParseNodeKind::ObjectExpr:
4465 break;
4466 case ParseNodeKind::CallExpr:
4467 if (!emitTree(lhs)) {
4468 return false;
4469 }
4470
4471 // Assignment to function calls is forbidden, but we have to make the
4472 // call first. Now we can throw.
4473 if (!emit2(JSOp::ThrowMsg, uint8_t(ThrowMsgKind::AssignToCall))) {
4474 return false;
4475 }
4476
4477 // Rebalance the stack to placate stack-depth assertions.
4478 if (!emit1(JSOp::Pop)) {
4479 return false;
4480 }
4481 break;
4482 default:
4483 MOZ_ASSERT(0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(0)>::isValid, "invalid assertion condition"); if (
(__builtin_expect(!!(!(!!(0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("0", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4483); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0" ")"); do
{ *((volatile int*)__null) = 4483; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
4484 }
4485
4486 if (isCompound) {
4487 MOZ_ASSERT(rhs)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(rhs)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(rhs))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("rhs", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4487); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rhs" ")"); do
{ *((volatile int*)__null) = 4487; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
4488 switch (lhs->getKind()) {
4489 case ParseNodeKind::ArgumentsLength:
4490 case ParseNodeKind::DotExpr: {
4491 PropertyAccess* prop = &lhs->as<PropertyAccess>();
4492 if (!poe->emitGet(prop->key().atom())) {
4493 // [stack] # if Super
4494 // [stack] THIS SUPERBASE PROP
4495 // [stack] # otherwise
4496 // [stack] OBJ PROP
4497 return false;
4498 }
4499 break;
4500 }
4501 case ParseNodeKind::ElemExpr: {
4502 if (!eoe->emitGet()) {
4503 // [stack] KEY THIS OBJ ELEM
4504 return false;
4505 }
4506 break;
4507 }
4508 case ParseNodeKind::PrivateMemberExpr: {
4509 if (!xoe->emitGet()) {
4510 // [stack] OBJ KEY VALUE
4511 return false;
4512 }
4513 break;
4514 }
4515 case ParseNodeKind::CallExpr:
4516 // We just emitted a JSOp::ThrowMsg and popped the call's return
4517 // value. Push a random value to make sure the stack depth is
4518 // correct.
4519 if (!emit1(JSOp::Null)) {
4520 // [stack] NULL
4521 return false;
4522 }
4523 break;
4524 default:;
4525 }
4526 }
4527
4528 switch (lhs->getKind()) {
4529 case ParseNodeKind::Name:
4530 if (!noe->prepareForRhs()) {
4531 // [stack] ENV? VAL?
4532 return false;
4533 }
4534 offset += noe->emittedBindOp();
4535 break;
4536 case ParseNodeKind::ArgumentsLength:
4537 case ParseNodeKind::DotExpr:
4538 if (!poe->prepareForRhs()) {
4539 // [stack] # if Simple Assignment with Super
4540 // [stack] THIS SUPERBASE
4541 // [stack] # if Simple Assignment with other
4542 // [stack] OBJ
4543 // [stack] # if Compound Assignment with Super
4544 // [stack] THIS SUPERBASE PROP
4545 // [stack] # if Compound Assignment with other
4546 // [stack] OBJ PROP
4547 return false;
4548 }
4549 break;
4550 case ParseNodeKind::ElemExpr:
4551 if (!eoe->prepareForRhs()) {
4552 // [stack] # if Simple Assignment with Super
4553 // [stack] THIS KEY SUPERBASE
4554 // [stack] # if Simple Assignment with other
4555 // [stack] OBJ KEY
4556 // [stack] # if Compound Assignment with Super
4557 // [stack] THIS KEY SUPERBASE ELEM
4558 // [stack] # if Compound Assignment with other
4559 // [stack] OBJ KEY ELEM
4560 return false;
4561 }
4562 break;
4563 case ParseNodeKind::PrivateMemberExpr:
4564 // no stack adjustment needed
4565 break;
4566 default:
4567 break;
4568 }
4569
4570 if (rhs) {
4571 if (!emitAssignmentRhs(rhs, anonFunctionName)) {
4572 // [stack] ... VAL? RHS
4573 return false;
4574 }
4575 } else {
4576 // Assumption: Things with pre-emitted RHS values never need to be named.
4577 if (!emitAssignmentRhs(offset)) {
4578 // [stack] ... VAL? RHS
4579 return false;
4580 }
4581 }
4582
4583 /* If += etc., emit the binary operator with a hint for the decompiler. */
4584 if (isCompound) {
4585 if (!emit1(compoundOp)) {
4586 // [stack] ... VAL
4587 return false;
4588 }
4589 if (!emit1(JSOp::NopIsAssignOp)) {
4590 // [stack] ... VAL
4591 return false;
4592 }
4593 }
4594
4595 /* Finally, emit the specialized assignment bytecode. */
4596 switch (lhs->getKind()) {
4597 case ParseNodeKind::Name: {
4598 if (!noe->emitAssignment()) {
4599 // [stack] VAL
4600 return false;
4601 }
4602 break;
4603 }
4604 case ParseNodeKind::ArgumentsLength:
4605 case ParseNodeKind::DotExpr: {
4606 PropertyAccess* prop = &lhs->as<PropertyAccess>();
4607 if (!poe->emitAssignment(prop->key().atom())) {
4608 // [stack] VAL
4609 return false;
4610 }
4611 break;
4612 }
4613 case ParseNodeKind::CallExpr:
4614 // We threw above, so nothing to do here.
4615 break;
4616 case ParseNodeKind::ElemExpr: {
4617 if (!eoe->emitAssignment()) {
4618 // [stack] VAL
4619 return false;
4620 }
4621 break;
4622 }
4623 case ParseNodeKind::PrivateMemberExpr:
4624 if (!xoe->emitAssignment()) {
4625 // [stack] VAL
4626 return false;
4627 }
4628 break;
4629 case ParseNodeKind::ArrayExpr:
4630 case ParseNodeKind::ObjectExpr:
4631 if (!emitDestructuringOps(&lhs->as<ListNode>(),
4632 DestructuringFlavor::Assignment)) {
4633 return false;
4634 }
4635 break;
4636 default:
4637 MOZ_ASSERT(0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(0)>::isValid, "invalid assertion condition"); if (
(__builtin_expect(!!(!(!!(0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("0", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4637); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0" ")"); do
{ *((volatile int*)__null) = 4637; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
4638 }
4639 return true;
4640}
4641
4642bool BytecodeEmitter::emitShortCircuitAssignment(AssignmentNode* node) {
4643 TDZCheckCache tdzCache(this);
4644
4645 JSOp op;
4646 switch (node->getKind()) {
4647 case ParseNodeKind::CoalesceAssignExpr:
4648 op = JSOp::Coalesce;
4649 break;
4650 case ParseNodeKind::OrAssignExpr:
4651 op = JSOp::Or;
4652 break;
4653 case ParseNodeKind::AndAssignExpr:
4654 op = JSOp::And;
4655 break;
4656 default:
4657 MOZ_CRASH("Unexpected ParseNodeKind")do { do { } while (false); MOZ_ReportCrash("" "Unexpected ParseNodeKind"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4657); AnnotateMozCrashReason("MOZ_CRASH(" "Unexpected ParseNodeKind"
")"); do { *((volatile int*)__null) = 4657; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
4658 }
4659
4660 ParseNode* lhs = node->left();
4661 ParseNode* rhs = node->right();
4662
4663 // |name| is used within NameOpEmitter, so its lifetime must surpass |noe|.
4664 TaggedParserAtomIndex name;
4665
4666 // Select the appropriate emitter based on the left-hand side.
4667 Maybe<NameOpEmitter> noe;
4668 Maybe<PropOpEmitter> poe;
4669 Maybe<ElemOpEmitter> eoe;
4670 Maybe<PrivateOpEmitter> xoe;
4671
4672 int32_t depth = bytecodeSection().stackDepth();
4673
4674 // Number of values pushed onto the stack in addition to the lhs value.
4675 int32_t numPushed;
4676
4677 // Evaluate the left-hand side expression and compute any stack values needed
4678 // for the assignment.
4679 switch (lhs->getKind()) {
4680 case ParseNodeKind::Name: {
4681 name = lhs->as<NameNode>().name();
4682 noe.emplace(this, name, NameOpEmitter::Kind::CompoundAssignment);
4683
4684 if (!noe->prepareForRhs()) {
4685 // [stack] ENV? LHS
4686 return false;
4687 }
4688
4689 numPushed = noe->emittedBindOp();
4690 break;
4691 }
4692 case ParseNodeKind::ArgumentsLength:
4693 case ParseNodeKind::DotExpr: {
4694 PropertyAccess* prop = &lhs->as<PropertyAccess>();
4695 bool isSuper = prop->isSuper();
4696
4697 poe.emplace(this, PropOpEmitter::Kind::CompoundAssignment,
4698 isSuper ? PropOpEmitter::ObjKind::Super
4699 : PropOpEmitter::ObjKind::Other);
4700
4701 if (!poe->prepareForObj()) {
4702 return false;
4703 }
4704
4705 if (isSuper) {
4706 UnaryNode* base = &prop->expression().as<UnaryNode>();
4707 if (!emitGetThisForSuperBase(base)) {
4708 // [stack] THIS SUPERBASE
4709 return false;
4710 }
4711 } else {
4712 if (!emitTree(&prop->expression())) {
4713 // [stack] OBJ
4714 return false;
4715 }
4716 }
4717
4718 if (!poe->emitGet(prop->key().atom())) {
4719 // [stack] # if Super
4720 // [stack] THIS SUPERBASE LHS
4721 // [stack] # otherwise
4722 // [stack] OBJ LHS
4723 return false;
4724 }
4725
4726 if (!poe->prepareForRhs()) {
4727 // [stack] # if Super
4728 // [stack] THIS SUPERBASE LHS
4729 // [stack] # otherwise
4730 // [stack] OBJ LHS
4731 return false;
4732 }
4733
4734 numPushed = 1 + isSuper;
4735 break;
4736 }
4737
4738 case ParseNodeKind::ElemExpr: {
4739 PropertyByValue* elem = &lhs->as<PropertyByValue>();
4740 bool isSuper = elem->isSuper();
4741 MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!elem->key().isKind(ParseNodeKind::PrivateName))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!elem->key().isKind(ParseNodeKind::PrivateName)))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!elem->key().isKind(ParseNodeKind::PrivateName)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4741); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 4741; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4742 eoe.emplace(this, ElemOpEmitter::Kind::CompoundAssignment,
4743 isSuper ? ElemOpEmitter::ObjKind::Super
4744 : ElemOpEmitter::ObjKind::Other);
4745
4746 if (!emitElemObjAndKey(elem, *eoe)) {
4747 // [stack] # if Super
4748 // [stack] THIS KEY
4749 // [stack] # otherwise
4750 // [stack] OBJ KEY
4751 return false;
4752 }
4753
4754 if (!eoe->emitGet()) {
4755 // [stack] # if Super
4756 // [stack] THIS KEY SUPERBASE LHS
4757 // [stack] # otherwise
4758 // [stack] OBJ KEY LHS
4759 return false;
4760 }
4761
4762 if (!eoe->prepareForRhs()) {
4763 // [stack] # if Super
4764 // [stack] THIS KEY SUPERBASE LHS
4765 // [stack] # otherwise
4766 // [stack] OBJ KEY LHS
4767 return false;
4768 }
4769
4770 numPushed = 2 + isSuper;
4771 break;
4772 }
4773
4774 case ParseNodeKind::PrivateMemberExpr: {
4775 PrivateMemberAccess* privateExpr = &lhs->as<PrivateMemberAccess>();
4776 xoe.emplace(this, PrivateOpEmitter::Kind::CompoundAssignment,
4777 privateExpr->privateName().name());
4778 if (!emitTree(&privateExpr->expression())) {
4779 // [stack] OBJ
4780 return false;
4781 }
4782 if (!xoe->emitReference()) {
4783 // [stack] OBJ NAME
4784 return false;
4785 }
4786 if (!xoe->emitGet()) {
4787 // [stack] OBJ NAME LHS
4788 return false;
4789 }
4790 numPushed = xoe->numReferenceSlots();
4791 break;
4792 }
4793
4794 default:
4795 MOZ_CRASH()do { do { } while (false); MOZ_ReportCrash("" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4795); AnnotateMozCrashReason("MOZ_CRASH(" ")"); do { *((volatile
int*)__null) = 4795; __attribute__((nomerge)) ::abort(); } while
(false); } while (false)
;
4796 }
4797
4798 MOZ_ASSERT(bytecodeSection().stackDepth() == depth + numPushed + 1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bytecodeSection().stackDepth() == depth + numPushed +
1)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(bytecodeSection().stackDepth() == depth + numPushed +
1))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("bytecodeSection().stackDepth() == depth + numPushed + 1", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4798); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == depth + numPushed + 1"
")"); do { *((volatile int*)__null) = 4798; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4799
4800 // Test for the short-circuit condition.
4801 JumpList jump;
4802 if (!emitJump(op, &jump)) {
4803 // [stack] ... LHS
4804 return false;
4805 }
4806
4807 // The short-circuit condition wasn't fulfilled, pop the left-hand side value
4808 // which was kept on the stack.
4809 if (!emit1(JSOp::Pop)) {
4810 // [stack] ...
4811 return false;
4812 }
4813
4814 if (!emitAssignmentRhs(rhs, name)) {
4815 // [stack] ... RHS
4816 return false;
4817 }
4818
4819 // Perform the actual assignment.
4820 switch (lhs->getKind()) {
4821 case ParseNodeKind::Name: {
4822 if (!noe->emitAssignment()) {
4823 // [stack] RHS
4824 return false;
4825 }
4826 break;
4827 }
4828 case ParseNodeKind::ArgumentsLength:
4829 case ParseNodeKind::DotExpr: {
4830 PropertyAccess* prop = &lhs->as<PropertyAccess>();
4831
4832 if (!poe->emitAssignment(prop->key().atom())) {
4833 // [stack] RHS
4834 return false;
4835 }
4836 break;
4837 }
4838
4839 case ParseNodeKind::ElemExpr: {
4840 if (!eoe->emitAssignment()) {
4841 // [stack] RHS
4842 return false;
4843 }
4844 break;
4845 }
4846
4847 case ParseNodeKind::PrivateMemberExpr:
4848 if (!xoe->emitAssignment()) {
4849 // [stack] RHS
4850 return false;
4851 }
4852 break;
4853
4854 default:
4855 MOZ_CRASH()do { do { } while (false); MOZ_ReportCrash("" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4855); AnnotateMozCrashReason("MOZ_CRASH(" ")"); do { *((volatile
int*)__null) = 4855; __attribute__((nomerge)) ::abort(); } while
(false); } while (false)
;
4856 }
4857
4858 MOZ_ASSERT(bytecodeSection().stackDepth() == depth + 1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bytecodeSection().stackDepth() == depth + 1)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(bytecodeSection().stackDepth() == depth + 1))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("bytecodeSection().stackDepth() == depth + 1"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4858); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == depth + 1"
")"); do { *((volatile int*)__null) = 4858; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4859
4860 // Join with the short-circuit jump and pop anything left on the stack.
4861 if (numPushed > 0) {
4862 JumpList jumpAroundPop;
4863 if (!emitJump(JSOp::Goto, &jumpAroundPop)) {
4864 // [stack] RHS
4865 return false;
4866 }
4867
4868 if (!emitJumpTargetAndPatch(jump)) {
4869 // [stack] ... LHS
4870 return false;
4871 }
4872
4873 // Reconstruct the stack depth after the jump.
4874 bytecodeSection().setStackDepth(depth + 1 + numPushed);
4875
4876 // Move the left-hand side value to the bottom and pop the rest.
4877 if (!emitUnpickN(numPushed)) {
4878 // [stack] LHS ...
4879 return false;
4880 }
4881 if (!emitPopN(numPushed)) {
4882 // [stack] LHS
4883 return false;
4884 }
4885
4886 if (!emitJumpTargetAndPatch(jumpAroundPop)) {
4887 // [stack] LHS | RHS
4888 return false;
4889 }
4890 } else {
4891 if (!emitJumpTargetAndPatch(jump)) {
4892 // [stack] LHS | RHS
4893 return false;
4894 }
4895 }
4896
4897 MOZ_ASSERT(bytecodeSection().stackDepth() == depth + 1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bytecodeSection().stackDepth() == depth + 1)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(bytecodeSection().stackDepth() == depth + 1))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("bytecodeSection().stackDepth() == depth + 1"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4897); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == depth + 1"
")"); do { *((volatile int*)__null) = 4897; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4898
4899 return true;
4900}
4901
4902bool BytecodeEmitter::emitCallSiteObjectArray(ObjLiteralWriter& writer,
4903 ListNode* cookedOrRaw,
4904 ParseNode* head, uint32_t count) {
4905 DebugOnly<size_t> idx = 0;
4906 for (ParseNode* pn : cookedOrRaw->contentsFrom(head)) {
4907 MOZ_ASSERT(pn->isKind(ParseNodeKind::TemplateStringExpr) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->isKind(ParseNodeKind::TemplateStringExpr) || pn
->isKind(ParseNodeKind::RawUndefinedExpr))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->isKind(ParseNodeKind::
TemplateStringExpr) || pn->isKind(ParseNodeKind::RawUndefinedExpr
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("pn->isKind(ParseNodeKind::TemplateStringExpr) || pn->isKind(ParseNodeKind::RawUndefinedExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4908); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->isKind(ParseNodeKind::TemplateStringExpr) || pn->isKind(ParseNodeKind::RawUndefinedExpr)"
")"); do { *((volatile int*)__null) = 4908; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4908 pn->isKind(ParseNodeKind::RawUndefinedExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->isKind(ParseNodeKind::TemplateStringExpr) || pn
->isKind(ParseNodeKind::RawUndefinedExpr))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->isKind(ParseNodeKind::
TemplateStringExpr) || pn->isKind(ParseNodeKind::RawUndefinedExpr
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("pn->isKind(ParseNodeKind::TemplateStringExpr) || pn->isKind(ParseNodeKind::RawUndefinedExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4908); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->isKind(ParseNodeKind::TemplateStringExpr) || pn->isKind(ParseNodeKind::RawUndefinedExpr)"
")"); do { *((volatile int*)__null) = 4908; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4909
4910 if (!emitObjLiteralValue(writer, pn)) {
4911 return false;
4912 }
4913 idx++;
4914 }
4915 MOZ_ASSERT(idx == count)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(idx == count)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(idx == count))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("idx == count", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4915); AnnotateMozCrashReason("MOZ_ASSERT" "(" "idx == count"
")"); do { *((volatile int*)__null) = 4915; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4916
4917 return true;
4918}
4919
4920bool BytecodeEmitter::emitCallSiteObject(CallSiteNode* callSiteObj) {
4921 constexpr JSOp op = JSOp::CallSiteObj;
4922
4923 // The first element of a call-site node is the raw-values list. Skip over it.
4924 ListNode* raw = callSiteObj->rawNodes();
4925 MOZ_ASSERT(raw->isKind(ParseNodeKind::ArrayExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(raw->isKind(ParseNodeKind::ArrayExpr))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(raw->isKind(ParseNodeKind::ArrayExpr)))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("raw->isKind(ParseNodeKind::ArrayExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4925); AnnotateMozCrashReason("MOZ_ASSERT" "(" "raw->isKind(ParseNodeKind::ArrayExpr)"
")"); do { *((volatile int*)__null) = 4925; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4926 ParseNode* head = callSiteObj->head()->pn_next;
4927
4928 uint32_t count = callSiteObj->count() - 1;
4929 MOZ_ASSERT(count == raw->count())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(count == raw->count())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(count == raw->count()))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("count == raw->count()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4929); AnnotateMozCrashReason("MOZ_ASSERT" "(" "count == raw->count()"
")"); do { *((volatile int*)__null) = 4929; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4930
4931 ObjLiteralWriter writer;
4932 writer.beginCallSiteObj(op);
4933 writer.beginDenseArrayElements();
4934
4935 // Write elements of the two arrays: the 'cooked' values followed by the
4936 // 'raw' values.
4937 MOZ_RELEASE_ASSERT(count < UINT32_MAX / 2,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(count < (4294967295U) / 2)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(count < (4294967295U) / 2
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"count < (4294967295U) / 2" " (" "Number of elements for both arrays must fit in uint32_t"
")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4938); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "count < (4294967295U) / 2"
") (" "Number of elements for both arrays must fit in uint32_t"
")"); do { *((volatile int*)__null) = 4938; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4938 "Number of elements for both arrays must fit in uint32_t")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(count < (4294967295U) / 2)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(count < (4294967295U) / 2
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"count < (4294967295U) / 2" " (" "Number of elements for both arrays must fit in uint32_t"
")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4938); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "count < (4294967295U) / 2"
") (" "Number of elements for both arrays must fit in uint32_t"
")"); do { *((volatile int*)__null) = 4938; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4939 if (!emitCallSiteObjectArray(writer, callSiteObj, head, count)) {
4940 return false;
4941 }
4942 if (!emitCallSiteObjectArray(writer, raw, raw->head(), count)) {
4943 return false;
4944 }
4945
4946 GCThingIndex cookedIndex;
4947 if (!addObjLiteralData(writer, &cookedIndex)) {
4948 return false;
4949 }
4950
4951 MOZ_ASSERT(sc->hasCallSiteObj())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sc->hasCallSiteObj())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sc->hasCallSiteObj()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("sc->hasCallSiteObj()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4951); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->hasCallSiteObj()"
")"); do { *((volatile int*)__null) = 4951; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4952
4953 return emitInternedObjectOp(cookedIndex, op);
4954}
4955
4956bool BytecodeEmitter::emitCatch(BinaryNode* catchClause) {
4957 // We must be nested under a try-finally statement.
4958 MOZ_ASSERT(innermostNestableControl->is<TryFinallyControl>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(innermostNestableControl->is<TryFinallyControl
>())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(innermostNestableControl->is<TryFinallyControl
>()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("innermostNestableControl->is<TryFinallyControl>()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4958); AnnotateMozCrashReason("MOZ_ASSERT" "(" "innermostNestableControl->is<TryFinallyControl>()"
")"); do { *((volatile int*)__null) = 4958; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4959
4960 ParseNode* param = catchClause->left();
4961 if (!param) {
4962 // Catch parameter was omitted; just discard the exception.
4963 if (!emit1(JSOp::Pop)) {
4964 return false;
4965 }
4966 } else {
4967 switch (param->getKind()) {
4968 case ParseNodeKind::ArrayExpr:
4969 case ParseNodeKind::ObjectExpr:
4970 if (!emitDestructuringOps(&param->as<ListNode>(),
4971 DestructuringFlavor::Declaration)) {
4972 return false;
4973 }
4974 if (!emit1(JSOp::Pop)) {
4975 return false;
4976 }
4977 break;
4978
4979 case ParseNodeKind::Name:
4980 if (!emitLexicalInitialization(&param->as<NameNode>())) {
4981 return false;
4982 }
4983 if (!emit1(JSOp::Pop)) {
4984 return false;
4985 }
4986 break;
4987
4988 default:
4989 MOZ_ASSERT(0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(0)>::isValid, "invalid assertion condition"); if (
(__builtin_expect(!!(!(!!(0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("0", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4989); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0" ")"); do
{ *((volatile int*)__null) = 4989; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
4990 }
4991 }
4992
4993 /* Emit the catch body. */
4994 return emitTree(catchClause->right());
4995}
4996
4997// Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See the
4998// comment on EmitSwitch.
4999MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitTry(TryNode* tryNode) {
5000 LexicalScopeNode* catchScope = tryNode->catchScope();
5001 ParseNode* finallyNode = tryNode->finallyBlock();
5002
5003 TryEmitter::Kind kind;
5004 if (catchScope) {
5005 if (finallyNode) {
5006 kind = TryEmitter::Kind::TryCatchFinally;
5007 } else {
5008 kind = TryEmitter::Kind::TryCatch;
5009 }
5010 } else {
5011 MOZ_ASSERT(finallyNode)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(finallyNode)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(finallyNode))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("finallyNode", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5011); AnnotateMozCrashReason("MOZ_ASSERT" "(" "finallyNode"
")"); do { *((volatile int*)__null) = 5011; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5012 kind = TryEmitter::Kind::TryFinally;
5013 }
5014 TryEmitter tryCatch(this, kind, TryEmitter::ControlKind::Syntactic);
5015
5016 if (!tryCatch.emitTry()) {
5017 return false;
5018 }
5019
5020 if (!emitTree(tryNode->body())) {
5021 return false;
5022 }
5023
5024 // If this try has a catch block, emit it.
5025 if (catchScope) {
5026 // The emitted code for a catch block looks like:
5027 //
5028 // [pushlexicalenv] only if any local aliased
5029 // exception
5030 // setlocal 0; pop assign or possibly destructure exception
5031 // < catch block contents >
5032 // debugleaveblock
5033 // [poplexicalenv] only if any local aliased
5034 // if there is a finally block:
5035 // goto <finally>
5036 // [jump target for returning from finally]
5037 // goto <after finally>
5038 if (!tryCatch.emitCatch()) {
5039 return false;
5040 }
5041
5042 // Emit the lexical scope and catch body.
5043 if (!emitTree(catchScope)) {
5044 return false;
5045 }
5046 }
5047
5048 // Emit the finally handler, if there is one.
5049 if (finallyNode) {
5050 if (!tryCatch.emitFinally(Some(finallyNode->pn_pos.begin))) {
5051 return false;
5052 }
5053
5054 if (!emitTree(finallyNode)) {
5055 return false;
5056 }
5057 }
5058
5059 if (!tryCatch.emitEnd()) {
5060 return false;
5061 }
5062
5063 return true;
5064}
5065
5066[[nodiscard]] bool BytecodeEmitter::emitJumpToFinally(JumpList* jump,
5067 uint32_t idx) {
5068 // Push the continuation index.
5069 if (!emitNumberOp(idx)) {
5070 return false;
5071 }
5072
5073 // Push |exception_stack|.
5074 if (!emit1(JSOp::Null)) {
5075 return false;
5076 }
5077
5078 // Push |throwing|.
5079 if (!emit1(JSOp::False)) {
5080 return false;
5081 }
5082
5083 // Jump to the finally block.
5084 if (!emitJumpNoFallthrough(JSOp::Goto, jump)) {
5085 return false;
5086 }
5087
5088 return true;
5089}
5090
5091bool BytecodeEmitter::emitIf(TernaryNode* ifNode) {
5092 IfEmitter ifThenElse(this);
5093
5094 if (!ifThenElse.emitIf(Some(ifNode->kid1()->pn_pos.begin))) {
5095 return false;
5096 }
5097
5098if_again:
5099 ParseNode* testNode = ifNode->kid1();
5100 auto conditionKind = IfEmitter::ConditionKind::Positive;
5101 if (testNode->isKind(ParseNodeKind::NotExpr)) {
5102 testNode = testNode->as<UnaryNode>().kid();
5103 conditionKind = IfEmitter::ConditionKind::Negative;
5104 }
5105
5106 if (!markStepBreakpoint()) {
5107 return false;
5108 }
5109
5110 // Emit code for the condition before pushing stmtInfo.
5111 // NOTE: NotExpr of testNode may be unwrapped, and in that case the negation
5112 // is handled by conditionKind.
5113 if (!emitTree(testNode)) {
5114 return false;
5115 }
5116
5117 ParseNode* elseNode = ifNode->kid3();
5118 if (elseNode) {
5119 if (!ifThenElse.emitThenElse(conditionKind)) {
5120 return false;
5121 }
5122 } else {
5123 if (!ifThenElse.emitThen(conditionKind)) {
5124 return false;
5125 }
5126 }
5127
5128 /* Emit code for the then part. */
5129 if (!emitTree(ifNode->kid2())) {
5130 return false;
5131 }
5132
5133 if (elseNode) {
5134 if (elseNode->isKind(ParseNodeKind::IfStmt)) {
5135 ifNode = &elseNode->as<TernaryNode>();
5136
5137 if (!ifThenElse.emitElseIf(Some(ifNode->kid1()->pn_pos.begin))) {
5138 return false;
5139 }
5140
5141 goto if_again;
5142 }
5143
5144 if (!ifThenElse.emitElse()) {
5145 return false;
5146 }
5147
5148 /* Emit code for the else part. */
5149 if (!emitTree(elseNode)) {
5150 return false;
5151 }
5152 }
5153
5154 if (!ifThenElse.emitEnd()) {
5155 return false;
5156 }
5157
5158 return true;
5159}
5160
5161bool BytecodeEmitter::emitHoistedFunctionsInList(ListNode* stmtList) {
5162 MOZ_ASSERT(stmtList->hasTopLevelFunctionDeclarations())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(stmtList->hasTopLevelFunctionDeclarations())>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(stmtList->hasTopLevelFunctionDeclarations()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("stmtList->hasTopLevelFunctionDeclarations()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5162); AnnotateMozCrashReason("MOZ_ASSERT" "(" "stmtList->hasTopLevelFunctionDeclarations()"
")"); do { *((volatile int*)__null) = 5162; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5163
5164 // We can call this multiple times for sloppy eval scopes.
5165 if (stmtList->emittedTopLevelFunctionDeclarations()) {
5166 return true;
5167 }
5168
5169 stmtList->setEmittedTopLevelFunctionDeclarations();
5170
5171 for (ParseNode* stmt : stmtList->contents()) {
5172 ParseNode* maybeFun = stmt;
5173
5174 if (!sc->strict()) {
5175 while (maybeFun->isKind(ParseNodeKind::LabelStmt)) {
5176 maybeFun = maybeFun->as<LabeledStatement>().statement();
5177 }
5178 }
5179
5180 if (maybeFun->is<FunctionNode>() &&
5181 maybeFun->as<FunctionNode>().functionIsHoisted()) {
5182 if (!emitTree(maybeFun)) {
5183 return false;
5184 }
5185 }
5186 }
5187
5188 return true;
5189}
5190
5191bool BytecodeEmitter::emitLexicalScopeBody(
5192 ParseNode* body, EmitLineNumberNote emitLineNote /* = EMIT_LINENOTE */) {
5193 if (body->isKind(ParseNodeKind::StatementList) &&
5194 body->as<ListNode>().hasTopLevelFunctionDeclarations()) {
5195 // This block contains function statements whose definitions are
5196 // hoisted to the top of the block. Emit these as a separate pass
5197 // before the rest of the block.
5198 if (!emitHoistedFunctionsInList(&body->as<ListNode>())) {
5199 return false;
5200 }
5201 }
5202
5203 // Line notes were updated by emitLexicalScope or emitScript.
5204 return emitTree(body, ValueUsage::WantValue, emitLineNote);
5205}
5206
5207// Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See
5208// the comment on emitSwitch.
5209MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitLexicalScope(
5210 LexicalScopeNode* lexicalScope) {
5211 LexicalScopeEmitter lse(this);
5212
5213 ParseNode* body = lexicalScope->scopeBody();
5214 if (lexicalScope->isEmptyScope()) {
5215 if (!lse.emitEmptyScope()) {
5216 return false;
5217 }
5218
5219 if (!emitLexicalScopeBody(body)) {
5220 return false;
5221 }
5222
5223 if (!lse.emitEnd()) {
5224 return false;
5225 }
5226
5227 return true;
5228 }
5229
5230 // We are about to emit some bytecode for what the spec calls "declaration
5231 // instantiation". Assign these instructions to the opening `{` of the
5232 // block. (Using the location of each declaration we're instantiating is
5233 // too weird when stepping in the debugger.)
5234 if (!ParseNodeRequiresSpecialLineNumberNotes(body)) {
5235 if (!updateSourceCoordNotes(lexicalScope->pn_pos.begin)) {
5236 return false;
5237 }
5238 }
5239
5240 ScopeKind kind;
5241 if (body->isKind(ParseNodeKind::Catch)) {
5242 BinaryNode* catchNode = &body->as<BinaryNode>();
5243 kind =
5244 (!catchNode->left() || catchNode->left()->isKind(ParseNodeKind::Name))
5245 ? ScopeKind::SimpleCatch
5246 : ScopeKind::Catch;
5247 } else {
5248 kind = lexicalScope->kind();
5249 }
5250
5251#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT1
5252 BlockKind blockKind = BlockKind::Other;
5253 if (body->isKind(ParseNodeKind::ForStmt) &&
5254 body->as<ForNode>().head()->isKind(ParseNodeKind::ForOf)) {
5255 MOZ_ASSERT(kind == ScopeKind::Lexical)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(kind == ScopeKind::Lexical)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(kind == ScopeKind::Lexical))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("kind == ScopeKind::Lexical"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5255); AnnotateMozCrashReason("MOZ_ASSERT" "(" "kind == ScopeKind::Lexical"
")"); do { *((volatile int*)__null) = 5255; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5256 blockKind = BlockKind::ForOf;
5257 }
5258#endif
5259
5260 if (!lse.emitScope(kind, lexicalScope->scopeBindings()
5261#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT1
5262 ,
5263 blockKind
5264#endif
5265 )) {
5266 return false;
5267 }
5268
5269 if (body->isKind(ParseNodeKind::ForStmt)) {
5270 // for loops need to emit JSOp::FreshenLexicalEnv/JSOp::RecreateLexicalEnv
5271 // if there are lexical declarations in the head. Signal this by passing a
5272 // non-nullptr lexical scope.
5273 if (!emitFor(&body->as<ForNode>(), &lse.emitterScope())) {
5274 return false;
5275 }
5276 } else {
5277 if (!emitLexicalScopeBody(body, SUPPRESS_LINENOTE)) {
5278 return false;
5279 }
5280 }
5281
5282 if (!lse.emitEnd()) {
5283 return false;
5284 }
5285 return true;
5286}
5287
5288bool BytecodeEmitter::emitWith(BinaryNode* withNode) {
5289 // Ensure that the column of the 'with' is set properly.
5290 if (!updateSourceCoordNotes(withNode->left()->pn_pos.begin)) {
5291 return false;
5292 }
5293
5294 if (!markStepBreakpoint()) {
5295 return false;
5296 }
5297
5298 if (!emitTree(withNode->left())) {
5299 return false;
5300 }
5301
5302 EmitterScope emitterScope(this);
5303 if (!emitterScope.enterWith(this)) {
5304 return false;
5305 }
5306
5307 if (!emitTree(withNode->right())) {
5308 return false;
5309 }
5310
5311 return emitterScope.leave(this);
5312}
5313
5314bool BytecodeEmitter::emitCopyDataProperties(CopyOption option) {
5315 DebugOnly<int32_t> depth = bytecodeSection().stackDepth();
5316
5317 uint32_t argc;
5318 if (option == CopyOption::Filtered) {
5319 MOZ_ASSERT(depth > 2)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(depth > 2)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(depth > 2))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("depth > 2", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5319); AnnotateMozCrashReason("MOZ_ASSERT" "(" "depth > 2"
")"); do { *((volatile int*)__null) = 5319; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5320 // [stack] TARGET SOURCE SET
5321 argc = 3;
5322
5323 if (!emitAtomOp(JSOp::GetIntrinsic,
5324 TaggedParserAtomIndex::WellKnown::CopyDataProperties())) {
5325 // [stack] TARGET SOURCE SET COPYDATAPROPERTIES
5326 return false;
5327 }
5328 } else {
5329 MOZ_ASSERT(depth > 1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(depth > 1)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(depth > 1))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("depth > 1", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5329); AnnotateMozCrashReason("MOZ_ASSERT" "(" "depth > 1"
")"); do { *((volatile int*)__null) = 5329; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5330 // [stack] TARGET SOURCE
5331 argc = 2;
5332
5333 if (!emitAtomOp(
5334 JSOp::GetIntrinsic,
5335 TaggedParserAtomIndex::WellKnown::CopyDataPropertiesUnfiltered())) {
5336 // [stack] TARGET SOURCE COPYDATAPROPERTIES
5337 return false;
5338 }
5339 }
5340
5341 if (!emit1(JSOp::Undefined)) {
5342 // [stack] TARGET SOURCE SET? COPYDATAPROPERTIES
5343 // UNDEFINED
5344 return false;
5345 }
5346 if (!emit2(JSOp::Pick, argc + 1)) {
5347 // [stack] SOURCE SET? COPYDATAPROPERTIES UNDEFINED
5348 // TARGET
5349 return false;
5350 }
5351 if (!emit2(JSOp::Pick, argc + 1)) {
5352 // [stack] SET? COPYDATAPROPERTIES UNDEFINED TARGET
5353 // SOURCE
5354 return false;
5355 }
5356 if (option == CopyOption::Filtered) {
5357 if (!emit2(JSOp::Pick, argc + 1)) {
5358 // [stack] COPYDATAPROPERTIES UNDEFINED TARGET SOURCE SET
5359 return false;
5360 }
5361 }
5362 // Callee is always self-hosted instrinsic, and cannot be content function.
5363 if (!emitCall(JSOp::CallIgnoresRv, argc)) {
5364 // [stack] IGNORED
5365 return false;
5366 }
5367
5368 if (!emit1(JSOp::Pop)) {
5369 // [stack]
5370 return false;
5371 }
5372
5373 MOZ_ASSERT(depth - int(argc) == bytecodeSection().stackDepth())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(depth - int(argc) == bytecodeSection().stackDepth())
>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(depth - int(argc) == bytecodeSection().stackDepth())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("depth - int(argc) == bytecodeSection().stackDepth()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5373); AnnotateMozCrashReason("MOZ_ASSERT" "(" "depth - int(argc) == bytecodeSection().stackDepth()"
")"); do { *((volatile int*)__null) = 5373; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5374 return true;
5375}
5376
5377bool BytecodeEmitter::emitBigIntOp(BigIntLiteral* bigint) {
5378 GCThingIndex index;
5379 if (!perScriptData().gcThingList().append(bigint, &index)) {
5380 return false;
5381 }
5382 return emitGCIndexOp(JSOp::BigInt, index);
5383}
5384
5385bool BytecodeEmitter::emitIterable(ParseNode* value,
5386 SelfHostedIter selfHostedIter,
5387 IteratorKind iterKind) {
5388 MOZ_ASSERT(getSelfHostedIterFor(value) == selfHostedIter)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(getSelfHostedIterFor(value) == selfHostedIter)>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(getSelfHostedIterFor(value) == selfHostedIter))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("getSelfHostedIterFor(value) == selfHostedIter"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5388); AnnotateMozCrashReason("MOZ_ASSERT" "(" "getSelfHostedIterFor(value) == selfHostedIter"
")"); do { *((volatile int*)__null) = 5388; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5389
5390 if (!emitTree(value)) {
5391 // [stack] ITERABLE
5392 return false;
5393 }
5394
5395 switch (selfHostedIter) {
5396 case SelfHostedIter::Deny:
5397 case SelfHostedIter::AllowContent:
5398 // [stack] ITERABLE
5399 return true;
5400
5401 case SelfHostedIter::AllowContentWith: {
5402 // This is the following case:
5403 //
5404 // for (const nextValue of allowContentIterWith(items, usingIterator)) {
5405 //
5406 // `items` is emitted by `emitTree(value)` above, and the result is on the
5407 // stack as ITERABLE.
5408 // `usingIterator` is the value of `items[Symbol.iterator]`, that's
5409 // already retrieved.
5410 ListNode* argsList = value->as<CallNode>().args();
5411 MOZ_ASSERT_IF(iterKind == IteratorKind::Sync, argsList->count() == 2)do { if (iterKind == IteratorKind::Sync) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(argsList
->count() == 2)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(argsList->count() == 2)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 2"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5411); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2"
")"); do { *((volatile int*)__null) = 5411; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
5412 MOZ_ASSERT_IF(iterKind == IteratorKind::Async, argsList->count() == 3)do { if (iterKind == IteratorKind::Async) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(argsList
->count() == 3)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(argsList->count() == 3)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 3"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5412); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 3"
")"); do { *((volatile int*)__null) = 5412; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
5413
5414 if (!emitTree(argsList->head()->pn_next)) {
5415 // [stack] ITERABLE ITERFN
5416 return false;
5417 }
5418
5419 // Async iterator has two possible iterators: An async iterator and a sync
5420 // iterator.
5421 if (iterKind == IteratorKind::Async) {
5422 if (!emitTree(argsList->head()->pn_next->pn_next)) {
5423 // [stack] ITERABLE ASYNC_ITERFN SYNC_ITERFN
5424 return false;
5425 }
5426 }
5427
5428 // [stack] ITERABLE ASYNC_ITERFN? SYNC_ITERFN
5429 return true;
5430 }
5431
5432 case SelfHostedIter::AllowContentWithNext: {
5433 // This is the following case:
5434 //
5435 // for (const nextValue of allowContentIterWithNext(iterator, next)) {
5436 //
5437 // `iterator` is emitted by `emitTree(value)` above, and the result is on
5438 // the stack as ITER.
5439 // `next` is the value of `iterator.next`, that's already retrieved.
5440 ListNode* argsList = value->as<CallNode>().args();
5441 MOZ_ASSERT(argsList->count() == 2)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(argsList->count() == 2)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(argsList->count() == 2)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 2"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5441); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2"
")"); do { *((volatile int*)__null) = 5441; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5442
5443 if (!emitTree(argsList->head()->pn_next)) {
5444 // [stack] ITER NEXT
5445 return false;
5446 }
5447
5448 if (!emit1(JSOp::Swap)) {
5449 // [stack] NEXT ITER
5450 return false;
5451 }
5452
5453 // [stack] NEXT ITER
5454 return true;
5455 }
5456 }
5457
5458 MOZ_CRASH("invalid self-hosted iteration kind")do { do { } while (false); MOZ_ReportCrash("" "invalid self-hosted iteration kind"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5458); AnnotateMozCrashReason("MOZ_CRASH(" "invalid self-hosted iteration kind"
")"); do { *((volatile int*)__null) = 5458; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
5459}
5460
5461bool BytecodeEmitter::emitIterator(SelfHostedIter selfHostedIter) {
5462 MOZ_ASSERT(selfHostedIter != SelfHostedIter::Deny ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode
!= BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter
::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
" (" "[Symbol.iterator]() call is prohibited in self-hosted code "
"because it can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5465); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
") (" "[Symbol.iterator]() call is prohibited in self-hosted code "
"because it can run user-modifiable iteration code" ")"); do
{ *((volatile int*)__null) = 5465; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
5463 emitterMode != BytecodeEmitter::SelfHosting,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode
!= BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter
::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
" (" "[Symbol.iterator]() call is prohibited in self-hosted code "
"because it can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5465); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
") (" "[Symbol.iterator]() call is prohibited in self-hosted code "
"because it can run user-modifiable iteration code" ")"); do
{ *((volatile int*)__null) = 5465; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
5464 "[Symbol.iterator]() call is prohibited in self-hosted code "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode
!= BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter
::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
" (" "[Symbol.iterator]() call is prohibited in self-hosted code "
"because it can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5465); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
") (" "[Symbol.iterator]() call is prohibited in self-hosted code "
"because it can run user-modifiable iteration code" ")"); do
{ *((volatile int*)__null) = 5465; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
5465 "because it can run user-modifiable iteration code")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode
!= BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter
::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
" (" "[Symbol.iterator]() call is prohibited in self-hosted code "
"because it can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5465); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
") (" "[Symbol.iterator]() call is prohibited in self-hosted code "
"because it can run user-modifiable iteration code" ")"); do
{ *((volatile int*)__null) = 5465; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
5466
5467 if (selfHostedIter == SelfHostedIter::AllowContentWithNext) {
5468 // [stack] NEXT ITER
5469
5470 // Nothing to do, stack already contains the iterator and its `next` method.
5471 return true;
5472 }
5473
5474 if (selfHostedIter != SelfHostedIter::AllowContentWith) {
5475 // [stack] OBJ
5476
5477 // Convert iterable to iterator.
5478 if (!emit1(JSOp::Dup)) {
5479 // [stack] OBJ OBJ
5480 return false;
5481 }
5482 if (!emit2(JSOp::Symbol, uint8_t(JS::SymbolCode::iterator))) {
5483 // [stack] OBJ OBJ @@ITERATOR
5484 return false;
5485 }
5486 if (!emitElemOpBase(JSOp::GetElem)) {
5487 // [stack] OBJ ITERFN
5488 return false;
5489 }
5490 }
5491
5492 if (!emit1(JSOp::Swap)) {
5493 // [stack] ITERFN OBJ
5494 return false;
5495 }
5496 if (!emitCall(getIterCallOp(JSOp::CallIter, selfHostedIter), 0)) {
5497 // [stack] ITER
5498 return false;
5499 }
5500 if (!emitCheckIsObj(CheckIsObjectKind::GetIterator)) {
5501 // [stack] ITER
5502 return false;
5503 }
5504 if (!emit1(JSOp::Dup)) {
5505 // [stack] ITER ITER
5506 return false;
5507 }
5508 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::next())) {
5509 // [stack] ITER NEXT
5510 return false;
5511 }
5512 if (!emit1(JSOp::Swap)) {
5513 // [stack] NEXT ITER
5514 return false;
5515 }
5516 return true;
5517}
5518
5519bool BytecodeEmitter::emitAsyncIterator(SelfHostedIter selfHostedIter) {
5520 MOZ_ASSERT(selfHostedIter != SelfHostedIter::AllowContentWithNext)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(selfHostedIter != SelfHostedIter::AllowContentWithNext
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(selfHostedIter != SelfHostedIter::AllowContentWithNext
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"selfHostedIter != SelfHostedIter::AllowContentWithNext", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5520); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::AllowContentWithNext"
")"); do { *((volatile int*)__null) = 5520; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5521 MOZ_ASSERT(selfHostedIter != SelfHostedIter::Deny ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode
!= BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter
::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
" (" "[Symbol.asyncIterator]() call is prohibited in self-hosted code "
"because it can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5524); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
") (" "[Symbol.asyncIterator]() call is prohibited in self-hosted code "
"because it can run user-modifiable iteration code" ")"); do
{ *((volatile int*)__null) = 5524; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
5522 emitterMode != BytecodeEmitter::SelfHosting,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode
!= BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter
::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
" (" "[Symbol.asyncIterator]() call is prohibited in self-hosted code "
"because it can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5524); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
") (" "[Symbol.asyncIterator]() call is prohibited in self-hosted code "
"because it can run user-modifiable iteration code" ")"); do
{ *((volatile int*)__null) = 5524; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
5523 "[Symbol.asyncIterator]() call is prohibited in self-hosted code "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode
!= BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter
::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
" (" "[Symbol.asyncIterator]() call is prohibited in self-hosted code "
"because it can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5524); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
") (" "[Symbol.asyncIterator]() call is prohibited in self-hosted code "
"because it can run user-modifiable iteration code" ")"); do
{ *((volatile int*)__null) = 5524; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
5524 "because it can run user-modifiable iteration code")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode
!= BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter
::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
" (" "[Symbol.asyncIterator]() call is prohibited in self-hosted code "
"because it can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5524); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting"
") (" "[Symbol.asyncIterator]() call is prohibited in self-hosted code "
"because it can run user-modifiable iteration code" ")"); do
{ *((volatile int*)__null) = 5524; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
5525
5526 if (selfHostedIter != SelfHostedIter::AllowContentWith) {
5527 // [stack] OBJ
5528
5529 // Convert iterable to iterator.
5530 if (!emit1(JSOp::Dup)) {
5531 // [stack] OBJ OBJ
5532 return false;
5533 }
5534 if (!emit2(JSOp::Symbol, uint8_t(JS::SymbolCode::asyncIterator))) {
5535 // [stack] OBJ OBJ @@ASYNCITERATOR
5536 return false;
5537 }
5538 if (!emitElemOpBase(JSOp::GetElem)) {
5539 // [stack] OBJ ASYNC_ITERFN
5540 return false;
5541 }
5542 } else {
5543 // [stack] OBJ ASYNC_ITERFN SYNC_ITERFN
5544
5545 if (!emitElemOpBase(JSOp::Swap)) {
5546 // [stack] OBJ SYNC_ITERFN ASYNC_ITERFN
5547 return false;
5548 }
5549 }
5550
5551 InternalIfEmitter ifAsyncIterIsUndefined(this);
5552 if (!emit1(JSOp::IsNullOrUndefined)) {
5553 // [stack] OBJ SYNC_ITERFN? ASYNC_ITERFN NULL-OR-UNDEF
5554 return false;
5555 }
5556 if (!ifAsyncIterIsUndefined.emitThenElse()) {
5557 // [stack] OBJ SYNC_ITERFN? ASYNC_ITERFN
5558 return false;
5559 }
5560
5561 if (!emit1(JSOp::Pop)) {
5562 // [stack] OBJ SYNC_ITERFN?
5563 return false;
5564 }
5565
5566 if (selfHostedIter != SelfHostedIter::AllowContentWith) {
5567 if (!emit1(JSOp::Dup)) {
5568 // [stack] OBJ OBJ
5569 return false;
5570 }
5571 if (!emit2(JSOp::Symbol, uint8_t(JS::SymbolCode::iterator))) {
5572 // [stack] OBJ OBJ @@ITERATOR
5573 return false;
5574 }
5575 if (!emitElemOpBase(JSOp::GetElem)) {
5576 // [stack] OBJ SYNC_ITERFN
5577 return false;
5578 }
5579 } else {
5580 // [stack] OBJ SYNC_ITERFN
5581 }
5582
5583 if (!emit1(JSOp::Swap)) {
5584 // [stack] SYNC_ITERFN OBJ
5585 return false;
5586 }
5587 if (!emitCall(getIterCallOp(JSOp::CallIter, selfHostedIter), 0)) {
5588 // [stack] ITER
5589 return false;
5590 }
5591 if (!emitCheckIsObj(CheckIsObjectKind::GetIterator)) {
5592 // [stack] ITER
5593 return false;
5594 }
5595
5596 if (!emit1(JSOp::Dup)) {
5597 // [stack] ITER ITER
5598 return false;
5599 }
5600 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::next())) {
5601 // [stack] ITER SYNCNEXT
5602 return false;
5603 }
5604
5605 if (!emit1(JSOp::ToAsyncIter)) {
5606 // [stack] ITER
5607 return false;
5608 }
5609
5610 if (!ifAsyncIterIsUndefined.emitElse()) {
5611 // [stack] OBJ SYNC_ITERFN? ASYNC_ITERFN
5612 return false;
5613 }
5614
5615 if (selfHostedIter == SelfHostedIter::AllowContentWith) {
5616 if (!emit1(JSOp::Swap)) {
5617 // [stack] OBJ ASYNC_ITERFN SYNC_ITERFN
5618 return false;
5619 }
5620 if (!emit1(JSOp::Pop)) {
5621 // [stack] OBJ ASYNC_ITERFN
5622 return false;
5623 }
5624 }
5625
5626 if (!emit1(JSOp::Swap)) {
5627 // [stack] ASYNC_ITERFN OBJ
5628 return false;
5629 }
5630 if (!emitCall(getIterCallOp(JSOp::CallIter, selfHostedIter), 0)) {
5631 // [stack] ITER
5632 return false;
5633 }
5634 if (!emitCheckIsObj(CheckIsObjectKind::GetAsyncIterator)) {
5635 // [stack] ITER
5636 return false;
5637 }
5638
5639 if (!ifAsyncIterIsUndefined.emitEnd()) {
5640 // [stack] ITER
5641 return false;
5642 }
5643
5644 if (!emit1(JSOp::Dup)) {
5645 // [stack] ITER ITER
5646 return false;
5647 }
5648 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::next())) {
5649 // [stack] ITER NEXT
5650 return false;
5651 }
5652 if (!emit1(JSOp::Swap)) {
5653 // [stack] NEXT ITER
5654 return false;
5655 }
5656
5657 return true;
5658}
5659
5660bool BytecodeEmitter::emitSpread(SelfHostedIter selfHostedIter) {
5661 // [stack] NEXT ITER ARR I
5662 return emitSpread(selfHostedIter, 2, JSOp::InitElemInc);
5663 // [stack] ARR FINAL_INDEX
5664}
5665
5666bool BytecodeEmitter::emitSpread(SelfHostedIter selfHostedIter,
5667 int spreadeeStackItems, JSOp storeElementOp) {
5668 LoopControl loopInfo(this, StatementKind::Spread);
5669 // In the [stack] annotations, (spreadee) can be "ARR I" (when spreading
5670 // into an array or into call parameters, or "TUPLE" (when spreading into a
5671 // tuple)
5672
5673 if (!loopInfo.emitLoopHead(this, Nothing())) {
5674 // [stack] NEXT ITER (spreadee)
5675 return false;
5676 }
5677
5678 {
5679#ifdef DEBUG1
5680 auto loopDepth = bytecodeSection().stackDepth();
5681#endif
5682
5683 // Spread operations can't contain |continue|, so don't bother setting loop
5684 // and enclosing "update" offsets, as we do with for-loops.
5685
5686 if (!emitDupAt(spreadeeStackItems + 1, 2)) {
5687 // [stack] NEXT ITER (spreadee) NEXT ITER
5688 return false;
5689 }
5690 if (!emitIteratorNext(Nothing(), IteratorKind::Sync, selfHostedIter)) {
5691 // [stack] NEXT ITER (spreadee) RESULT
5692 return false;
5693 }
5694 if (!emit1(JSOp::Dup)) {
5695 // [stack] NEXT ITER (spreadee) RESULT RESULT
5696 return false;
5697 }
5698 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::done())) {
5699 // [stack] NEXT ITER (spreadee) RESULT DONE
5700 return false;
5701 }
5702 if (!emitJump(JSOp::JumpIfTrue, &loopInfo.breaks)) {
5703 // [stack] NEXT ITER (spreadee) RESULT
5704 return false;
5705 }
5706
5707 // Emit code to assign result.value to the iteration variable.
5708 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::value())) {
5709 // [stack] NEXT ITER (spreadee) VALUE
5710 return false;
5711 }
5712 if (!emit1(storeElementOp)) {
5713 // [stack] NEXT ITER (spreadee)
5714 return false;
5715 }
5716
5717 if (!loopInfo.emitLoopEnd(this, JSOp::Goto, TryNoteKind::ForOf)) {
5718 // [stack] NEXT ITER (spreadee)
5719 return false;
5720 }
5721
5722 MOZ_ASSERT(bytecodeSection().stackDepth() == loopDepth)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bytecodeSection().stackDepth() == loopDepth)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(bytecodeSection().stackDepth() == loopDepth))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("bytecodeSection().stackDepth() == loopDepth"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5722); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == loopDepth"
")"); do { *((volatile int*)__null) = 5722; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5723 }
5724
5725 // When we leave the loop body and jump to this point, the result value is
5726 // still on the stack. Account for that by updating the stack depth
5727 // manually.
5728 bytecodeSection().setStackDepth(bytecodeSection().stackDepth() + 1);
5729
5730 // No continues should occur in spreads.
5731 MOZ_ASSERT(!loopInfo.continues.offset.valid())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!loopInfo.continues.offset.valid())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!loopInfo.continues.offset.valid
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!loopInfo.continues.offset.valid()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5731); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!loopInfo.continues.offset.valid()"
")"); do { *((volatile int*)__null) = 5731; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5732
5733 if (!emit2(JSOp::Pick, spreadeeStackItems + 2)) {
5734 // [stack] ITER (spreadee) RESULT NEXT
5735 return false;
5736 }
5737 if (!emit2(JSOp::Pick, spreadeeStackItems + 2)) {
5738 // [stack] (spreadee) RESULT NEXT ITER
5739 return false;
5740 }
5741
5742 return emitPopN(3);
5743 // [stack] (spreadee)
5744}
5745
5746bool BytecodeEmitter::emitInitializeForInOrOfTarget(TernaryNode* forHead) {
5747 MOZ_ASSERT(forHead->isKind(ParseNodeKind::ForIn) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(forHead->isKind(ParseNodeKind::ForIn) || forHead->
isKind(ParseNodeKind::ForOf))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(forHead->isKind(ParseNodeKind
::ForIn) || forHead->isKind(ParseNodeKind::ForOf)))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("forHead->isKind(ParseNodeKind::ForIn) || forHead->isKind(ParseNodeKind::ForOf)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5748); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forHead->isKind(ParseNodeKind::ForIn) || forHead->isKind(ParseNodeKind::ForOf)"
")"); do { *((volatile int*)__null) = 5748; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5748 forHead->isKind(ParseNodeKind::ForOf))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(forHead->isKind(ParseNodeKind::ForIn) || forHead->
isKind(ParseNodeKind::ForOf))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(forHead->isKind(ParseNodeKind
::ForIn) || forHead->isKind(ParseNodeKind::ForOf)))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("forHead->isKind(ParseNodeKind::ForIn) || forHead->isKind(ParseNodeKind::ForOf)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5748); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forHead->isKind(ParseNodeKind::ForIn) || forHead->isKind(ParseNodeKind::ForOf)"
")"); do { *((volatile int*)__null) = 5748; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5749
5750 MOZ_ASSERT(bytecodeSection().stackDepth() >= 1,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bytecodeSection().stackDepth() >= 1)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(bytecodeSection().stackDepth() >= 1))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("bytecodeSection().stackDepth() >= 1"
" (" "must have a per-iteration value for initializing" ")",
"/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5751); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() >= 1"
") (" "must have a per-iteration value for initializing" ")"
); do { *((volatile int*)__null) = 5751; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5751 "must have a per-iteration value for initializing")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bytecodeSection().stackDepth() >= 1)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(bytecodeSection().stackDepth() >= 1))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("bytecodeSection().stackDepth() >= 1"
" (" "must have a per-iteration value for initializing" ")",
"/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5751); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() >= 1"
") (" "must have a per-iteration value for initializing" ")"
); do { *((volatile int*)__null) = 5751; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5752
5753 ParseNode* target = forHead->kid1();
5754 MOZ_ASSERT(!forHead->kid2())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!forHead->kid2())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!forHead->kid2()))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("!forHead->kid2()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5754); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!forHead->kid2()"
")"); do { *((volatile int*)__null) = 5754; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5755
5756 // If the for-in/of loop didn't have a variable declaration, per-loop
5757 // initialization is just assigning the iteration value to a target
5758 // expression.
5759 if (!target->is<DeclarationListNode>()) {
5760 return emitAssignmentOrInit(ParseNodeKind::AssignExpr, target, nullptr);
5761 // [stack] ... ITERVAL
5762 }
5763
5764 // Otherwise, per-loop initialization is (possibly) declaration
5765 // initialization. If the declaration is a lexical declaration, it must be
5766 // initialized. If the declaration is a variable declaration, an
5767 // assignment to that name (which does *not* necessarily assign to the
5768 // variable!) must be generated.
5769
5770 auto* declarationList = &target->as<DeclarationListNode>();
5771 if (!updateSourceCoordNotes(declarationList->pn_pos.begin)) {
5772 return false;
5773 }
5774
5775 target = declarationList->singleBinding();
5776
5777 NameNode* nameNode = nullptr;
5778 if (target->isKind(ParseNodeKind::Name)) {
5779 nameNode = &target->as<NameNode>();
5780 } else if (target->isKind(ParseNodeKind::AssignExpr)) {
5781 BinaryNode* assignNode = &target->as<BinaryNode>();
5782 if (assignNode->left()->is<NameNode>()) {
5783 nameNode = &assignNode->left()->as<NameNode>();
5784 }
5785 }
5786
5787 if (nameNode) {
5788 auto nameAtom = nameNode->name();
5789 NameOpEmitter noe(this, nameAtom, NameOpEmitter::Kind::Initialize);
5790 if (!noe.prepareForRhs()) {
5791 return false;
5792 }
5793 if (noe.emittedBindOp()) {
5794 // Per-iteration initialization in for-in/of loops computes the
5795 // iteration value *before* initializing. Thus the initializing
5796 // value may be buried under a bind-specific value on the stack.
5797 // Swap it to the top of the stack.
5798 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"
, 5798); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() >= 2"
")"); do { *((volatile int*)__null) = 5798; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5799 if (!emit1(JSOp::Swap)) {
5800 return false;
5801 }
5802 } else {
5803 // In cases of emitting a frame slot or environment slot,
5804 // nothing needs be done.
5805 MOZ_ASSERT(bytecodeSection().stackDepth() >= 1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bytecodeSection().stackDepth() >= 1)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(bytecodeSection().stackDepth() >= 1))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("bytecodeSection().stackDepth() >= 1"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5805); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() >= 1"
")"); do { *((volatile int*)__null) = 5805; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5806 }
5807
5808#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT1
5809 if (declarationList->isKind(ParseNodeKind::UsingDecl)) {
5810 if (!innermostEmitterScope()->prepareForDisposableAssignment(
5811 UsingHint::Sync)) {
5812 // [stack] ENV? V
5813 return false;
5814 }
5815 } else if (declarationList->isKind(ParseNodeKind::AwaitUsingDecl)) {
5816 if (!innermostEmitterScope()->prepareForDisposableAssignment(
5817 UsingHint::Async)) {
5818 // [stack] ENV? V
5819 return false;
5820 }
5821 }
5822#endif
5823
5824 if (!noe.emitAssignment()) {
5825 return false;
5826 }
5827
5828 // The caller handles removing the iteration value from the stack.
5829 return true;
5830 }
5831
5832 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!target->isKind(ParseNodeKind::AssignExpr))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!target->isKind(ParseNodeKind::AssignExpr)))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("!target->isKind(ParseNodeKind::AssignExpr)"
" (" "for-in/of loop destructuring declarations can't have initializers"
")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5834); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!target->isKind(ParseNodeKind::AssignExpr)"
") (" "for-in/of loop destructuring declarations can't have initializers"
")"); do { *((volatile int*)__null) = 5834; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5833 !target->isKind(ParseNodeKind::AssignExpr),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!target->isKind(ParseNodeKind::AssignExpr))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!target->isKind(ParseNodeKind::AssignExpr)))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("!target->isKind(ParseNodeKind::AssignExpr)"
" (" "for-in/of loop destructuring declarations can't have initializers"
")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5834); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!target->isKind(ParseNodeKind::AssignExpr)"
") (" "for-in/of loop destructuring declarations can't have initializers"
")"); do { *((volatile int*)__null) = 5834; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5834 "for-in/of loop destructuring declarations can't have initializers")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!target->isKind(ParseNodeKind::AssignExpr))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!target->isKind(ParseNodeKind::AssignExpr)))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("!target->isKind(ParseNodeKind::AssignExpr)"
" (" "for-in/of loop destructuring declarations can't have initializers"
")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5834); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!target->isKind(ParseNodeKind::AssignExpr)"
") (" "for-in/of loop destructuring declarations can't have initializers"
")"); do { *((volatile int*)__null) = 5834; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5835
5836 MOZ_ASSERT(target->isKind(ParseNodeKind::ArrayExpr) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(target->isKind(ParseNodeKind::ArrayExpr) || target
->isKind(ParseNodeKind::ObjectExpr))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(target->isKind(ParseNodeKind
::ArrayExpr) || target->isKind(ParseNodeKind::ObjectExpr))
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("target->isKind(ParseNodeKind::ArrayExpr) || target->isKind(ParseNodeKind::ObjectExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5837); AnnotateMozCrashReason("MOZ_ASSERT" "(" "target->isKind(ParseNodeKind::ArrayExpr) || target->isKind(ParseNodeKind::ObjectExpr)"
")"); do { *((volatile int*)__null) = 5837; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5837 target->isKind(ParseNodeKind::ObjectExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(target->isKind(ParseNodeKind::ArrayExpr) || target
->isKind(ParseNodeKind::ObjectExpr))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(target->isKind(ParseNodeKind
::ArrayExpr) || target->isKind(ParseNodeKind::ObjectExpr))
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("target->isKind(ParseNodeKind::ArrayExpr) || target->isKind(ParseNodeKind::ObjectExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5837); AnnotateMozCrashReason("MOZ_ASSERT" "(" "target->isKind(ParseNodeKind::ArrayExpr) || target->isKind(ParseNodeKind::ObjectExpr)"
")"); do { *((volatile int*)__null) = 5837; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5838 return emitDestructuringOps(&target->as<ListNode>(),
5839 DestructuringFlavor::Declaration);
5840}
5841
5842bool BytecodeEmitter::emitForOf(ForNode* forOfLoop,
5843 const EmitterScope* headLexicalEmitterScope) {
5844 MOZ_ASSERT(forOfLoop->isKind(ParseNodeKind::ForStmt))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(forOfLoop->isKind(ParseNodeKind::ForStmt))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(forOfLoop->isKind(ParseNodeKind::ForStmt)))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("forOfLoop->isKind(ParseNodeKind::ForStmt)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5844); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfLoop->isKind(ParseNodeKind::ForStmt)"
")"); do { *((volatile int*)__null) = 5844; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5845
5846 TernaryNode* forOfHead = forOfLoop->head();
5847 MOZ_ASSERT(forOfHead->isKind(ParseNodeKind::ForOf))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(forOfHead->isKind(ParseNodeKind::ForOf))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(forOfHead->isKind(ParseNodeKind::ForOf)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("forOfHead->isKind(ParseNodeKind::ForOf)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5847); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfHead->isKind(ParseNodeKind::ForOf)"
")"); do { *((volatile int*)__null) = 5847; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5848
5849 unsigned iflags = forOfLoop->iflags();
5850 IteratorKind iterKind =
5851 (iflags & JSITER_FORAWAITOF0x80) ? IteratorKind::Async : IteratorKind::Sync;
5852 MOZ_ASSERT_IF(iterKind == IteratorKind::Async, sc->isSuspendableContext())do { if (iterKind == IteratorKind::Async) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(sc->
isSuspendableContext())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sc->isSuspendableContext(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("sc->isSuspendableContext()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5852); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isSuspendableContext()"
")"); do { *((volatile int*)__null) = 5852; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
5853 MOZ_ASSERT_IF(iterKind == IteratorKind::Async,do { if (iterKind == IteratorKind::Async) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(sc->
asSuspendableContext()->isAsync())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sc->asSuspendableContext(
)->isAsync()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("sc->asSuspendableContext()->isAsync()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5854); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->asSuspendableContext()->isAsync()"
")"); do { *((volatile int*)__null) = 5854; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
5854 sc->asSuspendableContext()->isAsync())do { if (iterKind == IteratorKind::Async) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(sc->
asSuspendableContext()->isAsync())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sc->asSuspendableContext(
)->isAsync()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("sc->asSuspendableContext()->isAsync()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5854); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->asSuspendableContext()->isAsync()"
")"); do { *((volatile int*)__null) = 5854; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
5855
5856 ParseNode* forHeadExpr = forOfHead->kid3();
5857
5858 // Certain builtins (e.g. Array.from) are implemented in self-hosting
5859 // as for-of loops.
5860 auto selfHostedIter = getSelfHostedIterFor(forHeadExpr);
5861#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT1
5862 ForOfEmitter::HeadUsingDeclarationKind headUsingDeclKind =
5863 ForOfEmitter::HeadUsingDeclarationKind::None;
5864 if (forOfHead->kid1()->isKind(ParseNodeKind::UsingDecl)) {
5865 headUsingDeclKind = ForOfEmitter::HeadUsingDeclarationKind::Sync;
5866 } else if (forOfHead->kid1()->isKind(ParseNodeKind::AwaitUsingDecl)) {
5867 headUsingDeclKind = ForOfEmitter::HeadUsingDeclarationKind::Async;
5868 }
5869#endif
5870
5871 ForOfEmitter forOf(this, headLexicalEmitterScope, selfHostedIter, iterKind
5872#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT1
5873 ,
5874 headUsingDeclKind
5875#endif
5876 );
5877
5878 if (!forOf.emitIterated()) {
5879 // [stack]
5880 return false;
5881 }
5882
5883 if (!updateSourceCoordNotes(forHeadExpr->pn_pos.begin)) {
5884 return false;
5885 }
5886 if (!markStepBreakpoint()) {
5887 return false;
5888 }
5889 if (!emitIterable(forHeadExpr, selfHostedIter, iterKind)) {
5890 // [stack] ITERABLE
5891 return false;
5892 }
5893
5894 if (headLexicalEmitterScope) {
5895 DebugOnly<ParseNode*> forOfTarget = forOfHead->kid1();
5896 MOZ_ASSERT(forOfTarget->isKind(ParseNodeKind::LetDecl) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget
->isKind(ParseNodeKind::ConstDecl)ifdef 1 || forOfTarget->
isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind
::AwaitUsingDecl)endif)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(forOfTarget->isKind(ParseNodeKind
::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl
)ifdef 1 || forOfTarget->isKind(ParseNodeKind::UsingDecl) ||
forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)endif))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef 1 || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)endif"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5902); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef 1 || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)endif"
")"); do { *((volatile int*)__null) = 5902; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5897 forOfTarget->isKind(ParseNodeKind::ConstDecl)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget
->isKind(ParseNodeKind::ConstDecl)ifdef 1 || forOfTarget->
isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind
::AwaitUsingDecl)endif)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(forOfTarget->isKind(ParseNodeKind
::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl
)ifdef 1 || forOfTarget->isKind(ParseNodeKind::UsingDecl) ||
forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)endif))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef 1 || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)endif"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5902); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef 1 || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)endif"
")"); do { *((volatile int*)__null) = 5902; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5898#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENTdo { static_assert( mozilla::detail::AssertionConditionType<
decltype(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget
->isKind(ParseNodeKind::ConstDecl)ifdef 1 || forOfTarget->
isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind
::AwaitUsingDecl)endif)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(forOfTarget->isKind(ParseNodeKind
::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl
)ifdef 1 || forOfTarget->isKind(ParseNodeKind::UsingDecl) ||
forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)endif))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef 1 || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)endif"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5902); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef 1 || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)endif"
")"); do { *((volatile int*)__null) = 5902; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5899 || forOfTarget->isKind(ParseNodeKind::UsingDecl) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget
->isKind(ParseNodeKind::ConstDecl)ifdef 1 || forOfTarget->
isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind
::AwaitUsingDecl)endif)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(forOfTarget->isKind(ParseNodeKind
::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl
)ifdef 1 || forOfTarget->isKind(ParseNodeKind::UsingDecl) ||
forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)endif))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef 1 || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)endif"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5902); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef 1 || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)endif"
")"); do { *((volatile int*)__null) = 5902; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5900 forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget
->isKind(ParseNodeKind::ConstDecl)ifdef 1 || forOfTarget->
isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind
::AwaitUsingDecl)endif)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(forOfTarget->isKind(ParseNodeKind
::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl
)ifdef 1 || forOfTarget->isKind(ParseNodeKind::UsingDecl) ||
forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)endif))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef 1 || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)endif"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5902); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef 1 || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)endif"
")"); do { *((volatile int*)__null) = 5902; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5901#endifdo { static_assert( mozilla::detail::AssertionConditionType<
decltype(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget
->isKind(ParseNodeKind::ConstDecl)ifdef 1 || forOfTarget->
isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind
::AwaitUsingDecl)endif)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(forOfTarget->isKind(ParseNodeKind
::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl
)ifdef 1 || forOfTarget->isKind(ParseNodeKind::UsingDecl) ||
forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)endif))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef 1 || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)endif"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5902); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef 1 || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)endif"
")"); do { *((volatile int*)__null) = 5902; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5902 )do { static_assert( mozilla::detail::AssertionConditionType<
decltype(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget
->isKind(ParseNodeKind::ConstDecl)ifdef 1 || forOfTarget->
isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind
::AwaitUsingDecl)endif)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(forOfTarget->isKind(ParseNodeKind
::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl
)ifdef 1 || forOfTarget->isKind(ParseNodeKind::UsingDecl) ||
forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)endif))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef 1 || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)endif"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5902); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef 1 || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)endif"
")"); do { *((volatile int*)__null) = 5902; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5903 }
5904
5905 if (!forOf.emitInitialize(forOfHead->pn_pos.begin)) {
5906 // [stack] NEXT ITER VALUE
5907 return false;
5908 }
5909
5910 if (!emitInitializeForInOrOfTarget(forOfHead)) {
5911 // [stack] NEXT ITER VALUE
5912 return false;
5913 }
5914
5915 if (!forOf.emitBody()) {
5916 // [stack] NEXT ITER UNDEF
5917 return false;
5918 }
5919
5920 // Perform the loop body.
5921 ParseNode* forBody = forOfLoop->body();
5922 if (!emitTree(forBody)) {
5923 // [stack] NEXT ITER UNDEF
5924 return false;
5925 }
5926
5927 if (!forOf.emitEnd(forHeadExpr->pn_pos.begin)) {
5928 // [stack]
5929 return false;
5930 }
5931
5932 return true;
5933}
5934
5935bool BytecodeEmitter::emitForIn(ForNode* forInLoop,
5936 const EmitterScope* headLexicalEmitterScope) {
5937 TernaryNode* forInHead = forInLoop->head();
5938 MOZ_ASSERT(forInHead->isKind(ParseNodeKind::ForIn))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(forInHead->isKind(ParseNodeKind::ForIn))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(forInHead->isKind(ParseNodeKind::ForIn)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("forInHead->isKind(ParseNodeKind::ForIn)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5938); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInHead->isKind(ParseNodeKind::ForIn)"
")"); do { *((volatile int*)__null) = 5938; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5939
5940 ForInEmitter forIn(this, headLexicalEmitterScope);
5941
5942 // Annex B: Evaluate the var-initializer expression if present.
5943 // |for (var i = initializer in expr) { ... }|
5944 ParseNode* forInTarget = forInHead->kid1();
5945 if (forInTarget->is<DeclarationListNode>()) {
5946 auto* declarationList = &forInTarget->as<DeclarationListNode>();
5947
5948 ParseNode* decl = declarationList->singleBinding();
5949 if (decl->isKind(ParseNodeKind::AssignExpr)) {
5950 BinaryNode* assignNode = &decl->as<BinaryNode>();
5951 if (assignNode->left()->is<NameNode>()) {
5952 NameNode* nameNode = &assignNode->left()->as<NameNode>();
5953 ParseNode* initializer = assignNode->right();
5954 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(forInTarget->isKind(ParseNodeKind::VarStmt))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(forInTarget->isKind(ParseNodeKind::VarStmt)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("forInTarget->isKind(ParseNodeKind::VarStmt)"
" (" "for-in initializers are only permitted for |var| declarations"
")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5956); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInTarget->isKind(ParseNodeKind::VarStmt)"
") (" "for-in initializers are only permitted for |var| declarations"
")"); do { *((volatile int*)__null) = 5956; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5955 forInTarget->isKind(ParseNodeKind::VarStmt),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(forInTarget->isKind(ParseNodeKind::VarStmt))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(forInTarget->isKind(ParseNodeKind::VarStmt)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("forInTarget->isKind(ParseNodeKind::VarStmt)"
" (" "for-in initializers are only permitted for |var| declarations"
")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5956); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInTarget->isKind(ParseNodeKind::VarStmt)"
") (" "for-in initializers are only permitted for |var| declarations"
")"); do { *((volatile int*)__null) = 5956; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5956 "for-in initializers are only permitted for |var| declarations")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(forInTarget->isKind(ParseNodeKind::VarStmt))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(forInTarget->isKind(ParseNodeKind::VarStmt)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("forInTarget->isKind(ParseNodeKind::VarStmt)"
" (" "for-in initializers are only permitted for |var| declarations"
")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5956); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInTarget->isKind(ParseNodeKind::VarStmt)"
") (" "for-in initializers are only permitted for |var| declarations"
")"); do { *((volatile int*)__null) = 5956; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5957
5958 if (!updateSourceCoordNotes(decl->pn_pos.begin)) {
5959 return false;
5960 }
5961
5962 auto nameAtom = nameNode->name();
5963 NameOpEmitter noe(this, nameAtom, NameOpEmitter::Kind::Initialize);
5964 if (!noe.prepareForRhs()) {
5965 return false;
5966 }
5967 if (!emitInitializer(initializer, nameNode)) {
5968 return false;
5969 }
5970 if (!noe.emitAssignment()) {
5971 return false;
5972 }
5973
5974 // Pop the initializer.
5975 if (!emit1(JSOp::Pop)) {
5976 return false;
5977 }
5978 }
5979 }
5980 }
5981
5982 if (!forIn.emitIterated()) {
5983 // [stack]
5984 return false;
5985 }
5986
5987 // Evaluate the expression being iterated.
5988 ParseNode* expr = forInHead->kid3();
5989
5990 if (!updateSourceCoordNotes(expr->pn_pos.begin)) {
5991 return false;
5992 }
5993 if (!markStepBreakpoint()) {
5994 return false;
5995 }
5996 if (!emitTree(expr)) {
5997 // [stack] EXPR
5998 return false;
5999 }
6000
6001 MOZ_ASSERT(forInLoop->iflags() == 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(forInLoop->iflags() == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(forInLoop->iflags() == 0)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("forInLoop->iflags() == 0"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6001); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInLoop->iflags() == 0"
")"); do { *((volatile int*)__null) = 6001; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6002
6003 MOZ_ASSERT_IF(headLexicalEmitterScope,do { if (headLexicalEmitterScope) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(forInTarget->
isKind(ParseNodeKind::LetDecl) || forInTarget->isKind(ParseNodeKind
::ConstDecl))>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(forInTarget->isKind(ParseNodeKind
::LetDecl) || forInTarget->isKind(ParseNodeKind::ConstDecl
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("forInTarget->isKind(ParseNodeKind::LetDecl) || forInTarget->isKind(ParseNodeKind::ConstDecl)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6005); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInTarget->isKind(ParseNodeKind::LetDecl) || forInTarget->isKind(ParseNodeKind::ConstDecl)"
")"); do { *((volatile int*)__null) = 6005; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
6004 forInTarget->isKind(ParseNodeKind::LetDecl) ||do { if (headLexicalEmitterScope) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(forInTarget->
isKind(ParseNodeKind::LetDecl) || forInTarget->isKind(ParseNodeKind
::ConstDecl))>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(forInTarget->isKind(ParseNodeKind
::LetDecl) || forInTarget->isKind(ParseNodeKind::ConstDecl
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("forInTarget->isKind(ParseNodeKind::LetDecl) || forInTarget->isKind(ParseNodeKind::ConstDecl)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6005); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInTarget->isKind(ParseNodeKind::LetDecl) || forInTarget->isKind(ParseNodeKind::ConstDecl)"
")"); do { *((volatile int*)__null) = 6005; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
6005 forInTarget->isKind(ParseNodeKind::ConstDecl))do { if (headLexicalEmitterScope) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(forInTarget->
isKind(ParseNodeKind::LetDecl) || forInTarget->isKind(ParseNodeKind
::ConstDecl))>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(forInTarget->isKind(ParseNodeKind
::LetDecl) || forInTarget->isKind(ParseNodeKind::ConstDecl
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("forInTarget->isKind(ParseNodeKind::LetDecl) || forInTarget->isKind(ParseNodeKind::ConstDecl)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6005); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInTarget->isKind(ParseNodeKind::LetDecl) || forInTarget->isKind(ParseNodeKind::ConstDecl)"
")"); do { *((volatile int*)__null) = 6005; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
6006
6007 if (!forIn.emitInitialize()) {
6008 // [stack] ITER ITERVAL
6009 return false;
6010 }
6011
6012 if (!emitInitializeForInOrOfTarget(forInHead)) {
6013 // [stack] ITER ITERVAL
6014 return false;
6015 }
6016
6017 if (!forIn.emitBody()) {
6018 // [stack] ITER ITERVAL
6019 return false;
6020 }
6021
6022 // Perform the loop body.
6023 ParseNode* forBody = forInLoop->body();
6024 if (!emitTree(forBody)) {
6025 // [stack] ITER ITERVAL
6026 return false;
6027 }
6028
6029 if (!forIn.emitEnd(forInHead->pn_pos.begin)) {
6030 // [stack]
6031 return false;
6032 }
6033
6034 return true;
6035}
6036
6037/* C-style `for (init; cond; update) ...` loop. */
6038bool BytecodeEmitter::emitCStyleFor(
6039 ForNode* forNode, const EmitterScope* headLexicalEmitterScope) {
6040 TernaryNode* forHead = forNode->head();
6041 ParseNode* forBody = forNode->body();
6042 ParseNode* init = forHead->kid1();
6043 ParseNode* cond = forHead->kid2();
6044 ParseNode* update = forHead->kid3();
6045 bool isLet = init && init->isKind(ParseNodeKind::LetDecl);
6046
6047 CForEmitter cfor(this, isLet ? headLexicalEmitterScope : nullptr);
6048
6049 if (!cfor.emitInit(init ? Some(init->pn_pos.begin) : Nothing())) {
6050 // [stack]
6051 return false;
6052 }
6053
6054 // If the head of this for-loop declared any lexical variables, the parser
6055 // wrapped this ParseNodeKind::For node in a ParseNodeKind::LexicalScope
6056 // representing the implicit scope of those variables. By the time we get
6057 // here, we have already entered that scope. So far, so good.
6058 if (init) {
6059 // Emit the `init` clause, whether it's an expression or a variable
6060 // declaration. (The loop variables were hoisted into an enclosing
6061 // scope, but we still need to emit code for the initializers.)
6062 if (init->is<DeclarationListNode>()) {
6063 MOZ_ASSERT(!init->as<DeclarationListNode>().empty())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!init->as<DeclarationListNode>().empty())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!init->as<DeclarationListNode>().empty())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("!init->as<DeclarationListNode>().empty()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6063); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!init->as<DeclarationListNode>().empty()"
")"); do { *((volatile int*)__null) = 6063; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6064
6065 if (!emitTree(init)) {
6066 // [stack]
6067 return false;
6068 }
6069 } else {
6070 if (!updateSourceCoordNotes(init->pn_pos.begin)) {
6071 return false;
6072 }
6073 if (!markStepBreakpoint()) {
6074 return false;
6075 }
6076
6077 // 'init' is an expression, not a declaration. emitTree left its
6078 // value on the stack.
6079 if (!emitTree(init, ValueUsage::IgnoreValue)) {
6080 // [stack] VAL
6081 return false;
6082 }
6083 if (!emit1(JSOp::Pop)) {
6084 // [stack]
6085 return false;
6086 }
6087 }
6088 }
6089
6090 if (!cfor.emitCond(cond ? Some(cond->pn_pos.begin) : Nothing())) {
6091 // [stack]
6092 return false;
6093 }
6094
6095 if (cond) {
6096 if (!updateSourceCoordNotes(cond->pn_pos.begin)) {
6097 return false;
6098 }
6099 if (!markStepBreakpoint()) {
6100 return false;
6101 }
6102 if (!emitTree(cond)) {
6103 // [stack] VAL
6104 return false;
6105 }
6106 }
6107
6108 if (!cfor.emitBody(cond ? CForEmitter::Cond::Present
6109 : CForEmitter::Cond::Missing)) {
6110 // [stack]
6111 return false;
6112 }
6113
6114 if (!emitTree(forBody)) {
6115 // [stack]
6116 return false;
6117 }
6118
6119 if (!cfor.emitUpdate(
6120 update ? CForEmitter::Update::Present : CForEmitter::Update::Missing,
6121 update ? Some(update->pn_pos.begin) : Nothing())) {
6122 // [stack]
6123 return false;
6124 }
6125
6126 // Check for update code to do before the condition (if any).
6127 if (update) {
6128 if (!updateSourceCoordNotes(update->pn_pos.begin)) {
6129 return false;
6130 }
6131 if (!markStepBreakpoint()) {
6132 return false;
6133 }
6134 if (!emitTree(update, ValueUsage::IgnoreValue)) {
6135 // [stack] VAL
6136 return false;
6137 }
6138 }
6139
6140 if (!cfor.emitEnd(forNode->pn_pos.begin)) {
6141 // [stack]
6142 return false;
6143 }
6144
6145 return true;
6146}
6147
6148bool BytecodeEmitter::emitFor(ForNode* forNode,
6149 const EmitterScope* headLexicalEmitterScope) {
6150 if (forNode->head()->isKind(ParseNodeKind::ForHead)) {
6151 return emitCStyleFor(forNode, headLexicalEmitterScope);
6152 }
6153
6154 if (!updateLineNumberNotes(forNode->pn_pos.begin)) {
6155 return false;
6156 }
6157
6158 if (forNode->head()->isKind(ParseNodeKind::ForIn)) {
6159 return emitForIn(forNode, headLexicalEmitterScope);
6160 }
6161
6162 MOZ_ASSERT(forNode->head()->isKind(ParseNodeKind::ForOf))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(forNode->head()->isKind(ParseNodeKind::ForOf))
>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(forNode->head()->isKind(ParseNodeKind::ForOf))
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("forNode->head()->isKind(ParseNodeKind::ForOf)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6162); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forNode->head()->isKind(ParseNodeKind::ForOf)"
")"); do { *((volatile int*)__null) = 6162; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6163 return emitForOf(forNode, headLexicalEmitterScope);
6164}
6165
6166MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitFunction(
6167 FunctionNode* funNode, bool needsProto /* = false */) {
6168 FunctionBox* funbox = funNode->funbox();
6169
6170 // [stack]
6171
6172 FunctionEmitter fe(this, funbox, funNode->syntaxKind(),
6173 funNode->functionIsHoisted()
6174 ? FunctionEmitter::IsHoisted::Yes
6175 : FunctionEmitter::IsHoisted::No);
6176
6177 // |wasEmittedByEnclosingScript| flag is set to true once the function has
6178 // been emitted. Function definitions that need hoisting to the top of the
6179 // function will be seen by emitFunction in two places.
6180 if (funbox->wasEmittedByEnclosingScript()) {
6181 if (!fe.emitAgain()) {
6182 // [stack]
6183 return false;
6184 }
6185 MOZ_ASSERT(funNode->functionIsHoisted())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(funNode->functionIsHoisted())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(funNode->functionIsHoisted
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("funNode->functionIsHoisted()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6185); AnnotateMozCrashReason("MOZ_ASSERT" "(" "funNode->functionIsHoisted()"
")"); do { *((volatile int*)__null) = 6185; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6186 } else if (funbox->isInterpreted()) {
6187 if (!funbox->emitBytecode) {
6188 return fe.emitLazy();
6189 // [stack] FUN?
6190 }
6191
6192 if (!fe.prepareForNonLazy()) {
6193 // [stack]
6194 return false;
6195 }
6196
6197 BytecodeEmitter bce2(this, funbox);
6198 if (!bce2.init(funNode->pn_pos)) {
6199 return false;
6200 }
6201
6202 /* We measured the max scope depth when we parsed the function. */
6203 if (!bce2.emitFunctionScript(funNode)) {
6204 return false;
6205 }
6206
6207 if (!fe.emitNonLazyEnd()) {
6208 // [stack] FUN?
6209 return false;
6210 }
6211 } else {
6212 if (!fe.emitAsmJSModule()) {
6213 // [stack]
6214 return false;
6215 }
6216 }
6217
6218 // Track the last emitted top-level self-hosted function, so that intrinsics
6219 // can adjust attributes at parse time.
6220 //
6221 // NOTE: We also disallow lambda functions in the top-level body. This is done
6222 // to simplify handling of the self-hosted stencil. Within normal function
6223 // declarations there are no such restrictions.
6224 if (emitterMode == EmitterMode::SelfHosting) {
6225 if (sc->isTopLevelContext()) {
6226 MOZ_ASSERT(!funbox->isLambda())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!funbox->isLambda())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!funbox->isLambda()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!funbox->isLambda()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6226); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!funbox->isLambda()"
")"); do { *((volatile int*)__null) = 6226; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6227 MOZ_ASSERT(funbox->explicitName())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(funbox->explicitName())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(funbox->explicitName())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("funbox->explicitName()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6227); AnnotateMozCrashReason("MOZ_ASSERT" "(" "funbox->explicitName()"
")"); do { *((volatile int*)__null) = 6227; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6228 prevSelfHostedTopLevelFunction = funbox;
6229 }
6230 }
6231
6232 return true;
6233}
6234
6235bool BytecodeEmitter::emitDo(BinaryNode* doNode) {
6236 ParseNode* bodyNode = doNode->left();
6237
6238 DoWhileEmitter doWhile(this);
6239 if (!doWhile.emitBody(doNode->pn_pos.begin, getOffsetForLoop(bodyNode))) {
6240 return false;
6241 }
6242
6243 if (!emitTree(bodyNode)) {
6244 return false;
6245 }
6246
6247 if (!doWhile.emitCond()) {
6248 return false;
6249 }
6250
6251 ParseNode* condNode = doNode->right();
6252 if (!updateSourceCoordNotes(condNode->pn_pos.begin)) {
6253 return false;
6254 }
6255 if (!markStepBreakpoint()) {
6256 return false;
6257 }
6258 if (!emitTree(condNode)) {
6259 return false;
6260 }
6261
6262 if (!doWhile.emitEnd()) {
6263 return false;
6264 }
6265
6266 return true;
6267}
6268
6269bool BytecodeEmitter::emitWhile(BinaryNode* whileNode) {
6270 ParseNode* bodyNode = whileNode->right();
6271
6272 WhileEmitter wh(this);
6273
6274 ParseNode* condNode = whileNode->left();
6275 if (!wh.emitCond(whileNode->pn_pos.begin, getOffsetForLoop(condNode),
6276 whileNode->pn_pos.end)) {
6277 return false;
6278 }
6279
6280 if (!updateSourceCoordNotes(condNode->pn_pos.begin)) {
6281 return false;
6282 }
6283 if (!markStepBreakpoint()) {
6284 return false;
6285 }
6286 if (!emitTree(condNode)) {
6287 return false;
6288 }
6289
6290 if (!wh.emitBody()) {
6291 return false;
6292 }
6293 if (!emitTree(bodyNode)) {
6294 return false;
6295 }
6296
6297 if (!wh.emitEnd()) {
6298 return false;
6299 }
6300
6301 return true;
6302}
6303
6304bool BytecodeEmitter::emitBreak(TaggedParserAtomIndex label) {
6305 BreakableControl* target;
6306 if (label) {
6307 // Any statement with the matching label may be the break target.
6308 auto hasSameLabel = [label](LabelControl* labelControl) {
6309 return labelControl->label() == label;
6310 };
6311 target = findInnermostNestableControl<LabelControl>(hasSameLabel);
6312 } else {
6313 auto isNotLabel = [](BreakableControl* control) {
6314 return !control->is<LabelControl>();
6315 };
6316 target = findInnermostNestableControl<BreakableControl>(isNotLabel);
6317 }
6318
6319 return emitGoto(target, GotoKind::Break);
6320}
6321
6322bool BytecodeEmitter::emitContinue(TaggedParserAtomIndex label) {
6323 LoopControl* target = nullptr;
6324 if (label) {
6325 // Find the loop statement enclosed by the matching label.
6326 NestableControl* control = innermostNestableControl;
6327 while (!control->is<LabelControl>() ||
6328 control->as<LabelControl>().label() != label) {
6329 if (control->is<LoopControl>()) {
6330 target = &control->as<LoopControl>();
6331 }
6332 control = control->enclosing();
6333 }
6334 } else {
6335 target = findInnermostNestableControl<LoopControl>();
6336 }
6337 return emitGoto(target, GotoKind::Continue);
6338}
6339
6340bool BytecodeEmitter::emitGetFunctionThis(NameNode* thisName) {
6341 MOZ_ASSERT(sc->hasFunctionThisBinding())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sc->hasFunctionThisBinding())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sc->hasFunctionThisBinding
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("sc->hasFunctionThisBinding()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6341); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->hasFunctionThisBinding()"
")"); do { *((volatile int*)__null) = 6341; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6342 MOZ_ASSERT(thisName->isName(TaggedParserAtomIndex::WellKnown::dot_this_()))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(thisName->isName(TaggedParserAtomIndex::WellKnown
::dot_this_()))>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(thisName->isName(TaggedParserAtomIndex
::WellKnown::dot_this_())))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("thisName->isName(TaggedParserAtomIndex::WellKnown::dot_this_())"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6342); AnnotateMozCrashReason("MOZ_ASSERT" "(" "thisName->isName(TaggedParserAtomIndex::WellKnown::dot_this_())"
")"); do { *((volatile int*)__null) = 6342; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6343
6344 if (!updateLineNumberNotes(thisName->pn_pos.begin)) {
6345 return false;
6346 }
6347
6348 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_this_())) {
6349 // [stack] THIS
6350 return false;
6351 }
6352 if (sc->needsThisTDZChecks()) {
6353 if (!emit1(JSOp::CheckThis)) {
6354 // [stack] THIS
6355 return false;
6356 }
6357 }
6358
6359 return true;
6360}
6361
6362bool BytecodeEmitter::emitGetThisForSuperBase(UnaryNode* superBase) {
6363 MOZ_ASSERT(superBase->isKind(ParseNodeKind::SuperBase))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(superBase->isKind(ParseNodeKind::SuperBase))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(superBase->isKind(ParseNodeKind::SuperBase)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("superBase->isKind(ParseNodeKind::SuperBase)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6363); AnnotateMozCrashReason("MOZ_ASSERT" "(" "superBase->isKind(ParseNodeKind::SuperBase)"
")"); do { *((volatile int*)__null) = 6363; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6364 NameNode* nameNode = &superBase->kid()->as<NameNode>();
6365 return emitGetFunctionThis(nameNode);
6366 // [stack] THIS
6367}
6368
6369bool BytecodeEmitter::emitThisLiteral(ThisLiteral* pn) {
6370 if (ParseNode* kid = pn->kid()) {
6371 NameNode* thisName = &kid->as<NameNode>();
6372 return emitGetFunctionThis(thisName);
6373 // [stack] THIS
6374 }
6375
6376 if (sc->thisBinding() == ThisBinding::Module) {
6377 return emit1(JSOp::Undefined);
6378 // [stack] UNDEF
6379 }
6380
6381 MOZ_ASSERT(sc->thisBinding() == ThisBinding::Global)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sc->thisBinding() == ThisBinding::Global)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(sc->thisBinding() == ThisBinding::Global))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("sc->thisBinding() == ThisBinding::Global"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6381); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->thisBinding() == ThisBinding::Global"
")"); do { *((volatile int*)__null) = 6381; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6382
6383 MOZ_ASSERT(outermostScope().hasNonSyntacticScopeOnChain() ==do { static_assert( mozilla::detail::AssertionConditionType<
decltype(outermostScope().hasNonSyntacticScopeOnChain() == sc
->hasNonSyntacticScope())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(outermostScope().hasNonSyntacticScopeOnChain
() == sc->hasNonSyntacticScope()))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("outermostScope().hasNonSyntacticScopeOnChain() == sc->hasNonSyntacticScope()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6384); AnnotateMozCrashReason("MOZ_ASSERT" "(" "outermostScope().hasNonSyntacticScopeOnChain() == sc->hasNonSyntacticScope()"
")"); do { *((volatile int*)__null) = 6384; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6384 sc->hasNonSyntacticScope())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(outermostScope().hasNonSyntacticScopeOnChain() == sc
->hasNonSyntacticScope())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(outermostScope().hasNonSyntacticScopeOnChain
() == sc->hasNonSyntacticScope()))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("outermostScope().hasNonSyntacticScopeOnChain() == sc->hasNonSyntacticScope()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6384); AnnotateMozCrashReason("MOZ_ASSERT" "(" "outermostScope().hasNonSyntacticScopeOnChain() == sc->hasNonSyntacticScope()"
")"); do { *((volatile int*)__null) = 6384; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6385 if (sc->hasNonSyntacticScope()) {
6386 return emit1(JSOp::NonSyntacticGlobalThis);
6387 // [stack] THIS
6388 }
6389
6390 return emit1(JSOp::GlobalThis);
6391 // [stack] THIS
6392}
6393
6394bool BytecodeEmitter::emitCheckDerivedClassConstructorReturn() {
6395 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(lookupName(TaggedParserAtomIndex::WellKnown::dot_this_
()).hasKnownSlot())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(lookupName(TaggedParserAtomIndex
::WellKnown::dot_this_()).hasKnownSlot()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("lookupName(TaggedParserAtomIndex::WellKnown::dot_this_()).hasKnownSlot()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6396); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lookupName(TaggedParserAtomIndex::WellKnown::dot_this_()).hasKnownSlot()"
")"); do { *((volatile int*)__null) = 6396; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6396 lookupName(TaggedParserAtomIndex::WellKnown::dot_this_()).hasKnownSlot())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(lookupName(TaggedParserAtomIndex::WellKnown::dot_this_
()).hasKnownSlot())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(lookupName(TaggedParserAtomIndex
::WellKnown::dot_this_()).hasKnownSlot()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("lookupName(TaggedParserAtomIndex::WellKnown::dot_this_()).hasKnownSlot()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6396); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lookupName(TaggedParserAtomIndex::WellKnown::dot_this_()).hasKnownSlot()"
")"); do { *((volatile int*)__null) = 6396; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6397 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_this_())) {
6398 return false;
6399 }
6400 if (!emit1(JSOp::CheckReturn)) {
6401 return false;
6402 }
6403 if (!emit1(JSOp::SetRval)) {
6404 return false;
6405 }
6406 return true;
6407}
6408
6409bool BytecodeEmitter::emitNewTarget() {
6410 MOZ_ASSERT(sc->allowNewTarget())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sc->allowNewTarget())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sc->allowNewTarget()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("sc->allowNewTarget()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6410); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->allowNewTarget()"
")"); do { *((volatile int*)__null) = 6410; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6411
6412 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_newTarget_())) {
6413 // [stack] NEW.TARGET
6414 return false;
6415 }
6416 return true;
6417}
6418
6419bool BytecodeEmitter::emitNewTarget(NewTargetNode* pn) {
6420 MOZ_ASSERT(pn->newTargetName()->isName(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->newTargetName()->isName( TaggedParserAtomIndex
::WellKnown::dot_newTarget_()))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->newTargetName()->isName
( TaggedParserAtomIndex::WellKnown::dot_newTarget_())))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("pn->newTargetName()->isName( TaggedParserAtomIndex::WellKnown::dot_newTarget_())"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6421); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->newTargetName()->isName( TaggedParserAtomIndex::WellKnown::dot_newTarget_())"
")"); do { *((volatile int*)__null) = 6421; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6421 TaggedParserAtomIndex::WellKnown::dot_newTarget_()))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->newTargetName()->isName( TaggedParserAtomIndex
::WellKnown::dot_newTarget_()))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->newTargetName()->isName
( TaggedParserAtomIndex::WellKnown::dot_newTarget_())))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("pn->newTargetName()->isName( TaggedParserAtomIndex::WellKnown::dot_newTarget_())"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6421); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->newTargetName()->isName( TaggedParserAtomIndex::WellKnown::dot_newTarget_())"
")"); do { *((volatile int*)__null) = 6421; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6422
6423 return emitNewTarget();
6424}
6425
6426bool BytecodeEmitter::emitNewTarget(CallNode* pn) {
6427 MOZ_ASSERT(pn->callOp() == JSOp::SuperCall ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->callOp() == JSOp::SuperCall || pn->callOp(
) == JSOp::SpreadSuperCall)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->callOp() == JSOp::SuperCall
|| pn->callOp() == JSOp::SpreadSuperCall))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("pn->callOp() == JSOp::SuperCall || pn->callOp() == JSOp::SpreadSuperCall"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6428); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->callOp() == JSOp::SuperCall || pn->callOp() == JSOp::SpreadSuperCall"
")"); do { *((volatile int*)__null) = 6428; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6428 pn->callOp() == JSOp::SpreadSuperCall)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->callOp() == JSOp::SuperCall || pn->callOp(
) == JSOp::SpreadSuperCall)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->callOp() == JSOp::SuperCall
|| pn->callOp() == JSOp::SpreadSuperCall))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("pn->callOp() == JSOp::SuperCall || pn->callOp() == JSOp::SpreadSuperCall"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6428); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->callOp() == JSOp::SuperCall || pn->callOp() == JSOp::SpreadSuperCall"
")"); do { *((volatile int*)__null) = 6428; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6429
6430 // The parser is responsible for marking the "new.target" binding as being
6431 // implicitly used in super() calls.
6432 return emitNewTarget();
6433}
6434
6435bool BytecodeEmitter::emitReturn(UnaryNode* returnNode) {
6436 if (!updateSourceCoordNotes(returnNode->pn_pos.begin)) {
6437 return false;
6438 }
6439
6440 if (!markStepBreakpoint()) {
6441 return false;
6442 }
6443
6444 /* Push a return value */
6445 if (ParseNode* expr = returnNode->kid()) {
6446 if (!emitTree(expr)) {
6447 return false;
6448 }
6449
6450 if (sc->asSuspendableContext()->isAsync() &&
6451 sc->asSuspendableContext()->isGenerator()) {
6452 if (!emitAwaitInInnermostScope()) {
6453 return false;
6454 }
6455 }
6456 } else {
6457 /* No explicit return value provided */
6458 if (!emit1(JSOp::Undefined)) {
6459 return false;
6460 }
6461 }
6462
6463 // We know functionBodyEndPos is set because "return" is only
6464 // valid in a function, and so we've passed through
6465 // emitFunctionScript.
6466 if (!updateSourceCoordNotes(*functionBodyEndPos)) {
6467 return false;
6468 }
6469
6470 /*
6471 * The return value is currently on the stack. We would like to
6472 * generate JSOp::Return, but if we have work to do before returning,
6473 * we will instead generate JSOp::SetRval / JSOp::RetRval.
6474 *
6475 * We don't know whether we will need fixup code until after calling
6476 * prepareForNonLocalJumpToOutermost, so we start by generating
6477 * JSOp::SetRval, then mutate it to JSOp::Return in finishReturn if it
6478 * wasn't needed.
6479 */
6480 BytecodeOffset setRvalOffset = bytecodeSection().offset();
6481 if (!emit1(JSOp::SetRval)) {
6482 return false;
6483 }
6484
6485 NonLocalExitControl nle(this, NonLocalExitKind::Return);
6486 return nle.emitReturn(setRvalOffset);
6487}
6488
6489bool BytecodeEmitter::finishReturn(BytecodeOffset setRvalOffset) {
6490 // The return value is currently in rval. Depending on the current function,
6491 // we may have to do additional work before returning:
6492 // - Derived class constructors must check if the return value is an object.
6493 // - Generators and async functions must do a final yield.
6494 // - Non-async generators must return the value as an iterator result:
6495 // { value: <rval>, done: true }
6496 // - Non-generator async functions must resolve the function's result promise
6497 // with the value.
6498 //
6499 // If we have not generated any code since the SetRval that stored the return
6500 // value, we can also optimize the bytecode by rewriting that SetRval as a
6501 // JSOp::Return. See |emitReturn| above.
6502
6503 bool isDerivedClassConstructor =
6504 sc->isFunctionBox() && sc->asFunctionBox()->isDerivedClassConstructor();
6505 bool needsFinalYield =
6506 sc->isFunctionBox() && sc->asFunctionBox()->needsFinalYield();
6507 bool isSimpleReturn =
6508 setRvalOffset.valid() &&
6509 setRvalOffset + BytecodeOffsetDiff(JSOpLength_SetRval) ==
6510 bytecodeSection().offset();
6511
6512 if (isDerivedClassConstructor) {
6513 MOZ_ASSERT(!needsFinalYield)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!needsFinalYield)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!needsFinalYield))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("!needsFinalYield"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6513); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!needsFinalYield"
")"); do { *((volatile int*)__null) = 6513; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6514 if (!emitJump(JSOp::Goto, &endOfDerivedClassConstructorBody)) {
6515 return false;
6516 }
6517 return true;
6518 }
6519
6520 if (needsFinalYield) {
6521 if (!emitJump(JSOp::Goto, &finalYields)) {
6522 return false;
6523 }
6524 return true;
6525 }
6526
6527 if (isSimpleReturn) {
6528 MOZ_ASSERT(JSOp(bytecodeSection().code()[setRvalOffset.value()]) ==do { static_assert( mozilla::detail::AssertionConditionType<
decltype(JSOp(bytecodeSection().code()[setRvalOffset.value()]
) == JSOp::SetRval)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(JSOp(bytecodeSection().code(
)[setRvalOffset.value()]) == JSOp::SetRval))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("JSOp(bytecodeSection().code()[setRvalOffset.value()]) == JSOp::SetRval"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6529); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JSOp(bytecodeSection().code()[setRvalOffset.value()]) == JSOp::SetRval"
")"); do { *((volatile int*)__null) = 6529; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6529 JSOp::SetRval)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(JSOp(bytecodeSection().code()[setRvalOffset.value()]
) == JSOp::SetRval)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(JSOp(bytecodeSection().code(
)[setRvalOffset.value()]) == JSOp::SetRval))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("JSOp(bytecodeSection().code()[setRvalOffset.value()]) == JSOp::SetRval"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6529); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JSOp(bytecodeSection().code()[setRvalOffset.value()]) == JSOp::SetRval"
")"); do { *((volatile int*)__null) = 6529; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6530 bytecodeSection().code()[setRvalOffset.value()] = jsbytecode(JSOp::Return);
6531 return true;
6532 }
6533
6534 // Nothing special needs to be done.
6535 return emitReturnRval();
6536}
6537
6538bool BytecodeEmitter::emitGetDotGeneratorInScope(EmitterScope& currentScope) {
6539 if (!sc->isFunction() && sc->isModuleContext() &&
6540 sc->asModuleContext()->isAsync()) {
6541 NameLocation loc = *locationOfNameBoundInScopeType<ModuleScope>(
6542 TaggedParserAtomIndex::WellKnown::dot_generator_(), &currentScope);
6543 return emitGetNameAtLocation(
6544 TaggedParserAtomIndex::WellKnown::dot_generator_(), loc);
6545 }
6546 NameLocation loc = *locationOfNameBoundInScopeType<FunctionScope>(
6547 TaggedParserAtomIndex::WellKnown::dot_generator_(), &currentScope);
6548 return emitGetNameAtLocation(
6549 TaggedParserAtomIndex::WellKnown::dot_generator_(), loc);
6550}
6551
6552bool BytecodeEmitter::emitInitialYield(UnaryNode* yieldNode) {
6553 if (!emitTree(yieldNode->kid())) {
6554 return false;
6555 }
6556
6557 if (!emitYieldOp(JSOp::InitialYield)) {
6558 // [stack] RVAL GENERATOR RESUMEKIND
6559 return false;
6560 }
6561 if (!emit1(JSOp::CheckResumeKind)) {
6562 // [stack] RVAL
6563 return false;
6564 }
6565 if (!emit1(JSOp::Pop)) {
6566 // [stack]
6567 return false;
6568 }
6569
6570 return true;
6571}
6572
6573bool BytecodeEmitter::emitYield(UnaryNode* yieldNode) {
6574 MOZ_ASSERT(sc->isFunctionBox())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sc->isFunctionBox())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sc->isFunctionBox()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("sc->isFunctionBox()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6574); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isFunctionBox()"
")"); do { *((volatile int*)__null) = 6574; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6575 MOZ_ASSERT(sc->asFunctionBox()->isGenerator())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sc->asFunctionBox()->isGenerator())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(sc->asFunctionBox()->isGenerator()))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("sc->asFunctionBox()->isGenerator()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6575); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->asFunctionBox()->isGenerator()"
")"); do { *((volatile int*)__null) = 6575; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6576 MOZ_ASSERT(yieldNode->isKind(ParseNodeKind::YieldExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(yieldNode->isKind(ParseNodeKind::YieldExpr))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(yieldNode->isKind(ParseNodeKind::YieldExpr)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("yieldNode->isKind(ParseNodeKind::YieldExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6576); AnnotateMozCrashReason("MOZ_ASSERT" "(" "yieldNode->isKind(ParseNodeKind::YieldExpr)"
")"); do { *((volatile int*)__null) = 6576; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6577
6578 bool needsIteratorResult = sc->asFunctionBox()->needsIteratorResult();
6579 if (needsIteratorResult) {
6580 if (!emitPrepareIteratorResult()) {
6581 // [stack] ITEROBJ
6582 return false;
6583 }
6584 }
6585 if (ParseNode* expr = yieldNode->kid()) {
6586 if (!emitTree(expr)) {
6587 // [stack] ITEROBJ? VAL
6588 return false;
6589 }
6590 } else {
6591 if (!emit1(JSOp::Undefined)) {
6592 // [stack] ITEROBJ? UNDEFINED
6593 return false;
6594 }
6595 }
6596
6597 if (sc->asSuspendableContext()->isAsync()) {
6598 MOZ_ASSERT(!needsIteratorResult)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!needsIteratorResult)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!needsIteratorResult))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("!needsIteratorResult"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6598); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!needsIteratorResult"
")"); do { *((volatile int*)__null) = 6598; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6599 if (!emitAwaitInInnermostScope()) {
6600 // [stack] RESULT
6601 return false;
6602 }
6603 }
6604
6605 if (needsIteratorResult) {
6606 if (!emitFinishIteratorResult(false)) {
6607 // [stack] ITEROBJ
6608 return false;
6609 }
6610 }
6611
6612 if (!emitGetDotGeneratorInInnermostScope()) {
6613 // [stack] # if needsIteratorResult
6614 // [stack] ITEROBJ .GENERATOR
6615 // [stack] # else
6616 // [stack] RESULT .GENERATOR
6617 return false;
6618 }
6619
6620 if (!emitYieldOp(JSOp::Yield)) {
6621 // [stack] YIELDRESULT GENERATOR RESUMEKIND
6622 return false;
6623 }
6624
6625 if (!emit1(JSOp::CheckResumeKind)) {
6626 // [stack] YIELDRESULT
6627 return false;
6628 }
6629
6630 return true;
6631}
6632
6633bool BytecodeEmitter::emitAwaitInInnermostScope(UnaryNode* awaitNode) {
6634 MOZ_ASSERT(sc->isSuspendableContext())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sc->isSuspendableContext())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sc->isSuspendableContext(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("sc->isSuspendableContext()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6634); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isSuspendableContext()"
")"); do { *((volatile int*)__null) = 6634; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6635 MOZ_ASSERT(awaitNode->isKind(ParseNodeKind::AwaitExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(awaitNode->isKind(ParseNodeKind::AwaitExpr))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(awaitNode->isKind(ParseNodeKind::AwaitExpr)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("awaitNode->isKind(ParseNodeKind::AwaitExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6635); AnnotateMozCrashReason("MOZ_ASSERT" "(" "awaitNode->isKind(ParseNodeKind::AwaitExpr)"
")"); do { *((volatile int*)__null) = 6635; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6636
6637 if (!emitTree(awaitNode->kid())) {
6638 return false;
6639 }
6640 return emitAwaitInInnermostScope();
6641}
6642
6643bool BytecodeEmitter::emitAwaitInScope(EmitterScope& currentScope) {
6644 if (!emit1(JSOp::CanSkipAwait)) {
6645 // [stack] VALUE CANSKIP
6646 return false;
6647 }
6648
6649 if (!emit1(JSOp::MaybeExtractAwaitValue)) {
6650 // [stack] VALUE_OR_RESOLVED CANSKIP
6651 return false;
6652 }
6653
6654 InternalIfEmitter ifCanSkip(this);
6655 if (!ifCanSkip.emitThen(IfEmitter::ConditionKind::Negative)) {
6656 // [stack] VALUE_OR_RESOLVED
6657 return false;
6658 }
6659
6660 if (sc->asSuspendableContext()->needsPromiseResult()) {
6661 if (!emitGetDotGeneratorInScope(currentScope)) {
6662 // [stack] VALUE GENERATOR
6663 return false;
6664 }
6665 if (!emit1(JSOp::AsyncAwait)) {
6666 // [stack] PROMISE
6667 return false;
6668 }
6669 }
6670
6671 if (!emitGetDotGeneratorInScope(currentScope)) {
6672 // [stack] VALUE|PROMISE GENERATOR
6673 return false;
6674 }
6675 if (!emitYieldOp(JSOp::Await)) {
6676 // [stack] RESOLVED GENERATOR RESUMEKIND
6677 return false;
6678 }
6679 if (!emit1(JSOp::CheckResumeKind)) {
6680 // [stack] RESOLVED
6681 return false;
6682 }
6683
6684 if (!ifCanSkip.emitEnd()) {
6685 return false;
6686 }
6687
6688 MOZ_ASSERT(ifCanSkip.popped() == 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(ifCanSkip.popped() == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(ifCanSkip.popped() == 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("ifCanSkip.popped() == 0"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6688); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ifCanSkip.popped() == 0"
")"); do { *((volatile int*)__null) = 6688; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6689
6690 return true;
6691}
6692
6693// ES2019 draft rev 49b781ec80117b60f73327ef3054703a3111e40c
6694// 14.4.14 Runtime Semantics: Evaluation
6695// YieldExpression : yield* AssignmentExpression
6696bool BytecodeEmitter::emitYieldStar(ParseNode* iter) {
6697 MOZ_ASSERT(getSelfHostedIterFor(iter) == SelfHostedIter::Deny,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(getSelfHostedIterFor(iter) == SelfHostedIter::Deny)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(getSelfHostedIterFor(iter) == SelfHostedIter::Deny))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("getSelfHostedIterFor(iter) == SelfHostedIter::Deny"
" (" "yield* is prohibited in self-hosted code because it can run "
"user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6699); AnnotateMozCrashReason("MOZ_ASSERT" "(" "getSelfHostedIterFor(iter) == SelfHostedIter::Deny"
") (" "yield* is prohibited in self-hosted code because it can run "
"user-modifiable iteration code" ")"); do { *((volatile int*
)__null) = 6699; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
6698 "yield* is prohibited in self-hosted code because it can run "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(getSelfHostedIterFor(iter) == SelfHostedIter::Deny)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(getSelfHostedIterFor(iter) == SelfHostedIter::Deny))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("getSelfHostedIterFor(iter) == SelfHostedIter::Deny"
" (" "yield* is prohibited in self-hosted code because it can run "
"user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6699); AnnotateMozCrashReason("MOZ_ASSERT" "(" "getSelfHostedIterFor(iter) == SelfHostedIter::Deny"
") (" "yield* is prohibited in self-hosted code because it can run "
"user-modifiable iteration code" ")"); do { *((volatile int*
)__null) = 6699; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
6699 "user-modifiable iteration code")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(getSelfHostedIterFor(iter) == SelfHostedIter::Deny)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(getSelfHostedIterFor(iter) == SelfHostedIter::Deny))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("getSelfHostedIterFor(iter) == SelfHostedIter::Deny"
" (" "yield* is prohibited in self-hosted code because it can run "
"user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6699); AnnotateMozCrashReason("MOZ_ASSERT" "(" "getSelfHostedIterFor(iter) == SelfHostedIter::Deny"
") (" "yield* is prohibited in self-hosted code because it can run "
"user-modifiable iteration code" ")"); do { *((volatile int*
)__null) = 6699; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6700
6701 MOZ_ASSERT(sc->isSuspendableContext())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sc->isSuspendableContext())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sc->isSuspendableContext(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("sc->isSuspendableContext()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6701); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isSuspendableContext()"
")"); do { *((volatile int*)__null) = 6701; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6702 MOZ_ASSERT(sc->asSuspendableContext()->isGenerator())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sc->asSuspendableContext()->isGenerator())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(sc->asSuspendableContext()->isGenerator()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("sc->asSuspendableContext()->isGenerator()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6702); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->asSuspendableContext()->isGenerator()"
")"); do { *((volatile int*)__null) = 6702; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6703
6704 // Step 1.
6705 IteratorKind iterKind = sc->asSuspendableContext()->isAsync()
6706 ? IteratorKind::Async
6707 : IteratorKind::Sync;
6708 bool needsIteratorResult = sc->asSuspendableContext()->needsIteratorResult();
6709
6710 // Steps 2-5.
6711 if (!emitTree(iter)) {
6712 // [stack] ITERABLE
6713 return false;
6714 }
6715 if (iterKind == IteratorKind::Async) {
6716 if (!emitAsyncIterator(SelfHostedIter::Deny)) {
6717 // [stack] NEXT ITER
6718 return false;
6719 }
6720 } else {
6721 if (!emitIterator(SelfHostedIter::Deny)) {
6722 // [stack] NEXT ITER
6723 return false;
6724 }
6725 }
6726
6727 // Step 6.
6728 // Start with NormalCompletion(undefined).
6729 if (!emit1(JSOp::Undefined)) {
6730 // [stack] NEXT ITER RECEIVED
6731 return false;
6732 }
6733 if (!emitPushResumeKind(GeneratorResumeKind::Next)) {
6734 // [stack] NEXT ITER RECEIVED RESUMEKIND
6735 return false;
6736 }
6737
6738 const int32_t startDepth = bytecodeSection().stackDepth();
6739 MOZ_ASSERT(startDepth >= 4)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(startDepth >= 4)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(startDepth >= 4))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("startDepth >= 4"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 6739); AnnotateMozCrashReason("MOZ_ASSERT" "(" "startDepth >= 4"
")"); do { *((volatile int*)__null) = 6739; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6740
6741 // Step 7 is a loop.
6742 LoopControl loopInfo(this, StatementKind::YieldStar);
6743 if (!loopInfo.emitLoopHead(this, Nothing())) {
6744 // [stack] NEXT ITER RECEIVED RESUMEKIND
6745 return false;
6746 }
6747
6748 // Step 7.a. Check for Normal completion.
6749 if (!emit1(JSOp::Dup)) {
6750 // [stack] NEXT ITER RECEIVED RESUMEKIND RESUMEKIND
6751 return false;
6752 }
6753 if (!emitPushResumeKind(GeneratorResumeKind::Next)) {
6754 // [stack] NEXT ITER RECEIVED RESUMEKIND RESUMEKIND NORMAL
6755 return false;
6756 }
6757 if (!emit1(JSOp::StrictEq)) {
6758 // [stack] NEXT ITER RECEIVED RESUMEKIND IS_NORMAL
6759 return false;
6760 }
6761
6762 InternalIfEmitter ifKind(this);
6763 if (!ifKind.emitThenElse()) {
6764 // [stack] NEXT ITER RECEIVED RESUMEKIND
6765 return false;
6766 }
6767 {
6768 if (!emit1(JSOp::Pop)) {
6769 // [stack] NEXT ITER RECEIVED
6770 return false;
6771 }
6772
6773 // Step 7.a.i.
6774 // result = iter.next(received)
6775 if (!emit2(JSOp::Unpick, 2)) {
6776 // [stack] RECEIVED NEXT ITER
6777 return false;
6778 }
6779 if (!emit1(JSOp::Dup2)) {
6780 // [stack] RECEIVED NEXT ITER NEXT ITER
6781 return false;
6782 }
6783 if (!emit2(JSOp::Pick, 4)) {
6784 // [stack] NEXT ITER NEXT ITER RECEIVED
6785 return false;
6786 }
6787 if (!emitCall(JSOp::Call, 1, iter)) {
6788 // [stack] NEXT ITER RESULT
6789 return false;
6790 }
6791
6792 // Step 7.a.ii.
6793 if (iterKind == IteratorKind::Async) {
6794 if (!emitAwaitInInnermostScope()) {
6795 // [stack] NEXT ITER RESULT
6796 return false;
6797 }
6798 }
6799
6800 // Step 7.a.iii.
6801 if (!emitCheckIsObj(CheckIsObjectKind::IteratorNext)) {
6802 // [stack] NEXT ITER RESULT
6803 return false;
6804 }
6805
6806 // Bytecode for steps 7.a.iv-vii is emitted after the ifKind if-else because
6807 // it's shared with other branches.
6808 }
6809
6810 // Step 7.b. Check for Throw completion.
6811 if (!ifKind.emitElseIf(Nothing())) {
6812 // [stack] NEXT ITER RECEIVED RESUMEKIND
6813 return false;
6814 }
6815 if (!emit1(JSOp::Dup)) {
6816 // [stack] NEXT ITER RECEIVED RESUMEKIND RESUMEKIND
6817 return false;
6818 }
6819 if (!emitPushResumeKind(GeneratorResumeKind::Throw)) {
6820 // [stack] NEXT ITER RECEIVED RESUMEKIND RESUMEKIND THROW
6821 return false;
6822 }
6823 if (!emit1(JSOp::StrictEq)) {
6824 // [stack] NEXT ITER RECEIVED RESUMEKIND IS_THROW
6825 return false;
6826 }
6827 if (!ifKind.emitThenElse()) {
6828 // [stack] NEXT ITER RECEIVED RESUMEKIND
6829 return false;
6830 }
6831 {
6832 if (!emit1(JSOp::Pop)) {
6833 // [stack] NEXT ITER RECEIVED
6834 return false;
6835 }
6836 // Step 7.b.i.
6837 if (!emitDupAt(1)) {
6838 // [stack] NEXT ITER RECEIVED ITER
6839 return false;
6840 }
6841 if (!emit1(JSOp::Dup)) {
6842 // [stack] NEXT ITER RECEIVED ITER ITER
6843 return false;
6844 }
6845 if (!emitAtomOp(JSOp::GetProp,
6846 TaggedParserAtomIndex::WellKnown::throw_())) {
6847 // [stack] NEXT ITER RECEIVED ITER THROW
6848 return false;
6849 }
6850
6851 // Step 7.b.ii.
6852 InternalIfEmitter ifThrowMethodIsNotDefined(this);
6853 if (!emit1(JSOp::IsNullOrUndefined)) {
6854 // [stack] NEXT ITER RECEIVED ITER THROW NULL-OR-UNDEF
6855 return false;
6856 }
6857
6858 if (!ifThrowMethodIsNotDefined.emitThenElse(
6859 IfEmitter::ConditionKind::Negative)) {
6860 // [stack] NEXT ITER RECEIVED ITER THROW
6861 return false;
6862 }
6863
6864 // Step 7.b.ii.1.
6865 // RESULT = ITER.throw(EXCEPTION)
6866 if (!emit1(JSOp::Swap)) {
6867 // [stack] NEXT ITER RECEIVED THROW ITER
6868 return false;
6869 }
6870 if (!emit2(JSOp::Pick, 2)) {
6871 // [stack] NEXT ITER THROW ITER RECEIVED
6872 return false;
6873 }
6874 if (!emitCall(JSOp::Call, 1, iter)) {
6875 // [stack] NEXT ITER RESULT
6876 return false;
6877 }
6878
6879 // Step 7.b.ii.2.
6880 if (iterKind == IteratorKind::Async) {
6881 if (!emitAwaitInInnermostScope()) {
6882 // [stack] NEXT ITER RESULT
6883 return false;
6884 }
6885 }
6886
6887 // Step 7.b.ii.4.
6888 if (!emitCheckIsObj(CheckIsObjectKind::IteratorThrow)) {
6889 // [stack] NEXT ITER RESULT
6890 return false;
6891 }
6892
6893 // Bytecode for steps 7.b.ii.5-8 is emitted after the ifKind if-else because
6894 // it's shared with other branches.
6895
6896 // Step 7.b.iii.
6897 if (!ifThrowMethodIsNotDefined.emitElse()) {
6898 // [stack] NEXT ITER RECEIVED ITER THROW
6899 return false;
6900 }
6901 if (!emit1(JSOp::Pop)) {
6902 // [stack] NEXT ITER RECEIVED ITER
6903 return false;
6904 }
6905
6906 // Steps 7.b.iii.1-4.
6907 //
6908 // If the iterator does not have a "throw" method, it calls IteratorClose
6909 // and then throws a TypeError.
6910 if (!emitIteratorCloseInInnermostScope(iterKind, CompletionKind::Normal)) {
6911 // [stack] NEXT ITER RECEIVED ITER
6912 return false;
6913 }
6914 // Steps 7.b.iii.5-6.
6915 if (!emit2(JSOp::ThrowMsg, uint8_t(ThrowMsgKind::IteratorNoThrow))) {
6916 // [stack] NEXT ITER RECEIVED ITER
6917 // [stack] # throw
6918 return false;
6919 }
6920
6921 if (!ifThrowMethodIsNotDefined.emitEnd()) {
6922 return false;
6923 }
6924 }
6925
6926 // Step 7.c. It must be a Return completion.
6927 if (!ifKind.emitElse()) {
6928 // [stack] NEXT ITER RECEIVED RESUMEKIND
6929 return false;
6930 }
6931 {
6932 if (!emit1(JSOp::Pop)) {
6933 // [stack] NEXT ITER RECEIVED
6934 return false;
6935 }
6936
6937 // Step 7.c.i.
6938 //
6939 // Call iterator.return() for receiving a "forced return" completion from
6940 // the generator.
6941
6942 // Step 7.c.ii.
6943 //
6944 // Get the "return" method.
6945 if (!emitDupAt(1)) {
6946 // [stack] NEXT ITER RECEIVED ITER
6947 return false;
6948 }
6949 if (!emit1(JSOp::Dup)) {
6950 // [stack] NEXT ITER RECEIVED ITER ITER
6951 return false;
6952 }
6953 if (!emitAtomOp(JSOp::GetProp,
6954 TaggedParserAtomIndex::WellKnown::return_())) {
6955 // [stack] NEXT ITER RECEIVED ITER RET
6956 return false;
6957 }
6958
6959 // Step 7.c.iii.
6960 //
6961 // Do nothing if "return" is undefined or null.
6962 InternalIfEmitter ifReturnMethodIsDefined(this);
6963 if (!emit1(JSOp::IsNullOrUndefined)) {
6964 // [stack] NEXT ITER RECEIVED ITER RET NULL-OR-UNDEF
6965 return false;
6966 }
6967
6968 // Step 7.c.iv.
6969 //
6970 // Call "return" with the argument passed to Generator.prototype.return.
6971 if (!ifReturnMethodIsDefined.emitThenElse(
6972 IfEmitter::ConditionKind::Negative)) {
6973 // [stack] NEXT ITER RECEIVED ITER RET
6974 return false;
6975 }
6976 if (!emit1(JSOp::Swap)) {
6977 // [stack] NEXT ITER RECEIVED RET ITER
6978 return false;
6979 }
6980 if (!emit2(JSOp::Pick, 2)) {
6981 // [stack] NEXT ITER RET ITER RECEIVED
6982 return false;
6983 }
6984 if (needsIteratorResult) {
6985 if (!emitAtomOp(JSOp::GetProp,
6986 TaggedParserAtomIndex::WellKnown::value())) {
6987 // [stack] NEXT ITER RET ITER VAL
6988 return false;
6989 }
6990 }
6991 if (!emitCall(JSOp::Call, 1)) {
6992 // [stack] NEXT ITER RESULT
6993 return false;
6994 }
6995
6996 // Step 7.c.v.
6997 if (iterKind == IteratorKind::Async) {
6998 if (!emitAwaitInInnermostScope()) {
6999 // [stack] NEXT ITER RESULT
7000 return false;
7001 }
7002 }
7003
7004 // Step 7.c.vi.
7005 if (!emitCheckIsObj(CheckIsObjectKind::IteratorReturn)) {
7006 // [stack] NEXT ITER RESULT
7007 return false;
7008 }
7009
7010 // Check if the returned object from iterator.return() is done. If not,
7011 // continue yielding.
7012
7013 // Steps 7.c.vii-viii.
7014 InternalIfEmitter ifReturnDone(this);
7015 if (!emit1(JSOp::Dup)) {
7016 // [stack] NEXT ITER RESULT RESULT
7017 return false;
7018 }
7019 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::done())) {
7020 // [stack] NEXT ITER RESULT DONE
7021 return false;
7022 }
7023 if (!ifReturnDone.emitThenElse()) {
7024 // [stack] NEXT ITER RESULT
7025 return false;
7026 }
7027
7028 // Step 7.c.viii.1.
7029 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::value())) {
7030 // [stack] NEXT ITER VALUE
7031 return false;
7032 }
7033 if (needsIteratorResult) {
7034 if (!emitPrepareIteratorResult()) {
7035 // [stack] NEXT ITER VALUE RESULT
7036 return false;
7037 }
7038 if (!emit1(JSOp::Swap)) {
7039 // [stack] NEXT ITER RESULT VALUE
7040 return false;
7041 }
7042 if (!emitFinishIteratorResult(true)) {
7043 // [stack] NEXT ITER RESULT
7044 return false;
7045 }
7046 }
7047
7048 if (!ifReturnDone.emitElse()) {
7049 // [stack] NEXT ITER RESULT
7050 return false;
7051 }
7052
7053 // Jump to continue label for steps 7.c.ix-x.
7054 if (!emitJump(JSOp::Goto, &loopInfo.continues)) {
7055 // [stack] NEXT ITER RESULT
7056 return false;
7057 }
7058
7059 if (!ifReturnDone.emitEnd()) {
7060 // [stack] NEXT ITER RESULT
7061 return false;
7062 }
7063
7064 // Step 7.c.iii.
7065 if (!ifReturnMethodIsDefined.emitElse()) {
7066 // [stack] NEXT ITER RECEIVED ITER RET
7067 return false;
7068 }
7069 if (!emitPopN(2)) {
7070 // [stack] NEXT ITER RECEIVED
7071 return false;
7072 }
7073 if (iterKind == IteratorKind::Async) {
7074 // Step 7.c.iii.1.
7075 if (!emitAwaitInInnermostScope()) {
7076 // [stack] NEXT ITER RECEIVED
7077 return false;
7078 }
7079 }
7080 if (!ifReturnMethodIsDefined.emitEnd()) {
7081 // [stack] NEXT ITER RECEIVED
7082 return false;
7083 }
7084
7085 // Perform a "forced generator return".
7086 //
7087 // Step 7.c.iii.2.
7088 // Step 7.c.viii.2.
7089 if (!emitGetDotGeneratorInInnermostScope()) {
7090 // [stack] NEXT ITER RESULT GENOBJ
7091 return false;
7092 }
7093 if (!emitPushResumeKind(GeneratorResumeKind::Return)) {
7094 // [stack] NEXT ITER RESULT GENOBJ RESUMEKIND
7095 return false;
7096 }
7097 if (!emit1(JSOp::CheckResumeKind)) {
7098 // [stack] NEXT ITER RESULT GENOBJ RESUMEKIND
7099 return false;
7100 }
7101 }
7102
7103 if (!ifKind.emitEnd()) {
7104 // [stack] NEXT ITER RESULT
7105 return false;
7106 }
7107
7108 // Shared tail for Normal/Throw completions.
7109 //
7110 // Steps 7.a.iv-v.
7111 // Steps 7.b.ii.5-6.
7112 //
7113 // [stack] NEXT ITER RESULT
7114
7115 // if (result.done) break;
7116 if (!emit1(JSOp::Dup)) {
7117 // [stack] NEXT ITER RESULT RESULT
7118 return false;
7119 }
7120 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::done())) {
7121 // [stack] NEXT ITER RESULT DONE
7122 return false;
7123 }
7124 if (!emitJump(JSOp::JumpIfTrue, &loopInfo.breaks)) {
7125 // [stack] NEXT ITER RESULT
7126 return false;
7127 }
7128
7129 // Steps 7.a.vi-vii.
7130 // Steps 7.b.ii.7-8.
7131 // Steps 7.c.ix-x.
7132 if (!loopInfo.emitContinueTarget(this)) {
7133 // [stack] NEXT ITER RESULT
7134 return false;
7135 }
7136 if (iterKind == IteratorKind::Async) {
7137 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::value())) {
7138 // [stack] NEXT ITER RESULT
7139 return false;
7140 }
7141 }
7142 if (!emitGetDotGeneratorInInnermostScope()) {
7143 // [stack] NEXT ITER RESULT GENOBJ
7144 return false;
7145 }
7146 if (!emitYieldOp(JSOp::Yield)) {
7147 // [stack] NEXT ITER RVAL GENOBJ RESUMEKIND
7148 return false;
7149 }
7150 if (!emit1(JSOp::Swap)) {
7151 // [stack] NEXT ITER RVAL RESUMEKIND GENOBJ
7152 return false;
7153 }
7154 if (!emit1(JSOp::Pop)) {
7155 // [stack] NEXT ITER RVAL RESUMEKIND
7156 return false;
7157 }
7158 if (!loopInfo.emitLoopEnd(this, JSOp::Goto, TryNoteKind::Loop)) {
7159 // [stack] NEXT ITER RVAL RESUMEKIND
7160 return false;
7161 }
7162
7163 // Jumps to this point have 3 (instead of 4) values on the stack.
7164 MOZ_ASSERT(bytecodeSection().stackDepth() == startDepth)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bytecodeSection().stackDepth() == startDepth)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(bytecodeSection().stackDepth() == startDepth))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("bytecodeSection().stackDepth() == startDepth"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7164); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == startDepth"
")"); do { *((volatile int*)__null) = 7164; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7165 bytecodeSection().setStackDepth(startDepth - 1);
7166
7167 // [stack] NEXT ITER RESULT
7168
7169 // Step 7.a.v.1.
7170 // Step 7.b.ii.6.a.
7171 //
7172 // result.value
7173 if (!emit2(JSOp::Unpick, 2)) {
7174 // [stack] RESULT NEXT ITER
7175 return false;
7176 }
7177 if (!emitPopN(2)) {
7178 // [stack] RESULT
7179 return false;
7180 }
7181 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::value())) {
7182 // [stack] VALUE
7183 return false;
7184 }
7185
7186 MOZ_ASSERT(bytecodeSection().stackDepth() == startDepth - 3)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bytecodeSection().stackDepth() == startDepth - 3)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(bytecodeSection().stackDepth() == startDepth - 3))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("bytecodeSection().stackDepth() == startDepth - 3"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7186); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == startDepth - 3"
")"); do { *((volatile int*)__null) = 7186; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7187
7188 return true;
7189}
7190
7191bool BytecodeEmitter::emitStatementList(ListNode* stmtList) {
7192 for (ParseNode* stmt : stmtList->contents()) {
7193 if (!emitTree(stmt)) {
7194 return false;
7195 }
7196 }
7197 return true;
7198}
7199
7200bool BytecodeEmitter::emitExpressionStatement(UnaryNode* exprStmt) {
7201 MOZ_ASSERT(exprStmt->isKind(ParseNodeKind::ExpressionStmt))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(exprStmt->isKind(ParseNodeKind::ExpressionStmt))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(exprStmt->isKind(ParseNodeKind::ExpressionStmt)))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("exprStmt->isKind(ParseNodeKind::ExpressionStmt)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7201); AnnotateMozCrashReason("MOZ_ASSERT" "(" "exprStmt->isKind(ParseNodeKind::ExpressionStmt)"
")"); do { *((volatile int*)__null) = 7201; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7202
7203 /*
7204 * Top-level or called-from-a-native JS_Execute/EvaluateScript,
7205 * debugger, and eval frames may need the value of the ultimate
7206 * expression statement as the script's result, despite the fact
7207 * that it appears useless to the compiler.
7208 *
7209 * API users may also set the ReadOnlyCompileOptions::noScriptRval option when
7210 * calling JS_Compile* to suppress JSOp::SetRval.
7211 */
7212 bool wantval = false;
7213 bool useful = false;
7214 if (sc->isTopLevelContext()) {
7215 useful = wantval = !sc->noScriptRval();
7216 }
7217
7218 /* Don't eliminate expressions with side effects. */
7219 ParseNode* expr = exprStmt->kid();
7220 if (!useful) {
7221 if (!checkSideEffects(expr, &useful)) {
7222 return false;
7223 }
7224
7225 /*
7226 * Don't eliminate apparently useless expressions if they are labeled
7227 * expression statements. The startOffset() test catches the case
7228 * where we are nesting in emitTree for a labeled compound statement.
7229 */
7230 if (innermostNestableControl &&
7231 innermostNestableControl->is<LabelControl>() &&
7232 innermostNestableControl->as<LabelControl>().startOffset() >=
7233 bytecodeSection().offset()) {
7234 useful = true;
7235 }
7236 }
7237
7238 if (useful) {
7239 ValueUsage valueUsage =
7240 wantval ? ValueUsage::WantValue : ValueUsage::IgnoreValue;
7241 ExpressionStatementEmitter ese(this, valueUsage);
7242 if (!ese.prepareForExpr(exprStmt->pn_pos.begin)) {
7243 return false;
7244 }
7245 if (!markStepBreakpoint()) {
7246 return false;
7247 }
7248 if (!emitTree(expr, valueUsage)) {
7249 return false;
7250 }
7251 if (!ese.emitEnd()) {
7252 return false;
7253 }
7254 }
7255
7256 return true;
7257}
7258
7259bool BytecodeEmitter::emitDeleteName(UnaryNode* deleteNode) {
7260 MOZ_ASSERT(deleteNode->isKind(ParseNodeKind::DeleteNameExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(deleteNode->isKind(ParseNodeKind::DeleteNameExpr)
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(deleteNode->isKind(ParseNodeKind::DeleteNameExpr)
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"deleteNode->isKind(ParseNodeKind::DeleteNameExpr)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7260); AnnotateMozCrashReason("MOZ_ASSERT" "(" "deleteNode->isKind(ParseNodeKind::DeleteNameExpr)"
")"); do { *((volatile int*)__null) = 7260; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7261
7262 NameNode* nameExpr = &deleteNode->kid()->as<NameNode>();
7263 MOZ_ASSERT(nameExpr->isKind(ParseNodeKind::Name))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(nameExpr->isKind(ParseNodeKind::Name))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(nameExpr->isKind(ParseNodeKind::Name)))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("nameExpr->isKind(ParseNodeKind::Name)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7263); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nameExpr->isKind(ParseNodeKind::Name)"
")"); do { *((volatile int*)__null) = 7263; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7264
7265 return emitAtomOp(JSOp::DelName, nameExpr->atom());
7266}
7267
7268bool BytecodeEmitter::emitDeleteProperty(UnaryNode* deleteNode) {
7269 MOZ_ASSERT(deleteNode->isKind(ParseNodeKind::DeletePropExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(deleteNode->isKind(ParseNodeKind::DeletePropExpr)
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(deleteNode->isKind(ParseNodeKind::DeletePropExpr)
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"deleteNode->isKind(ParseNodeKind::DeletePropExpr)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7269); AnnotateMozCrashReason("MOZ_ASSERT" "(" "deleteNode->isKind(ParseNodeKind::DeletePropExpr)"
")"); do { *((volatile int*)__null) = 7269; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7270
7271 PropertyAccess* propExpr = &deleteNode->kid()->as<PropertyAccess>();
7272 PropOpEmitter poe(this, PropOpEmitter::Kind::Delete,
7273 propExpr->as<PropertyAccess>().isSuper()
7274 ? PropOpEmitter::ObjKind::Super
7275 : PropOpEmitter::ObjKind::Other);
7276
7277 if (!poe.prepareForObj()) {
7278 return false;
7279 }
7280
7281 if (propExpr->isSuper()) {
7282 // The expression |delete super.foo;| has to evaluate |super.foo|, which
7283 // could throw if |this| hasn't yet been set by a |super(...)| call.
7284 auto* base = &propExpr->expression().as<UnaryNode>();
7285 if (!emitGetThisForSuperBase(base)) {
7286 // [stack] THIS
7287 return false;
7288 }
7289 } else {
7290 if (!emitPropLHS(propExpr)) {
7291 // [stack] OBJ
7292 return false;
7293 }
7294 }
7295
7296 if (!poe.emitDelete(propExpr->key().atom())) {
7297 // [stack] # if Super
7298 // [stack] THIS
7299 // [stack] # otherwise
7300 // [stack] SUCCEEDED
7301 return false;
7302 }
7303
7304 return true;
7305}
7306
7307bool BytecodeEmitter::emitDeleteElement(UnaryNode* deleteNode) {
7308 MOZ_ASSERT(deleteNode->isKind(ParseNodeKind::DeleteElemExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(deleteNode->isKind(ParseNodeKind::DeleteElemExpr)
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(deleteNode->isKind(ParseNodeKind::DeleteElemExpr)
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"deleteNode->isKind(ParseNodeKind::DeleteElemExpr)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7308); AnnotateMozCrashReason("MOZ_ASSERT" "(" "deleteNode->isKind(ParseNodeKind::DeleteElemExpr)"
")"); do { *((volatile int*)__null) = 7308; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7309
7310 auto* elemExpr = &deleteNode->kid()->as<PropertyByValue>();
7311 bool isSuper = elemExpr->isSuper();
7312 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"
, 7312); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elemExpr->key().isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 7312; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7313 ElemOpEmitter eoe(
7314 this, ElemOpEmitter::Kind::Delete,
7315 isSuper ? ElemOpEmitter::ObjKind::Super : ElemOpEmitter::ObjKind::Other);
7316
7317 if (!emitElemObjAndKey(elemExpr, eoe)) {
7318 // [stack] # if Super
7319 // [stack] THIS KEY
7320 // [stack] # otherwise
7321 // [stack] OBJ KEY
7322 return false;
7323 }
7324
7325 if (!eoe.emitDelete()) {
7326 // [stack] # if Super
7327 // [stack] THIS
7328 // [stack] # otherwise
7329 // [stack] SUCCEEDED
7330 return false;
7331 }
7332
7333 return true;
7334}
7335
7336bool BytecodeEmitter::emitDeleteExpression(UnaryNode* deleteNode) {
7337 MOZ_ASSERT(deleteNode->isKind(ParseNodeKind::DeleteExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(deleteNode->isKind(ParseNodeKind::DeleteExpr))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(deleteNode->isKind(ParseNodeKind::DeleteExpr)))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("deleteNode->isKind(ParseNodeKind::DeleteExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7337); AnnotateMozCrashReason("MOZ_ASSERT" "(" "deleteNode->isKind(ParseNodeKind::DeleteExpr)"
")"); do { *((volatile int*)__null) = 7337; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7338
7339 ParseNode* expression = deleteNode->kid();
7340
7341 // If useless, just emit JSOp::True; otherwise convert |delete <expr>| to
7342 // effectively |<expr>, true|.
7343 bool useful = false;
7344 if (!checkSideEffects(expression, &useful)) {
7345 return false;
7346 }
7347
7348 if (useful) {
7349 if (!emitTree(expression)) {
7350 return false;
7351 }
7352 if (!emit1(JSOp::Pop)) {
7353 return false;
7354 }
7355 }
7356
7357 return emit1(JSOp::True);
7358}
7359
7360bool BytecodeEmitter::emitDeleteOptionalChain(UnaryNode* deleteNode) {
7361 MOZ_ASSERT(deleteNode->isKind(ParseNodeKind::DeleteOptionalChainExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(deleteNode->isKind(ParseNodeKind::DeleteOptionalChainExpr
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(deleteNode->isKind(ParseNodeKind::DeleteOptionalChainExpr
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("deleteNode->isKind(ParseNodeKind::DeleteOptionalChainExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7361); AnnotateMozCrashReason("MOZ_ASSERT" "(" "deleteNode->isKind(ParseNodeKind::DeleteOptionalChainExpr)"
")"); do { *((volatile int*)__null) = 7361; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7362
7363 OptionalEmitter oe(this, bytecodeSection().stackDepth());
7364
7365 ParseNode* kid = deleteNode->kid();
7366 switch (kid->getKind()) {
7367 case ParseNodeKind::ElemExpr:
7368 case ParseNodeKind::OptionalElemExpr: {
7369 auto* elemExpr = &kid->as<PropertyByValueBase>();
7370 if (!emitDeleteElementInOptChain(elemExpr, oe)) {
7371 // [stack] # If shortcircuit
7372 // [stack] UNDEFINED-OR-NULL
7373 // [stack] # otherwise
7374 // [stack] SUCCEEDED
7375 return false;
7376 }
7377
7378 break;
7379 }
7380 case ParseNodeKind::ArgumentsLength:
7381 case ParseNodeKind::DotExpr:
7382 case ParseNodeKind::OptionalDotExpr: {
7383 auto* propExpr = &kid->as<PropertyAccessBase>();
7384 if (!emitDeletePropertyInOptChain(propExpr, oe)) {
7385 // [stack] # If shortcircuit
7386 // [stack] UNDEFINED-OR-NULL
7387 // [stack] # otherwise
7388 // [stack] SUCCEEDED
7389 return false;
7390 }
7391 break;
7392 }
7393 default:
7394 MOZ_ASSERT_UNREACHABLE("Unrecognized optional delete ParseNodeKind")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"Unrecognized optional delete ParseNodeKind" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7394); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Unrecognized optional delete ParseNodeKind"
")"); do { *((volatile int*)__null) = 7394; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7395 }
7396
7397 if (!oe.emitOptionalJumpTarget(JSOp::True)) {
7398 // [stack] # If shortcircuit
7399 // [stack] TRUE
7400 // [stack] # otherwise
7401 // [stack] SUCCEEDED
7402 return false;
7403 }
7404
7405 return true;
7406}
7407
7408bool BytecodeEmitter::emitDeletePropertyInOptChain(PropertyAccessBase* propExpr,
7409 OptionalEmitter& oe) {
7410 MOZ_ASSERT_IF(propExpr->is<PropertyAccess>(),do { if (propExpr->is<PropertyAccess>()) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(!propExpr
->as<PropertyAccess>().isSuper())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!propExpr->as<PropertyAccess
>().isSuper()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!propExpr->as<PropertyAccess>().isSuper()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7411); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!propExpr->as<PropertyAccess>().isSuper()"
")"); do { *((volatile int*)__null) = 7411; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
7411 !propExpr->as<PropertyAccess>().isSuper())do { if (propExpr->is<PropertyAccess>()) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(!propExpr
->as<PropertyAccess>().isSuper())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!propExpr->as<PropertyAccess
>().isSuper()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!propExpr->as<PropertyAccess>().isSuper()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7411); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!propExpr->as<PropertyAccess>().isSuper()"
")"); do { *((volatile int*)__null) = 7411; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
7412 PropOpEmitter poe(this, PropOpEmitter::Kind::Delete,
7413 PropOpEmitter::ObjKind::Other);
7414
7415 if (!poe.prepareForObj()) {
7416 // [stack]
7417 return false;
7418 }
7419 if (!emitOptionalTree(&propExpr->expression(), oe)) {
7420 // [stack] OBJ
7421 return false;
7422 }
7423 if (propExpr->isKind(ParseNodeKind::OptionalDotExpr)) {
7424 if (!oe.emitJumpShortCircuit()) {
7425 // [stack] # if Jump
7426 // [stack] UNDEFINED-OR-NULL
7427 // [stack] # otherwise
7428 // [stack] OBJ
7429 return false;
7430 }
7431 }
7432
7433 if (!poe.emitDelete(propExpr->key().atom())) {
7434 // [stack] SUCCEEDED
7435 return false;
7436 }
7437
7438 return true;
7439}
7440
7441bool BytecodeEmitter::emitDeleteElementInOptChain(PropertyByValueBase* elemExpr,
7442 OptionalEmitter& oe) {
7443 MOZ_ASSERT_IF(elemExpr->is<PropertyByValue>(),do { if (elemExpr->is<PropertyByValue>()) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(!elemExpr
->as<PropertyByValue>().isSuper())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!elemExpr->as<PropertyByValue
>().isSuper()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!elemExpr->as<PropertyByValue>().isSuper()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7444); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elemExpr->as<PropertyByValue>().isSuper()"
")"); do { *((volatile int*)__null) = 7444; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
7444 !elemExpr->as<PropertyByValue>().isSuper())do { if (elemExpr->is<PropertyByValue>()) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(!elemExpr
->as<PropertyByValue>().isSuper())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!elemExpr->as<PropertyByValue
>().isSuper()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!elemExpr->as<PropertyByValue>().isSuper()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7444); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elemExpr->as<PropertyByValue>().isSuper()"
")"); do { *((volatile int*)__null) = 7444; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
7445 ElemOpEmitter eoe(this, ElemOpEmitter::Kind::Delete,
7446 ElemOpEmitter::ObjKind::Other);
7447
7448 if (!eoe.prepareForObj()) {
7449 // [stack]
7450 return false;
7451 }
7452
7453 if (!emitOptionalTree(&elemExpr->expression(), oe)) {
7454 // [stack] OBJ
7455 return false;
7456 }
7457
7458 if (elemExpr->isKind(ParseNodeKind::OptionalElemExpr)) {
7459 if (!oe.emitJumpShortCircuit()) {
7460 // [stack] # if Jump
7461 // [stack] UNDEFINED-OR-NULL
7462 // [stack] # otherwise
7463 // [stack] OBJ
7464 return false;
7465 }
7466 }
7467
7468 if (!eoe.prepareForKey()) {
7469 // [stack] OBJ
7470 return false;
7471 }
7472
7473 if (!emitTree(&elemExpr->key())) {
7474 // [stack] OBJ KEY
7475 return false;
7476 }
7477
7478 if (!eoe.emitDelete()) {
7479 // [stack] SUCCEEDED
7480 return false;
7481 }
7482
7483 return true;
7484}
7485
7486bool BytecodeEmitter::emitDebugCheckSelfHosted() {
7487 // [stack] CALLEE
7488
7489#ifdef DEBUG1
7490 if (!emit1(JSOp::DebugCheckSelfHosted)) {
7491 // [stack] CALLEE
7492 return false;
7493 }
7494#endif
7495
7496 return true;
7497}
7498
7499bool BytecodeEmitter::emitSelfHostedCallFunction(CallNode* callNode, JSOp op) {
7500 // Special-casing of callFunction to emit bytecode that directly
7501 // invokes the callee with the correct |this| object and arguments.
7502 // callFunction(fun, thisArg, arg0, arg1) thus becomes:
7503 // - emit lookup for fun
7504 // - emit lookup for thisArg
7505 // - emit lookups for arg0, arg1
7506 //
7507 // argc is set to the amount of actually emitted args and the
7508 // emitting of args below is disabled by setting emitArgs to false.
7509 NameNode* calleeNode = &callNode->callee()->as<NameNode>();
7510 ListNode* argsList = callNode->args();
7511
7512 MOZ_ASSERT(argsList->count() >= 2)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(argsList->count() >= 2)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(argsList->count() >= 2
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"argsList->count() >= 2", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7512); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() >= 2"
")"); do { *((volatile int*)__null) = 7512; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7513
7514 MOZ_ASSERT(callNode->callOp() == JSOp::Call)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(callNode->callOp() == JSOp::Call)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(callNode->callOp() == JSOp
::Call))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("callNode->callOp() == JSOp::Call", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7514); AnnotateMozCrashReason("MOZ_ASSERT" "(" "callNode->callOp() == JSOp::Call"
")"); do { *((volatile int*)__null) = 7514; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7515
7516 bool constructing =
7517 calleeNode->name() ==
7518 TaggedParserAtomIndex::WellKnown::constructContentFunction();
7519 ParseNode* funNode = argsList->head();
7520
7521 if (!emitTree(funNode)) {
7522 // [stack] CALLEE
7523 return false;
7524 }
7525
7526#ifdef DEBUG1
7527 MOZ_ASSERT(op == JSOp::Call || op == JSOp::CallContent ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(op == JSOp::Call || op == JSOp::CallContent || op ==
JSOp::NewContent)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(op == JSOp::Call || op == JSOp
::CallContent || op == JSOp::NewContent))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("op == JSOp::Call || op == JSOp::CallContent || op == JSOp::NewContent"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7528); AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::Call || op == JSOp::CallContent || op == JSOp::NewContent"
")"); do { *((volatile int*)__null) = 7528; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7528 op == JSOp::NewContent)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(op == JSOp::Call || op == JSOp::CallContent || op ==
JSOp::NewContent)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(op == JSOp::Call || op == JSOp
::CallContent || op == JSOp::NewContent))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("op == JSOp::Call || op == JSOp::CallContent || op == JSOp::NewContent"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7528); AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::Call || op == JSOp::CallContent || op == JSOp::NewContent"
")"); do { *((volatile int*)__null) = 7528; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7529 if (op == JSOp::Call) {
7530 if (!emitDebugCheckSelfHosted()) {
7531 // [stack] CALLEE
7532 return false;
7533 }
7534 }
7535#endif
7536
7537 ParseNode* thisOrNewTarget = funNode->pn_next;
7538 if (constructing) {
7539 // Save off the new.target value, but here emit a proper |this| for a
7540 // constructing call.
7541 if (!emit1(JSOp::IsConstructing)) {
7542 // [stack] CALLEE IS_CONSTRUCTING
7543 return false;
7544 }
7545 } else {
7546 // It's |this|, emit it.
7547 if (!emitTree(thisOrNewTarget)) {
7548 // [stack] CALLEE THIS
7549 return false;
7550 }
7551 }
7552
7553 for (ParseNode* argpn : argsList->contentsFrom(thisOrNewTarget->pn_next)) {
7554 if (!emitTree(argpn)) {
7555 // [stack] CALLEE ... ARGS...
7556 return false;
7557 }
7558 }
7559
7560 if (constructing) {
7561 if (!emitTree(thisOrNewTarget)) {
7562 // [stack] CALLEE IS_CONSTRUCTING ARGS... NEW.TARGET
7563 return false;
7564 }
7565 }
7566
7567 uint32_t argc = argsList->count() - 2;
7568 if (!emitCall(op, argc)) {
7569 // [stack] RVAL
7570 return false;
7571 }
7572
7573 return true;
7574}
7575
7576bool BytecodeEmitter::emitSelfHostedResumeGenerator(CallNode* callNode) {
7577 ListNode* argsList = callNode->args();
7578
7579 // Syntax: resumeGenerator(gen, value, 'next'|'throw'|'return')
7580 MOZ_ASSERT(argsList->count() == 3)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(argsList->count() == 3)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(argsList->count() == 3)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 3"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7580); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 3"
")"); do { *((volatile int*)__null) = 7580; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7581
7582 ParseNode* genNode = argsList->head();
7583 if (!emitTree(genNode)) {
7584 // [stack] GENERATOR
7585 return false;
7586 }
7587
7588 ParseNode* valNode = genNode->pn_next;
7589 if (!emitTree(valNode)) {
7590 // [stack] GENERATOR VALUE
7591 return false;
7592 }
7593
7594 ParseNode* kindNode = valNode->pn_next;
7595 MOZ_ASSERT(kindNode->isKind(ParseNodeKind::StringExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(kindNode->isKind(ParseNodeKind::StringExpr))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(kindNode->isKind(ParseNodeKind::StringExpr)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("kindNode->isKind(ParseNodeKind::StringExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7595); AnnotateMozCrashReason("MOZ_ASSERT" "(" "kindNode->isKind(ParseNodeKind::StringExpr)"
")"); do { *((volatile int*)__null) = 7595; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7596 GeneratorResumeKind kind =
7597 ParserAtomToResumeKind(kindNode->as<NameNode>().atom());
7598 MOZ_ASSERT(!kindNode->pn_next)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!kindNode->pn_next)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!kindNode->pn_next))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("!kindNode->pn_next"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7598); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!kindNode->pn_next"
")"); do { *((volatile int*)__null) = 7598; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7599
7600 if (!emitPushResumeKind(kind)) {
7601 // [stack] GENERATOR VALUE RESUMEKIND
7602 return false;
7603 }
7604
7605 if (!emit1(JSOp::Resume)) {
7606 // [stack] RVAL
7607 return false;
7608 }
7609
7610 return true;
7611}
7612
7613bool BytecodeEmitter::emitSelfHostedForceInterpreter() {
7614 // JSScript::hasForceInterpreterOp() relies on JSOp::ForceInterpreter being
7615 // the first bytecode op in the script.
7616 MOZ_ASSERT(bytecodeSection().code().empty())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bytecodeSection().code().empty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(bytecodeSection().code().empty
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("bytecodeSection().code().empty()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7616); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().code().empty()"
")"); do { *((volatile int*)__null) = 7616; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7617
7618 if (!emit1(JSOp::ForceInterpreter)) {
7619 return false;
7620 }
7621 if (!emit1(JSOp::Undefined)) {
7622 return false;
7623 }
7624
7625 return true;
7626}
7627
7628bool BytecodeEmitter::emitSelfHostedAllowContentIter(CallNode* callNode) {
7629 ListNode* argsList = callNode->args();
7630
7631 MOZ_ASSERT(argsList->count() == 1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(argsList->count() == 1)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(argsList->count() == 1)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 1"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7631); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1"
")"); do { *((volatile int*)__null) = 7631; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7632
7633 // We're just here as a sentinel. Pass the value through directly.
7634 return emitTree(argsList->head());
7635}
7636
7637bool BytecodeEmitter::emitSelfHostedAllowContentIterWith(CallNode* callNode) {
7638 ListNode* argsList = callNode->args();
7639
7640 MOZ_ASSERT(argsList->count() == 2 || argsList->count() == 3)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(argsList->count() == 2 || argsList->count() ==
3)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(argsList->count() == 2 || argsList->count() ==
3))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("argsList->count() == 2 || argsList->count() == 3", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7640); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2 || argsList->count() == 3"
")"); do { *((volatile int*)__null) = 7640; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7641
7642 // We're just here as a sentinel. Pass the value through directly.
7643 return emitTree(argsList->head());
7644}
7645
7646bool BytecodeEmitter::emitSelfHostedAllowContentIterWithNext(
7647 CallNode* callNode) {
7648 ListNode* argsList = callNode->args();
7649
7650 MOZ_ASSERT(argsList->count() == 2)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(argsList->count() == 2)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(argsList->count() == 2)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 2"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7650); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2"
")"); do { *((volatile int*)__null) = 7650; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7651
7652 // We're just here as a sentinel. Pass the value through directly.
7653 return emitTree(argsList->head());
7654}
7655
7656bool BytecodeEmitter::emitSelfHostedDefineDataProperty(CallNode* callNode) {
7657 ListNode* argsList = callNode->args();
7658
7659 // Only optimize when 3 arguments are passed.
7660 MOZ_ASSERT(argsList->count() == 3)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(argsList->count() == 3)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(argsList->count() == 3)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 3"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7660); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 3"
")"); do { *((volatile int*)__null) = 7660; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7661
7662 ParseNode* objNode = argsList->head();
7663 if (!emitTree(objNode)) {
7664 return false;
7665 }
7666
7667 ParseNode* idNode = objNode->pn_next;
7668 if (!emitTree(idNode)) {
7669 return false;
7670 }
7671
7672 ParseNode* valNode = idNode->pn_next;
7673 if (!emitTree(valNode)) {
7674 return false;
7675 }
7676
7677 // This will leave the object on the stack instead of pushing |undefined|,
7678 // but that's fine because the self-hosted code doesn't use the return
7679 // value.
7680 return emit1(JSOp::InitElem);
7681}
7682
7683bool BytecodeEmitter::emitSelfHostedHasOwn(CallNode* callNode) {
7684 ListNode* argsList = callNode->args();
7685
7686 MOZ_ASSERT(argsList->count() == 2)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(argsList->count() == 2)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(argsList->count() == 2)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 2"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7686); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2"
")"); do { *((volatile int*)__null) = 7686; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7687
7688 ParseNode* idNode = argsList->head();
7689 if (!emitTree(idNode)) {
7690 return false;
7691 }
7692
7693 ParseNode* objNode = idNode->pn_next;
7694 if (!emitTree(objNode)) {
7695 return false;
7696 }
7697
7698 return emit1(JSOp::HasOwn);
7699}
7700
7701bool BytecodeEmitter::emitSelfHostedGetPropertySuper(CallNode* callNode) {
7702 ListNode* argsList = callNode->args();
7703
7704 MOZ_ASSERT(argsList->count() == 3)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(argsList->count() == 3)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(argsList->count() == 3)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 3"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7704); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 3"
")"); do { *((volatile int*)__null) = 7704; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7705
7706 ParseNode* objNode = argsList->head();
7707 ParseNode* idNode = objNode->pn_next;
7708 ParseNode* receiverNode = idNode->pn_next;
7709
7710 if (!emitTree(receiverNode)) {
7711 return false;
7712 }
7713
7714 if (!emitTree(idNode)) {
7715 return false;
7716 }
7717
7718 if (!emitTree(objNode)) {
7719 return false;
7720 }
7721
7722 return emitElemOpBase(JSOp::GetElemSuper);
7723}
7724
7725bool BytecodeEmitter::emitSelfHostedToNumeric(CallNode* callNode) {
7726 ListNode* argsList = callNode->args();
7727
7728 MOZ_ASSERT(argsList->count() == 1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(argsList->count() == 1)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(argsList->count() == 1)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 1"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7728); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1"
")"); do { *((volatile int*)__null) = 7728; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7729
7730 ParseNode* argNode = argsList->head();
7731
7732 if (!emitTree(argNode)) {
7733 return false;
7734 }
7735
7736 return emit1(JSOp::ToNumeric);
7737}
7738
7739bool BytecodeEmitter::emitSelfHostedToString(CallNode* callNode) {
7740 ListNode* argsList = callNode->args();
7741
7742 MOZ_ASSERT(argsList->count() == 1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(argsList->count() == 1)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(argsList->count() == 1)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 1"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7742); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1"
")"); do { *((volatile int*)__null) = 7742; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7743
7744 ParseNode* argNode = argsList->head();
7745
7746 if (!emitTree(argNode)) {
7747 return false;
7748 }
7749
7750 return emit1(JSOp::ToString);
7751}
7752
7753bool BytecodeEmitter::emitSelfHostedIsNullOrUndefined(CallNode* callNode) {
7754 ListNode* argsList = callNode->args();
7755
7756 MOZ_ASSERT(argsList->count() == 1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(argsList->count() == 1)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(argsList->count() == 1)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 1"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7756); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1"
")"); do { *((volatile int*)__null) = 7756; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7757
7758 ParseNode* argNode = argsList->head();
7759
7760 if (!emitTree(argNode)) {
7761 // [stack] ARG
7762 return false;
7763 }
7764 if (!emit1(JSOp::IsNullOrUndefined)) {
7765 // [stack] ARG IS_NULL_OR_UNDEF
7766 return false;
7767 }
7768 if (!emit1(JSOp::Swap)) {
7769 // [stack] IS_NULL_OR_UNDEF ARG
7770 return false;
7771 }
7772 if (!emit1(JSOp::Pop)) {
7773 // [stack] IS_NULL_OR_UNDEF
7774 return false;
7775 }
7776 return true;
7777}
7778
7779bool BytecodeEmitter::emitSelfHostedIteratorClose(CallNode* callNode) {
7780 ListNode* argsList = callNode->args();
7781 MOZ_ASSERT(argsList->count() == 1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(argsList->count() == 1)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(argsList->count() == 1)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 1"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7781); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1"
")"); do { *((volatile int*)__null) = 7781; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7782
7783 ParseNode* argNode = argsList->head();
7784 if (!emitTree(argNode)) {
7785 // [stack] ARG
7786 return false;
7787 }
7788
7789 if (!emit2(JSOp::CloseIter, uint8_t(CompletionKind::Normal))) {
7790 // [stack]
7791 return false;
7792 }
7793
7794 // This is still a call node, so we must generate a stack value.
7795 if (!emit1(JSOp::Undefined)) {
7796 // [stack] RVAL
7797 return false;
7798 }
7799
7800 return true;
7801}
7802
7803bool BytecodeEmitter::emitSelfHostedGetBuiltinConstructorOrPrototype(
7804 CallNode* callNode, bool isConstructor) {
7805 ListNode* argsList = callNode->args();
7806
7807 MOZ_ASSERT(argsList->count() == 1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(argsList->count() == 1)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(argsList->count() == 1)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 1"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7807); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1"
")"); do { *((volatile int*)__null) = 7807; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7808
7809 ParseNode* argNode = argsList->head();
7810
7811 if (!argNode->isKind(ParseNodeKind::StringExpr)) {
7812 reportError(callNode, JSMSG_UNEXPECTED_TYPE, "built-in name",
7813 "not a string constant");
7814 return false;
7815 }
7816
7817 auto name = argNode->as<NameNode>().atom();
7818
7819 BuiltinObjectKind kind;
7820 if (isConstructor) {
7821 kind = BuiltinConstructorForName(name);
7822 } else {
7823 kind = BuiltinPrototypeForName(name);
7824 }
7825
7826 if (kind == BuiltinObjectKind::None) {
7827 reportError(callNode, JSMSG_UNEXPECTED_TYPE, "built-in name",
7828 "not a valid built-in");
7829 return false;
7830 }
7831
7832 return emitBuiltinObject(kind);
7833}
7834
7835bool BytecodeEmitter::emitSelfHostedGetBuiltinConstructor(CallNode* callNode) {
7836 return emitSelfHostedGetBuiltinConstructorOrPrototype(
7837 callNode, /* isConstructor = */ true);
7838}
7839
7840bool BytecodeEmitter::emitSelfHostedGetBuiltinPrototype(CallNode* callNode) {
7841 return emitSelfHostedGetBuiltinConstructorOrPrototype(
7842 callNode, /* isConstructor = */ false);
7843}
7844
7845JS::SymbolCode ParserAtomToSymbolCode(TaggedParserAtomIndex atom) {
7846 // NOTE: This is a linear search, but the set of entries is quite small and
7847 // this is only used for initial self-hosted parse.
7848#define MATCH_WELL_KNOWN_SYMBOL(NAME) \
7849 if (atom == TaggedParserAtomIndex::WellKnown::NAME()) { \
7850 return JS::SymbolCode::NAME; \
7851 }
7852 JS_FOR_EACH_WELL_KNOWN_SYMBOL(MATCH_WELL_KNOWN_SYMBOL)MATCH_WELL_KNOWN_SYMBOL(isConcatSpreadable) MATCH_WELL_KNOWN_SYMBOL
(iterator) MATCH_WELL_KNOWN_SYMBOL(match) MATCH_WELL_KNOWN_SYMBOL
(replace) MATCH_WELL_KNOWN_SYMBOL(search) MATCH_WELL_KNOWN_SYMBOL
(species) MATCH_WELL_KNOWN_SYMBOL(hasInstance) MATCH_WELL_KNOWN_SYMBOL
(split) MATCH_WELL_KNOWN_SYMBOL(toPrimitive) MATCH_WELL_KNOWN_SYMBOL
(toStringTag) MATCH_WELL_KNOWN_SYMBOL(unscopables) MATCH_WELL_KNOWN_SYMBOL
(asyncIterator) MATCH_WELL_KNOWN_SYMBOL(matchAll) MATCH_WELL_KNOWN_SYMBOL
(dispose) MATCH_WELL_KNOWN_SYMBOL(asyncDispose)
7853#undef MATCH_WELL_KNOWN_SYMBOL
7854
7855 return JS::SymbolCode::Limit;
7856}
7857
7858bool BytecodeEmitter::emitSelfHostedGetBuiltinSymbol(CallNode* callNode) {
7859 ListNode* argsList = callNode->args();
7860
7861 MOZ_ASSERT(argsList->count() == 1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(argsList->count() == 1)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(argsList->count() == 1)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 1"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7861); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1"
")"); do { *((volatile int*)__null) = 7861; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7862
7863 ParseNode* argNode = argsList->head();
7864
7865 if (!argNode->isKind(ParseNodeKind::StringExpr)) {
7866 reportError(callNode, JSMSG_UNEXPECTED_TYPE, "built-in name",
7867 "not a string constant");
7868 return false;
7869 }
7870
7871 auto name = argNode->as<NameNode>().atom();
7872
7873 JS::SymbolCode code = ParserAtomToSymbolCode(name);
7874 if (code == JS::SymbolCode::Limit) {
7875 reportError(callNode, JSMSG_UNEXPECTED_TYPE, "built-in name",
7876 "not a valid built-in");
7877 return false;
7878 }
7879
7880 return emit2(JSOp::Symbol, uint8_t(code));
7881}
7882
7883bool BytecodeEmitter::emitSelfHostedArgumentsLength(CallNode* callNode) {
7884 MOZ_ASSERT(!sc->asFunctionBox()->needsArgsObj())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!sc->asFunctionBox()->needsArgsObj())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!sc->asFunctionBox()->needsArgsObj()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!sc->asFunctionBox()->needsArgsObj()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7884); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sc->asFunctionBox()->needsArgsObj()"
")"); do { *((volatile int*)__null) = 7884; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7885 sc->asFunctionBox()->setUsesArgumentsIntrinsics();
7886
7887 MOZ_ASSERT(callNode->args()->count() == 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(callNode->args()->count() == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(callNode->args()->count
() == 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("callNode->args()->count() == 0", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7887); AnnotateMozCrashReason("MOZ_ASSERT" "(" "callNode->args()->count() == 0"
")"); do { *((volatile int*)__null) = 7887; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7888
7889 return emit1(JSOp::ArgumentsLength);
7890}
7891
7892bool BytecodeEmitter::emitSelfHostedGetArgument(CallNode* callNode) {
7893 MOZ_ASSERT(!sc->asFunctionBox()->needsArgsObj())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!sc->asFunctionBox()->needsArgsObj())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!sc->asFunctionBox()->needsArgsObj()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!sc->asFunctionBox()->needsArgsObj()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7893); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sc->asFunctionBox()->needsArgsObj()"
")"); do { *((volatile int*)__null) = 7893; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7894 sc->asFunctionBox()->setUsesArgumentsIntrinsics();
7895
7896 ListNode* argsList = callNode->args();
7897 MOZ_ASSERT(argsList->count() == 1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(argsList->count() == 1)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(argsList->count() == 1)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 1"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7897); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1"
")"); do { *((volatile int*)__null) = 7897; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7898
7899 ParseNode* argNode = argsList->head();
7900 if (!emitTree(argNode)) {
7901 return false;
7902 }
7903
7904 return emit1(JSOp::GetActualArg);
7905}
7906
7907#ifdef DEBUG1
7908void BytecodeEmitter::assertSelfHostedExpectedTopLevel(ParseNode* node) {
7909 // The function argument is expected to be a simple binding/function name.
7910 // Eg. `function foo() { }; SpecialIntrinsic(foo)`
7911 MOZ_ASSERT(node->isKind(ParseNodeKind::Name),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(node->isKind(ParseNodeKind::Name))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(node->isKind(ParseNodeKind
::Name)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("node->isKind(ParseNodeKind::Name)" " (" "argument must be a function name"
")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7912); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::Name)"
") (" "argument must be a function name" ")"); do { *((volatile
int*)__null) = 7912; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
7912 "argument must be a function name")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(node->isKind(ParseNodeKind::Name))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(node->isKind(ParseNodeKind
::Name)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("node->isKind(ParseNodeKind::Name)" " (" "argument must be a function name"
")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7912); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::Name)"
") (" "argument must be a function name" ")"); do { *((volatile
int*)__null) = 7912; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
7913 TaggedParserAtomIndex targetName = node->as<NameNode>().name();
7914
7915 // The special intrinsics must follow the target functions definition. A
7916 // simple assert is fine here since any hoisted function will cause a non-null
7917 // value to be set here.
7918 MOZ_ASSERT(prevSelfHostedTopLevelFunction)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(prevSelfHostedTopLevelFunction)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(prevSelfHostedTopLevelFunction
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"prevSelfHostedTopLevelFunction", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7918); AnnotateMozCrashReason("MOZ_ASSERT" "(" "prevSelfHostedTopLevelFunction"
")"); do { *((volatile int*)__null) = 7918; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7919
7920 // The target function must match the most recently defined top-level
7921 // self-hosted function.
7922 MOZ_ASSERT(prevSelfHostedTopLevelFunction->explicitName() == targetName,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(prevSelfHostedTopLevelFunction->explicitName() ==
targetName)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(prevSelfHostedTopLevelFunction->
explicitName() == targetName))), 0))) { do { } while (false);
MOZ_ReportAssertionFailure("prevSelfHostedTopLevelFunction->explicitName() == targetName"
" (" "selfhost decorator must immediately follow target function"
")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7923); AnnotateMozCrashReason("MOZ_ASSERT" "(" "prevSelfHostedTopLevelFunction->explicitName() == targetName"
") (" "selfhost decorator must immediately follow target function"
")"); do { *((volatile int*)__null) = 7923; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7923 "selfhost decorator must immediately follow target function")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(prevSelfHostedTopLevelFunction->explicitName() ==
targetName)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(prevSelfHostedTopLevelFunction->
explicitName() == targetName))), 0))) { do { } while (false);
MOZ_ReportAssertionFailure("prevSelfHostedTopLevelFunction->explicitName() == targetName"
" (" "selfhost decorator must immediately follow target function"
")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7923); AnnotateMozCrashReason("MOZ_ASSERT" "(" "prevSelfHostedTopLevelFunction->explicitName() == targetName"
") (" "selfhost decorator must immediately follow target function"
")"); do { *((volatile int*)__null) = 7923; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7924}
7925#endif
7926
7927bool BytecodeEmitter::emitSelfHostedSetIsInlinableLargeFunction(
7928 CallNode* callNode) {
7929#ifdef DEBUG1
7930 ListNode* argsList = callNode->args();
7931
7932 MOZ_ASSERT(argsList->count() == 1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(argsList->count() == 1)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(argsList->count() == 1)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 1"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7932); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1"
")"); do { *((volatile int*)__null) = 7932; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7933
7934 assertSelfHostedExpectedTopLevel(argsList->head());
7935#endif
7936
7937 MOZ_ASSERT(prevSelfHostedTopLevelFunction->isInitialCompilation)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(prevSelfHostedTopLevelFunction->isInitialCompilation
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(prevSelfHostedTopLevelFunction->isInitialCompilation
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"prevSelfHostedTopLevelFunction->isInitialCompilation", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7937); AnnotateMozCrashReason("MOZ_ASSERT" "(" "prevSelfHostedTopLevelFunction->isInitialCompilation"
")"); do { *((volatile int*)__null) = 7937; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7938 prevSelfHostedTopLevelFunction->setIsInlinableLargeFunction();
7939
7940 // This is still a call node, so we must generate a stack value.
7941 return emit1(JSOp::Undefined);
7942}
7943
7944bool BytecodeEmitter::emitSelfHostedSetCanonicalName(CallNode* callNode) {
7945 ListNode* argsList = callNode->args();
7946
7947 MOZ_ASSERT(argsList->count() == 2)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(argsList->count() == 2)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(argsList->count() == 2)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 2"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7947); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2"
")"); do { *((volatile int*)__null) = 7947; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7948
7949#ifdef DEBUG1
7950 assertSelfHostedExpectedTopLevel(argsList->head());
7951#endif
7952
7953 ParseNode* nameNode = argsList->last();
7954 MOZ_ASSERT(nameNode->isKind(ParseNodeKind::StringExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(nameNode->isKind(ParseNodeKind::StringExpr))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(nameNode->isKind(ParseNodeKind::StringExpr)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("nameNode->isKind(ParseNodeKind::StringExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7954); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nameNode->isKind(ParseNodeKind::StringExpr)"
")"); do { *((volatile int*)__null) = 7954; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7955 TaggedParserAtomIndex specName = nameNode->as<NameNode>().atom();
7956 // Canonical name must be atomized.
7957 compilationState.parserAtoms.markUsedByStencil(specName,
7958 ParserAtom::Atomize::Yes);
7959
7960 // Store the canonical name for instantiation.
7961 prevSelfHostedTopLevelFunction->functionStencil().setSelfHostedCanonicalName(
7962 specName);
7963
7964 return emit1(JSOp::Undefined);
7965}
7966
7967#ifdef DEBUG1
7968void BytecodeEmitter::assertSelfHostedUnsafeGetReservedSlot(
7969 ListNode* argsList) {
7970 MOZ_ASSERT(argsList->count() == 2)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(argsList->count() == 2)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(argsList->count() == 2)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 2"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7970); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2"
")"); do { *((volatile int*)__null) = 7970; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7971
7972 ParseNode* objNode = argsList->head();
7973 ParseNode* slotNode = objNode->pn_next;
7974
7975 // Ensure that the slot argument is fixed, this is required by the JITs.
7976 MOZ_ASSERT(slotNode->isKind(ParseNodeKind::NumberExpr),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(slotNode->isKind(ParseNodeKind::NumberExpr))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(slotNode->isKind(ParseNodeKind::NumberExpr)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("slotNode->isKind(ParseNodeKind::NumberExpr)"
" (" "slot argument must be a constant" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7977); AnnotateMozCrashReason("MOZ_ASSERT" "(" "slotNode->isKind(ParseNodeKind::NumberExpr)"
") (" "slot argument must be a constant" ")"); do { *((volatile
int*)__null) = 7977; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
7977 "slot argument must be a constant")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(slotNode->isKind(ParseNodeKind::NumberExpr))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(slotNode->isKind(ParseNodeKind::NumberExpr)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("slotNode->isKind(ParseNodeKind::NumberExpr)"
" (" "slot argument must be a constant" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7977); AnnotateMozCrashReason("MOZ_ASSERT" "(" "slotNode->isKind(ParseNodeKind::NumberExpr)"
") (" "slot argument must be a constant" ")"); do { *((volatile
int*)__null) = 7977; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
7978}
7979
7980void BytecodeEmitter::assertSelfHostedUnsafeSetReservedSlot(
7981 ListNode* argsList) {
7982 MOZ_ASSERT(argsList->count() == 3)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(argsList->count() == 3)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(argsList->count() == 3)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 3"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7982); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 3"
")"); do { *((volatile int*)__null) = 7982; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7983
7984 ParseNode* objNode = argsList->head();
7985 ParseNode* slotNode = objNode->pn_next;
7986
7987 // Ensure that the slot argument is fixed, this is required by the JITs.
7988 MOZ_ASSERT(slotNode->isKind(ParseNodeKind::NumberExpr),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(slotNode->isKind(ParseNodeKind::NumberExpr))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(slotNode->isKind(ParseNodeKind::NumberExpr)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("slotNode->isKind(ParseNodeKind::NumberExpr)"
" (" "slot argument must be a constant" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7989); AnnotateMozCrashReason("MOZ_ASSERT" "(" "slotNode->isKind(ParseNodeKind::NumberExpr)"
") (" "slot argument must be a constant" ")"); do { *((volatile
int*)__null) = 7989; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
7989 "slot argument must be a constant")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(slotNode->isKind(ParseNodeKind::NumberExpr))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(slotNode->isKind(ParseNodeKind::NumberExpr)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("slotNode->isKind(ParseNodeKind::NumberExpr)"
" (" "slot argument must be a constant" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7989); AnnotateMozCrashReason("MOZ_ASSERT" "(" "slotNode->isKind(ParseNodeKind::NumberExpr)"
") (" "slot argument must be a constant" ")"); do { *((volatile
int*)__null) = 7989; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
7990}
7991#endif
7992
7993/* A version of emitCalleeAndThis for the optional cases:
7994 * * a?.()
7995 * * a?.b()
7996 * * a?.["b"]()
7997 * * (a?.b)()
7998 * * a?.#b()
7999 *
8000 * See emitCallOrNew and emitOptionalCall for more context.
8001 */
8002bool BytecodeEmitter::emitOptionalCalleeAndThis(ParseNode* callee,
8003 CallNode* call,
8004 CallOrNewEmitter& cone,
8005 OptionalEmitter& oe) {
8006 AutoCheckRecursionLimit recursion(fc);
8007 if (!recursion.check(fc)) {
8008 return false;
8009 }
8010
8011 switch (ParseNodeKind kind = callee->getKind()) {
8012 case ParseNodeKind::Name: {
8013 auto name = callee->as<NameNode>().name();
8014 if (!cone.emitNameCallee(name)) {
8015 // [stack] CALLEE THIS
8016 return false;
8017 }
8018 break;
8019 }
8020
8021 case ParseNodeKind::OptionalDotExpr: {
8022 MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(emitterMode != BytecodeEmitter::SelfHosting)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(emitterMode != BytecodeEmitter::SelfHosting))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("emitterMode != BytecodeEmitter::SelfHosting"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8022); AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode != BytecodeEmitter::SelfHosting"
")"); do { *((volatile int*)__null) = 8022; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8023 OptionalPropertyAccess* prop = &callee->as<OptionalPropertyAccess>();
8024 bool isSuper = false;
8025
8026 PropOpEmitter& poe = cone.prepareForPropCallee(isSuper);
8027 if (!emitOptionalDotExpression(prop, poe, isSuper, oe)) {
8028 // [stack] CALLEE THIS
8029 return false;
8030 }
8031 break;
8032 }
8033 case ParseNodeKind::ArgumentsLength:
8034 case ParseNodeKind::DotExpr: {
8035 MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(emitterMode != BytecodeEmitter::SelfHosting)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(emitterMode != BytecodeEmitter::SelfHosting))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("emitterMode != BytecodeEmitter::SelfHosting"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8035); AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode != BytecodeEmitter::SelfHosting"
")"); do { *((volatile int*)__null) = 8035; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8036 PropertyAccess* prop = &callee->as<PropertyAccess>();
8037 bool isSuper = prop->isSuper();
8038
8039 PropOpEmitter& poe = cone.prepareForPropCallee(isSuper);
8040 if (!emitOptionalDotExpression(prop, poe, isSuper, oe)) {
8041 // [stack] CALLEE THIS
8042 return false;
8043 }
8044 break;
8045 }
8046
8047 case ParseNodeKind::OptionalElemExpr: {
8048 OptionalPropertyByValue* elem = &callee->as<OptionalPropertyByValue>();
8049 bool isSuper = false;
8050 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"
, 8050); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 8050; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8051 ElemOpEmitter& eoe = cone.prepareForElemCallee(isSuper);
8052 if (!emitOptionalElemExpression(elem, eoe, isSuper, oe)) {
8053 // [stack] CALLEE THIS
8054 return false;
8055 }
8056 break;
8057 }
8058 case ParseNodeKind::ElemExpr: {
8059 PropertyByValue* elem = &callee->as<PropertyByValue>();
8060 bool isSuper = elem->isSuper();
8061 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"
, 8061); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 8061; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8062 ElemOpEmitter& eoe = cone.prepareForElemCallee(isSuper);
8063 if (!emitOptionalElemExpression(elem, eoe, isSuper, oe)) {
8064 // [stack] CALLEE THIS
8065 return false;
8066 }
8067 break;
8068 }
8069
8070 case ParseNodeKind::PrivateMemberExpr:
8071 case ParseNodeKind::OptionalPrivateMemberExpr: {
8072 PrivateMemberAccessBase* privateExpr =
8073 &callee->as<PrivateMemberAccessBase>();
8074 PrivateOpEmitter& xoe =
8075 cone.prepareForPrivateCallee(privateExpr->privateName().name());
8076 if (!emitOptionalPrivateExpression(privateExpr, xoe, oe)) {
8077 // [stack] CALLEE THIS
8078 return false;
8079 }
8080 break;
8081 }
8082
8083 case ParseNodeKind::Function:
8084 if (!cone.prepareForFunctionCallee()) {
8085 return false;
8086 }
8087 if (!emitOptionalTree(callee, oe)) {
8088 // [stack] CALLEE
8089 return false;
8090 }
8091 break;
8092
8093 case ParseNodeKind::OptionalChain: {
8094 return emitCalleeAndThisForOptionalChain(&callee->as<UnaryNode>(), call,
8095 cone);
8096 }
8097
8098 default:
8099 MOZ_RELEASE_ASSERT(kind != ParseNodeKind::SuperBase)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(kind != ParseNodeKind::SuperBase)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(kind != ParseNodeKind::SuperBase
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"kind != ParseNodeKind::SuperBase", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8099); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "kind != ParseNodeKind::SuperBase"
")"); do { *((volatile int*)__null) = 8099; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8100
8101 if (!cone.prepareForOtherCallee()) {
8102 return false;
8103 }
8104 if (!emitOptionalTree(callee, oe)) {
8105 // [stack] CALLEE
8106 return false;
8107 }
8108 break;
8109 }
8110
8111 if (!cone.emitThis()) {
8112 // [stack] CALLEE THIS
8113 return false;
8114 }
8115
8116 return true;
8117}
8118
8119bool BytecodeEmitter::emitCalleeAndThis(ParseNode* callee, CallNode* maybeCall,
8120 CallOrNewEmitter& cone) {
8121 MOZ_ASSERT_IF(maybeCall, maybeCall->callee() == callee)do { if (maybeCall) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(maybeCall->callee() == callee)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(maybeCall->callee() == callee
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"maybeCall->callee() == callee", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8121); AnnotateMozCrashReason("MOZ_ASSERT" "(" "maybeCall->callee() == callee"
")"); do { *((volatile int*)__null) = 8121; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
8122
8123 switch (callee->getKind()) {
8124 case ParseNodeKind::Name: {
8125 auto name = callee->as<NameNode>().name();
8126 if (!cone.emitNameCallee(name)) {
8127 // [stack] CALLEE THIS?
8128 return false;
8129 }
8130 break;
8131 }
8132 case ParseNodeKind::ArgumentsLength:
8133 case ParseNodeKind::DotExpr: {
8134 MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(emitterMode != BytecodeEmitter::SelfHosting)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(emitterMode != BytecodeEmitter::SelfHosting))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("emitterMode != BytecodeEmitter::SelfHosting"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8134); AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode != BytecodeEmitter::SelfHosting"
")"); do { *((volatile int*)__null) = 8134; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8135 PropertyAccess* prop = &callee->as<PropertyAccess>();
8136 bool isSuper = prop->isSuper();
8137
8138 PropOpEmitter& poe = cone.prepareForPropCallee(isSuper);
8139 if (!poe.prepareForObj()) {
8140 return false;
8141 }
8142 if (isSuper) {
8143 UnaryNode* base = &prop->expression().as<UnaryNode>();
8144 if (!emitGetThisForSuperBase(base)) {
8145 // [stack] THIS
8146 return false;
8147 }
8148 } else {
8149 if (!emitPropLHS(prop)) {
8150 // [stack] OBJ
8151 return false;
8152 }
8153 }
8154 if (!poe.emitGet(prop->key().atom())) {
8155 // [stack] CALLEE THIS?
8156 return false;
8157 }
8158
8159 break;
8160 }
8161 case ParseNodeKind::ElemExpr: {
8162 MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(emitterMode != BytecodeEmitter::SelfHosting)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(emitterMode != BytecodeEmitter::SelfHosting))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("emitterMode != BytecodeEmitter::SelfHosting"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8162); AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode != BytecodeEmitter::SelfHosting"
")"); do { *((volatile int*)__null) = 8162; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8163 PropertyByValue* elem = &callee->as<PropertyByValue>();
8164 bool isSuper = elem->isSuper();
8165 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"
, 8165); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 8165; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8166 ElemOpEmitter& eoe = cone.prepareForElemCallee(isSuper);
8167 if (!emitElemObjAndKey(elem, eoe)) {
8168 // [stack] # if Super
8169 // [stack] THIS? THIS KEY
8170 // [stack] # otherwise
8171 // [stack] OBJ? OBJ KEY
8172 return false;
8173 }
8174 if (!eoe.emitGet()) {
8175 // [stack] CALLEE THIS?
8176 return false;
8177 }
8178
8179 break;
8180 }
8181 case ParseNodeKind::PrivateMemberExpr: {
8182 MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(emitterMode != BytecodeEmitter::SelfHosting)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(emitterMode != BytecodeEmitter::SelfHosting))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("emitterMode != BytecodeEmitter::SelfHosting"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8182); AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode != BytecodeEmitter::SelfHosting"
")"); do { *((volatile int*)__null) = 8182; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8183 PrivateMemberAccessBase* privateExpr =
8184 &callee->as<PrivateMemberAccessBase>();
8185 PrivateOpEmitter& xoe =
8186 cone.prepareForPrivateCallee(privateExpr->privateName().name());
8187 if (!emitTree(&privateExpr->expression())) {
8188 // [stack] OBJ
8189 return false;
8190 }
8191 if (!xoe.emitReference()) {
8192 // [stack] OBJ NAME
8193 return false;
8194 }
8195 if (!xoe.emitGetForCallOrNew()) {
8196 // [stack] CALLEE THIS
8197 return false;
8198 }
8199
8200 break;
8201 }
8202 case ParseNodeKind::Function:
8203 if (!cone.prepareForFunctionCallee()) {
8204 return false;
8205 }
8206 if (!emitTree(callee)) {
8207 // [stack] CALLEE
8208 return false;
8209 }
8210 break;
8211 case ParseNodeKind::SuperBase:
8212 MOZ_ASSERT(maybeCall)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(maybeCall)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(maybeCall))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("maybeCall", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8212); AnnotateMozCrashReason("MOZ_ASSERT" "(" "maybeCall" ")"
); do { *((volatile int*)__null) = 8212; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8213 MOZ_ASSERT(maybeCall->isKind(ParseNodeKind::SuperCallExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(maybeCall->isKind(ParseNodeKind::SuperCallExpr))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(maybeCall->isKind(ParseNodeKind::SuperCallExpr)))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("maybeCall->isKind(ParseNodeKind::SuperCallExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8213); AnnotateMozCrashReason("MOZ_ASSERT" "(" "maybeCall->isKind(ParseNodeKind::SuperCallExpr)"
")"); do { *((volatile int*)__null) = 8213; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8214 MOZ_ASSERT(callee->isKind(ParseNodeKind::SuperBase))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(callee->isKind(ParseNodeKind::SuperBase))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(callee->isKind(ParseNodeKind::SuperBase)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("callee->isKind(ParseNodeKind::SuperBase)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8214); AnnotateMozCrashReason("MOZ_ASSERT" "(" "callee->isKind(ParseNodeKind::SuperBase)"
")"); do { *((volatile int*)__null) = 8214; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8215 if (!cone.emitSuperCallee()) {
8216 // [stack] CALLEE IsConstructing
8217 return false;
8218 }
8219 break;
8220 case ParseNodeKind::OptionalChain: {
8221 MOZ_ASSERT(maybeCall)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(maybeCall)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(maybeCall))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("maybeCall", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8221); AnnotateMozCrashReason("MOZ_ASSERT" "(" "maybeCall" ")"
); do { *((volatile int*)__null) = 8221; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8222 return emitCalleeAndThisForOptionalChain(&callee->as<UnaryNode>(),
8223 maybeCall, cone);
8224 }
8225 default:
8226 if (!cone.prepareForOtherCallee()) {
8227 return false;
8228 }
8229 if (!emitTree(callee)) {
8230 return false;
8231 }
8232 break;
8233 }
8234
8235 if (!cone.emitThis()) {
8236 // [stack] CALLEE THIS
8237 return false;
8238 }
8239
8240 return true;
8241}
8242
8243ParseNode* BytecodeEmitter::getCoordNode(ParseNode* callNode,
8244 ParseNode* calleeNode, JSOp op,
8245 ListNode* argsList) const {
8246 ParseNode* coordNode = callNode;
8247 if (op == JSOp::Call || op == JSOp::SpreadCall) {
8248 // Default to using the location of the `(` itself.
8249 // obj[expr]() // expression
8250 // ^ // column coord
8251 coordNode = argsList;
8252
8253 switch (calleeNode->getKind()) {
8254 case ParseNodeKind::ArgumentsLength:
8255 case ParseNodeKind::DotExpr:
8256 // Use the position of a property access identifier.
8257 //
8258 // obj().aprop() // expression
8259 // ^ // column coord
8260 //
8261 // Note: Because of the constant folding logic in FoldElement,
8262 // this case also applies for constant string properties.
8263 //
8264 // obj()['aprop']() // expression
8265 // ^ // column coord
8266 coordNode = &calleeNode->as<PropertyAccess>().key();
8267 break;
8268 case ParseNodeKind::Name: {
8269 // Use the start of callee name unless it is at a separator
8270 // or has no args.
8271 //
8272 // 2 + obj() // expression
8273 // ^ // column coord
8274 //
8275 if (argsList->empty() ||
8276 !bytecodeSection().atSeparator(calleeNode->pn_pos.begin)) {
8277 // Use the start of callee names.
8278 coordNode = calleeNode;
8279 }
8280 break;
8281 }
8282
8283 default:
8284 break;
8285 }
8286 }
8287 return coordNode;
8288}
8289
8290bool BytecodeEmitter::emitArguments(ListNode* argsList, bool isCall,
8291 bool isSpread, CallOrNewEmitter& cone) {
8292 uint32_t argc = argsList->count();
8293 if (argc >= ARGC_LIMIT) {
8294 reportError(argsList,
8295 isCall ? JSMSG_TOO_MANY_FUN_ARGS : JSMSG_TOO_MANY_CON_ARGS);
8296 return false;
8297 }
8298 if (!isSpread) {
8299 if (!cone.prepareForNonSpreadArguments()) {
8300 // [stack] CALLEE THIS
8301 return false;
8302 }
8303 for (ParseNode* arg : argsList->contents()) {
8304 if (!updateSourceCoordNotesIfNonLiteral(arg)) {
8305 return false;
8306 }
8307 if (!emitTree(arg)) {
8308 // [stack] CALLEE THIS ARG*
8309 return false;
8310 }
8311 }
8312 } else if (cone.wantSpreadOperand()) {
8313 auto* spreadNode = &argsList->head()->as<UnaryNode>();
8314 if (!updateSourceCoordNotesIfNonLiteral(spreadNode->kid())) {
8315 return false;
8316 }
8317 if (!emitTree(spreadNode->kid())) {
8318 // [stack] CALLEE THIS ARG0
8319 return false;
8320 }
8321
8322 if (!cone.emitSpreadArgumentsTest()) {
8323 // [stack] CALLEE THIS ARG0
8324 return false;
8325 }
8326
8327 if (cone.wantSpreadIteration()) {
8328 if (!emitSpreadIntoArray(spreadNode)) {
8329 // [stack] CALLEE THIS ARR
8330 return false;
8331 }
8332 }
8333
8334 if (!cone.emitSpreadArgumentsTestEnd()) {
8335 // [stack] CALLEE THIS ARR
8336 return false;
8337 }
8338 } else {
8339 if (!cone.prepareForSpreadArguments()) {
8340 // [stack] CALLEE THIS
8341 return false;
8342 }
8343 if (!emitArray(argsList)) {
8344 // [stack] CALLEE THIS ARR
8345 return false;
8346 }
8347 }
8348
8349 return true;
8350}
8351
8352bool BytecodeEmitter::emitOptionalCall(CallNode* callNode, OptionalEmitter& oe,
8353 ValueUsage valueUsage) {
8354 /*
8355 * A modified version of emitCallOrNew that handles optional calls.
8356 *
8357 * These include the following:
8358 * a?.()
8359 * a.b?.()
8360 * a.["b"]?.()
8361 * (a?.b)?.()
8362 *
8363 * See CallOrNewEmitter for more context.
8364 */
8365 ParseNode* calleeNode = callNode->callee();
8366 ListNode* argsList = callNode->args();
8367 bool isSpread = IsSpreadOp(callNode->callOp());
8368 JSOp op = callNode->callOp();
8369 uint32_t argc = argsList->count();
8370 bool isOptimizableSpread = isSpread && argc == 1;
8371
8372 CallOrNewEmitter cone(this, op,
8373 isOptimizableSpread
8374 ? CallOrNewEmitter::ArgumentsKind::SingleSpread
8375 : CallOrNewEmitter::ArgumentsKind::Other,
8376 valueUsage);
8377
8378 ParseNode* coordNode = getCoordNode(callNode, calleeNode, op, argsList);
8379
8380 if (!emitOptionalCalleeAndThis(calleeNode, callNode, cone, oe)) {
8381 // [stack] CALLEE THIS
8382 return false;
8383 }
8384
8385 if (callNode->isKind(ParseNodeKind::OptionalCallExpr)) {
8386 if (!oe.emitJumpShortCircuitForCall()) {
8387 // [stack] CALLEE THIS
8388 return false;
8389 }
8390 }
8391
8392 if (!emitArguments(argsList, /* isCall = */ true, isSpread, cone)) {
8393 // [stack] CALLEE THIS ARGS...
8394 return false;
8395 }
8396
8397 if (!cone.emitEnd(argc, coordNode->pn_pos.begin)) {
8398 // [stack] RVAL
8399 return false;
8400 }
8401
8402 return true;
8403}
8404
8405#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT1
8406bool BytecodeEmitter::emitSelfHostedDisposeResources(CallNode* callNode,
8407 DisposalKind kind) {
8408 ListNode* argsList = callNode->args();
8409 MOZ_ASSERT(argsList->count() == 2)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(argsList->count() == 2)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(argsList->count() == 2)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 2"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8409); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2"
")"); do { *((volatile int*)__null) = 8409; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8410
8411 ParseNode* resourcesNode = argsList->head();
8412 ParseNode* countNode = resourcesNode->pn_next;
8413
8414 DisposalEmitter de(this, bool(kind), CompletionKind::Normal);
8415
8416 if (!de.prepareForDisposeCapability()) {
8417 // [stack] RVAL? NEEDS-AWAIT? HAS-AWAITED? THROWING UNDEF
8418 return false;
8419 }
8420
8421 if (!emitTree(resourcesNode)) {
8422 // [stack] RVAL? NEEDS-AWAIT? HAS-AWAITED? THROWING UNDEF RESOURCES
8423 return false;
8424 }
8425
8426 if (!emitTree(countNode)) {
8427 // [stack] RVAL? NEEDS-AWAIT? HAS-AWAITED? THROWING UNDEF RESOURCES COUNT
8428 return false;
8429 }
8430
8431 if (!de.emitEnd(*innermostEmitterScope())) {
8432 // [stack] EXC THROWING
8433 return false;
8434 }
8435
8436 // [stack] EXC THROWING
8437
8438 InternalIfEmitter ifThrow(this);
8439
8440 if (!ifThrow.emitThenElse()) {
8441 // [stack] EXC
8442 return false;
8443 }
8444
8445 if (!emit1(JSOp::Throw)) {
8446 // [stack]
8447 return false;
8448 }
8449
8450 if (!ifThrow.emitElse()) {
8451 // [stack] EXC
8452 return false;
8453 }
8454
8455 if (!emit1(JSOp::Pop)) {
8456 // [stack]
8457 return false;
8458 }
8459
8460 if (!ifThrow.emitEnd()) {
8461 // [stack]
8462 return false;
8463 }
8464
8465 if (!emit1(JSOp::Undefined)) {
8466 // [stack] RVAL
8467 return false;
8468 }
8469
8470 return true;
8471}
8472#endif
8473
8474bool BytecodeEmitter::emitCallOrNew(CallNode* callNode, ValueUsage valueUsage) {
8475 /*
8476 * Emit callable invocation or operator new (constructor call) code.
8477 * First, emit code for the left operand to evaluate the callable or
8478 * constructable object expression.
8479 *
8480 * Then (or in a call case that has no explicit reference-base
8481 * object) we emit JSOp::Undefined to produce the undefined |this|
8482 * value required for calls (which non-strict mode functions
8483 * will box into the global object).
8484 */
8485 bool isCall = callNode->isKind(ParseNodeKind::CallExpr) ||
8486 callNode->isKind(ParseNodeKind::TaggedTemplateExpr);
8487 ParseNode* calleeNode = callNode->callee();
8488 ListNode* argsList = callNode->args();
8489 JSOp op = callNode->callOp();
8490
8491 if (calleeNode->isKind(ParseNodeKind::Name) &&
8492 emitterMode == BytecodeEmitter::SelfHosting && op == JSOp::Call) {
8493 // Calls to "forceInterpreter", "callFunction",
8494 // "callContentFunction", or "resumeGenerator" in self-hosted
8495 // code generate inline bytecode.
8496 //
8497 // NOTE: The list of special instruction names has to be kept in sync with
8498 // "js/src/builtin/.eslintrc.js".
8499 auto calleeName = calleeNode->as<NameNode>().name();
8500 if (calleeName == TaggedParserAtomIndex::WellKnown::callFunction()) {
8501 return emitSelfHostedCallFunction(callNode, JSOp::Call);
8502 }
8503 if (calleeName == TaggedParserAtomIndex::WellKnown::callContentFunction()) {
8504 return emitSelfHostedCallFunction(callNode, JSOp::CallContent);
8505 }
8506 if (calleeName ==
8507 TaggedParserAtomIndex::WellKnown::constructContentFunction()) {
8508 return emitSelfHostedCallFunction(callNode, JSOp::NewContent);
8509 }
8510 if (calleeName == TaggedParserAtomIndex::WellKnown::resumeGenerator()) {
8511 return emitSelfHostedResumeGenerator(callNode);
8512 }
8513 if (calleeName == TaggedParserAtomIndex::WellKnown::forceInterpreter()) {
8514 return emitSelfHostedForceInterpreter();
8515 }
8516 if (calleeName == TaggedParserAtomIndex::WellKnown::allowContentIter()) {
8517 return emitSelfHostedAllowContentIter(callNode);
8518 }
8519 if (calleeName ==
8520 TaggedParserAtomIndex::WellKnown::allowContentIterWith()) {
8521 return emitSelfHostedAllowContentIterWith(callNode);
8522 }
8523 if (calleeName ==
8524 TaggedParserAtomIndex::WellKnown::allowContentIterWithNext()) {
8525 return emitSelfHostedAllowContentIterWithNext(callNode);
8526 }
8527 if (calleeName == TaggedParserAtomIndex::WellKnown::DefineDataProperty() &&
8528 argsList->count() == 3) {
8529 return emitSelfHostedDefineDataProperty(callNode);
8530 }
8531 if (calleeName == TaggedParserAtomIndex::WellKnown::hasOwn()) {
8532 return emitSelfHostedHasOwn(callNode);
8533 }
8534 if (calleeName == TaggedParserAtomIndex::WellKnown::getPropertySuper()) {
8535 return emitSelfHostedGetPropertySuper(callNode);
8536 }
8537 if (calleeName == TaggedParserAtomIndex::WellKnown::ToNumeric()) {
8538 return emitSelfHostedToNumeric(callNode);
8539 }
8540 if (calleeName == TaggedParserAtomIndex::WellKnown::ToString()) {
8541 return emitSelfHostedToString(callNode);
8542 }
8543 if (calleeName ==
8544 TaggedParserAtomIndex::WellKnown::GetBuiltinConstructor()) {
8545 return emitSelfHostedGetBuiltinConstructor(callNode);
8546 }
8547 if (calleeName == TaggedParserAtomIndex::WellKnown::GetBuiltinPrototype()) {
8548 return emitSelfHostedGetBuiltinPrototype(callNode);
8549 }
8550 if (calleeName == TaggedParserAtomIndex::WellKnown::GetBuiltinSymbol()) {
8551 return emitSelfHostedGetBuiltinSymbol(callNode);
8552 }
8553 if (calleeName == TaggedParserAtomIndex::WellKnown::ArgumentsLength()) {
8554 return emitSelfHostedArgumentsLength(callNode);
8555 }
8556 if (calleeName == TaggedParserAtomIndex::WellKnown::GetArgument()) {
8557 return emitSelfHostedGetArgument(callNode);
8558 }
8559 if (calleeName ==
8560 TaggedParserAtomIndex::WellKnown::SetIsInlinableLargeFunction()) {
8561 return emitSelfHostedSetIsInlinableLargeFunction(callNode);
8562 }
8563 if (calleeName == TaggedParserAtomIndex::WellKnown::SetCanonicalName()) {
8564 return emitSelfHostedSetCanonicalName(callNode);
8565 }
8566 if (calleeName == TaggedParserAtomIndex::WellKnown::IsNullOrUndefined()) {
8567 return emitSelfHostedIsNullOrUndefined(callNode);
8568 }
8569 if (calleeName == TaggedParserAtomIndex::WellKnown::IteratorClose()) {
8570 return emitSelfHostedIteratorClose(callNode);
8571 }
8572#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT1
8573 if (calleeName ==
8574 TaggedParserAtomIndex::WellKnown::DisposeResourcesAsync()) {
8575 return emitSelfHostedDisposeResources(callNode, DisposalKind::Async);
8576 }
8577 if (calleeName ==
8578 TaggedParserAtomIndex::WellKnown::DisposeResourcesSync()) {
8579 return emitSelfHostedDisposeResources(callNode, DisposalKind::Sync);
8580 }
8581#endif
8582#ifdef DEBUG1
8583 if (calleeName ==
8584 TaggedParserAtomIndex::WellKnown::UnsafeGetReservedSlot() ||
8585 calleeName == TaggedParserAtomIndex::WellKnown::
8586 UnsafeGetObjectFromReservedSlot() ||
8587 calleeName == TaggedParserAtomIndex::WellKnown::
8588 UnsafeGetInt32FromReservedSlot() ||
8589 calleeName == TaggedParserAtomIndex::WellKnown::
8590 UnsafeGetStringFromReservedSlot()) {
8591 // Make sure that this call is correct, but don't emit any special code.
8592 assertSelfHostedUnsafeGetReservedSlot(argsList);
8593 }
8594 if (calleeName ==
8595 TaggedParserAtomIndex::WellKnown::UnsafeSetReservedSlot()) {
8596 // Make sure that this call is correct, but don't emit any special code.
8597 assertSelfHostedUnsafeSetReservedSlot(argsList);
8598 }
8599#endif
8600 // Fall through
8601 }
8602
8603 uint32_t argc = argsList->count();
8604 bool isSpread = IsSpreadOp(op);
8605 bool isOptimizableSpread = isSpread && argc == 1;
8606 bool isDefaultDerivedClassConstructor =
8607 sc->isFunctionBox() && sc->asFunctionBox()->isDerivedClassConstructor() &&
8608 sc->asFunctionBox()->isSyntheticFunction();
8609 MOZ_ASSERT_IF(isDefaultDerivedClassConstructor, isOptimizableSpread)do { if (isDefaultDerivedClassConstructor) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(isOptimizableSpread
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(isOptimizableSpread))), 0))) { do { } while (false);
MOZ_ReportAssertionFailure("isOptimizableSpread", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8609); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isOptimizableSpread"
")"); do { *((volatile int*)__null) = 8609; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
8610 CallOrNewEmitter cone(
8611 this, op,
8612 isOptimizableSpread
8613 ? isDefaultDerivedClassConstructor
8614 ? CallOrNewEmitter::ArgumentsKind::PassthroughRest
8615 : CallOrNewEmitter::ArgumentsKind::SingleSpread
8616 : CallOrNewEmitter::ArgumentsKind::Other,
8617 valueUsage);
8618
8619 if (!emitCalleeAndThis(calleeNode, callNode, cone)) {
8620 // [stack] CALLEE THIS
8621 return false;
8622 }
8623 if (!emitArguments(argsList, isCall, isSpread, cone)) {
8624 // [stack] CALLEE THIS ARGS...
8625 return false;
8626 }
8627
8628 // Push new.target for construct calls.
8629 if (IsConstructOp(op)) {
8630 if (op == JSOp::SuperCall || op == JSOp::SpreadSuperCall) {
8631 if (!emitNewTarget(callNode)) {
8632 // [stack] CALLEE THIS ARGS.. NEW.TARGET
8633 return false;
8634 }
8635 } else {
8636 // Repush the callee as new.target
8637 uint32_t effectiveArgc = isSpread ? 1 : argc;
8638 if (!emitDupAt(effectiveArgc + 1)) {
8639 // [stack] CALLEE THIS ARGS.. CALLEE
8640 return false;
8641 }
8642 }
8643 }
8644
8645 ParseNode* coordNode = getCoordNode(callNode, calleeNode, op, argsList);
8646
8647 if (!cone.emitEnd(argc, coordNode->pn_pos.begin)) {
8648 // [stack] RVAL
8649 return false;
8650 }
8651
8652 return true;
8653}
8654
8655// This list must be kept in the same order in several places:
8656// - The binary operators in ParseNode.h ,
8657// - the binary operators in TokenKind.h
8658// - the precedence list in Parser.cpp
8659static const JSOp ParseNodeKindToJSOp[] = {
8660 // Some binary ops require special code generation (PrivateIn);
8661 // these should not use BinaryOpParseNodeKindToJSOp. This table fills those
8662 // slots with Nops to make the rest of the table lookup work.
8663 JSOp::Coalesce, JSOp::Or, JSOp::And, JSOp::BitOr, JSOp::BitXor,
8664 JSOp::BitAnd, JSOp::StrictEq, JSOp::Eq, JSOp::StrictNe, JSOp::Ne,
8665 JSOp::Lt, JSOp::Le, JSOp::Gt, JSOp::Ge, JSOp::Instanceof,
8666 JSOp::In, JSOp::Nop, JSOp::Lsh, JSOp::Rsh, JSOp::Ursh,
8667 JSOp::Add, JSOp::Sub, JSOp::Mul, JSOp::Div, JSOp::Mod,
8668 JSOp::Pow};
8669
8670static inline JSOp BinaryOpParseNodeKindToJSOp(ParseNodeKind pnk) {
8671 MOZ_ASSERT(pnk >= ParseNodeKind::BinOpFirst)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pnk >= ParseNodeKind::BinOpFirst)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pnk >= ParseNodeKind::BinOpFirst
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"pnk >= ParseNodeKind::BinOpFirst", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8671); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pnk >= ParseNodeKind::BinOpFirst"
")"); do { *((volatile int*)__null) = 8671; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8672 MOZ_ASSERT(pnk <= ParseNodeKind::BinOpLast)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pnk <= ParseNodeKind::BinOpLast)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pnk <= ParseNodeKind::BinOpLast
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"pnk <= ParseNodeKind::BinOpLast", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8672); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pnk <= ParseNodeKind::BinOpLast"
")"); do { *((volatile int*)__null) = 8672; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8673 int parseNodeFirst = size_t(ParseNodeKind::BinOpFirst);
8674#ifdef DEBUG1
8675 int jsopArraySize = std::size(ParseNodeKindToJSOp);
8676 int parseNodeKindListSize =
8677 size_t(ParseNodeKind::BinOpLast) - parseNodeFirst + 1;
8678 MOZ_ASSERT(jsopArraySize == parseNodeKindListSize)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(jsopArraySize == parseNodeKindListSize)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(jsopArraySize == parseNodeKindListSize))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("jsopArraySize == parseNodeKindListSize"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8678); AnnotateMozCrashReason("MOZ_ASSERT" "(" "jsopArraySize == parseNodeKindListSize"
")"); do { *((volatile int*)__null) = 8678; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8679 // Ensure we don't use this to find an op for a parse node
8680 // requiring special emission rules.
8681 MOZ_ASSERT(ParseNodeKindToJSOp[size_t(pnk) - parseNodeFirst] != JSOp::Nop)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(ParseNodeKindToJSOp[size_t(pnk) - parseNodeFirst] !=
JSOp::Nop)>::isValid, "invalid assertion condition"); if (
(__builtin_expect(!!(!(!!(ParseNodeKindToJSOp[size_t(pnk) - parseNodeFirst
] != JSOp::Nop))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("ParseNodeKindToJSOp[size_t(pnk) - parseNodeFirst] != JSOp::Nop"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8681); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ParseNodeKindToJSOp[size_t(pnk) - parseNodeFirst] != JSOp::Nop"
")"); do { *((volatile int*)__null) = 8681; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8682#endif
8683 return ParseNodeKindToJSOp[size_t(pnk) - parseNodeFirst];
8684}
8685
8686bool BytecodeEmitter::emitRightAssociative(ListNode* node) {
8687 // ** is the only right-associative operator.
8688 MOZ_ASSERT(node->isKind(ParseNodeKind::PowExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(node->isKind(ParseNodeKind::PowExpr))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(node->isKind(ParseNodeKind::PowExpr)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("node->isKind(ParseNodeKind::PowExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8688); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::PowExpr)"
")"); do { *((volatile int*)__null) = 8688; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8689
8690 // Right-associative operator chain.
8691 for (ParseNode* subexpr : node->contents()) {
8692 if (!updateSourceCoordNotesIfNonLiteral(subexpr)) {
8693 return false;
8694 }
8695 if (!emitTree(subexpr)) {
8696 return false;
8697 }
8698 }
8699 for (uint32_t i = 0; i < node->count() - 1; i++) {
8700 if (!emit1(JSOp::Pow)) {
8701 return false;
8702 }
8703 }
8704 return true;
8705}
8706
8707bool BytecodeEmitter::emitLeftAssociative(ListNode* node) {
8708 // Left-associative operator chain.
8709 if (!emitTree(node->head())) {
8710 return false;
8711 }
8712 JSOp op = BinaryOpParseNodeKindToJSOp(node->getKind());
8713 ParseNode* nextExpr = node->head()->pn_next;
8714 do {
8715 if (!updateSourceCoordNotesIfNonLiteral(nextExpr)) {
8716 return false;
8717 }
8718 if (!emitTree(nextExpr)) {
8719 return false;
8720 }
8721 if (!emit1(op)) {
8722 return false;
8723 }
8724 } while ((nextExpr = nextExpr->pn_next));
8725 return true;
8726}
8727
8728bool BytecodeEmitter::emitPrivateInExpr(ListNode* node) {
8729 MOZ_ASSERT(node->head()->isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(node->head()->isKind(ParseNodeKind::PrivateName
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(node->head()->isKind(ParseNodeKind::PrivateName
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("node->head()->isKind(ParseNodeKind::PrivateName)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8729); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->head()->isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 8729; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8730
8731 NameNode& privateNameNode = node->head()->as<NameNode>();
8732 TaggedParserAtomIndex privateName = privateNameNode.name();
8733
8734 PrivateOpEmitter xoe(this, PrivateOpEmitter::Kind::ErgonomicBrandCheck,
8735 privateName);
8736
8737 ParseNode* valueNode = node->head()->pn_next;
8738 MOZ_ASSERT(valueNode->pn_next == nullptr)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(valueNode->pn_next == nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(valueNode->pn_next == nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"valueNode->pn_next == nullptr", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8738); AnnotateMozCrashReason("MOZ_ASSERT" "(" "valueNode->pn_next == nullptr"
")"); do { *((volatile int*)__null) = 8738; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8739
8740 if (!emitTree(valueNode)) {
8741 // [stack] OBJ
8742 return false;
8743 }
8744
8745 if (!xoe.emitReference()) {
8746 // [stack] OBJ BRAND if private method
8747 // [stack] OBJ NAME if private field or accessor.
8748 return false;
8749 }
8750
8751 if (!xoe.emitBrandCheck()) {
8752 // [stack] OBJ BRAND BOOL if private method
8753 // [stack] OBJ NAME BOOL if private field or accessor.
8754 return false;
8755 }
8756
8757 if (!emitUnpickN(2)) {
8758 // [stack] BOOL OBJ BRAND if private method
8759 // [stack] BOOL OBJ NAME if private field or accessor.
8760 return false;
8761 }
8762
8763 if (!emitPopN(2)) {
8764 // [stack] BOOL
8765 return false;
8766 }
8767
8768 return true;
8769}
8770
8771/*
8772 * Special `emitTree` for Optional Chaining case.
8773 * Examples of this are `emitOptionalChain`, `emitDeleteOptionalChain` and
8774 * `emitCalleeAndThisForOptionalChain`.
8775 */
8776bool BytecodeEmitter::emitOptionalTree(
8777 ParseNode* pn, OptionalEmitter& oe,
8778 ValueUsage valueUsage /* = ValueUsage::WantValue */) {
8779 AutoCheckRecursionLimit recursion(fc);
8780 if (!recursion.check(fc)) {
8781 return false;
8782 }
8783 ParseNodeKind kind = pn->getKind();
8784 switch (kind) {
8785 case ParseNodeKind::OptionalDotExpr: {
8786 OptionalPropertyAccess* prop = &pn->as<OptionalPropertyAccess>();
8787 bool isSuper = false;
8788 PropOpEmitter poe(this, PropOpEmitter::Kind::Get,
8789 PropOpEmitter::ObjKind::Other);
8790 if (!emitOptionalDotExpression(prop, poe, isSuper, oe)) {
8791 return false;
8792 }
8793 break;
8794 }
8795 case ParseNodeKind::ArgumentsLength:
8796 case ParseNodeKind::DotExpr: {
8797 PropertyAccess* prop = &pn->as<PropertyAccess>();
8798 bool isSuper = prop->isSuper();
8799 PropOpEmitter poe(this, PropOpEmitter::Kind::Get,
8800 isSuper ? PropOpEmitter::ObjKind::Super
8801 : PropOpEmitter::ObjKind::Other);
8802 if (!emitOptionalDotExpression(prop, poe, isSuper, oe)) {
8803 return false;
8804 }
8805 break;
8806 }
8807
8808 case ParseNodeKind::OptionalElemExpr: {
8809 OptionalPropertyByValue* elem = &pn->as<OptionalPropertyByValue>();
8810 bool isSuper = false;
8811 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"
, 8811); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 8811; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8812 ElemOpEmitter eoe(this, ElemOpEmitter::Kind::Get,
8813 ElemOpEmitter::ObjKind::Other);
8814
8815 if (!emitOptionalElemExpression(elem, eoe, isSuper, oe)) {
8816 return false;
8817 }
8818 break;
8819 }
8820 case ParseNodeKind::ElemExpr: {
8821 PropertyByValue* elem = &pn->as<PropertyByValue>();
8822 bool isSuper = elem->isSuper();
8823 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"
, 8823); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 8823; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8824 ElemOpEmitter eoe(this, ElemOpEmitter::Kind::Get,
8825 isSuper ? ElemOpEmitter::ObjKind::Super
8826 : ElemOpEmitter::ObjKind::Other);
8827
8828 if (!emitOptionalElemExpression(elem, eoe, isSuper, oe)) {
8829 return false;
8830 }
8831 break;
8832 }
8833 case ParseNodeKind::PrivateMemberExpr:
8834 case ParseNodeKind::OptionalPrivateMemberExpr: {
8835 PrivateMemberAccessBase* privateExpr = &pn->as<PrivateMemberAccessBase>();
8836 PrivateOpEmitter xoe(this, PrivateOpEmitter::Kind::Get,
8837 privateExpr->privateName().name());
8838 if (!emitOptionalPrivateExpression(privateExpr, xoe, oe)) {
8839 return false;
8840 }
8841 break;
8842 }
8843 case ParseNodeKind::CallExpr:
8844 case ParseNodeKind::OptionalCallExpr:
8845 if (!emitOptionalCall(&pn->as<CallNode>(), oe, valueUsage)) {
8846 return false;
8847 }
8848 break;
8849 // List of accepted ParseNodeKinds that might appear only at the beginning
8850 // of an Optional Chain.
8851 // For example, a taggedTemplateExpr node might occur if we have
8852 // `test`?.b, with `test` as the taggedTemplateExpr ParseNode.
8853 default:
8854#ifdef DEBUG1
8855 // https://tc39.es/ecma262/#sec-primary-expression
8856 bool isPrimaryExpression =
8857 kind == ParseNodeKind::ThisExpr || kind == ParseNodeKind::Name ||
8858 kind == ParseNodeKind::PrivateName ||
8859 kind == ParseNodeKind::NullExpr || kind == ParseNodeKind::TrueExpr ||
8860 kind == ParseNodeKind::FalseExpr ||
8861 kind == ParseNodeKind::NumberExpr ||
8862 kind == ParseNodeKind::BigIntExpr ||
8863 kind == ParseNodeKind::StringExpr ||
8864 kind == ParseNodeKind::ArrayExpr ||
8865 kind == ParseNodeKind::ObjectExpr ||
8866 kind == ParseNodeKind::Function || kind == ParseNodeKind::ClassDecl ||
8867 kind == ParseNodeKind::RegExpExpr ||
8868 kind == ParseNodeKind::TemplateStringExpr ||
8869 kind == ParseNodeKind::TemplateStringListExpr ||
8870 kind == ParseNodeKind::RawUndefinedExpr || pn->isInParens();
8871
8872 // https://tc39.es/ecma262/#sec-left-hand-side-expressions
8873 bool isMemberExpression = isPrimaryExpression ||
8874 kind == ParseNodeKind::TaggedTemplateExpr ||
8875 kind == ParseNodeKind::NewExpr ||
8876 kind == ParseNodeKind::NewTargetExpr ||
8877 kind == ParseNodeKind::ImportMetaExpr;
8878
8879 bool isCallExpression = kind == ParseNodeKind::SetThis ||
8880 kind == ParseNodeKind::CallImportExpr;
8881
8882 MOZ_ASSERT(isMemberExpression || isCallExpression,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(isMemberExpression || isCallExpression)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(isMemberExpression || isCallExpression))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("isMemberExpression || isCallExpression"
" (" "Unknown ParseNodeKind for OptionalChain" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8883); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isMemberExpression || isCallExpression"
") (" "Unknown ParseNodeKind for OptionalChain" ")"); do { *
((volatile int*)__null) = 8883; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
8883 "Unknown ParseNodeKind for OptionalChain")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(isMemberExpression || isCallExpression)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(isMemberExpression || isCallExpression))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("isMemberExpression || isCallExpression"
" (" "Unknown ParseNodeKind for OptionalChain" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8883); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isMemberExpression || isCallExpression"
") (" "Unknown ParseNodeKind for OptionalChain" ")"); do { *
((volatile int*)__null) = 8883; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
8884#endif
8885 return emitTree(pn);
8886 }
8887 return true;
8888}
8889
8890// Handle the case of a call made on a OptionalChainParseNode.
8891// For example `(a?.b)()` and `(a?.b)?.()`.
8892bool BytecodeEmitter::emitCalleeAndThisForOptionalChain(
8893 UnaryNode* optionalChain, CallNode* callNode, CallOrNewEmitter& cone) {
8894 ParseNode* calleeNode = optionalChain->kid();
8895
8896 // Create a new OptionalEmitter, in order to emit the right bytecode
8897 // in isolation.
8898 OptionalEmitter oe(this, bytecodeSection().stackDepth());
8899
8900 if (!emitOptionalCalleeAndThis(calleeNode, callNode, cone, oe)) {
8901 // [stack] CALLEE THIS
8902 return false;
8903 }
8904
8905 // complete the jump if necessary. This will set both the "this" value
8906 // and the "callee" value to undefined, if the callee is undefined. It
8907 // does not matter much what the this value is, the function call will
8908 // fail if it is not optional, and be set to undefined otherwise.
8909 if (!oe.emitOptionalJumpTarget(JSOp::Undefined,
8910 OptionalEmitter::Kind::Reference)) {
8911 // [stack] # If shortcircuit
8912 // [stack] UNDEFINED UNDEFINED
8913 // [stack] # otherwise
8914 // [stack] CALLEE THIS
8915 return false;
8916 }
8917 return true;
8918}
8919
8920bool BytecodeEmitter::emitOptionalChain(UnaryNode* optionalChain,
8921 ValueUsage valueUsage) {
8922 ParseNode* expr = optionalChain->kid();
8923
8924 OptionalEmitter oe(this, bytecodeSection().stackDepth());
8925
8926 if (!emitOptionalTree(expr, oe, valueUsage)) {
8927 // [stack] VAL
8928 return false;
8929 }
8930
8931 if (!oe.emitOptionalJumpTarget(JSOp::Undefined)) {
8932 // [stack] # If shortcircuit
8933 // [stack] UNDEFINED
8934 // [stack] # otherwise
8935 // [stack] VAL
8936 return false;
8937 }
8938
8939 return true;
8940}
8941
8942bool BytecodeEmitter::emitOptionalDotExpression(PropertyAccessBase* prop,
8943 PropOpEmitter& poe,
8944 bool isSuper,
8945 OptionalEmitter& oe) {
8946 if (!poe.prepareForObj()) {
8947 // [stack]
8948 return false;
8949 }
8950
8951 if (isSuper) {
8952 UnaryNode* base = &prop->expression().as<UnaryNode>();
8953 if (!emitGetThisForSuperBase(base)) {
8954 // [stack] OBJ
8955 return false;
8956 }
8957 } else {
8958 if (!emitOptionalTree(&prop->expression(), oe)) {
8959 // [stack] OBJ
8960 return false;
8961 }
8962 }
8963
8964 if (prop->isKind(ParseNodeKind::OptionalDotExpr)) {
8965 MOZ_ASSERT(!isSuper)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!isSuper)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!isSuper))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!isSuper", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 8965); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!isSuper" ")"
); do { *((volatile int*)__null) = 8965; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8966 if (!oe.emitJumpShortCircuit()) {
8967 // [stack] # if Jump
8968 // [stack] UNDEFINED-OR-NULL
8969 // [stack] # otherwise
8970 // [stack] OBJ
8971 return false;
8972 }
8973 }
8974
8975 if (!poe.emitGet(prop->key().atom())) {
8976 // [stack] PROP
8977 return false;
8978 }
8979
8980 return true;
8981}
8982
8983bool BytecodeEmitter::emitOptionalElemExpression(PropertyByValueBase* elem,
8984 ElemOpEmitter& eoe,
8985 bool isSuper,
8986 OptionalEmitter& oe) {
8987 if (!eoe.prepareForObj()) {
8988 // [stack]
8989 return false;
8990 }
8991
8992 if (isSuper) {
8993 UnaryNode* base = &elem->expression().as<UnaryNode>();
8994 if (!emitGetThisForSuperBase(base)) {
8995 // [stack] OBJ
8996 return false;
8997 }
8998 } else {
8999 if (!emitOptionalTree(&elem->expression(), oe)) {
9000 // [stack] OBJ
9001 return false;
9002 }
9003 }
9004
9005 if (elem->isKind(ParseNodeKind::OptionalElemExpr)) {
9006 MOZ_ASSERT(!isSuper)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!isSuper)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!isSuper))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!isSuper", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9006); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!isSuper" ")"
); do { *((volatile int*)__null) = 9006; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9007 if (!oe.emitJumpShortCircuit()) {
9008 // [stack] # if Jump
9009 // [stack] UNDEFINED-OR-NULL
9010 // [stack] # otherwise
9011 // [stack] OBJ
9012 return false;
9013 }
9014 }
9015
9016 if (!eoe.prepareForKey()) {
9017 // [stack] OBJ? OBJ
9018 return false;
9019 }
9020
9021 if (!emitTree(&elem->key())) {
9022 // [stack] OBJ? OBJ KEY
9023 return false;
9024 }
9025
9026 if (!eoe.emitGet()) {
9027 // [stack] ELEM
9028 return false;
9029 }
9030
9031 return true;
9032}
9033
9034bool BytecodeEmitter::emitOptionalPrivateExpression(
9035 PrivateMemberAccessBase* privateExpr, PrivateOpEmitter& xoe,
9036 OptionalEmitter& oe) {
9037 if (!emitOptionalTree(&privateExpr->expression(), oe)) {
9038 // [stack] OBJ
9039 return false;
9040 }
9041
9042 if (privateExpr->isKind(ParseNodeKind::OptionalPrivateMemberExpr)) {
9043 if (!oe.emitJumpShortCircuit()) {
9044 // [stack] # if Jump
9045 // [stack] UNDEFINED-OR-NULL
9046 // [stack] # otherwise
9047 // [stack] OBJ
9048 return false;
9049 }
9050 }
9051
9052 if (!xoe.emitReference()) {
9053 // [stack] OBJ NAME
9054 return false;
9055 }
9056 if (!xoe.emitGet()) {
9057 // [stack] CALLEE THIS # if call
9058 // [stack] VALUE # otherwise
9059 return false;
9060 }
9061
9062 return true;
9063}
9064
9065bool BytecodeEmitter::emitShortCircuit(ListNode* node, ValueUsage valueUsage) {
9066 MOZ_ASSERT(node->isKind(ParseNodeKind::OrExpr) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(node->isKind(ParseNodeKind::OrExpr) || node->isKind
(ParseNodeKind::CoalesceExpr) || node->isKind(ParseNodeKind
::AndExpr))>::isValid, "invalid assertion condition"); if (
(__builtin_expect(!!(!(!!(node->isKind(ParseNodeKind::OrExpr
) || node->isKind(ParseNodeKind::CoalesceExpr) || node->
isKind(ParseNodeKind::AndExpr)))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("node->isKind(ParseNodeKind::OrExpr) || node->isKind(ParseNodeKind::CoalesceExpr) || node->isKind(ParseNodeKind::AndExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9068); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::OrExpr) || node->isKind(ParseNodeKind::CoalesceExpr) || node->isKind(ParseNodeKind::AndExpr)"
")"); do { *((volatile int*)__null) = 9068; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9067 node->isKind(ParseNodeKind::CoalesceExpr) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(node->isKind(ParseNodeKind::OrExpr) || node->isKind
(ParseNodeKind::CoalesceExpr) || node->isKind(ParseNodeKind
::AndExpr))>::isValid, "invalid assertion condition"); if (
(__builtin_expect(!!(!(!!(node->isKind(ParseNodeKind::OrExpr
) || node->isKind(ParseNodeKind::CoalesceExpr) || node->
isKind(ParseNodeKind::AndExpr)))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("node->isKind(ParseNodeKind::OrExpr) || node->isKind(ParseNodeKind::CoalesceExpr) || node->isKind(ParseNodeKind::AndExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9068); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::OrExpr) || node->isKind(ParseNodeKind::CoalesceExpr) || node->isKind(ParseNodeKind::AndExpr)"
")"); do { *((volatile int*)__null) = 9068; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9068 node->isKind(ParseNodeKind::AndExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(node->isKind(ParseNodeKind::OrExpr) || node->isKind
(ParseNodeKind::CoalesceExpr) || node->isKind(ParseNodeKind
::AndExpr))>::isValid, "invalid assertion condition"); if (
(__builtin_expect(!!(!(!!(node->isKind(ParseNodeKind::OrExpr
) || node->isKind(ParseNodeKind::CoalesceExpr) || node->
isKind(ParseNodeKind::AndExpr)))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("node->isKind(ParseNodeKind::OrExpr) || node->isKind(ParseNodeKind::CoalesceExpr) || node->isKind(ParseNodeKind::AndExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9068); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::OrExpr) || node->isKind(ParseNodeKind::CoalesceExpr) || node->isKind(ParseNodeKind::AndExpr)"
")"); do { *((volatile int*)__null) = 9068; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9069
9070 /*
9071 * JSOp::Or converts the operand on the stack to boolean, leaves the original
9072 * value on the stack and jumps if true; otherwise it falls into the next
9073 * bytecode, which pops the left operand and then evaluates the right operand.
9074 * The jump goes around the right operand evaluation.
9075 *
9076 * JSOp::And converts the operand on the stack to boolean and jumps if false;
9077 * otherwise it falls into the right operand's bytecode.
9078 */
9079
9080 TDZCheckCache tdzCache(this);
9081
9082 JSOp op;
9083 switch (node->getKind()) {
9084 case ParseNodeKind::OrExpr:
9085 op = JSOp::Or;
9086 break;
9087 case ParseNodeKind::CoalesceExpr:
9088 op = JSOp::Coalesce;
9089 break;
9090 case ParseNodeKind::AndExpr:
9091 op = JSOp::And;
9092 break;
9093 default:
9094 MOZ_CRASH("Unexpected ParseNodeKind")do { do { } while (false); MOZ_ReportCrash("" "Unexpected ParseNodeKind"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9094); AnnotateMozCrashReason("MOZ_CRASH(" "Unexpected ParseNodeKind"
")"); do { *((volatile int*)__null) = 9094; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
9095 }
9096
9097 JumpList jump;
9098
9099 // Left-associative operator chain: avoid too much recursion.
9100 //
9101 // Emit all nodes but the last.
9102 for (ParseNode* expr : node->contentsTo(node->last())) {
9103 if (!emitTree(expr)) {
9104 return false;
9105 }
9106 if (!emitJump(op, &jump)) {
9107 return false;
9108 }
9109 if (!emit1(JSOp::Pop)) {
9110 return false;
9111 }
9112 }
9113
9114 // Emit the last node
9115 if (!emitTree(node->last(), valueUsage)) {
9116 return false;
9117 }
9118
9119 if (!emitJumpTargetAndPatch(jump)) {
9120 return false;
9121 }
9122 return true;
9123}
9124
9125bool BytecodeEmitter::emitSequenceExpr(ListNode* node, ValueUsage valueUsage) {
9126 for (ParseNode* child : node->contentsTo(node->last())) {
9127 if (!updateSourceCoordNotes(child->pn_pos.begin)) {
9128 return false;
9129 }
9130 if (!emitTree(child, ValueUsage::IgnoreValue)) {
9131 return false;
9132 }
9133 if (!emit1(JSOp::Pop)) {
9134 return false;
9135 }
9136 }
9137
9138 ParseNode* child = node->last();
9139 if (!updateSourceCoordNotes(child->pn_pos.begin)) {
9140 return false;
9141 }
9142 if (!emitTree(child, valueUsage)) {
9143 return false;
9144 }
9145 return true;
9146}
9147
9148// Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See
9149// the comment on emitSwitch.
9150MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitIncOrDec(UnaryNode* incDec,
9151 ValueUsage valueUsage) {
9152 switch (incDec->kid()->getKind()) {
9153 case ParseNodeKind::ArgumentsLength:
9154 case ParseNodeKind::DotExpr:
9155 return emitPropIncDec(incDec, valueUsage);
9156 case ParseNodeKind::ElemExpr:
9157 return emitElemIncDec(incDec, valueUsage);
9158 case ParseNodeKind::PrivateMemberExpr:
9159 return emitPrivateIncDec(incDec, valueUsage);
9160 case ParseNodeKind::CallExpr:
9161 return emitCallIncDec(incDec);
9162 default:
9163 return emitNameIncDec(incDec, valueUsage);
9164 }
9165}
9166
9167// Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See
9168// the comment on emitSwitch.
9169MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitLabeledStatement(
9170 const LabeledStatement* labeledStmt) {
9171 auto name = labeledStmt->label();
9172 LabelEmitter label(this);
9173
9174 label.emitLabel(name);
9175
9176 if (!emitTree(labeledStmt->statement())) {
9177 return false;
9178 }
9179 if (!label.emitEnd()) {
9180 return false;
9181 }
9182
9183 return true;
9184}
9185
9186bool BytecodeEmitter::emitConditionalExpression(
9187 ConditionalExpression& conditional, ValueUsage valueUsage) {
9188 CondEmitter cond(this);
9189 if (!cond.emitCond()) {
9190 return false;
9191 }
9192
9193 ParseNode* conditionNode = &conditional.condition();
9194 auto conditionKind = IfEmitter::ConditionKind::Positive;
9195 if (conditionNode->isKind(ParseNodeKind::NotExpr)) {
9196 conditionNode = conditionNode->as<UnaryNode>().kid();
9197 conditionKind = IfEmitter::ConditionKind::Negative;
9198 }
9199
9200 // NOTE: NotExpr of conditionNode may be unwrapped, and in that case the
9201 // negation is handled by conditionKind.
9202 if (!emitTree(conditionNode)) {
9203 return false;
9204 }
9205
9206 if (!cond.emitThenElse(conditionKind)) {
9207 return false;
9208 }
9209
9210 if (!emitTree(&conditional.thenExpression(), valueUsage)) {
9211 return false;
9212 }
9213
9214 if (!cond.emitElse()) {
9215 return false;
9216 }
9217
9218 if (!emitTree(&conditional.elseExpression(), valueUsage)) {
9219 return false;
9220 }
9221
9222 if (!cond.emitEnd()) {
9223 return false;
9224 }
9225 MOZ_ASSERT(cond.pushed() == 1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(cond.pushed() == 1)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(cond.pushed() == 1))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("cond.pushed() == 1"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9225); AnnotateMozCrashReason("MOZ_ASSERT" "(" "cond.pushed() == 1"
")"); do { *((volatile int*)__null) = 9225; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9226
9227 return true;
9228}
9229
9230// Check for an object-literal property list that can be handled by the
9231// ObjLiteral writer. We ensure that for each `prop: value` pair, the key is a
9232// constant name or numeric index, there is no accessor specified, and the value
9233// can be encoded by an ObjLiteral instruction (constant number, string,
9234// boolean, null/undefined).
9235void BytecodeEmitter::isPropertyListObjLiteralCompatible(
9236 ListNode* obj, bool* withValues, bool* withoutValues) const {
9237 bool keysOK = true;
9238 bool valuesOK = true;
9239 uint32_t propCount = 0;
9240
9241 for (ParseNode* propdef : obj->contents()) {
9242 if (!propdef->is<BinaryNode>()) {
9243 keysOK = false;
9244 break;
9245 }
9246 propCount++;
9247
9248 BinaryNode* prop = &propdef->as<BinaryNode>();
9249 ParseNode* key = prop->left();
9250 ParseNode* value = prop->right();
9251
9252 // Computed keys not OK (ObjLiteral data stores constant keys).
9253 if (key->isKind(ParseNodeKind::ComputedName)) {
9254 keysOK = false;
9255 break;
9256 }
9257
9258 // BigIntExprs should have been lowered to computed names at parse
9259 // time, and so should be excluded above.
9260 MOZ_ASSERT(!key->isKind(ParseNodeKind::BigIntExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!key->isKind(ParseNodeKind::BigIntExpr))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!key->isKind(ParseNodeKind::BigIntExpr)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!key->isKind(ParseNodeKind::BigIntExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9260); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!key->isKind(ParseNodeKind::BigIntExpr)"
")"); do { *((volatile int*)__null) = 9260; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9261
9262 // Numeric keys OK as long as they are integers and in range.
9263 if (key->isKind(ParseNodeKind::NumberExpr)) {
9264 double numValue = key->as<NumericLiteral>().value();
9265 int32_t i = 0;
9266 if (!NumberIsInt32(numValue, &i)) {
9267 keysOK = false;
9268 break;
9269 }
9270 if (!ObjLiteralWriter::arrayIndexInRange(i)) {
9271 keysOK = false;
9272 break;
9273 }
9274 }
9275
9276 MOZ_ASSERT(key->isKind(ParseNodeKind::ObjectPropertyName) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(key->isKind(ParseNodeKind::ObjectPropertyName) ||
key->isKind(ParseNodeKind::StringExpr) || key->isKind(
ParseNodeKind::NumberExpr))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(key->isKind(ParseNodeKind
::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr
) || key->isKind(ParseNodeKind::NumberExpr)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("key->isKind(ParseNodeKind::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9278); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr)"
")"); do { *((volatile int*)__null) = 9278; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9277 key->isKind(ParseNodeKind::StringExpr) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(key->isKind(ParseNodeKind::ObjectPropertyName) ||
key->isKind(ParseNodeKind::StringExpr) || key->isKind(
ParseNodeKind::NumberExpr))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(key->isKind(ParseNodeKind
::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr
) || key->isKind(ParseNodeKind::NumberExpr)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("key->isKind(ParseNodeKind::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9278); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr)"
")"); do { *((volatile int*)__null) = 9278; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9278 key->isKind(ParseNodeKind::NumberExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(key->isKind(ParseNodeKind::ObjectPropertyName) ||
key->isKind(ParseNodeKind::StringExpr) || key->isKind(
ParseNodeKind::NumberExpr))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(key->isKind(ParseNodeKind
::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr
) || key->isKind(ParseNodeKind::NumberExpr)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("key->isKind(ParseNodeKind::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9278); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr)"
")"); do { *((volatile int*)__null) = 9278; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9279
9280 AccessorType accessorType =
9281 prop->is<PropertyDefinition>()
9282 ? prop->as<PropertyDefinition>().accessorType()
9283 : AccessorType::None;
9284 if (accessorType != AccessorType::None) {
9285 keysOK = false;
9286 break;
9287 }
9288
9289 if (!isRHSObjLiteralCompatible(value)) {
9290 valuesOK = false;
9291 }
9292 }
9293
9294 if (propCount > SharedPropMap::MaxPropsForNonDictionary) {
9295 // JSOp::NewObject cannot accept dictionary-mode objects.
9296 keysOK = false;
9297 }
9298
9299 *withValues = keysOK && valuesOK;
9300 *withoutValues = keysOK;
9301}
9302
9303bool BytecodeEmitter::isArrayObjLiteralCompatible(ListNode* array) const {
9304 for (ParseNode* elem : array->contents()) {
9305 if (elem->isKind(ParseNodeKind::Spread)) {
9306 return false;
9307 }
9308 if (!isRHSObjLiteralCompatible(elem)) {
9309 return false;
9310 }
9311 }
9312 return true;
9313}
9314
9315bool BytecodeEmitter::emitPropertyList(ListNode* obj, PropertyEmitter& pe,
9316 PropListType type) {
9317 // [stack] CTOR? OBJ
9318
9319 size_t curFieldKeyIndex = 0;
9320 size_t curStaticFieldKeyIndex = 0;
9321 for (ParseNode* propdef : obj->contents()) {
9322 if (propdef->is<ClassField>()) {
9323 MOZ_ASSERT(type == ClassBody)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(type == ClassBody)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(type == ClassBody))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("type == ClassBody"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9323); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == ClassBody"
")"); do { *((volatile int*)__null) = 9323; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9324 // Only handle computing field keys here: the .initializers lambda array
9325 // is created elsewhere.
9326 ClassField* field = &propdef->as<ClassField>();
9327 if (field->name().getKind() == ParseNodeKind::ComputedName) {
9328 auto fieldKeys =
9329 field->isStatic()
9330 ? TaggedParserAtomIndex::WellKnown::dot_staticFieldKeys_()
9331 : TaggedParserAtomIndex::WellKnown::dot_fieldKeys_();
9332 if (!emitGetName(fieldKeys)) {
9333 // [stack] CTOR OBJ ARRAY
9334 return false;
9335 }
9336
9337 ParseNode* nameExpr = field->name().as<UnaryNode>().kid();
9338
9339 if (!emitTree(nameExpr, ValueUsage::WantValue)) {
9340 // [stack] CTOR OBJ ARRAY KEY
9341 return false;
9342 }
9343
9344 if (!emit1(JSOp::ToPropertyKey)) {
9345 // [stack] CTOR OBJ ARRAY KEY
9346 return false;
9347 }
9348
9349 size_t fieldKeysIndex;
9350 if (field->isStatic()) {
9351 fieldKeysIndex = curStaticFieldKeyIndex++;
9352 } else {
9353 fieldKeysIndex = curFieldKeyIndex++;
9354 }
9355
9356 if (!emitUint32Operand(JSOp::InitElemArray, fieldKeysIndex)) {
9357 // [stack] CTOR OBJ ARRAY
9358 return false;
9359 }
9360
9361 if (!emit1(JSOp::Pop)) {
9362 // [stack] CTOR OBJ
9363 return false;
9364 }
9365 }
9366 continue;
9367 }
9368
9369 if (propdef->isKind(ParseNodeKind::StaticClassBlock)) {
9370 // Static class blocks are emitted as part of
9371 // emitCreateMemberInitializers.
9372 continue;
9373 }
9374
9375 if (propdef->is<LexicalScopeNode>()) {
9376 // Constructors are sometimes wrapped in LexicalScopeNodes. As we
9377 // already handled emitting the constructor, skip it.
9378 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(propdef->as<LexicalScopeNode>().scopeBody()
->is<ClassMethod>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(propdef->as<LexicalScopeNode
>().scopeBody()->is<ClassMethod>()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("propdef->as<LexicalScopeNode>().scopeBody()->is<ClassMethod>()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9379); AnnotateMozCrashReason("MOZ_ASSERT" "(" "propdef->as<LexicalScopeNode>().scopeBody()->is<ClassMethod>()"
")"); do { *((volatile int*)__null) = 9379; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9379 propdef->as<LexicalScopeNode>().scopeBody()->is<ClassMethod>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(propdef->as<LexicalScopeNode>().scopeBody()
->is<ClassMethod>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(propdef->as<LexicalScopeNode
>().scopeBody()->is<ClassMethod>()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("propdef->as<LexicalScopeNode>().scopeBody()->is<ClassMethod>()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9379); AnnotateMozCrashReason("MOZ_ASSERT" "(" "propdef->as<LexicalScopeNode>().scopeBody()->is<ClassMethod>()"
")"); do { *((volatile int*)__null) = 9379; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9380 continue;
9381 }
9382
9383 // Handle __proto__: v specially because *only* this form, and no other
9384 // involving "__proto__", performs [[Prototype]] mutation.
9385 if (propdef->isKind(ParseNodeKind::MutateProto)) {
9386 // [stack] OBJ
9387 MOZ_ASSERT(type == ObjectLiteral)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(type == ObjectLiteral)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(type == ObjectLiteral))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("type == ObjectLiteral"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9387); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == ObjectLiteral"
")"); do { *((volatile int*)__null) = 9387; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9388 if (!pe.prepareForProtoValue(propdef->pn_pos.begin)) {
9389 // [stack] OBJ
9390 return false;
9391 }
9392 if (!emitTree(propdef->as<UnaryNode>().kid())) {
9393 // [stack] OBJ PROTO
9394 return false;
9395 }
9396 if (!pe.emitMutateProto()) {
9397 // [stack] OBJ
9398 return false;
9399 }
9400 continue;
9401 }
9402
9403 if (propdef->isKind(ParseNodeKind::Spread)) {
9404 MOZ_ASSERT(type == ObjectLiteral)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(type == ObjectLiteral)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(type == ObjectLiteral))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("type == ObjectLiteral"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9404); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == ObjectLiteral"
")"); do { *((volatile int*)__null) = 9404; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9405 // [stack] OBJ
9406 if (!pe.prepareForSpreadOperand(propdef->pn_pos.begin)) {
9407 // [stack] OBJ OBJ
9408 return false;
9409 }
9410 if (!emitTree(propdef->as<UnaryNode>().kid())) {
9411 // [stack] OBJ OBJ VAL
9412 return false;
9413 }
9414 if (!pe.emitSpread()) {
9415 // [stack] OBJ
9416 return false;
9417 }
9418 continue;
9419 }
9420
9421 BinaryNode* prop = &propdef->as<BinaryNode>();
9422
9423 ParseNode* key = prop->left();
9424 AccessorType accessorType;
9425 if (prop->is<ClassMethod>()) {
9426 ClassMethod& method = prop->as<ClassMethod>();
9427 accessorType = method.accessorType();
9428
9429 if (!method.isStatic() && key->isKind(ParseNodeKind::PrivateName) &&
9430 accessorType != AccessorType::None) {
9431 // Private non-static accessors are stamped onto instances from
9432 // initializers; see emitCreateMemberInitializers.
9433 continue;
9434 }
9435 } else if (prop->is<PropertyDefinition>()) {
9436 accessorType = prop->as<PropertyDefinition>().accessorType();
9437 } else {
9438 accessorType = AccessorType::None;
9439 }
9440
9441 auto emitValue = [this, &key, &prop, accessorType, &pe]() {
9442 // [stack] CTOR? OBJ CTOR? KEY?
9443
9444 ParseNode* propVal = prop->right();
9445 if (propVal->isDirectRHSAnonFunction()) {
9446 // The following branches except for the last `else` clause emit the
9447 // cases handled in NameResolver::resolveFun (see NameFunctions.cpp)
9448 if (key->isKind(ParseNodeKind::ObjectPropertyName) ||
9449 key->isKind(ParseNodeKind::PrivateName) ||
9450 key->isKind(ParseNodeKind::StringExpr)) {
9451 auto keyAtom = key->as<NameNode>().atom();
9452 if (!emitAnonymousFunctionWithName(propVal, keyAtom)) {
9453 // [stack] CTOR? OBJ CTOR? VAL
9454 return false;
9455 }
9456 } else if (key->isKind(ParseNodeKind::NumberExpr)) {
9457 MOZ_ASSERT(accessorType == AccessorType::None)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(accessorType == AccessorType::None)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(accessorType == AccessorType
::None))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("accessorType == AccessorType::None", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9457); AnnotateMozCrashReason("MOZ_ASSERT" "(" "accessorType == AccessorType::None"
")"); do { *((volatile int*)__null) = 9457; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9458
9459 auto keyAtom = key->as<NumericLiteral>().toAtom(fc, parserAtoms());
9460 if (!keyAtom) {
9461 return false;
9462 }
9463 if (!emitAnonymousFunctionWithName(propVal, keyAtom)) {
9464 // [stack] CTOR? OBJ CTOR? KEY VAL
9465 return false;
9466 }
9467 } else if (key->isKind(ParseNodeKind::ComputedName) &&
9468 (key->as<UnaryNode>().kid()->isKind(
9469 ParseNodeKind::NumberExpr) ||
9470 key->as<UnaryNode>().kid()->isKind(
9471 ParseNodeKind::StringExpr)) &&
9472 accessorType == AccessorType::None) {
9473 ParseNode* keyKid = key->as<UnaryNode>().kid();
9474 if (keyKid->isKind(ParseNodeKind::NumberExpr)) {
9475 auto keyAtom =
9476 keyKid->as<NumericLiteral>().toAtom(fc, parserAtoms());
9477 if (!keyAtom) {
9478 return false;
9479 }
9480 if (!emitAnonymousFunctionWithName(propVal, keyAtom)) {
9481 // [stack] CTOR? OBJ CTOR? KEY VAL
9482 return false;
9483 }
9484 } else {
9485 MOZ_ASSERT(keyKid->isKind(ParseNodeKind::StringExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(keyKid->isKind(ParseNodeKind::StringExpr))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(keyKid->isKind(ParseNodeKind::StringExpr)))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("keyKid->isKind(ParseNodeKind::StringExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9485); AnnotateMozCrashReason("MOZ_ASSERT" "(" "keyKid->isKind(ParseNodeKind::StringExpr)"
")"); do { *((volatile int*)__null) = 9485; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9486 auto keyAtom = keyKid->as<NameNode>().atom();
9487 if (!emitAnonymousFunctionWithName(propVal, keyAtom)) {
9488 // [stack] CTOR? OBJ CTOR? KEY VAL
9489 return false;
9490 }
9491 }
9492 } else {
9493 // Either a proper computed property name or a synthetic computed
9494 // property name for BigInt keys.
9495 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"
, 9495); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::ComputedName)"
")"); do { *((volatile int*)__null) = 9495; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9496
9497 FunctionPrefixKind prefix =
9498 accessorType == AccessorType::None ? FunctionPrefixKind::None
9499 : accessorType == AccessorType::Getter ? FunctionPrefixKind::Get
9500 : FunctionPrefixKind::Set;
9501
9502 if (!emitAnonymousFunctionWithComputedName(propVal, prefix)) {
9503 // [stack] CTOR? OBJ CTOR? KEY VAL
9504 return false;
9505 }
9506 }
9507 } else {
9508 if (!emitTree(propVal)) {
9509 // [stack] CTOR? OBJ CTOR? KEY? VAL
9510 return false;
9511 }
9512 }
9513
9514 if (propVal->is<FunctionNode>() &&
9515 propVal->as<FunctionNode>().funbox()->needsHomeObject()) {
9516 if (!pe.emitInitHomeObject()) {
9517 // [stack] CTOR? OBJ CTOR? KEY? FUN
9518 return false;
9519 }
9520 }
9521
9522#ifdef ENABLE_DECORATORS
9523 if (prop->is<ClassMethod>()) {
9524 ClassMethod& method = prop->as<ClassMethod>();
9525 if (method.decorators() && !method.decorators()->empty()) {
9526 DecoratorEmitter::Kind kind;
9527 switch (method.accessorType()) {
9528 case AccessorType::Getter:
9529 kind = DecoratorEmitter::Getter;
9530 break;
9531 case AccessorType::Setter:
9532 kind = DecoratorEmitter::Setter;
9533 break;
9534 case AccessorType::None:
9535 kind = DecoratorEmitter::Method;
9536 break;
9537 }
9538
9539 if (!method.isStatic()) {
9540 bool hasKeyOnStack = key->isKind(ParseNodeKind::NumberExpr) ||
9541 key->isKind(ParseNodeKind::ComputedName);
9542 if (!emitDupAt(hasKeyOnStack ? 4 : 3)) {
9543 // [stack] ADDINIT OBJ KEY? VAL ADDINIT
9544 return false;
9545 }
9546 } else {
9547 // TODO: See bug 1868220 for support for static methods.
9548 // Note: Key will be present if this has a private name.
9549 if (!emit1(JSOp::Undefined)) {
9550 // [stack] CTOR OBJ CTOR KEY? VAL ADDINIT
9551 return false;
9552 }
9553 }
9554
9555 if (!emit1(JSOp::Swap)) {
9556 // [stack] ADDINIT CTOR? OBJ CTOR? KEY? ADDINIT VAL
9557 return false;
9558 }
9559
9560 // The decorators are applied to the current value on the stack,
9561 // possibly replacing it.
9562 DecoratorEmitter de(this);
9563 if (!de.emitApplyDecoratorsToElementDefinition(
9564 kind, key, method.decorators(), method.isStatic())) {
9565 // [stack] ADDINIT CTOR? OBJ CTOR? KEY? ADDINIT VAL
9566 return false;
9567 }
9568
9569 if (!emit1(JSOp::Swap)) {
9570 // [stack] ADDINIT CTOR? OBJ CTOR? KEY? VAL ADDINIT
9571 return false;
9572 }
9573
9574 if (!emitPopN(1)) {
9575 // [stack] ADDINIT CTOR? OBJ CTOR? KEY? VAL
9576 return false;
9577 }
9578 }
9579 }
9580#endif
9581
9582 return true;
9583 };
9584
9585 PropertyEmitter::Kind kind =
9586 (type == ClassBody && propdef->as<ClassMethod>().isStatic())
9587 ? PropertyEmitter::Kind::Static
9588 : PropertyEmitter::Kind::Prototype;
9589 if (key->isKind(ParseNodeKind::ObjectPropertyName) ||
9590 key->isKind(ParseNodeKind::StringExpr)) {
9591 // [stack] CTOR? OBJ
9592
9593 auto keyAtom = key->as<NameNode>().atom();
9594
9595 // emitClass took care of constructor already.
9596 if (type == ClassBody &&
9597 keyAtom == TaggedParserAtomIndex::WellKnown::constructor() &&
9598 !propdef->as<ClassMethod>().isStatic()) {
9599 continue;
9600 }
9601
9602 if (!pe.prepareForPropValue(propdef->pn_pos.begin, kind)) {
9603 // [stack] CTOR? OBJ CTOR?
9604 return false;
9605 }
9606
9607 if (!emitValue()) {
9608 // [stack] CTOR? OBJ CTOR? VAL
9609 return false;
9610 }
9611
9612 if (!pe.emitInit(accessorType, keyAtom)) {
9613 // [stack] CTOR? OBJ
9614 return false;
9615 }
9616
9617 continue;
9618 }
9619
9620 if (key->isKind(ParseNodeKind::NumberExpr)) {
9621 // [stack] CTOR? OBJ
9622 if (!pe.prepareForIndexPropKey(propdef->pn_pos.begin, kind)) {
9623 // [stack] CTOR? OBJ CTOR?
9624 return false;
9625 }
9626 if (!emitNumberOp(key->as<NumericLiteral>().value())) {
9627 // [stack] CTOR? OBJ CTOR? KEY
9628 return false;
9629 }
9630 if (!pe.prepareForIndexPropValue()) {
9631 // [stack] CTOR? OBJ CTOR? KEY
9632 return false;
9633 }
9634 if (!emitValue()) {
9635 // [stack] CTOR? OBJ CTOR? KEY VAL
9636 return false;
9637 }
9638
9639 if (!pe.emitInitIndexOrComputed(accessorType)) {
9640 // [stack] CTOR? OBJ
9641 return false;
9642 }
9643
9644 continue;
9645 }
9646
9647 if (key->isKind(ParseNodeKind::ComputedName)) {
9648 // Either a proper computed property name or a synthetic computed property
9649 // name for BigInt keys.
9650
9651 // [stack] CTOR? OBJ
9652
9653 if (!pe.prepareForComputedPropKey(propdef->pn_pos.begin, kind)) {
9654 // [stack] CTOR? OBJ CTOR?
9655 return false;
9656 }
9657 if (!emitTree(key->as<UnaryNode>().kid())) {
9658 // [stack] CTOR? OBJ CTOR? KEY
9659 return false;
9660 }
9661 if (!pe.prepareForComputedPropValue()) {
9662 // [stack] CTOR? OBJ CTOR? KEY
9663 return false;
9664 }
9665 if (!emitValue()) {
9666 // [stack] CTOR? OBJ CTOR? KEY VAL
9667 return false;
9668 }
9669
9670 if (!pe.emitInitIndexOrComputed(accessorType)) {
9671 // [stack] CTOR? OBJ
9672 return false;
9673 }
9674
9675 continue;
9676 }
9677
9678 MOZ_ASSERT(key->isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(key->isKind(ParseNodeKind::PrivateName))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(key->isKind(ParseNodeKind::PrivateName)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("key->isKind(ParseNodeKind::PrivateName)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9678); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 9678; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9679 MOZ_ASSERT(type == ClassBody)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(type == ClassBody)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(type == ClassBody))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("type == ClassBody"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9679); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == ClassBody"
")"); do { *((volatile int*)__null) = 9679; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9680
9681 auto* privateName = &key->as<NameNode>();
9682
9683 if (kind == PropertyEmitter::Kind::Prototype) {
9684 MOZ_ASSERT(accessorType == AccessorType::None)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(accessorType == AccessorType::None)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(accessorType == AccessorType
::None))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("accessorType == AccessorType::None", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9684); AnnotateMozCrashReason("MOZ_ASSERT" "(" "accessorType == AccessorType::None"
")"); do { *((volatile int*)__null) = 9684; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9685 if (!pe.prepareForPrivateMethod()) {
9686 // [stack] CTOR OBJ
9687 return false;
9688 }
9689 NameOpEmitter noe(this, privateName->atom(),
9690 NameOpEmitter::Kind::SimpleAssignment);
9691
9692 // Ensure the NameOp emitter doesn't push an environment onto the stack,
9693 // because that would change the stack location of the home object.
9694 MOZ_ASSERT(noe.loc().kind() == NameLocation::Kind::FrameSlot ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(noe.loc().kind() == NameLocation::Kind::FrameSlot ||
noe.loc().kind() == NameLocation::Kind::EnvironmentCoordinate
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(noe.loc().kind() == NameLocation::Kind::FrameSlot ||
noe.loc().kind() == NameLocation::Kind::EnvironmentCoordinate
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"noe.loc().kind() == NameLocation::Kind::FrameSlot || noe.loc().kind() == NameLocation::Kind::EnvironmentCoordinate"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9695); AnnotateMozCrashReason("MOZ_ASSERT" "(" "noe.loc().kind() == NameLocation::Kind::FrameSlot || noe.loc().kind() == NameLocation::Kind::EnvironmentCoordinate"
")"); do { *((volatile int*)__null) = 9695; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9695 noe.loc().kind() == NameLocation::Kind::EnvironmentCoordinate)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(noe.loc().kind() == NameLocation::Kind::FrameSlot ||
noe.loc().kind() == NameLocation::Kind::EnvironmentCoordinate
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(noe.loc().kind() == NameLocation::Kind::FrameSlot ||
noe.loc().kind() == NameLocation::Kind::EnvironmentCoordinate
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"noe.loc().kind() == NameLocation::Kind::FrameSlot || noe.loc().kind() == NameLocation::Kind::EnvironmentCoordinate"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9695); AnnotateMozCrashReason("MOZ_ASSERT" "(" "noe.loc().kind() == NameLocation::Kind::FrameSlot || noe.loc().kind() == NameLocation::Kind::EnvironmentCoordinate"
")"); do { *((volatile int*)__null) = 9695; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9696
9697 if (!noe.prepareForRhs()) {
9698 // [stack] CTOR OBJ
9699 return false;
9700 }
9701 if (!emitValue()) {
9702 // [stack] CTOR OBJ METHOD
9703 return false;
9704 }
9705 if (!noe.emitAssignment()) {
9706 // [stack] CTOR OBJ METHOD
9707 return false;
9708 }
9709 if (!emit1(JSOp::Pop)) {
9710 // [stack] CTOR OBJ
9711 return false;
9712 }
9713 if (!pe.skipInit()) {
9714 // [stack] CTOR OBJ
9715 return false;
9716 }
9717 continue;
9718 }
9719
9720 MOZ_ASSERT(kind == PropertyEmitter::Kind::Static)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(kind == PropertyEmitter::Kind::Static)>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(kind == PropertyEmitter::Kind::Static))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("kind == PropertyEmitter::Kind::Static"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9720); AnnotateMozCrashReason("MOZ_ASSERT" "(" "kind == PropertyEmitter::Kind::Static"
")"); do { *((volatile int*)__null) = 9720; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9721
9722 // [stack] CTOR OBJ
9723
9724 if (!pe.prepareForPrivateStaticMethod(propdef->pn_pos.begin)) {
9725 // [stack] CTOR OBJ CTOR
9726 return false;
9727 }
9728 if (!emitGetPrivateName(privateName)) {
9729 // [stack] CTOR OBJ CTOR KEY
9730 return false;
9731 }
9732 if (!emitValue()) {
9733 // [stack] CTOR OBJ CTOR KEY VAL
9734 return false;
9735 }
9736
9737 if (!pe.emitPrivateStaticMethod(accessorType)) {
9738 // [stack] CTOR OBJ
9739 return false;
9740 }
9741
9742 if (privateName->privateNameKind() == PrivateNameKind::Setter) {
9743 if (!emitDupAt(1)) {
9744 // [stack] CTOR OBJ CTOR
9745 return false;
9746 }
9747 if (!emitGetPrivateName(privateName)) {
9748 // [stack] CTOR OBJ CTOR NAME
9749 return false;
9750 }
9751 if (!emitAtomOp(JSOp::GetIntrinsic,
9752 TaggedParserAtomIndex::WellKnown::NoPrivateGetter())) {
9753 // [stack] CTOR OBJ CTOR NAME FUN
9754 return false;
9755 }
9756 if (!emit1(JSOp::InitHiddenElemGetter)) {
9757 // [stack] CTOR OBJ CTOR
9758 return false;
9759 }
9760 if (!emit1(JSOp::Pop)) {
9761 // [stack] CTOR OBJ
9762 return false;
9763 }
9764 }
9765 }
9766
9767 return true;
9768}
9769
9770bool BytecodeEmitter::emitPropertyListObjLiteral(ListNode* obj, JSOp op,
9771 bool useObjLiteralValues) {
9772 ObjLiteralWriter writer;
9773
9774#ifdef DEBUG1
9775 // In self-hosted JS, we check duplication only on debug build.
9776 mozilla::Maybe<mozilla::HashSet<frontend::TaggedParserAtomIndex,
9777 frontend::TaggedParserAtomIndexHasher>>
9778 selfHostedPropNames;
9779 if (emitterMode == BytecodeEmitter::SelfHosting) {
9780 selfHostedPropNames.emplace();
9781 }
9782#endif
9783
9784 if (op == JSOp::Object) {
9785 writer.beginObject(op);
9786 } else {
9787 MOZ_ASSERT(op == JSOp::NewObject)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(op == JSOp::NewObject)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(op == JSOp::NewObject))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("op == JSOp::NewObject"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9787); AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::NewObject"
")"); do { *((volatile int*)__null) = 9787; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9788 writer.beginShape(op);
9789 }
9790
9791 for (ParseNode* propdef : obj->contents()) {
9792 BinaryNode* prop = &propdef->as<BinaryNode>();
9793 ParseNode* key = prop->left();
9794
9795 if (key->is<NameNode>()) {
9796 if (emitterMode == BytecodeEmitter::SelfHosting) {
9797 auto propName = key->as<NameNode>().atom();
9798#ifdef DEBUG1
9799 // Self-hosted JS shouldn't contain duplicate properties.
9800 auto p = selfHostedPropNames->lookupForAdd(propName);
9801 MOZ_ASSERT(!p)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!p)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(!p))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("!p", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9801); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!p" ")"); do
{ *((volatile int*)__null) = 9801; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
9802 if (!selfHostedPropNames->add(p, propName)) {
9803 js::ReportOutOfMemory(fc);
9804 return false;
9805 }
9806#endif
9807 writer.setPropNameNoDuplicateCheck(parserAtoms(), propName);
9808 } else {
9809 if (!writer.setPropName(parserAtoms(), key->as<NameNode>().atom())) {
9810 return false;
9811 }
9812 }
9813 } else {
9814 double numValue = key->as<NumericLiteral>().value();
9815 int32_t i = 0;
9816 DebugOnly<bool> numIsInt =
9817 NumberIsInt32(numValue, &i); // checked previously.
9818 MOZ_ASSERT(numIsInt)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(numIsInt)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(numIsInt))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("numIsInt", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9818); AnnotateMozCrashReason("MOZ_ASSERT" "(" "numIsInt" ")"
); do { *((volatile int*)__null) = 9818; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9819 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(ObjLiteralWriter::arrayIndexInRange(i))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(ObjLiteralWriter::arrayIndexInRange(i)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("ObjLiteralWriter::arrayIndexInRange(i)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9820); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ObjLiteralWriter::arrayIndexInRange(i)"
")"); do { *((volatile int*)__null) = 9820; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9820 ObjLiteralWriter::arrayIndexInRange(i))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(ObjLiteralWriter::arrayIndexInRange(i))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(ObjLiteralWriter::arrayIndexInRange(i)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("ObjLiteralWriter::arrayIndexInRange(i)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9820); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ObjLiteralWriter::arrayIndexInRange(i)"
")"); do { *((volatile int*)__null) = 9820; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
; // checked previously.
9821
9822 // Ignore indexed properties if we're not storing property values, and
9823 // rely on InitElem ops to define those. These properties will be either
9824 // dense elements (not possible to represent in the literal's shape) or
9825 // sparse elements (enumerated separately, so this doesn't affect property
9826 // iteration order).
9827 if (!useObjLiteralValues) {
9828 continue;
9829 }
9830
9831 writer.setPropIndex(i);
9832 }
9833
9834 if (useObjLiteralValues) {
9835 MOZ_ASSERT(op == JSOp::Object)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(op == JSOp::Object)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(op == JSOp::Object))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("op == JSOp::Object"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9835); AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::Object"
")"); do { *((volatile int*)__null) = 9835; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9836 ParseNode* value = prop->right();
9837 if (!emitObjLiteralValue(writer, value)) {
9838 return false;
9839 }
9840 } else {
9841 if (!writer.propWithUndefinedValue(fc)) {
9842 return false;
9843 }
9844 }
9845 }
9846
9847 GCThingIndex index;
9848 if (!addObjLiteralData(writer, &index)) {
9849 return false;
9850 }
9851
9852 // JSOp::Object may only be used by (top-level) run-once scripts.
9853 MOZ_ASSERT_IF(op == JSOp::Object,do { if (op == JSOp::Object) { do { static_assert( mozilla::detail
::AssertionConditionType<decltype(sc->isTopLevelContext
() && sc->treatAsRunOnce())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sc->isTopLevelContext() &&
sc->treatAsRunOnce()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("sc->isTopLevelContext() && sc->treatAsRunOnce()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9854); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isTopLevelContext() && sc->treatAsRunOnce()"
")"); do { *((volatile int*)__null) = 9854; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
9854 sc->isTopLevelContext() && sc->treatAsRunOnce())do { if (op == JSOp::Object) { do { static_assert( mozilla::detail
::AssertionConditionType<decltype(sc->isTopLevelContext
() && sc->treatAsRunOnce())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sc->isTopLevelContext() &&
sc->treatAsRunOnce()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("sc->isTopLevelContext() && sc->treatAsRunOnce()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9854); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isTopLevelContext() && sc->treatAsRunOnce()"
")"); do { *((volatile int*)__null) = 9854; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
9855
9856 if (!emitGCIndexOp(op, index)) {
9857 // [stack] OBJ
9858 return false;
9859 }
9860
9861 return true;
9862}
9863
9864bool BytecodeEmitter::emitDestructuringRestExclusionSetObjLiteral(
9865 ListNode* pattern) {
9866 // Note: if we want to squeeze out a little more performance, we could switch
9867 // to the `JSOp::Object` opcode, because the exclusion set object is never
9868 // exposed to the user, so it's safe to bake the object into the bytecode.
9869 constexpr JSOp op = JSOp::NewObject;
9870
9871 ObjLiteralWriter writer;
9872 writer.beginShape(op);
9873
9874 for (ParseNode* member : pattern->contents()) {
9875 if (member->isKind(ParseNodeKind::Spread)) {
9876 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"
, 9876); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!member->pn_next"
") (" "unexpected trailing element after spread" ")"); do { *
((volatile int*)__null) = 9876; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
9877 break;
9878 }
9879
9880 TaggedParserAtomIndex atom;
9881 if (member->isKind(ParseNodeKind::MutateProto)) {
9882 atom = TaggedParserAtomIndex::WellKnown::proto_();
9883 } else {
9884 ParseNode* key = member->as<BinaryNode>().left();
9885 atom = key->as<NameNode>().atom();
9886 }
9887
9888 if (!writer.setPropName(parserAtoms(), atom)) {
9889 return false;
9890 }
9891
9892 if (!writer.propWithUndefinedValue(fc)) {
9893 return false;
9894 }
9895 }
9896
9897 GCThingIndex index;
9898 if (!addObjLiteralData(writer, &index)) {
9899 return false;
9900 }
9901
9902 if (!emitGCIndexOp(op, index)) {
9903 // [stack] OBJ
9904 return false;
9905 }
9906
9907 return true;
9908}
9909
9910bool BytecodeEmitter::emitObjLiteralArray(ListNode* array) {
9911 MOZ_ASSERT(checkSingletonContext())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(checkSingletonContext())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(checkSingletonContext()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("checkSingletonContext()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9911); AnnotateMozCrashReason("MOZ_ASSERT" "(" "checkSingletonContext()"
")"); do { *((volatile int*)__null) = 9911; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9912
9913 constexpr JSOp op = JSOp::Object;
9914
9915 ObjLiteralWriter writer;
9916 writer.beginArray(op);
9917
9918 writer.beginDenseArrayElements();
9919 for (ParseNode* elem : array->contents()) {
9920 if (!emitObjLiteralValue(writer, elem)) {
9921 return false;
9922 }
9923 }
9924
9925 GCThingIndex index;
9926 if (!addObjLiteralData(writer, &index)) {
9927 return false;
9928 }
9929
9930 if (!emitGCIndexOp(op, index)) {
9931 // [stack] OBJ
9932 return false;
9933 }
9934
9935 return true;
9936}
9937
9938bool BytecodeEmitter::isRHSObjLiteralCompatible(ParseNode* value) const {
9939 return value->isKind(ParseNodeKind::NumberExpr) ||
9940 value->isKind(ParseNodeKind::TrueExpr) ||
9941 value->isKind(ParseNodeKind::FalseExpr) ||
9942 value->isKind(ParseNodeKind::NullExpr) ||
9943 value->isKind(ParseNodeKind::RawUndefinedExpr) ||
9944 value->isKind(ParseNodeKind::StringExpr) ||
9945 value->isKind(ParseNodeKind::TemplateStringExpr);
9946}
9947
9948bool BytecodeEmitter::emitObjLiteralValue(ObjLiteralWriter& writer,
9949 ParseNode* value) {
9950 MOZ_ASSERT(isRHSObjLiteralCompatible(value))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(isRHSObjLiteralCompatible(value))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(isRHSObjLiteralCompatible(value
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("isRHSObjLiteralCompatible(value)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9950); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isRHSObjLiteralCompatible(value)"
")"); do { *((volatile int*)__null) = 9950; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9951 if (value->isKind(ParseNodeKind::NumberExpr)) {
9952 double numValue = value->as<NumericLiteral>().value();
9953 int32_t i = 0;
9954 js::Value v;
9955 if (NumberIsInt32(numValue, &i)) {
9956 v.setInt32(i);
9957 } else {
9958 v.setDouble(numValue);
9959 }
9960 if (!writer.propWithConstNumericValue(fc, v)) {
9961 return false;
9962 }
9963 } else if (value->isKind(ParseNodeKind::TrueExpr)) {
9964 if (!writer.propWithTrueValue(fc)) {
9965 return false;
9966 }
9967 } else if (value->isKind(ParseNodeKind::FalseExpr)) {
9968 if (!writer.propWithFalseValue(fc)) {
9969 return false;
9970 }
9971 } else if (value->isKind(ParseNodeKind::NullExpr)) {
9972 if (!writer.propWithNullValue(fc)) {
9973 return false;
9974 }
9975 } else if (value->isKind(ParseNodeKind::RawUndefinedExpr)) {
9976 if (!writer.propWithUndefinedValue(fc)) {
9977 return false;
9978 }
9979 } else if (value->isKind(ParseNodeKind::StringExpr) ||
9980 value->isKind(ParseNodeKind::TemplateStringExpr)) {
9981 if (!writer.propWithAtomValue(fc, parserAtoms(),
9982 value->as<NameNode>().atom())) {
9983 return false;
9984 }
9985 } else {
9986 MOZ_CRASH("Unexpected parse node")do { do { } while (false); MOZ_ReportCrash("" "Unexpected parse node"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9986); AnnotateMozCrashReason("MOZ_CRASH(" "Unexpected parse node"
")"); do { *((volatile int*)__null) = 9986; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
9987 }
9988 return true;
9989}
9990
9991static bool NeedsPrivateBrand(ParseNode* member) {
9992 return member->is<ClassMethod>() &&
9993 member->as<ClassMethod>().name().isKind(ParseNodeKind::PrivateName) &&
9994 !member->as<ClassMethod>().isStatic();
9995}
9996
9997#ifdef ENABLE_DECORATORS
9998static bool HasDecorators(ParseNode* member) {
9999 return member->is<ClassMethod>() && member->as<ClassMethod>().decorators();
10000}
10001#endif
10002
10003mozilla::Maybe<MemberInitializers> BytecodeEmitter::setupMemberInitializers(
10004 ListNode* classMembers, FieldPlacement placement) const {
10005 bool isStatic = placement == FieldPlacement::Static;
10006
10007 size_t numFields = 0;
10008 size_t numPrivateInitializers = 0;
10009 bool hasPrivateBrand = false;
10010#ifdef ENABLE_DECORATORS
10011 bool hasDecorators = false;
10012#endif
10013 for (ParseNode* member : classMembers->contents()) {
10014 if (NeedsFieldInitializer(member, isStatic)) {
10015 numFields++;
10016 } else if (NeedsAccessorInitializer(member, isStatic)) {
10017 numPrivateInitializers++;
10018 hasPrivateBrand = true;
10019 } else if (NeedsPrivateBrand(member)) {
10020 hasPrivateBrand = true;
10021 }
10022#ifdef ENABLE_DECORATORS
10023 if (!hasDecorators && HasDecorators(member)) {
10024 hasDecorators = true;
10025 }
10026#endif
10027 }
10028
10029 // If there are more initializers than can be represented, return invalid.
10030 if (numFields + numPrivateInitializers >
10031 MemberInitializers::MaxInitializers) {
10032 return Nothing();
10033 }
10034 return Some(MemberInitializers(hasPrivateBrand,
10035#ifdef ENABLE_DECORATORS
10036 hasDecorators,
10037#endif
10038 numFields + numPrivateInitializers));
10039}
10040
10041// Purpose of .fieldKeys:
10042// Computed field names (`["x"] = 2;`) must be ran at class-evaluation time,
10043// not object construction time. The transformation to do so is roughly as
10044// follows:
10045//
10046// class C {
10047// [keyExpr] = valueExpr;
10048// }
10049// -->
10050// let .fieldKeys = [keyExpr];
10051// let .initializers = [
10052// () => {
10053// this[.fieldKeys[0]] = valueExpr;
10054// }
10055// ];
10056// class C {
10057// constructor() {
10058// .initializers[0]();
10059// }
10060// }
10061//
10062// BytecodeEmitter::emitCreateFieldKeys does `let .fieldKeys = [...];`
10063// BytecodeEmitter::emitPropertyList fills in the elements of the array.
10064// See GeneralParser::fieldInitializer for the `this[.fieldKeys[0]]` part.
10065bool BytecodeEmitter::emitCreateFieldKeys(ListNode* obj,
10066 FieldPlacement placement) {
10067 bool isStatic = placement == FieldPlacement::Static;
10068 auto isFieldWithComputedName = [isStatic](ParseNode* propdef) {
10069 return propdef->is<ClassField>() &&
10070 propdef->as<ClassField>().isStatic() == isStatic &&
10071 propdef->as<ClassField>().name().getKind() ==
10072 ParseNodeKind::ComputedName;
10073 };
10074
10075 size_t numFieldKeys = std::count_if(
10076 obj->contents().begin(), obj->contents().end(), isFieldWithComputedName);
10077 if (numFieldKeys == 0) {
10078 return true;
10079 }
10080
10081 auto fieldKeys =
10082 isStatic ? TaggedParserAtomIndex::WellKnown::dot_staticFieldKeys_()
10083 : TaggedParserAtomIndex::WellKnown::dot_fieldKeys_();
10084 NameOpEmitter noe(this, fieldKeys, NameOpEmitter::Kind::Initialize);
10085 if (!noe.prepareForRhs()) {
10086 return false;
10087 }
10088
10089 if (!emitUint32Operand(JSOp::NewArray, numFieldKeys)) {
10090 // [stack] ARRAY
10091 return false;
10092 }
10093
10094 if (!noe.emitAssignment()) {
10095 // [stack] ARRAY
10096 return false;
10097 }
10098
10099 if (!emit1(JSOp::Pop)) {
10100 // [stack]
10101 return false;
10102 }
10103
10104 return true;
10105}
10106
10107static bool HasInitializer(ParseNode* node, bool isStaticContext) {
10108 return (node->is<ClassField>() &&
10109 node->as<ClassField>().isStatic() == isStaticContext) ||
10110 (isStaticContext && node->is<StaticClassBlock>());
10111}
10112
10113static FunctionNode* GetInitializer(ParseNode* node, bool isStaticContext) {
10114 MOZ_ASSERT(HasInitializer(node, isStaticContext))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(HasInitializer(node, isStaticContext))>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(HasInitializer(node, isStaticContext)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("HasInitializer(node, isStaticContext)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 10114); AnnotateMozCrashReason("MOZ_ASSERT" "(" "HasInitializer(node, isStaticContext)"
")"); do { *((volatile int*)__null) = 10114; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10115 MOZ_ASSERT_IF(!node->is<ClassField>(), isStaticContext)do { if (!node->is<ClassField>()) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(isStaticContext
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(isStaticContext))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("isStaticContext", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 10115); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isStaticContext"
")"); do { *((volatile int*)__null) = 10115; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
10116 return node->is<ClassField>() ? node->as<ClassField>().initializer()
10117 : node->as<StaticClassBlock>().function();
10118}
10119
10120static bool IsPrivateInstanceAccessor(const ClassMethod* classMethod) {
10121 return !classMethod->isStatic() &&
10122 classMethod->name().isKind(ParseNodeKind::PrivateName) &&
10123 classMethod->accessorType() != AccessorType::None;
10124}
10125
10126bool BytecodeEmitter::emitCreateMemberInitializers(ClassEmitter& ce,
10127 ListNode* obj,
10128 FieldPlacement placement
10129#ifdef ENABLE_DECORATORS
10130 ,
10131 bool hasHeritage
10132#endif
10133) {
10134 // FieldPlacement::Instance, hasHeritage == false
10135 // [stack] HOME
10136 //
10137 // FieldPlacement::Instance, hasHeritage == true
10138 // [stack] HOME HERIT
10139 //
10140 // FieldPlacement::Static
10141 // [stack] CTOR HOME
10142#ifdef ENABLE_DECORATORS
10143 MOZ_ASSERT_IF(placement == FieldPlacement::Static, !hasHeritage)do { if (placement == FieldPlacement::Static) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(!hasHeritage
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!hasHeritage))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!hasHeritage", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 10143); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!hasHeritage"
")"); do { *((volatile int*)__null) = 10143; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
10144#endif
10145 mozilla::Maybe<MemberInitializers> memberInitializers =
10146 setupMemberInitializers(obj, placement);
10147 if (!memberInitializers) {
10148 ReportAllocationOverflow(fc);
10149 return false;
10150 }
10151
10152 size_t numInitializers = memberInitializers->numMemberInitializers;
10153 if (numInitializers == 0) {
10154 return true;
10155 }
10156
10157 bool isStatic = placement == FieldPlacement::Static;
10158 if (!ce.prepareForMemberInitializers(numInitializers, isStatic)) {
10159 // [stack] HOME HERIT? ARR
10160 // or:
10161 // [stack] CTOR HOME ARR
10162 return false;
10163 }
10164
10165 // Private accessors could be used in the field initializers, so make sure
10166 // accessor initializers appear earlier in the .initializers array so they
10167 // run first. Static private methods are not initialized using initializers
10168 // (emitPropertyList emits bytecode to stamp them onto the constructor), so
10169 // skip this step if isStatic.
10170 if (!isStatic) {
10171 if (!emitPrivateMethodInitializers(ce, obj)) {
10172 return false;
10173 }
10174 }
10175
10176 for (ParseNode* propdef : obj->contents()) {
10177 if (!HasInitializer(propdef, isStatic)) {
10178 continue;
10179 }
10180
10181 FunctionNode* initializer = GetInitializer(propdef, isStatic);
10182
10183 if (!ce.prepareForMemberInitializer()) {
10184 return false;
10185 }
10186 if (!emitTree(initializer)) {
10187 // [stack] HOME HERIT? ARR LAMBDA
10188 // or:
10189 // [stack] CTOR HOME ARR LAMBDA
10190 return false;
10191 }
10192 if (initializer->funbox()->needsHomeObject()) {
10193 MOZ_ASSERT(initializer->funbox()->allowSuperProperty())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(initializer->funbox()->allowSuperProperty())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(initializer->funbox()->allowSuperProperty())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("initializer->funbox()->allowSuperProperty()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 10193); AnnotateMozCrashReason("MOZ_ASSERT" "(" "initializer->funbox()->allowSuperProperty()"
")"); do { *((volatile int*)__null) = 10193; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10194 if (!ce.emitMemberInitializerHomeObject(isStatic)) {
10195 // [stack] HOME HERIT? ARR LAMBDA
10196 // or:
10197 // [stack] CTOR HOME ARR LAMBDA
10198 return false;
10199 }
10200 }
10201 if (!ce.emitStoreMemberInitializer()) {
10202 // [stack] HOME HERIT? ARR
10203 // or:
10204 // [stack] CTOR HOME ARR
10205 return false;
10206 }
10207 }
10208
10209#ifdef ENABLE_DECORATORS
10210 // Index to use to append new initializers returned by decorators to the array
10211 if (!emitNumberOp(numInitializers)) {
10212 // [stack] HOME HERIT? ARR I
10213 // or:
10214 // [stack] CTOR HOME ARR I
10215 return false;
10216 }
10217
10218 for (ParseNode* propdef : obj->contents()) {
10219 if (!propdef->is<ClassField>()) {
10220 continue;
10221 }
10222 ClassField* field = &propdef->as<ClassField>();
10223 if (field->isStatic() != isStatic) {
10224 continue;
10225 }
10226 if (field->decorators() && !field->decorators()->empty()) {
10227 DecoratorEmitter de(this);
10228 if (!field->hasAccessor()) {
10229 if (!emitDupAt((hasHeritage || isStatic) ? 4 : 3)) {
10230 // [stack] ADDINIT HOME HERIT? ARR I ADDINIT
10231 // or:
10232 // [stack] ADDINIT CTOR HOME ARR I ADDINIT
10233 return false;
10234 }
10235 if (!de.emitApplyDecoratorsToFieldDefinition(
10236 &field->name(), field->decorators(), field->isStatic())) {
10237 // [stack] HOME HERIT? ARR I ADDINIT INITS
10238 // or:
10239 // [stack] CTOR HOME ARR I ADDINIT INITS
10240 return false;
10241 }
10242 if (!emit1(JSOp::Swap)) {
10243 // [stack] HOME HERIT? ARR I INITS ADDINIT
10244 // or:
10245 // [stack] CTOR HOME ARR I INITS ADDINIT
10246 return false;
10247 }
10248 if (!emitPopN(1)) {
10249 // [stack] ADDINIT HOME HERIT? ARR I INITS
10250 // or:
10251 // [stack] ADDINIT CTOR HOME ARR I INITS
10252 return false;
10253 }
10254 } else {
10255 ClassMethod* accessorGetterNode = field->accessorGetterNode();
10256 auto accessorGetterKeyAtom =
10257 accessorGetterNode->left()->as<NameNode>().atom();
10258 ClassMethod* accessorSetterNode = field->accessorSetterNode();
10259 auto accessorSetterKeyAtom =
10260 accessorSetterNode->left()->as<NameNode>().atom();
10261 if (!IsPrivateInstanceAccessor(accessorGetterNode)) {
10262 if (!emitTree(&accessorGetterNode->method())) {
10263 // [stack] ADDINIT HOME HERIT? ARR I GET
10264 // or:
10265 // [stack] ADDINIT CTOR HOME ARR I GET
10266 return false;
10267 }
10268 if (!emitTree(&accessorSetterNode->method())) {
10269 // [stack] ADDINIT HOME HERIT? ARR I GET
10270 // SET
10271 // or:
10272 // [stack] ADDINIT CTOR HOME ARR I GET SET
10273 return false;
10274 }
10275 } else {
10276 MOZ_ASSERT(IsPrivateInstanceAccessor(accessorSetterNode))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsPrivateInstanceAccessor(accessorSetterNode))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(IsPrivateInstanceAccessor(accessorSetterNode)))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("IsPrivateInstanceAccessor(accessorSetterNode)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 10276); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsPrivateInstanceAccessor(accessorSetterNode)"
")"); do { *((volatile int*)__null) = 10276; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10277 auto getAccessor = [this](
10278 ClassMethod* classMethod,
10279 TaggedParserAtomIndex& updatedAtom) -> bool {
10280 // [stack]
10281
10282 // Synthesize a name for the lexical variable that will store the
10283 // private method body.
10284 TaggedParserAtomIndex name =
10285 classMethod->name().as<NameNode>().atom();
10286 AccessorType accessorType = classMethod->accessorType();
10287 StringBuilder storedMethodName(fc);
10288 if (!storedMethodName.append(parserAtoms(), name)) {
10289 return false;
10290 }
10291 if (!storedMethodName.append(accessorType == AccessorType::Getter
10292 ? ".getter"
10293 : ".setter")) {
10294 return false;
10295 }
10296 updatedAtom = storedMethodName.finishParserAtom(parserAtoms(), fc);
10297 if (!updatedAtom) {
10298 return false;
10299 }
10300
10301 return emitGetName(updatedAtom);
10302 // [stack] ACCESSOR
10303 };
10304
10305 if (!getAccessor(accessorGetterNode, accessorGetterKeyAtom)) {
10306 // [stack] ADDINIT HOME HERIT? ARR I GET
10307 // or:
10308 // [stack] ADDINIT CTOR HOME ARR I GET
10309 return false;
10310 };
10311
10312 if (!getAccessor(accessorSetterNode, accessorSetterKeyAtom)) {
10313 // [stack] ADDINIT HOME HERIT? ARR I GET SET
10314 // or:
10315 // [stack] ADDINIT CTOR HOME ARR I GET SET
10316 return false;
10317 };
10318 }
10319
10320 if (!emitDupAt((hasHeritage || isStatic) ? 6 : 5)) {
10321 // [stack] ADDINIT HOME HERIT? ARR I GET SET ADDINIT
10322 // or:
10323 // [stack] ADDINIT CTOR HOME ARR I GET SET ADDINIT
10324 return false;
10325 }
10326
10327 if (!emitUnpickN(2)) {
10328 // [stack] ADDINIT HOME HERIT? ARR I ADDINIT GET SET
10329 // or:
10330 // [stack] ADDINIT CTOR HOME ARR I ADDINIT GET SET
10331 return false;
10332 }
10333
10334 if (!de.emitApplyDecoratorsToAccessorDefinition(
10335 &field->name(), field->decorators(), field->isStatic())) {
10336 // [stack] ADDINIT HOME HERIT? ARR I ADDINIT GET SET INITS
10337 // or:
10338 // [stack] ADDINIT CTOR HOME ARR I ADDINIT GET SET INITS
10339 return false;
10340 }
10341
10342 if (!emitPickN(3)) {
10343 // [stack] HOME HERIT? ARR I GET SET INITS ADDINIT
10344 // or:
10345 // [stack] CTOR HOME ARR I GET SET INITS ADDINIT
10346 return false;
10347 }
10348
10349 if (!emitPopN(1)) {
10350 // [stack] ADDINIT HOME HERIT? ARR I GET SET INITS
10351 // or:
10352 // [stack] ADDINIT CTOR HOME ARR I GET SET INITS
10353 return false;
10354 }
10355
10356 if (!emitUnpickN(2)) {
10357 // [stack] ADDINIT HOME HERIT? ARR I INITS GET SET
10358 // or:
10359 // [stack] ADDINIT CTOR HOME ARR I INITS GET SET
10360 return false;
10361 }
10362
10363 if (!IsPrivateInstanceAccessor(accessorGetterNode)) {
10364 if (!isStatic) {
10365 if (!emitDupAt(hasHeritage ? 6 : 5)) {
10366 // [stack] ADDINIT HOME HERIT? ARR I INITS GET SET HOME
10367 return false;
10368 }
10369 } else {
10370 if (!emitDupAt(6)) {
10371 // [stack] ADDINIT CTOR HOME ARR I INITS GET SET CTOR
10372 return false;
10373 }
10374 if (!emitDupAt(6)) {
10375 // [stack] ADDINIT CTOR HOME ARR I INITS GET SET CTOR HOME
10376 return false;
10377 }
10378 }
10379
10380 PropertyEmitter::Kind kind = field->isStatic()
10381 ? PropertyEmitter::Kind::Static
10382 : PropertyEmitter::Kind::Prototype;
10383 if (!accessorGetterNode->name().isKind(ParseNodeKind::PrivateName)) {
10384 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!accessorSetterNode->name().isKind(ParseNodeKind::
PrivateName))>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(!accessorSetterNode->name().isKind
(ParseNodeKind::PrivateName)))), 0))) { do { } while (false);
MOZ_ReportAssertionFailure("!accessorSetterNode->name().isKind(ParseNodeKind::PrivateName)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 10385); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!accessorSetterNode->name().isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 10385; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10385 !accessorSetterNode->name().isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!accessorSetterNode->name().isKind(ParseNodeKind::
PrivateName))>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(!accessorSetterNode->name().isKind
(ParseNodeKind::PrivateName)))), 0))) { do { } while (false);
MOZ_ReportAssertionFailure("!accessorSetterNode->name().isKind(ParseNodeKind::PrivateName)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 10385); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!accessorSetterNode->name().isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 10385; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10386
10387 if (!ce.prepareForPropValue(propdef->pn_pos.begin, kind)) {
10388 // [stack] ADDINIT HOME HERIT? ARR I INITS GET SET HOME
10389 // or:
10390 // [stack] ADDINIT CTOR HOME ARR I INITS GET SET CTOR HOME CTOR
10391 return false;
10392 }
10393 if (!emitPickN(isStatic ? 3 : 1)) {
10394 // [stack] ADDINIT HOME HERIT? ARR I INITS GET HOME SET
10395 // or:
10396 // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME CTOR SET
10397 return false;
10398 }
10399 if (!ce.emitInit(AccessorType::Setter, accessorSetterKeyAtom)) {
10400 // [stack] ADDINIT HOME HERIT? ARR I INITS GET HOME
10401 // or:
10402 // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME
10403 return false;
10404 }
10405
10406 if (!ce.prepareForPropValue(propdef->pn_pos.begin, kind)) {
10407 // [stack] ADDINIT HOME HERIT? ARR I INITS GET HOME
10408 // or:
10409 // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME CTOR
10410 return false;
10411 }
10412 if (!emitPickN(isStatic ? 3 : 1)) {
10413 // [stack] ADDINIT HOME HERIT? ARR I INITS HOME GET
10414 // or:
10415 // [stack] ADDINIT CTOR HOME ARR I INITS CTOR HOME CTOR GET
10416 return false;
10417 }
10418 if (!ce.emitInit(AccessorType::Getter, accessorGetterKeyAtom)) {
10419 // [stack] ADDINIT HOME HERIT? ARR I INITS HOME
10420 // or:
10421 // [stack] ADDINIT CTOR HOME ARR I INITS CTOR HOME
10422 return false;
10423 }
10424 } else {
10425 MOZ_ASSERT(isStatic)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(isStatic)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(isStatic))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("isStatic", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 10425); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isStatic" ")"
); do { *((volatile int*)__null) = 10425; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10426 // The getter and setter share the same name.
10427 if (!emitNewPrivateName(accessorSetterKeyAtom,
10428 accessorSetterKeyAtom)) {
10429 return false;
10430 }
10431 if (!ce.prepareForPrivateStaticMethod(propdef->pn_pos.begin)) {
10432 // [stack] ADDINIT CTOR HOME ARR I INITS GET SET CTOR HOME CTOR
10433 return false;
10434 }
10435 if (!emitGetPrivateName(
10436 &accessorSetterNode->name().as<NameNode>())) {
10437 // [stack] ADDINIT CTOR HOME ARR I INITS GET SET CTOR HOME CTOR
10438 // KEY
10439 return false;
10440 }
10441 if (!emitPickN(4)) {
10442 // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME CTOR KEY
10443 // SET
10444 return false;
10445 }
10446 if (!ce.emitPrivateStaticMethod(AccessorType::Setter)) {
10447 // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME
10448 return false;
10449 }
10450
10451 if (!ce.prepareForPrivateStaticMethod(propdef->pn_pos.begin)) {
10452 // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME CTOR
10453 return false;
10454 }
10455 if (!emitGetPrivateName(
10456 &accessorGetterNode->name().as<NameNode>())) {
10457 // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME CTOR KEY
10458 return false;
10459 }
10460 if (!emitPickN(4)) {
10461 // [stack] ADDINIT CTOR HOME ARR I INITS CTOR HOME CTOR KEY GET
10462 return false;
10463 }
10464 if (!ce.emitPrivateStaticMethod(AccessorType::Getter)) {
10465 // [stack] ADDINIT CTOR HOME ARR I INITS CTOR HOME
10466 return false;
10467 }
10468 }
10469
10470 if (!isStatic) {
10471 if (!emitPopN(1)) {
10472 // [stack] ADDINIT HOME HERIT? ARR I INITS
10473 return false;
10474 }
10475 } else {
10476 if (!emitPopN(2)) {
10477 // [stack] ADDINIT CTOR HOME ARR I INITS
10478 return false;
10479 }
10480 }
10481 } else {
10482 MOZ_ASSERT(IsPrivateInstanceAccessor(accessorSetterNode))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsPrivateInstanceAccessor(accessorSetterNode))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(IsPrivateInstanceAccessor(accessorSetterNode)))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("IsPrivateInstanceAccessor(accessorSetterNode)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 10482); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsPrivateInstanceAccessor(accessorSetterNode)"
")"); do { *((volatile int*)__null) = 10482; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10483
10484 if (!emitLexicalInitialization(accessorSetterKeyAtom)) {
10485 // [stack] ADDINIT HOME HERIT? ARR I INITS GET SET
10486 // or:
10487 // [stack] ADDINIT CTOR HOME ARR I INITS GET SET
10488 return false;
10489 }
10490
10491 if (!emitPopN(1)) {
10492 // [stack] ADDINIT HOME HERIT? ARR I INITS GET
10493 // or:
10494 // [stack] ADDINIT CTOR HOME ARR I INITS GET
10495 return false;
10496 }
10497
10498 if (!emitLexicalInitialization(accessorGetterKeyAtom)) {
10499 // [stack] ADDINIT HOME HERIT? ARR I INITS GET
10500 // or:
10501 // [stack] ADDINIT CTOR HOME ARR I INITS GET
10502 return false;
10503 }
10504
10505 if (!emitPopN(1)) {
10506 // [stack] ADDINIT HOME HERIT? ARR I INITS
10507 // or:
10508 // [stack] ADDINIT CTOR HOME ARR I INITS
10509 return false;
10510 }
10511 }
10512 }
10513 if (!emit1(JSOp::InitElemInc)) {
10514 // [stack] ADDINIT HOME HERIT? ARR I
10515 // or:
10516 // [stack] ADDINIT CTOR HOME ARR I
10517 return false;
10518 }
10519 }
10520 }
10521
10522 // Pop I
10523 if (!emitPopN(1)) {
10524 // [stack] ADDINIT HOME HERIT? ARR
10525 // or:
10526 // [stack] ADDINIT CTOR HOME ARR
10527 return false;
10528 }
10529#endif
10530
10531 if (!ce.emitMemberInitializersEnd()) {
10532 // [stack] ADDINIT HOME HERIT?
10533 // or:
10534 // [stack] ADDINIT CTOR HOME
10535 return false;
10536 }
10537
10538 return true;
10539}
10540
10541bool BytecodeEmitter::emitPrivateMethodInitializers(ClassEmitter& ce,
10542 ListNode* obj) {
10543 for (ParseNode* propdef : obj->contents()) {
10544 if (!propdef->is<ClassMethod>()) {
10545 continue;
10546 }
10547 auto* classMethod = &propdef->as<ClassMethod>();
10548
10549 // Skip over anything which isn't a private instance accessor.
10550 if (!IsPrivateInstanceAccessor(classMethod)) {
10551 continue;
10552 }
10553
10554 if (!ce.prepareForMemberInitializer()) {
10555 // [stack] HOMEOBJ HERITAGE? ARRAY
10556 // or:
10557 // [stack] CTOR HOMEOBJ ARRAY
10558 return false;
10559 }
10560
10561 // Synthesize a name for the lexical variable that will store the
10562 // private method body.
10563 TaggedParserAtomIndex name = classMethod->name().as<NameNode>().atom();
10564 AccessorType accessorType = classMethod->accessorType();
10565 StringBuilder storedMethodName(fc);
10566 if (!storedMethodName.append(parserAtoms(), name)) {
10567 return false;
10568 }
10569 if (!storedMethodName.append(
10570 accessorType == AccessorType::Getter ? ".getter" : ".setter")) {
10571 return false;
10572 }
10573 auto storedMethodAtom =
10574 storedMethodName.finishParserAtom(parserAtoms(), fc);
10575
10576 // Emit the private method body and store it as a lexical var.
10577 if (!emitFunction(&classMethod->method())) {
10578 // [stack] HOMEOBJ HERITAGE? ARRAY METHOD
10579 // or:
10580 // [stack] CTOR HOMEOBJ ARRAY METHOD
10581 return false;
10582 }
10583 // The private method body needs to access the home object,
10584 // and the CE knows where that is on the stack.
10585 if (classMethod->method().funbox()->needsHomeObject()) {
10586 if (!ce.emitMemberInitializerHomeObject(false)) {
10587 // [stack] HOMEOBJ HERITAGE? ARRAY METHOD
10588 // or:
10589 // [stack] CTOR HOMEOBJ ARRAY METHOD
10590 return false;
10591 }
10592 }
10593 if (!emitLexicalInitialization(storedMethodAtom)) {
10594 // [stack] HOMEOBJ HERITAGE? ARRAY METHOD
10595 // or:
10596 // [stack] CTOR HOMEOBJ ARRAY METHOD
10597 return false;
10598 }
10599 if (!emit1(JSOp::Pop)) {
10600 // [stack] HOMEOBJ HERITAGE? ARRAY
10601 // or:
10602 // [stack] CTOR HOMEOBJ ARRAY
10603 return false;
10604 }
10605
10606 if (!emitPrivateMethodInitializer(classMethod, storedMethodAtom)) {
10607 // [stack] HOMEOBJ HERITAGE? ARRAY
10608 // or:
10609 // [stack] CTOR HOMEOBJ ARRAY
10610 return false;
10611 }
10612
10613 // Store the emitted initializer function into the .initializers array.
10614 if (!ce.emitStoreMemberInitializer()) {
10615 // [stack] HOMEOBJ HERITAGE? ARRAY
10616 // or:
10617 // [stack] CTOR HOMEOBJ ARRAY
10618 return false;
10619 }
10620 }
10621
10622 return true;
10623}
10624
10625bool BytecodeEmitter::emitPrivateMethodInitializer(
10626 ClassMethod* classMethod, TaggedParserAtomIndex storedMethodAtom) {
10627 MOZ_ASSERT(IsPrivateInstanceAccessor(classMethod))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsPrivateInstanceAccessor(classMethod))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(IsPrivateInstanceAccessor(classMethod)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("IsPrivateInstanceAccessor(classMethod)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 10627); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsPrivateInstanceAccessor(classMethod)"
")"); do { *((volatile int*)__null) = 10627; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10628
10629 auto* name = &classMethod->name().as<NameNode>();
10630
10631 // Emit the synthesized initializer function.
10632 FunctionNode* funNode = classMethod->initializerIfPrivate();
10633 MOZ_ASSERT(funNode)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(funNode)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(funNode))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("funNode", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 10633); AnnotateMozCrashReason("MOZ_ASSERT" "(" "funNode" ")"
); do { *((volatile int*)__null) = 10633; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10634 FunctionBox* funbox = funNode->funbox();
10635 FunctionEmitter fe(this, funbox, funNode->syntaxKind(),
10636 FunctionEmitter::IsHoisted::No);
10637 if (!fe.prepareForNonLazy()) {
10638 // [stack]
10639 return false;
10640 }
10641
10642 BytecodeEmitter bce2(this, funbox);
10643 if (!bce2.init(funNode->pn_pos)) {
10644 return false;
10645 }
10646 ParamsBodyNode* paramsBody = funNode->body();
10647 FunctionScriptEmitter fse(&bce2, funbox, Nothing(), Nothing());
10648 if (!fse.prepareForParameters()) {
10649 // [stack]
10650 return false;
10651 }
10652 if (!bce2.emitFunctionFormalParameters(paramsBody)) {
10653 // [stack]
10654 return false;
10655 }
10656 if (!fse.prepareForBody()) {
10657 // [stack]
10658 return false;
10659 }
10660
10661 if (!bce2.emit1(JSOp::FunctionThis)) {
10662 // [stack] THIS
10663 return false;
10664 }
10665 if (!bce2.emitGetPrivateName(name)) {
10666 // [stack] THIS NAME
10667 return false;
10668 }
10669 if (!bce2.emitGetName(storedMethodAtom)) {
10670 // [stack] THIS NAME METHOD
10671 return false;
10672 }
10673
10674 switch (name->privateNameKind()) {
10675 case PrivateNameKind::Setter:
10676 if (!bce2.emit1(JSOp::InitHiddenElemSetter)) {
10677 // [stack] THIS
10678 return false;
10679 }
10680 if (!bce2.emitGetPrivateName(name)) {
10681 // [stack] THIS NAME
10682 return false;
10683 }
10684 if (!bce2.emitAtomOp(
10685 JSOp::GetIntrinsic,
10686 TaggedParserAtomIndex::WellKnown::NoPrivateGetter())) {
10687 // [stack] THIS NAME FUN
10688 return false;
10689 }
10690 if (!bce2.emit1(JSOp::InitHiddenElemGetter)) {
10691 // [stack] THIS
10692 return false;
10693 }
10694 break;
10695 case PrivateNameKind::Getter:
10696 case PrivateNameKind::GetterSetter:
10697 if (classMethod->accessorType() == AccessorType::Getter) {
10698 if (!bce2.emit1(JSOp::InitHiddenElemGetter)) {
10699 // [stack] THIS
10700 return false;
10701 }
10702 } else {
10703 if (!bce2.emit1(JSOp::InitHiddenElemSetter)) {
10704 // [stack] THIS
10705 return false;
10706 }
10707 }
10708 break;
10709 default:
10710 MOZ_CRASH("Invalid op")do { do { } while (false); MOZ_ReportCrash("" "Invalid op", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 10710); AnnotateMozCrashReason("MOZ_CRASH(" "Invalid op" ")"
); do { *((volatile int*)__null) = 10710; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
10711 }
10712
10713 // Pop remaining THIS.
10714 if (!bce2.emit1(JSOp::Pop)) {
10715 // [stack]
10716 return false;
10717 }
10718
10719 if (!fse.emitEndBody()) {
10720 // [stack]
10721 return false;
10722 }
10723 if (!fse.intoStencil()) {
10724 return false;
10725 }
10726
10727 if (!fe.emitNonLazyEnd()) {
10728 // [stack] HOMEOBJ HERITAGE? ARRAY FUN
10729 // or:
10730 // [stack] CTOR HOMEOBJ ARRAY FUN
10731 return false;
10732 }
10733
10734 return true;
10735}
10736
10737const MemberInitializers& BytecodeEmitter::findMemberInitializersForCall()
10738 const {
10739 for (const auto* current = this; current; current = current->parent) {
10740 if (current->sc->isFunctionBox()) {
10741 FunctionBox* funbox = current->sc->asFunctionBox();
10742
10743 if (funbox->isArrow()) {
10744 continue;
10745 }
10746
10747 // If we found a non-arrow / non-constructor we were never allowed to
10748 // expect fields in the first place.
10749 MOZ_RELEASE_ASSERT(funbox->isClassConstructor())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(funbox->isClassConstructor())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(funbox->isClassConstructor
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("funbox->isClassConstructor()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 10749); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "funbox->isClassConstructor()"
")"); do { *((volatile int*)__null) = 10749; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10750
10751 return funbox->useMemberInitializers() ? funbox->memberInitializers()
10752 : MemberInitializers::Empty();
10753 }
10754 }
10755
10756 MOZ_RELEASE_ASSERT(compilationState.scopeContext.memberInitializers)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(compilationState.scopeContext.memberInitializers)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(compilationState.scopeContext.memberInitializers))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("compilationState.scopeContext.memberInitializers"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 10756); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "compilationState.scopeContext.memberInitializers"
")"); do { *((volatile int*)__null) = 10756; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10757 return *compilationState.scopeContext.memberInitializers;
10758}
10759
10760bool BytecodeEmitter::emitInitializeInstanceMembers(
10761 bool isDerivedClassConstructor) {
10762 const MemberInitializers& memberInitializers =
10763 findMemberInitializersForCall();
10764 MOZ_ASSERT(memberInitializers.valid)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(memberInitializers.valid)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(memberInitializers.valid))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("memberInitializers.valid"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 10764); AnnotateMozCrashReason("MOZ_ASSERT" "(" "memberInitializers.valid"
")"); do { *((volatile int*)__null) = 10764; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10765
10766 if (memberInitializers.hasPrivateBrand) {
10767 // This is guaranteed to run after super(), so we don't need TDZ checks.
10768 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_this_())) {
10769 // [stack] THIS
10770 return false;
10771 }
10772 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_privateBrand_())) {
10773 // [stack] THIS BRAND
10774 return false;
10775 }
10776 if (isDerivedClassConstructor) {
10777 if (!emitCheckPrivateField(ThrowCondition::ThrowHas,
10778 ThrowMsgKind::PrivateBrandDoubleInit)) {
10779 // [stack] THIS BRAND BOOL
10780 return false;
10781 }
10782 if (!emit1(JSOp::Pop)) {
10783 // [stack] THIS BRAND
10784 return false;
10785 }
10786 }
10787 if (!emit1(JSOp::Null)) {
10788 // [stack] THIS BRAND NULL
10789 return false;
10790 }
10791 if (!emit1(JSOp::InitHiddenElem)) {
10792 // [stack] THIS
10793 return false;
10794 }
10795 if (!emit1(JSOp::Pop)) {
10796 // [stack]
10797 return false;
10798 }
10799 }
10800
10801 size_t numInitializers = memberInitializers.numMemberInitializers;
10802 if (numInitializers > 0) {
10803 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_initializers_())) {
10804 // [stack] ARRAY
10805 return false;
10806 }
10807
10808 for (size_t index = 0; index < numInitializers; index++) {
10809 if (index < numInitializers - 1) {
10810 // We Dup to keep the array around (it is consumed in the bytecode
10811 // below) for next iterations of this loop, except for the last
10812 // iteration, which avoids an extra Pop at the end of the loop.
10813 if (!emit1(JSOp::Dup)) {
10814 // [stack] ARRAY ARRAY
10815 return false;
10816 }
10817 }
10818
10819 if (!emitNumberOp(index)) {
10820 // [stack] ARRAY? ARRAY INDEX
10821 return false;
10822 }
10823
10824 if (!emit1(JSOp::GetElem)) {
10825 // [stack] ARRAY? FUNC
10826 return false;
10827 }
10828
10829 // This is guaranteed to run after super(), so we don't need TDZ checks.
10830 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_this_())) {
10831 // [stack] ARRAY? FUNC THIS
10832 return false;
10833 }
10834
10835 // Callee is always internal function.
10836 if (!emitCall(JSOp::CallIgnoresRv, 0)) {
10837 // [stack] ARRAY? RVAL
10838 return false;
10839 }
10840
10841 if (!emit1(JSOp::Pop)) {
10842 // [stack] ARRAY?
10843 return false;
10844 }
10845 }
10846#ifdef ENABLE_DECORATORS
10847 if (memberInitializers.hasDecorators) {
10848 // Decorators Proposal
10849 // https://arai-a.github.io/ecma262-compare/?pr=2417&id=sec-initializeinstanceelements
10850 // 4. For each element e of elements, do
10851 // 4.a. If elementRecord.[[Kind]] is field or accessor, then
10852 // 4.a.i. Perform ? InitializeFieldOrAccessor(O, elementRecord).
10853 //
10854
10855 // TODO: (See Bug 1817993) At the moment, we're applying the
10856 // initialization logic in two steps. The pre-decorator initialization
10857 // code runs, stores the initial value, and then we retrieve it here and
10858 // apply the initializers added by decorators. We should unify these two
10859 // steps.
10860 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_initializers_())) {
10861 // [stack] ARRAY
10862 return false;
10863 }
10864
10865 if (!emit1(JSOp::Dup)) {
10866 // [stack] ARRAY ARRAY
10867 return false;
10868 }
10869
10870 if (!emitAtomOp(JSOp::GetProp,
10871 TaggedParserAtomIndex::WellKnown::length())) {
10872 // [stack] ARRAY LENGTH
10873 return false;
10874 }
10875
10876 if (!emitNumberOp(static_cast<double>(numInitializers))) {
10877 // [stack] ARRAY LENGTH INDEX
10878 return false;
10879 }
10880
10881 InternalWhileEmitter wh(this);
10882 // At this point, we have no context to determine offsets in the
10883 // code for this while statement. Ideally, it would correspond to
10884 // the field we're initializing.
10885 if (!wh.emitCond()) {
10886 // [stack] ARRAY LENGTH INDEX
10887 return false;
10888 }
10889
10890 if (!emit1(JSOp::Dup)) {
10891 // [stack] ARRAY LENGTH INDEX INDEX
10892 return false;
10893 }
10894
10895 if (!emitDupAt(2)) {
10896 // [stack] ARRAY LENGTH INDEX INDEX LENGTH
10897 return false;
10898 }
10899
10900 if (!emit1(JSOp::Lt)) {
10901 // [stack] ARRAY LENGTH INDEX BOOL
10902 return false;
10903 }
10904
10905 if (!wh.emitBody()) {
10906 // [stack] ARRAY LENGTH INDEX
10907 return false;
10908 }
10909
10910 if (!emitDupAt(2)) {
10911 // [stack] ARRAY LENGTH INDEX ARRAY
10912 return false;
10913 }
10914
10915 if (!emitDupAt(1)) {
10916 // [stack] ARRAY LENGTH INDEX ARRAY INDEX
10917 return false;
10918 }
10919
10920 // Retrieve initializers for this field
10921 if (!emit1(JSOp::GetElem)) {
10922 // [stack] ARRAY LENGTH INDEX INITIALIZERS
10923 return false;
10924 }
10925
10926 // This is guaranteed to run after super(), so we don't need TDZ checks.
10927 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_this_())) {
10928 // [stack] ARRAY LENGTH INDEX INITIALIZERS THIS
10929 return false;
10930 }
10931
10932 if (!emit1(JSOp::Swap)) {
10933 // [stack] ARRAY LENGTH INDEX THIS INITIALIZERS
10934 return false;
10935 }
10936
10937 DecoratorEmitter de(this);
10938 if (!de.emitInitializeFieldOrAccessor()) {
10939 // [stack] ARRAY LENGTH INDEX
10940 return false;
10941 }
10942
10943 if (!emit1(JSOp::Inc)) {
10944 // [stack] ARRAY LENGTH INDEX
10945 return false;
10946 }
10947
10948 if (!wh.emitEnd()) {
10949 // [stack] ARRAY LENGTH INDEX
10950 return false;
10951 }
10952
10953 if (!emitPopN(3)) {
10954 // [stack]
10955 return false;
10956 }
10957 // 5. Return unused.
10958
10959 if (!de.emitCallExtraInitializers(TaggedParserAtomIndex::WellKnown::
10960 dot_instanceExtraInitializers_())) {
10961 return false;
10962 }
10963 }
10964#endif
10965 }
10966 return true;
10967}
10968
10969bool BytecodeEmitter::emitInitializeStaticFields(ListNode* classMembers) {
10970 auto isStaticField = [](ParseNode* propdef) {
10971 return HasInitializer(propdef, true);
10972 };
10973 size_t numFields =
10974 std::count_if(classMembers->contents().begin(),
10975 classMembers->contents().end(), isStaticField);
10976
10977 if (numFields == 0) {
10978 return true;
10979 }
10980
10981 if (!emitGetName(
10982 TaggedParserAtomIndex::WellKnown::dot_staticInitializers_())) {
10983 // [stack] CTOR ARRAY
10984 return false;
10985 }
10986
10987 for (size_t fieldIndex = 0; fieldIndex < numFields; fieldIndex++) {
10988 bool hasNext = fieldIndex < numFields - 1;
10989 if (hasNext) {
10990 // We Dup to keep the array around (it is consumed in the bytecode below)
10991 // for next iterations of this loop, except for the last iteration, which
10992 // avoids an extra Pop at the end of the loop.
10993 if (!emit1(JSOp::Dup)) {
10994 // [stack] CTOR ARRAY ARRAY
10995 return false;
10996 }
10997 }
10998
10999 if (!emitNumberOp(fieldIndex)) {
11000 // [stack] CTOR ARRAY? ARRAY INDEX
11001 return false;
11002 }
11003
11004 if (!emit1(JSOp::GetElem)) {
11005 // [stack] CTOR ARRAY? FUNC
11006 return false;
11007 }
11008
11009 if (!emitDupAt(1 + hasNext)) {
11010 // [stack] CTOR ARRAY? FUNC CTOR
11011 return false;
11012 }
11013
11014 // Callee is always internal function.
11015 if (!emitCall(JSOp::CallIgnoresRv, 0)) {
11016 // [stack] CTOR ARRAY? RVAL
11017 return false;
11018 }
11019
11020 if (!emit1(JSOp::Pop)) {
11021 // [stack] CTOR ARRAY?
11022 return false;
11023 }
11024 }
11025
11026#ifdef ENABLE_DECORATORS
11027 // Decorators Proposal
11028 // https://arai-a.github.io/ecma262-compare/?pr=2417&id=sec-initializeinstanceelements
11029 // 4. For each element e of elements, do
11030 // 4.a. If elementRecord.[[Kind]] is field or accessor, then
11031 // 4.a.i. Perform ? InitializeFieldOrAccessor(O, elementRecord).
11032 //
11033
11034 // TODO: (See Bug 1817993) At the moment, we're applying the initialization
11035 // logic in two steps. The pre-decorator initialization code runs, stores
11036 // the initial value, and then we retrieve it here and apply the
11037 // initializers added by decorators. We should unify these two steps.
11038 if (!emitGetName(
11039 TaggedParserAtomIndex::WellKnown::dot_staticInitializers_())) {
11040 // [stack] CTOR ARRAY
11041 return false;
11042 }
11043
11044 if (!emit1(JSOp::Dup)) {
11045 // [stack] CTOR ARRAY ARRAY
11046 return false;
11047 }
11048
11049 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::length())) {
11050 // [stack] CTOR ARRAY LENGTH
11051 return false;
11052 }
11053
11054 if (!emitNumberOp(static_cast<double>(numFields))) {
11055 // [stack] CTOR ARRAY LENGTH INDEX
11056 return false;
11057 }
11058
11059 InternalWhileEmitter wh(this);
11060 // At this point, we have no context to determine offsets in the
11061 // code for this while statement. Ideally, it would correspond to
11062 // the field we're initializing.
11063 if (!wh.emitCond()) {
11064 // [stack] CTOR ARRAY LENGTH INDEX
11065 return false;
11066 }
11067
11068 if (!emit1(JSOp::Dup)) {
11069 // [stack] CTOR ARRAY LENGTH INDEX INDEX
11070 return false;
11071 }
11072
11073 if (!emitDupAt(2)) {
11074 // [stack] CTOR ARRAY LENGTH INDEX INDEX LENGTH
11075 return false;
11076 }
11077
11078 if (!emit1(JSOp::Lt)) {
11079 // [stack] CTOR ARRAY LENGTH INDEX BOOL
11080 return false;
11081 }
11082
11083 if (!wh.emitBody()) {
11084 // [stack] CTOR ARRAY LENGTH INDEX
11085 return false;
11086 }
11087
11088 if (!emitDupAt(2)) {
11089 // [stack] CTOR ARRAY LENGTH INDEX ARRAY
11090 return false;
11091 }
11092
11093 if (!emitDupAt(1)) {
11094 // [stack] CTOR ARRAY LENGTH INDEX ARRAY INDEX
11095 return false;
11096 }
11097
11098 // Retrieve initializers for this field
11099 if (!emit1(JSOp::GetElem)) {
11100 // [stack] CTOR ARRAY LENGTH INDEX INITIALIZERS
11101 return false;
11102 }
11103
11104 if (!emitDupAt(4)) {
11105 // [stack] CTOR ARRAY LENGTH INDEX INITIALIZERS CTOR
11106 return false;
11107 }
11108
11109 if (!emit1(JSOp::Swap)) {
11110 // [stack] CTOR ARRAY LENGTH INDEX CTOR INITIALIZERS
11111 return false;
11112 }
11113
11114 DecoratorEmitter de(this);
11115 if (!de.emitInitializeFieldOrAccessor()) {
11116 // [stack] CTOR ARRAY LENGTH INDEX
11117 return false;
11118 }
11119
11120 if (!emit1(JSOp::Inc)) {
11121 // [stack] CTOR ARRAY LENGTH INDEX
11122 return false;
11123 }
11124
11125 if (!wh.emitEnd()) {
11126 // [stack] CTOR ARRAY LENGTH INDEX
11127 return false;
11128 }
11129
11130 if (!emitPopN(3)) {
11131 // [stack] CTOR
11132 return false;
11133 }
11134 // 5. Return unused.
11135#endif
11136
11137 // Overwrite |.staticInitializers| and |.staticFieldKeys| with undefined to
11138 // avoid keeping the arrays alive indefinitely.
11139 auto clearStaticFieldSlot = [&](TaggedParserAtomIndex name) {
11140 NameOpEmitter noe(this, name, NameOpEmitter::Kind::SimpleAssignment);
11141 if (!noe.prepareForRhs()) {
11142 // [stack] ENV? VAL?
11143 return false;
11144 }
11145
11146 if (!emit1(JSOp::Undefined)) {
11147 // [stack] ENV? VAL? UNDEFINED
11148 return false;
11149 }
11150
11151 if (!noe.emitAssignment()) {
11152 // [stack] VAL
11153 return false;
11154 }
11155
11156 if (!emit1(JSOp::Pop)) {
11157 // [stack]
11158 return false;
11159 }
11160
11161 return true;
11162 };
11163
11164 if (!clearStaticFieldSlot(
11165 TaggedParserAtomIndex::WellKnown::dot_staticInitializers_())) {
11166 return false;
11167 }
11168
11169 auto isStaticFieldWithComputedName = [](ParseNode* propdef) {
11170 return propdef->is<ClassField>() && propdef->as<ClassField>().isStatic() &&
11171 propdef->as<ClassField>().name().getKind() ==
11172 ParseNodeKind::ComputedName;
11173 };
11174
11175 if (std::any_of(classMembers->contents().begin(),
11176 classMembers->contents().end(),
11177 isStaticFieldWithComputedName)) {
11178 if (!clearStaticFieldSlot(
11179 TaggedParserAtomIndex::WellKnown::dot_staticFieldKeys_())) {
11180 return false;
11181 }
11182 }
11183
11184 return true;
11185}
11186
11187// Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See
11188// the comment on emitSwitch.
11189MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitObject(ListNode* objNode) {
11190 // Note: this method uses the ObjLiteralWriter and emits ObjLiteralStencil
11191 // objects into the GCThingList, which will evaluate them into real GC objects
11192 // or shapes during JSScript::fullyInitFromEmitter. Eventually we want
11193 // JSOp::Object to be a real opcode, but for now, performance constraints
11194 // limit us to evaluating object literals at the end of parse, when we're
11195 // allowed to allocate GC things.
11196 //
11197 // There are four cases here, in descending order of preference:
11198 //
11199 // 1. The list of property names is "normal" and constant (no computed
11200 // values, no integer indices), the values are all simple constants
11201 // (numbers, booleans, strings), *and* this occurs in a run-once
11202 // (singleton) context. In this case, we can emit ObjLiteral
11203 // instructions to build an object with values, and the object will be
11204 // attached to a JSOp::Object opcode, whose semantics are for the backend
11205 // to simply steal the object from the script.
11206 //
11207 // 2. The list of property names is "normal" and constant as above, *and* this
11208 // occurs in a run-once (singleton) context, but some values are complex
11209 // (computed expressions, sub-objects, functions, etc.). In this case, we
11210 // can still use JSOp::Object (because singleton context), but the object
11211 // has |undefined| property values and InitProp ops are emitted to set the
11212 // values.
11213 //
11214 // 3. The list of property names is "normal" and constant as above, but this
11215 // occurs in a non-run-once (non-singleton) context. In this case, we can
11216 // use the ObjLiteral functionality to describe an *empty* object (all
11217 // values left undefined) with the right fields, which will become a
11218 // JSOp::NewObject opcode using the object's shape to speed up the creation
11219 // of the object each time it executes. The emitted bytecode still needs
11220 // InitProp ops to set the values in this case.
11221 //
11222 // 4. Any other case. As a fallback, we use NewInit to create a new, empty
11223 // object (i.e., `{}`) and then emit bytecode to initialize its properties
11224 // one-by-one.
11225
11226 bool useObjLiteral = false;
11227 bool useObjLiteralValues = false;
11228 isPropertyListObjLiteralCompatible(objNode, &useObjLiteralValues,
11229 &useObjLiteral);
11230
11231 // [stack]
11232 //
11233 ObjectEmitter oe(this);
11234 if (useObjLiteral) {
11235 bool singleton = checkSingletonContext() &&
11236 !objNode->hasNonConstInitializer() && objNode->head();
11237 JSOp op;
11238 if (singleton) {
11239 // Case 1 or 2.
11240 op = JSOp::Object;
11241 } else {
11242 // Case 3.
11243 useObjLiteralValues = false;
11244 op = JSOp::NewObject;
11245 }
11246
11247 // Use an ObjLiteral op. This will record ObjLiteral insns in the
11248 // objLiteralWriter's buffer and add a fixup to the list of ObjLiteral
11249 // fixups so that at GC-publish time at the end of parse, the full object
11250 // (case 1 or 2) or shape (case 3) can be allocated and the bytecode can be
11251 // patched to refer to it.
11252 if (!emitPropertyListObjLiteral(objNode, op, useObjLiteralValues)) {
11253 // [stack] OBJ
11254 return false;
11255 }
11256 // Put the ObjectEmitter in the right state. This tells it that there will
11257 // already be an object on the stack as a result of the (eventual)
11258 // NewObject or Object op, and prepares it to emit values if needed.
11259 if (!oe.emitObjectWithTemplateOnStack()) {
11260 // [stack] OBJ
11261 return false;
11262 }
11263 if (!useObjLiteralValues) {
11264 // Case 2 or 3 above: we still need to emit bytecode to fill in the
11265 // object's property values.
11266 if (!emitPropertyList(objNode, oe, ObjectLiteral)) {
11267 // [stack] OBJ
11268 return false;
11269 }
11270 }
11271 } else {
11272 // Case 4 above: no ObjLiteral use, just bytecode to build the object from
11273 // scratch.
11274 if (!oe.emitObject(objNode->count())) {
11275 // [stack] OBJ
11276 return false;
11277 }
11278 if (!emitPropertyList(objNode, oe, ObjectLiteral)) {
11279 // [stack] OBJ
11280 return false;
11281 }
11282 }
11283
11284 if (!oe.emitEnd()) {
11285 // [stack] OBJ
11286 return false;
11287 }
11288
11289 return true;
11290}
11291
11292bool BytecodeEmitter::emitArrayLiteral(ListNode* array) {
11293 // Emit JSOp::Object if the array consists entirely of primitive values and we
11294 // are in a singleton context.
11295 if (checkSingletonContext() && !array->hasNonConstInitializer() &&
11296 !array->empty() && isArrayObjLiteralCompatible(array)) {
11297 return emitObjLiteralArray(array);
11298 }
11299
11300 return emitArray(array);
11301}
11302
11303bool BytecodeEmitter::emitArray(ListNode* array) {
11304 /*
11305 * Emit code for [a, b, c] that is equivalent to constructing a new
11306 * array and in source order evaluating each element value and adding
11307 * it to the array, without invoking latent setters. We use the
11308 * JSOp::NewInit and JSOp::InitElemArray bytecodes to ignore setters and
11309 * to avoid dup'ing and popping the array as each element is added, as
11310 * JSOp::SetElem/JSOp::SetProp would do.
11311 */
11312
11313 uint32_t nspread = 0;
11314 for (ParseNode* elem : array->contents()) {
11315 if (elem->isKind(ParseNodeKind::Spread)) {
11316 nspread++;
11317 }
11318 }
11319
11320 // Array literal's length is limited to NELEMENTS_LIMIT in parser.
11321 static_assert(NativeObject::MAX_DENSE_ELEMENTS_COUNT <= INT32_MAX(2147483647),
11322 "array literals' maximum length must not exceed limits "
11323 "required by BaselineCompiler::emit_NewArray, "
11324 "BaselineCompiler::emit_InitElemArray, "
11325 "and DoSetElemFallback's handling of JSOp::InitElemArray");
11326
11327 uint32_t count = array->count();
11328 MOZ_ASSERT(count >= nspread)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(count >= nspread)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(count >= nspread))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("count >= nspread"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11328); AnnotateMozCrashReason("MOZ_ASSERT" "(" "count >= nspread"
")"); do { *((volatile int*)__null) = 11328; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11329 MOZ_ASSERT(count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT"
" (" "the parser must throw an error if the array exceeds maximum "
"length" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11331); AnnotateMozCrashReason("MOZ_ASSERT" "(" "count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT"
") (" "the parser must throw an error if the array exceeds maximum "
"length" ")"); do { *((volatile int*)__null) = 11331; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
11330 "the parser must throw an error if the array exceeds maximum "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT"
" (" "the parser must throw an error if the array exceeds maximum "
"length" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11331); AnnotateMozCrashReason("MOZ_ASSERT" "(" "count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT"
") (" "the parser must throw an error if the array exceeds maximum "
"length" ")"); do { *((volatile int*)__null) = 11331; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
11331 "length")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT"
" (" "the parser must throw an error if the array exceeds maximum "
"length" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11331); AnnotateMozCrashReason("MOZ_ASSERT" "(" "count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT"
") (" "the parser must throw an error if the array exceeds maximum "
"length" ")"); do { *((volatile int*)__null) = 11331; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
11332
11333 // For arrays with spread, this is a very pessimistic allocation, the
11334 // minimum possible final size.
11335 if (!emitUint32Operand(JSOp::NewArray, count - nspread)) {
11336 // [stack] ARRAY
11337 return false;
11338 }
11339
11340 uint32_t index = 0;
11341 bool afterSpread = false;
11342 for (ParseNode* elem : array->contents()) {
11343 if (elem->isKind(ParseNodeKind::Spread)) {
11344 if (!afterSpread) {
11345 afterSpread = true;
11346 if (!emitNumberOp(index)) {
11347 // [stack] ARRAY INDEX
11348 return false;
11349 }
11350 }
11351
11352 ParseNode* expr = elem->as<UnaryNode>().kid();
11353 SelfHostedIter selfHostedIter = getSelfHostedIterFor(expr);
11354
11355 if (!updateSourceCoordNotes(elem->pn_pos.begin)) {
11356 return false;
11357 }
11358 if (!emitIterable(expr, selfHostedIter)) {
11359 // [stack] ARRAY INDEX ITERABLE
11360 return false;
11361 }
11362 if (!emitIterator(selfHostedIter)) {
11363 // [stack] ARRAY INDEX NEXT ITER
11364 return false;
11365 }
11366 if (!emit2(JSOp::Pick, 3)) {
11367 // [stack] INDEX NEXT ITER ARRAY
11368 return false;
11369 }
11370 if (!emit2(JSOp::Pick, 3)) {
11371 // [stack] NEXT ITER ARRAY INDEX
11372 return false;
11373 }
11374 if (!emitSpread(selfHostedIter)) {
11375 // [stack] ARRAY INDEX
11376 return false;
11377 }
11378 } else {
11379 if (!updateSourceCoordNotesIfNonLiteral(elem)) {
11380 return false;
11381 }
11382 if (elem->isKind(ParseNodeKind::Elision)) {
11383 if (!emit1(JSOp::Hole)) {
11384 return false;
11385 }
11386 } else {
11387 if (!emitTree(elem, ValueUsage::WantValue)) {
11388 // [stack] ARRAY INDEX? VALUE
11389 return false;
11390 }
11391 }
11392
11393 if (afterSpread) {
11394 if (!emit1(JSOp::InitElemInc)) {
11395 // [stack] ARRAY (INDEX+1)
11396 return false;
11397 }
11398 } else {
11399 if (!emitUint32Operand(JSOp::InitElemArray, index)) {
11400 // [stack] ARRAY
11401 return false;
11402 }
11403 }
11404 }
11405
11406 index++;
11407 }
11408 MOZ_ASSERT(index == count)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(index == count)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(index == count))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("index == count"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11408); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index == count"
")"); do { *((volatile int*)__null) = 11408; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11409 if (afterSpread) {
11410 if (!emit1(JSOp::Pop)) {
11411 // [stack] ARRAY
11412 return false;
11413 }
11414 }
11415 return true;
11416}
11417
11418bool BytecodeEmitter::emitSpreadIntoArray(UnaryNode* elem) {
11419 MOZ_ASSERT(elem->isKind(ParseNodeKind::Spread))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(elem->isKind(ParseNodeKind::Spread))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(elem->isKind(ParseNodeKind::Spread)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("elem->isKind(ParseNodeKind::Spread)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11419); AnnotateMozCrashReason("MOZ_ASSERT" "(" "elem->isKind(ParseNodeKind::Spread)"
")"); do { *((volatile int*)__null) = 11419; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11420
11421 if (!updateSourceCoordNotes(elem->pn_pos.begin)) {
11422 // [stack] VALUE
11423 return false;
11424 }
11425
11426 SelfHostedIter selfHostedIter = getSelfHostedIterFor(elem->kid());
11427 MOZ_ASSERT(selfHostedIter == SelfHostedIter::Deny ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(selfHostedIter == SelfHostedIter::Deny || selfHostedIter
== SelfHostedIter::AllowContent)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(selfHostedIter == SelfHostedIter
::Deny || selfHostedIter == SelfHostedIter::AllowContent))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter == SelfHostedIter::Deny || selfHostedIter == SelfHostedIter::AllowContent"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11428); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter == SelfHostedIter::Deny || selfHostedIter == SelfHostedIter::AllowContent"
")"); do { *((volatile int*)__null) = 11428; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11428 selfHostedIter == SelfHostedIter::AllowContent)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(selfHostedIter == SelfHostedIter::Deny || selfHostedIter
== SelfHostedIter::AllowContent)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(selfHostedIter == SelfHostedIter
::Deny || selfHostedIter == SelfHostedIter::AllowContent))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter == SelfHostedIter::Deny || selfHostedIter == SelfHostedIter::AllowContent"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11428); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter == SelfHostedIter::Deny || selfHostedIter == SelfHostedIter::AllowContent"
")"); do { *((volatile int*)__null) = 11428; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11429
11430 if (!emitIterator(selfHostedIter)) {
11431 // [stack] NEXT ITER
11432 return false;
11433 }
11434
11435 if (!emitUint32Operand(JSOp::NewArray, 0)) {
11436 // [stack] NEXT ITER ARRAY
11437 return false;
11438 }
11439
11440 if (!emitNumberOp(0)) {
11441 // [stack] NEXT ITER ARRAY INDEX
11442 return false;
11443 }
11444
11445 if (!emitSpread(selfHostedIter)) {
11446 // [stack] ARRAY INDEX
11447 return false;
11448 }
11449
11450 if (!emit1(JSOp::Pop)) {
11451 // [stack] ARRAY
11452 return false;
11453 }
11454 return true;
11455}
11456
11457#ifdef ENABLE_RECORD_TUPLE
11458bool BytecodeEmitter::emitRecordLiteral(ListNode* record) {
11459 if (!emitUint32Operand(JSOp::InitRecord, record->count())) {
11460 // [stack] RECORD
11461 return false;
11462 }
11463
11464 for (ParseNode* propdef : record->contents()) {
11465 if (propdef->isKind(ParseNodeKind::Spread)) {
11466 if (!emitTree(propdef->as<UnaryNode>().kid())) {
11467 // [stack] RECORD SPREADEE
11468 return false;
11469 }
11470 if (!emit1(JSOp::AddRecordSpread)) {
11471 // [stack] RECORD
11472 return false;
11473 }
11474 } else {
11475 BinaryNode* prop = &propdef->as<BinaryNode>();
11476
11477 ParseNode* key = prop->left();
11478 ParseNode* value = prop->right();
11479
11480 switch (key->getKind()) {
11481 case ParseNodeKind::ObjectPropertyName:
11482 if (!emitStringOp(JSOp::String, key->as<NameNode>().atom())) {
11483 return false;
11484 }
11485 break;
11486 case ParseNodeKind::ComputedName:
11487 if (!emitTree(key->as<UnaryNode>().kid())) {
11488 return false;
11489 }
11490 break;
11491 default:
11492 MOZ_ASSERT(key->isKind(ParseNodeKind::StringExpr) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(key->isKind(ParseNodeKind::StringExpr) || key->
isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind
::BigIntExpr))>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(key->isKind(ParseNodeKind::StringExpr
) || key->isKind(ParseNodeKind::NumberExpr) || key->isKind
(ParseNodeKind::BigIntExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11494); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr)"
")"); do { *((volatile int*)__null) = 11494; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11493 key->isKind(ParseNodeKind::NumberExpr) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(key->isKind(ParseNodeKind::StringExpr) || key->
isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind
::BigIntExpr))>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(key->isKind(ParseNodeKind::StringExpr
) || key->isKind(ParseNodeKind::NumberExpr) || key->isKind
(ParseNodeKind::BigIntExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11494); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr)"
")"); do { *((volatile int*)__null) = 11494; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11494 key->isKind(ParseNodeKind::BigIntExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(key->isKind(ParseNodeKind::StringExpr) || key->
isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind
::BigIntExpr))>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(key->isKind(ParseNodeKind::StringExpr
) || key->isKind(ParseNodeKind::NumberExpr) || key->isKind
(ParseNodeKind::BigIntExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11494); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr)"
")"); do { *((volatile int*)__null) = 11494; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11495 if (!emitTree(key)) {
11496 return false;
11497 }
11498 break;
11499 }
11500 // [stack] RECORD KEY
11501
11502 if (!emitTree(value)) {
11503 // [stack] RECORD KEY VALUE
11504 return false;
11505 }
11506
11507 if (!emit1(JSOp::AddRecordProperty)) {
11508 // [stack] RECORD
11509 return false;
11510 }
11511 }
11512 }
11513
11514 if (!emit1(JSOp::FinishRecord)) {
11515 // [stack] RECORD
11516 return false;
11517 }
11518
11519 return true;
11520}
11521
11522bool BytecodeEmitter::emitTupleLiteral(ListNode* tuple) {
11523 if (!emitUint32Operand(JSOp::InitTuple, tuple->count())) {
11524 // [stack] TUPLE
11525 return false;
11526 }
11527
11528 for (ParseNode* elt : tuple->contents()) {
11529 if (elt->isKind(ParseNodeKind::Spread)) {
11530 ParseNode* expr = elt->as<UnaryNode>().kid();
11531 auto selfHostedIter = getSelfHostedIterFor(expr);
11532
11533 if (!emitIterable(expr, selfHostedIter)) {
11534 // [stack] TUPLE ITERABLE
11535 return false;
11536 }
11537 if (!emitIterator(selfHostedIter)) {
11538 // [stack] TUPLE NEXT ITER
11539 return false;
11540 }
11541 if (!emit2(JSOp::Pick, 2)) {
11542 // [stack] NEXT ITER TUPLE
11543 return false;
11544 }
11545 if (!emitSpread(selfHostedIter, /* spreadeeStackItems = */ 1,
11546 JSOp::AddTupleElement)) {
11547 // [stack] TUPLE
11548 return false;
11549 }
11550 } else {
11551 // Update location to throw errors about non-primitive elements
11552 // in the correct position.
11553 if (!updateSourceCoordNotesIfNonLiteral(elt)) {
11554 return false;
11555 }
11556
11557 if (!emitTree(elt)) {
11558 // [stack] TUPLE VALUE
11559 return false;
11560 }
11561
11562 if (!emit1(JSOp::AddTupleElement)) {
11563 // [stack] TUPLE
11564 return false;
11565 }
11566 }
11567 }
11568
11569 if (!emit1(JSOp::FinishTuple)) {
11570 // [stack] TUPLE
11571 return false;
11572 }
11573
11574 return true;
11575}
11576#endif
11577
11578static inline JSOp UnaryOpParseNodeKindToJSOp(ParseNodeKind pnk) {
11579 switch (pnk) {
11580 case ParseNodeKind::ThrowStmt:
11581 return JSOp::Throw;
11582 case ParseNodeKind::VoidExpr:
11583 return JSOp::Void;
11584 case ParseNodeKind::NotExpr:
11585 return JSOp::Not;
11586 case ParseNodeKind::BitNotExpr:
11587 return JSOp::BitNot;
11588 case ParseNodeKind::PosExpr:
11589 return JSOp::Pos;
11590 case ParseNodeKind::NegExpr:
11591 return JSOp::Neg;
11592 default:
11593 MOZ_CRASH("unexpected unary op")do { do { } while (false); MOZ_ReportCrash("" "unexpected unary op"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11593); AnnotateMozCrashReason("MOZ_CRASH(" "unexpected unary op"
")"); do { *((volatile int*)__null) = 11593; __attribute__((
nomerge)) ::abort(); } while (false); } while (false)
;
11594 }
11595}
11596
11597bool BytecodeEmitter::emitUnary(UnaryNode* unaryNode) {
11598 if (!updateSourceCoordNotes(unaryNode->pn_pos.begin)) {
11599 return false;
11600 }
11601
11602 JSOp op = UnaryOpParseNodeKindToJSOp(unaryNode->getKind());
11603 ValueUsage valueUsage =
11604 op == JSOp::Void ? ValueUsage::IgnoreValue : ValueUsage::WantValue;
11605 if (!emitTree(unaryNode->kid(), valueUsage)) {
11606 return false;
11607 }
11608 return emit1(op);
11609}
11610
11611bool BytecodeEmitter::emitTypeof(UnaryNode* typeofNode, JSOp op) {
11612 MOZ_ASSERT(op == JSOp::Typeof || op == JSOp::TypeofExpr)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(op == JSOp::Typeof || op == JSOp::TypeofExpr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(op == JSOp::Typeof || op == JSOp::TypeofExpr))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("op == JSOp::Typeof || op == JSOp::TypeofExpr"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11612); AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::Typeof || op == JSOp::TypeofExpr"
")"); do { *((volatile int*)__null) = 11612; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11613
11614 if (!updateSourceCoordNotes(typeofNode->pn_pos.begin)) {
11615 return false;
11616 }
11617
11618 if (!emitTree(typeofNode->kid())) {
11619 return false;
11620 }
11621
11622 return emit1(op);
11623}
11624
11625bool BytecodeEmitter::tryEmitTypeofEq(ListNode* node, bool* emitted) {
11626 // Emit specialized opcode for `typeof val == "type` or `typeof val != "type`
11627 // if possible.
11628 //
11629 // NOTE: Given the comparison is done for string, `==` and `===` have
11630 // no difference. Same for `!=` and `!==`.
11631 MOZ_ASSERT(node->isKind(ParseNodeKind::StrictEqExpr) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(node->isKind(ParseNodeKind::StrictEqExpr) || node
->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind
::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(node->isKind(ParseNodeKind::StrictEqExpr) || node
->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind
::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("node->isKind(ParseNodeKind::StrictEqExpr) || node->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11634); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::StrictEqExpr) || node->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)"
")"); do { *((volatile int*)__null) = 11634; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11632 node->isKind(ParseNodeKind::EqExpr) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(node->isKind(ParseNodeKind::StrictEqExpr) || node
->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind
::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(node->isKind(ParseNodeKind::StrictEqExpr) || node
->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind
::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("node->isKind(ParseNodeKind::StrictEqExpr) || node->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11634); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::StrictEqExpr) || node->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)"
")"); do { *((volatile int*)__null) = 11634; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11633 node->isKind(ParseNodeKind::StrictNeExpr) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(node->isKind(ParseNodeKind::StrictEqExpr) || node
->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind
::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(node->isKind(ParseNodeKind::StrictEqExpr) || node
->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind
::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("node->isKind(ParseNodeKind::StrictEqExpr) || node->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11634); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::StrictEqExpr) || node->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)"
")"); do { *((volatile int*)__null) = 11634; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11634 node->isKind(ParseNodeKind::NeExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(node->isKind(ParseNodeKind::StrictEqExpr) || node
->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind
::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(node->isKind(ParseNodeKind::StrictEqExpr) || node
->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind
::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("node->isKind(ParseNodeKind::StrictEqExpr) || node->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11634); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::StrictEqExpr) || node->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)"
")"); do { *((volatile int*)__null) = 11634; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11635
11636 if (node->count() != 2) {
11637 *emitted = false;
11638 return true;
11639 }
11640
11641 ParseNode* left = node->head();
11642 ParseNode* right = left->pn_next;
11643 MOZ_ASSERT(right)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(right)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(right))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("right", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11643); AnnotateMozCrashReason("MOZ_ASSERT" "(" "right" ")"
); do { *((volatile int*)__null) = 11643; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
11644
11645 UnaryNode* typeofNode;
11646 NameNode* typenameNode;
11647 JSOp op;
11648
11649 if (node->isKind(ParseNodeKind::StrictEqExpr) ||
11650 node->isKind(ParseNodeKind::EqExpr)) {
11651 op = JSOp::Eq;
11652 } else {
11653 op = JSOp::Ne;
11654 }
11655
11656 // NOTE: ParseNodeKind::TypeOfExpr cannot use JSOp::TypeofEq.
11657 // See JSOp::GetName document.
11658 if (left->isKind(ParseNodeKind::TypeOfNameExpr) &&
11659 right->isKind(ParseNodeKind::StringExpr)) {
11660 typeofNode = &left->as<UnaryNode>();
11661 typenameNode = &right->as<NameNode>();
11662 } else if (right->isKind(ParseNodeKind::TypeOfNameExpr) &&
11663 left->isKind(ParseNodeKind::StringExpr)) {
11664 typeofNode = &right->as<UnaryNode>();
11665 typenameNode = &left->as<NameNode>();
11666 } else {
11667 *emitted = false;
11668 return true;
11669 }
11670
11671 JSType type;
11672 TaggedParserAtomIndex typeName = typenameNode->atom();
11673 if (typeName == TaggedParserAtomIndex::WellKnown::undefined()) {
11674 type = JSTYPE_UNDEFINED;
11675 } else if (typeName == TaggedParserAtomIndex::WellKnown::object()) {
11676 type = JSTYPE_OBJECT;
11677 } else if (typeName == TaggedParserAtomIndex::WellKnown::function()) {
11678 type = JSTYPE_FUNCTION;
11679 } else if (typeName == TaggedParserAtomIndex::WellKnown::string()) {
11680 type = JSTYPE_STRING;
11681 } else if (typeName == TaggedParserAtomIndex::WellKnown::number()) {
11682 type = JSTYPE_NUMBER;
11683 } else if (typeName == TaggedParserAtomIndex::WellKnown::boolean()) {
11684 type = JSTYPE_BOOLEAN;
11685 } else if (typeName == TaggedParserAtomIndex::WellKnown::symbol()) {
11686 type = JSTYPE_SYMBOL;
11687 } else if (typeName == TaggedParserAtomIndex::WellKnown::bigint()) {
11688 type = JSTYPE_BIGINT;
11689 }
11690#ifdef ENABLE_RECORD_TUPLE
11691 else if (typeName == TaggedParserAtomIndex::WellKnown::record()) {
11692 type = JSTYPE_RECORD;
11693 } else if (typeName == TaggedParserAtomIndex::WellKnown::tuple()) {
11694 type = JSTYPE_TUPLE;
11695 }
11696#endif
11697 else {
11698 *emitted = false;
11699 return true;
11700 }
11701
11702 if (!updateSourceCoordNotes(typeofNode->pn_pos.begin)) {
11703 return false;
11704 }
11705
11706 if (!emitTree(typeofNode->kid())) {
11707 // [stack] VAL
11708 return false;
11709 }
11710
11711 if (!emit2(JSOp::TypeofEq, TypeofEqOperand(type, op).rawValue())) {
11712 // [stack] CMP
11713 return false;
11714 }
11715
11716 *emitted = true;
11717 return true;
11718}
11719
11720bool BytecodeEmitter::emitFunctionFormalParameters(ParamsBodyNode* paramsBody) {
11721 FunctionBox* funbox = sc->asFunctionBox();
11722
11723 bool hasRest = funbox->hasRest();
11724
11725 FunctionParamsEmitter fpe(this, funbox);
11726 for (ParseNode* arg : paramsBody->parameters()) {
11727 ParseNode* bindingElement = arg;
11728 ParseNode* initializer = nullptr;
11729 if (arg->isKind(ParseNodeKind::AssignExpr)) {
11730 bindingElement = arg->as<BinaryNode>().left();
11731 initializer = arg->as<BinaryNode>().right();
11732 }
11733 bool hasInitializer = !!initializer;
11734 bool isRest =
11735 hasRest && arg->pn_next == *std::end(paramsBody->parameters());
11736 bool isDestructuring = !bindingElement->isKind(ParseNodeKind::Name);
11737
11738 // Left-hand sides are either simple names or destructuring patterns.
11739 MOZ_ASSERT(bindingElement->isKind(ParseNodeKind::Name) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bindingElement->isKind(ParseNodeKind::Name) || bindingElement
->isKind(ParseNodeKind::ArrayExpr) || bindingElement->isKind
(ParseNodeKind::ObjectExpr))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(bindingElement->isKind(ParseNodeKind
::Name) || bindingElement->isKind(ParseNodeKind::ArrayExpr
) || bindingElement->isKind(ParseNodeKind::ObjectExpr)))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("bindingElement->isKind(ParseNodeKind::Name) || bindingElement->isKind(ParseNodeKind::ArrayExpr) || bindingElement->isKind(ParseNodeKind::ObjectExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11741); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bindingElement->isKind(ParseNodeKind::Name) || bindingElement->isKind(ParseNodeKind::ArrayExpr) || bindingElement->isKind(ParseNodeKind::ObjectExpr)"
")"); do { *((volatile int*)__null) = 11741; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11740 bindingElement->isKind(ParseNodeKind::ArrayExpr) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bindingElement->isKind(ParseNodeKind::Name) || bindingElement
->isKind(ParseNodeKind::ArrayExpr) || bindingElement->isKind
(ParseNodeKind::ObjectExpr))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(bindingElement->isKind(ParseNodeKind
::Name) || bindingElement->isKind(ParseNodeKind::ArrayExpr
) || bindingElement->isKind(ParseNodeKind::ObjectExpr)))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("bindingElement->isKind(ParseNodeKind::Name) || bindingElement->isKind(ParseNodeKind::ArrayExpr) || bindingElement->isKind(ParseNodeKind::ObjectExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11741); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bindingElement->isKind(ParseNodeKind::Name) || bindingElement->isKind(ParseNodeKind::ArrayExpr) || bindingElement->isKind(ParseNodeKind::ObjectExpr)"
")"); do { *((volatile int*)__null) = 11741; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11741 bindingElement->isKind(ParseNodeKind::ObjectExpr))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bindingElement->isKind(ParseNodeKind::Name) || bindingElement
->isKind(ParseNodeKind::ArrayExpr) || bindingElement->isKind
(ParseNodeKind::ObjectExpr))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(bindingElement->isKind(ParseNodeKind
::Name) || bindingElement->isKind(ParseNodeKind::ArrayExpr
) || bindingElement->isKind(ParseNodeKind::ObjectExpr)))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("bindingElement->isKind(ParseNodeKind::Name) || bindingElement->isKind(ParseNodeKind::ArrayExpr) || bindingElement->isKind(ParseNodeKind::ObjectExpr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11741); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bindingElement->isKind(ParseNodeKind::Name) || bindingElement->isKind(ParseNodeKind::ArrayExpr) || bindingElement->isKind(ParseNodeKind::ObjectExpr)"
")"); do { *((volatile int*)__null) = 11741; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11742
11743 auto emitDefaultInitializer = [this, &initializer, &bindingElement]() {
11744 // [stack]
11745
11746 if (!this->emitInitializer(initializer, bindingElement)) {
11747 // [stack] DEFAULT
11748 return false;
11749 }
11750 return true;
11751 };
11752
11753 auto emitDestructuring = [this, &bindingElement]() {
11754 // [stack] ARG
11755
11756 if (!this->emitDestructuringOps(&bindingElement->as<ListNode>(),
11757 DestructuringFlavor::Declaration)) {
11758 // [stack] ARG
11759 return false;
11760 }
11761
11762 return true;
11763 };
11764
11765 if (isRest) {
11766 if (isDestructuring) {
11767 if (!fpe.prepareForDestructuringRest()) {
11768 // [stack]
11769 return false;
11770 }
11771 if (!emitDestructuring()) {
11772 // [stack]
11773 return false;
11774 }
11775 if (!fpe.emitDestructuringRestEnd()) {
11776 // [stack]
11777 return false;
11778 }
11779 } else {
11780 auto paramName = bindingElement->as<NameNode>().name();
11781 if (!fpe.emitRest(paramName)) {
11782 // [stack]
11783 return false;
11784 }
11785 }
11786
11787 continue;
11788 }
11789
11790 if (isDestructuring) {
11791 if (hasInitializer) {
11792 if (!fpe.prepareForDestructuringDefaultInitializer()) {
11793 // [stack]
11794 return false;
11795 }
11796 if (!emitDefaultInitializer()) {
11797 // [stack]
11798 return false;
11799 }
11800 if (!fpe.prepareForDestructuringDefault()) {
11801 // [stack]
11802 return false;
11803 }
11804 if (!emitDestructuring()) {
11805 // [stack]
11806 return false;
11807 }
11808 if (!fpe.emitDestructuringDefaultEnd()) {
11809 // [stack]
11810 return false;
11811 }
11812 } else {
11813 if (!fpe.prepareForDestructuring()) {
11814 // [stack]
11815 return false;
11816 }
11817 if (!emitDestructuring()) {
11818 // [stack]
11819 return false;
11820 }
11821 if (!fpe.emitDestructuringEnd()) {
11822 // [stack]
11823 return false;
11824 }
11825 }
11826
11827 continue;
11828 }
11829
11830 if (hasInitializer) {
11831 if (!fpe.prepareForDefault()) {
11832 // [stack]
11833 return false;
11834 }
11835 if (!emitDefaultInitializer()) {
11836 // [stack]
11837 return false;
11838 }
11839 auto paramName = bindingElement->as<NameNode>().name();
11840 if (!fpe.emitDefaultEnd(paramName)) {
11841 // [stack]
11842 return false;
11843 }
11844
11845 continue;
11846 }
11847
11848 auto paramName = bindingElement->as<NameNode>().name();
11849 if (!fpe.emitSimple(paramName)) {
11850 // [stack]
11851 return false;
11852 }
11853 }
11854
11855 return true;
11856}
11857
11858bool BytecodeEmitter::emitInitializeFunctionSpecialNames() {
11859 FunctionBox* funbox = sc->asFunctionBox();
11860
11861 // [stack]
11862
11863 auto emitInitializeFunctionSpecialName =
11864 [](BytecodeEmitter* bce, TaggedParserAtomIndex name, JSOp op) {
11865 // A special name must be slotful, either on the frame or on the
11866 // call environment.
11867 MOZ_ASSERT(bce->lookupName(name).hasKnownSlot())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bce->lookupName(name).hasKnownSlot())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(bce->lookupName(name).hasKnownSlot()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("bce->lookupName(name).hasKnownSlot()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11867); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bce->lookupName(name).hasKnownSlot()"
")"); do { *((volatile int*)__null) = 11867; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11868
11869 NameOpEmitter noe(bce, name, NameOpEmitter::Kind::Initialize);
11870 if (!noe.prepareForRhs()) {
11871 // [stack]
11872 return false;
11873 }
11874 if (!bce->emit1(op)) {
11875 // [stack] THIS/ARGUMENTS/NEW.TARGET
11876 return false;
11877 }
11878 if (!noe.emitAssignment()) {
11879 // [stack] THIS/ARGUMENTS/NEW.TARGET
11880 return false;
11881 }
11882 if (!bce->emit1(JSOp::Pop)) {
11883 // [stack]
11884 return false;
11885 }
11886
11887 return true;
11888 };
11889
11890 // Do nothing if the function doesn't have an arguments binding.
11891 if (funbox->needsArgsObj()) {
11892 // Self-hosted code should use the more efficient ArgumentsLength and
11893 // GetArgument intrinsics instead of `arguments`.
11894 MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(emitterMode != BytecodeEmitter::SelfHosting)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(emitterMode != BytecodeEmitter::SelfHosting))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("emitterMode != BytecodeEmitter::SelfHosting"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11894); AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode != BytecodeEmitter::SelfHosting"
")"); do { *((volatile int*)__null) = 11894; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11895 if (!emitInitializeFunctionSpecialName(
11896 this, TaggedParserAtomIndex::WellKnown::arguments(),
11897 JSOp::Arguments)) {
11898 // [stack]
11899 return false;
11900 }
11901 }
11902
11903 // Do nothing if the function doesn't have a this-binding (this
11904 // happens for instance if it doesn't use this/eval or if it's an
11905 // arrow function).
11906 if (funbox->functionHasThisBinding()) {
11907 if (!emitInitializeFunctionSpecialName(
11908 this, TaggedParserAtomIndex::WellKnown::dot_this_(),
11909 JSOp::FunctionThis)) {
11910 return false;
11911 }
11912 }
11913
11914 // Do nothing if the function doesn't have a new.target-binding (this happens
11915 // for instance if it doesn't use new.target/eval or if it's an arrow
11916 // function).
11917 if (funbox->functionHasNewTargetBinding()) {
11918 if (!emitInitializeFunctionSpecialName(
11919 this, TaggedParserAtomIndex::WellKnown::dot_newTarget_(),
11920 JSOp::NewTarget)) {
11921 return false;
11922 }
11923 }
11924
11925 // Do nothing if the function doesn't implicitly return a promise result.
11926 if (funbox->needsPromiseResult()) {
11927 if (!emitInitializeFunctionSpecialName(
11928 this, TaggedParserAtomIndex::WellKnown::dot_generator_(),
11929 JSOp::Generator)) {
11930 // [stack]
11931 return false;
11932 }
11933 }
11934 return true;
11935}
11936
11937bool BytecodeEmitter::emitLexicalInitialization(NameNode* name) {
11938 return emitLexicalInitialization(name->name());
11939}
11940
11941bool BytecodeEmitter::emitLexicalInitialization(TaggedParserAtomIndex name) {
11942 NameOpEmitter noe(this, name, NameOpEmitter::Kind::Initialize);
11943 if (!noe.prepareForRhs()) {
11944 return false;
11945 }
11946
11947 // The caller has pushed the RHS to the top of the stack. Assert that the
11948 // binding can be initialized without a binding object on the stack, and that
11949 // no JSOp::BindUnqualifiedName or JSOp::BindUnqualifiedGName ops were
11950 // emitted.
11951 MOZ_ASSERT(noe.loc().isLexical() || noe.loc().isSynthetic() ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(noe.loc().isLexical() || noe.loc().isSynthetic() || noe
.loc().isPrivateMethod())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(noe.loc().isLexical() || noe
.loc().isSynthetic() || noe.loc().isPrivateMethod()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("noe.loc().isLexical() || noe.loc().isSynthetic() || noe.loc().isPrivateMethod()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11952); AnnotateMozCrashReason("MOZ_ASSERT" "(" "noe.loc().isLexical() || noe.loc().isSynthetic() || noe.loc().isPrivateMethod()"
")"); do { *((volatile int*)__null) = 11952; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11952 noe.loc().isPrivateMethod())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(noe.loc().isLexical() || noe.loc().isSynthetic() || noe
.loc().isPrivateMethod())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(noe.loc().isLexical() || noe
.loc().isSynthetic() || noe.loc().isPrivateMethod()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("noe.loc().isLexical() || noe.loc().isSynthetic() || noe.loc().isPrivateMethod()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11952); AnnotateMozCrashReason("MOZ_ASSERT" "(" "noe.loc().isLexical() || noe.loc().isSynthetic() || noe.loc().isPrivateMethod()"
")"); do { *((volatile int*)__null) = 11952; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11953 MOZ_ASSERT(!noe.emittedBindOp())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!noe.emittedBindOp())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!noe.emittedBindOp()))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("!noe.emittedBindOp()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 11953); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!noe.emittedBindOp()"
")"); do { *((volatile int*)__null) = 11953; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11954
11955 if (!noe.emitAssignment()) {
11956 return false;
11957 }
11958
11959 return true;
11960}
11961
11962static MOZ_ALWAYS_INLINEinline ParseNode* FindConstructor(ListNode* classMethods) {
11963 for (ParseNode* classElement : classMethods->contents()) {
11964 ParseNode* unwrappedElement = classElement;
11965 if (unwrappedElement->is<LexicalScopeNode>()) {
11966 unwrappedElement = unwrappedElement->as<LexicalScopeNode>().scopeBody();
11967 }
11968 if (unwrappedElement->is<ClassMethod>()) {
11969 ClassMethod& method = unwrappedElement->as<ClassMethod>();
11970 ParseNode& methodName = method.name();
11971 if (!method.isStatic() &&
11972 (methodName.isKind(ParseNodeKind::ObjectPropertyName) ||
11973 methodName.isKind(ParseNodeKind::StringExpr)) &&
11974 methodName.as<NameNode>().atom() ==
11975 TaggedParserAtomIndex::WellKnown::constructor()) {
11976 return classElement;
11977 }
11978 }
11979 }
11980 return nullptr;
11981}
11982
11983bool BytecodeEmitter::emitNewPrivateName(TaggedParserAtomIndex bindingName,
11984 TaggedParserAtomIndex symbolName) {
11985 if (!emitAtomOp(JSOp::NewPrivateName, symbolName)) {
11986 // [stack] HERITAGE PRIVATENAME
11987 return false;
11988 }
11989
11990 // Add a binding for #name => privatename
11991 if (!emitLexicalInitialization(bindingName)) {
11992 // [stack] HERITAGE PRIVATENAME
11993 return false;
11994 }
11995
11996 // Pop Private name off the stack.
11997 if (!emit1(JSOp::Pop)) {
11998 // [stack] HERITAGE
11999 return false;
12000 }
12001
12002 return true;
12003}
12004
12005bool BytecodeEmitter::emitNewPrivateNames(
12006 TaggedParserAtomIndex privateBrandName, ListNode* classMembers) {
12007 bool hasPrivateBrand = false;
12008
12009 for (ParseNode* classElement : classMembers->contents()) {
12010 ParseNode* elementName;
12011 if (classElement->is<ClassMethod>()) {
12012 elementName = &classElement->as<ClassMethod>().name();
12013 } else if (classElement->is<ClassField>()) {
12014 elementName = &classElement->as<ClassField>().name();
12015 } else {
12016 continue;
12017 }
12018
12019 if (!elementName->isKind(ParseNodeKind::PrivateName)) {
12020 continue;
12021 }
12022
12023 // Non-static private methods' private names are optimized away.
12024 bool isOptimized = false;
12025 if (classElement->is<ClassMethod>() &&
12026 !classElement->as<ClassMethod>().isStatic()) {
12027 hasPrivateBrand = true;
12028 if (classElement->as<ClassMethod>().accessorType() ==
12029 AccessorType::None) {
12030 isOptimized = true;
12031 }
12032 }
12033
12034 if (!isOptimized) {
12035 auto privateName = elementName->as<NameNode>().name();
12036 if (!emitNewPrivateName(privateName, privateName)) {
12037 return false;
12038 }
12039 }
12040 }
12041
12042 if (hasPrivateBrand) {
12043 // We don't make a private name for every optimized method, but we need one
12044 // private name per class, the `.privateBrand`.
12045 if (!emitNewPrivateName(
12046 TaggedParserAtomIndex::WellKnown::dot_privateBrand_(),
12047 privateBrandName)) {
12048 return false;
12049 }
12050 }
12051 return true;
12052}
12053
12054// This follows ES6 14.5.14 (ClassDefinitionEvaluation) and ES6 14.5.15
12055// (BindingClassDeclarationEvaluation).
12056bool BytecodeEmitter::emitClass(
12057 ClassNode* classNode,
12058 ClassNameKind nameKind /* = ClassNameKind::BindingName */,
12059 TaggedParserAtomIndex
12060 nameForAnonymousClass /* = TaggedParserAtomIndex::null() */) {
12061 MOZ_ASSERT((nameKind == ClassNameKind::InferredName) ==do { static_assert( mozilla::detail::AssertionConditionType<
decltype((nameKind == ClassNameKind::InferredName) == bool(nameForAnonymousClass
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!((nameKind == ClassNameKind::InferredName) == bool(nameForAnonymousClass
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("(nameKind == ClassNameKind::InferredName) == bool(nameForAnonymousClass)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12062); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(nameKind == ClassNameKind::InferredName) == bool(nameForAnonymousClass)"
")"); do { *((volatile int*)__null) = 12062; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12062 bool(nameForAnonymousClass))do { static_assert( mozilla::detail::AssertionConditionType<
decltype((nameKind == ClassNameKind::InferredName) == bool(nameForAnonymousClass
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!((nameKind == ClassNameKind::InferredName) == bool(nameForAnonymousClass
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("(nameKind == ClassNameKind::InferredName) == bool(nameForAnonymousClass)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12062); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(nameKind == ClassNameKind::InferredName) == bool(nameForAnonymousClass)"
")"); do { *((volatile int*)__null) = 12062; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12063
12064 ParseNode* heritageExpression = classNode->heritage();
12065 ListNode* classMembers = classNode->memberList();
12066 ParseNode* constructor = FindConstructor(classMembers);
12067
12068 // If |nameKind != ClassNameKind::ComputedName|
12069 // [stack]
12070 // Else
12071 // [stack] NAME
12072
12073 ClassEmitter ce(this);
12074 TaggedParserAtomIndex innerName;
12075 ClassEmitter::Kind kind = ClassEmitter::Kind::Expression;
12076 if (ClassNames* names = classNode->names()) {
12077 MOZ_ASSERT(nameKind == ClassNameKind::BindingName)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(nameKind == ClassNameKind::BindingName)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(nameKind == ClassNameKind::BindingName))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("nameKind == ClassNameKind::BindingName"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12077); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nameKind == ClassNameKind::BindingName"
")"); do { *((volatile int*)__null) = 12077; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12078 innerName = names->innerBinding()->name();
12079 MOZ_ASSERT(innerName)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(innerName)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(innerName))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("innerName", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12079); AnnotateMozCrashReason("MOZ_ASSERT" "(" "innerName"
")"); do { *((volatile int*)__null) = 12079; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12080
12081 if (names->outerBinding()) {
12082 MOZ_ASSERT(names->outerBinding()->name())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(names->outerBinding()->name())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(names->outerBinding()->
name()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("names->outerBinding()->name()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12082); AnnotateMozCrashReason("MOZ_ASSERT" "(" "names->outerBinding()->name()"
")"); do { *((volatile int*)__null) = 12082; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12083 MOZ_ASSERT(names->outerBinding()->name() == innerName)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(names->outerBinding()->name() == innerName)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(names->outerBinding()->name() == innerName))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("names->outerBinding()->name() == innerName"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12083); AnnotateMozCrashReason("MOZ_ASSERT" "(" "names->outerBinding()->name() == innerName"
")"); do { *((volatile int*)__null) = 12083; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12084 kind = ClassEmitter::Kind::Declaration;
12085 }
12086 }
12087
12088 if (LexicalScopeNode* scopeBindings = classNode->scopeBindings()) {
12089 if (!ce.emitScope(scopeBindings->scopeBindings())) {
12090 // [stack]
12091 return false;
12092 }
12093 }
12094
12095 bool isDerived = !!heritageExpression;
12096 if (isDerived) {
12097 if (!updateSourceCoordNotes(classNode->pn_pos.begin)) {
12098 return false;
12099 }
12100 if (!markStepBreakpoint()) {
12101 return false;
12102 }
12103 if (!emitTree(heritageExpression)) {
12104 // [stack] HERITAGE
12105 return false;
12106 }
12107 }
12108
12109 // The class body scope holds any private names. Those mustn't be visible in
12110 // the heritage expression and hence the scope must be emitted after the
12111 // heritage expression.
12112 if (ClassBodyScopeNode* bodyScopeBindings = classNode->bodyScopeBindings()) {
12113 if (!ce.emitBodyScope(bodyScopeBindings->scopeBindings())) {
12114 // [stack] HERITAGE
12115 return false;
12116 }
12117
12118 // The spec does not say anything about private brands being symbols. It's
12119 // an implementation detail. So we can give the special private brand
12120 // symbol any description we want and users won't normally see it. For
12121 // debugging, use the class name.
12122 auto privateBrandName = innerName;
12123 if (!innerName) {
12124 privateBrandName = nameForAnonymousClass
12125 ? nameForAnonymousClass
12126 : TaggedParserAtomIndex::WellKnown::anonymous();
12127 }
12128 if (!emitNewPrivateNames(privateBrandName, classMembers)) {
12129 return false;
12130 }
12131 }
12132
12133 bool hasNameOnStack = nameKind == ClassNameKind::ComputedName;
12134 if (isDerived) {
12135 if (!ce.emitDerivedClass(innerName, nameForAnonymousClass,
12136 hasNameOnStack)) {
12137 // [stack] HOMEOBJ HERITAGE
12138 return false;
12139 }
12140 } else {
12141 if (!ce.emitClass(innerName, nameForAnonymousClass, hasNameOnStack)) {
12142 // [stack] HOMEOBJ
12143 return false;
12144 }
12145 }
12146
12147 // Stack currently has HOMEOBJ followed by optional HERITAGE. When HERITAGE
12148 // is not used, an implicit value of %FunctionPrototype% is implied.
12149
12150 // See |Parser::classMember(...)| for the reason why |.initializers| is
12151 // created within its own scope.
12152 Maybe<LexicalScopeEmitter> lse;
12153 FunctionNode* ctor;
12154#ifdef ENABLE_DECORATORS
12155 bool extraInitializersPresent = false;
12156#endif
12157 if (constructor->is<LexicalScopeNode>()) {
12158 LexicalScopeNode* constructorScope = &constructor->as<LexicalScopeNode>();
12159
12160 MOZ_ASSERT(!constructorScope->isEmptyScope())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!constructorScope->isEmptyScope())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!constructorScope->isEmptyScope
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!constructorScope->isEmptyScope()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12160); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!constructorScope->isEmptyScope()"
")"); do { *((volatile int*)__null) = 12160; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12161#ifdef ENABLE_DECORATORS
12162 // With decorators enabled we expect to see |.initializers|,
12163 // and |.instanceExtraInitializers| in this scope.
12164 MOZ_ASSERT(constructorScope->scopeBindings()->length == 2)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(constructorScope->scopeBindings()->length == 2
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(constructorScope->scopeBindings()->length == 2
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"constructorScope->scopeBindings()->length == 2", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12164); AnnotateMozCrashReason("MOZ_ASSERT" "(" "constructorScope->scopeBindings()->length == 2"
")"); do { *((volatile int*)__null) = 12164; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12165 MOZ_ASSERT(GetScopeDataTrailingNames(constructorScope->scopeBindings())[0]do { static_assert( mozilla::detail::AssertionConditionType<
decltype(GetScopeDataTrailingNames(constructorScope->scopeBindings
())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(GetScopeDataTrailingNames(constructorScope->scopeBindings
())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12167); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()"
")"); do { *((volatile int*)__null) = 12167; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12166 .name() ==do { static_assert( mozilla::detail::AssertionConditionType<
decltype(GetScopeDataTrailingNames(constructorScope->scopeBindings
())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(GetScopeDataTrailingNames(constructorScope->scopeBindings
())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12167); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()"
")"); do { *((volatile int*)__null) = 12167; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12167 TaggedParserAtomIndex::WellKnown::dot_initializers_())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(GetScopeDataTrailingNames(constructorScope->scopeBindings
())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(GetScopeDataTrailingNames(constructorScope->scopeBindings
())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12167); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()"
")"); do { *((volatile int*)__null) = 12167; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12168 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(GetScopeDataTrailingNames(constructorScope->scopeBindings
())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(GetScopeDataTrailingNames(constructorScope->scopeBindings
())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("GetScopeDataTrailingNames(constructorScope->scopeBindings())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12171); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_()"
")"); do { *((volatile int*)__null) = 12171; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12169 GetScopeDataTrailingNames(constructorScope->scopeBindings())[1]do { static_assert( mozilla::detail::AssertionConditionType<
decltype(GetScopeDataTrailingNames(constructorScope->scopeBindings
())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(GetScopeDataTrailingNames(constructorScope->scopeBindings
())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("GetScopeDataTrailingNames(constructorScope->scopeBindings())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12171); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_()"
")"); do { *((volatile int*)__null) = 12171; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12170 .name() ==do { static_assert( mozilla::detail::AssertionConditionType<
decltype(GetScopeDataTrailingNames(constructorScope->scopeBindings
())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(GetScopeDataTrailingNames(constructorScope->scopeBindings
())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("GetScopeDataTrailingNames(constructorScope->scopeBindings())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12171); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_()"
")"); do { *((volatile int*)__null) = 12171; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12171 TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(GetScopeDataTrailingNames(constructorScope->scopeBindings
())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(GetScopeDataTrailingNames(constructorScope->scopeBindings
())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("GetScopeDataTrailingNames(constructorScope->scopeBindings())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12171); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_()"
")"); do { *((volatile int*)__null) = 12171; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12172
12173 // We should only call this code if we know decorators are present, see bug
12174 // 1871147.
12175 lse.emplace(this);
12176 if (!lse->emitScope(ScopeKind::Lexical,
12177 constructorScope->scopeBindings())) {
12178 return false;
12179 }
12180
12181 // TODO: See bug 1868220 for support for static extra initializers.
12182 if (!ce.prepareForExtraInitializers(TaggedParserAtomIndex::WellKnown::
12183 dot_instanceExtraInitializers_())) {
12184 return false;
12185 }
12186
12187 if (classNode->addInitializerFunction()) {
12188 DecoratorEmitter de(this);
12189 if (!de.emitCreateAddInitializerFunction(
12190 classNode->addInitializerFunction(),
12191 TaggedParserAtomIndex::WellKnown::
12192 dot_instanceExtraInitializers_())) {
12193 // [stack] HOMEOBJ HERITAGE? ADDINIT
12194 return false;
12195 }
12196
12197 if (!emitUnpickN(isDerived ? 2 : 1)) {
12198 // [stack] ADDINIT HOMEOBJ HERITAGE?
12199 return false;
12200 }
12201
12202 extraInitializersPresent = true;
12203 }
12204#else
12205 // The constructor scope should only contain the |.initializers| binding.
12206 MOZ_ASSERT(constructorScope->scopeBindings()->length == 1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(constructorScope->scopeBindings()->length == 1
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(constructorScope->scopeBindings()->length == 1
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"constructorScope->scopeBindings()->length == 1", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12206); AnnotateMozCrashReason("MOZ_ASSERT" "(" "constructorScope->scopeBindings()->length == 1"
")"); do { *((volatile int*)__null) = 12206; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12207 MOZ_ASSERT(GetScopeDataTrailingNames(constructorScope->scopeBindings())[0]do { static_assert( mozilla::detail::AssertionConditionType<
decltype(GetScopeDataTrailingNames(constructorScope->scopeBindings
())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(GetScopeDataTrailingNames(constructorScope->scopeBindings
())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12209); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()"
")"); do { *((volatile int*)__null) = 12209; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12208 .name() ==do { static_assert( mozilla::detail::AssertionConditionType<
decltype(GetScopeDataTrailingNames(constructorScope->scopeBindings
())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(GetScopeDataTrailingNames(constructorScope->scopeBindings
())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12209); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()"
")"); do { *((volatile int*)__null) = 12209; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12209 TaggedParserAtomIndex::WellKnown::dot_initializers_())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(GetScopeDataTrailingNames(constructorScope->scopeBindings
())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(GetScopeDataTrailingNames(constructorScope->scopeBindings
())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12209); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()"
")"); do { *((volatile int*)__null) = 12209; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12210#endif
12211
12212 auto needsInitializer = [](ParseNode* propdef) {
12213 return NeedsFieldInitializer(propdef, false) ||
12214 NeedsAccessorInitializer(propdef, false);
12215 };
12216
12217 // As an optimization omit the |.initializers| binding when no instance
12218 // fields or private methods are present.
12219 bool needsInitializers =
12220 std::any_of(classMembers->contents().begin(),
12221 classMembers->contents().end(), needsInitializer);
12222 if (needsInitializers) {
12223#ifndef ENABLE_DECORATORS
12224 lse.emplace(this);
12225 if (!lse->emitScope(ScopeKind::Lexical,
12226 constructorScope->scopeBindings())) {
12227 return false;
12228 }
12229#endif
12230 // Any class with field initializers will have a constructor
12231 if (!emitCreateMemberInitializers(ce, classMembers,
12232 FieldPlacement::Instance
12233#ifdef ENABLE_DECORATORS
12234 ,
12235 isDerived
12236#endif
12237 )) {
12238 return false;
12239 }
12240 }
12241
12242 ctor = &constructorScope->scopeBody()->as<ClassMethod>().method();
12243 } else {
12244 // The |.initializers| binding is never emitted when in self-hosting mode.
12245 MOZ_ASSERT(emitterMode == BytecodeEmitter::SelfHosting)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(emitterMode == BytecodeEmitter::SelfHosting)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(emitterMode == BytecodeEmitter::SelfHosting))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("emitterMode == BytecodeEmitter::SelfHosting"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12245); AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode == BytecodeEmitter::SelfHosting"
")"); do { *((volatile int*)__null) = 12245; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12246 ctor = &constructor->as<ClassMethod>().method();
12247 }
12248
12249 bool needsHomeObject = ctor->funbox()->needsHomeObject();
12250 // HERITAGE is consumed inside emitFunction.
12251 if (nameKind == ClassNameKind::InferredName) {
12252 setFunName(ctor->funbox(), nameForAnonymousClass);
12253 }
12254 if (!emitFunction(ctor, isDerived)) {
12255 // [stack] HOMEOBJ CTOR
12256 return false;
12257 }
12258 if (lse.isSome()) {
12259 if (!lse->emitEnd()) {
12260 return false;
12261 }
12262 lse.reset();
12263 }
12264 if (!ce.emitInitConstructor(needsHomeObject)) {
12265 // [stack] CTOR HOMEOBJ
12266 return false;
12267 }
12268
12269 if (!emitCreateFieldKeys(classMembers, FieldPlacement::Instance)) {
12270 return false;
12271 }
12272
12273#ifdef ENABLE_DECORATORS
12274 // TODO: See Bug 1868220 for support for static extra initializers.
12275 if (!emit1(JSOp::Undefined)) {
12276 // [stack] ADDINIT? CTOR HOMEOBJ UNDEFINED
12277 return false;
12278 }
12279 if (!emitUnpickN(2)) {
12280 // [stack] ADDINIT? UNDEFINED CTOR HOMEOBJ
12281 return false;
12282 }
12283#endif
12284
12285 if (!emitCreateMemberInitializers(ce, classMembers, FieldPlacement::Static
12286#ifdef ENABLE_DECORATORS
12287 ,
12288 false
12289#endif
12290 )) {
12291 return false;
12292 }
12293
12294#ifdef ENABLE_DECORATORS
12295 if (!emitPickN(2)) {
12296 // [stack] ADDINIT? CTOR HOMEOBJ UNDEFINED
12297 return false;
12298 }
12299 if (!emitPopN(1)) {
12300 // [stack] ADDINIT? CTOR HOMEOBJ
12301 return false;
12302 }
12303#endif
12304
12305 if (!emitCreateFieldKeys(classMembers, FieldPlacement::Static)) {
12306 return false;
12307 }
12308
12309 if (!emitPropertyList(classMembers, ce, ClassBody)) {
12310 // [stack] CTOR HOMEOBJ
12311 return false;
12312 }
12313
12314#ifdef ENABLE_DECORATORS
12315 if (extraInitializersPresent) {
12316 if (!emitPickN(2)) {
12317 // [stack] CTOR HOMEOBJ ADDINIT
12318 return false;
12319 }
12320 if (!emitPopN(1)) {
12321 // [stack] CTOR HOMEOBJ
12322 return false;
12323 }
12324 }
12325#endif
12326
12327 if (!ce.emitBinding()) {
12328 // [stack] CTOR
12329 return false;
12330 }
12331
12332 if (!emitInitializeStaticFields(classMembers)) {
12333 // [stack] CTOR
12334 return false;
12335 }
12336
12337#if ENABLE_DECORATORS
12338 if (!ce.prepareForDecorators()) {
12339 // [stack] CTOR
12340 return false;
12341 }
12342 if (classNode->decorators() != nullptr) {
12343 DecoratorEmitter de(this);
12344 NameNode* className =
12345 classNode->names() ? classNode->names()->innerBinding() : nullptr;
12346 if (!de.emitApplyDecoratorsToClassDefinition(className,
12347 classNode->decorators())) {
12348 // [stack] CTOR
12349 return false;
12350 }
12351 }
12352#endif
12353
12354 if (!ce.emitEnd(kind)) {
12355 // [stack] # class declaration
12356 // [stack]
12357 // [stack] # class expression
12358 // [stack] CTOR
12359 return false;
12360 }
12361
12362 return true;
12363}
12364
12365bool BytecodeEmitter::emitExportDefault(BinaryNode* exportNode) {
12366 MOZ_ASSERT(exportNode->isKind(ParseNodeKind::ExportDefaultStmt))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(exportNode->isKind(ParseNodeKind::ExportDefaultStmt
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(exportNode->isKind(ParseNodeKind::ExportDefaultStmt
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("exportNode->isKind(ParseNodeKind::ExportDefaultStmt)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12366); AnnotateMozCrashReason("MOZ_ASSERT" "(" "exportNode->isKind(ParseNodeKind::ExportDefaultStmt)"
")"); do { *((volatile int*)__null) = 12366; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12367
12368 ParseNode* valueNode = exportNode->left();
12369 if (valueNode->isDirectRHSAnonFunction()) {
12370 MOZ_ASSERT(exportNode->right())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(exportNode->right())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(exportNode->right()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("exportNode->right()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12370); AnnotateMozCrashReason("MOZ_ASSERT" "(" "exportNode->right()"
")"); do { *((volatile int*)__null) = 12370; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12371
12372 if (!emitAnonymousFunctionWithName(
12373 valueNode, TaggedParserAtomIndex::WellKnown::default_())) {
12374 return false;
12375 }
12376 } else {
12377 if (!emitTree(valueNode)) {
12378 return false;
12379 }
12380 }
12381
12382 if (ParseNode* binding = exportNode->right()) {
12383 if (!emitLexicalInitialization(&binding->as<NameNode>())) {
12384 return false;
12385 }
12386
12387 if (!emit1(JSOp::Pop)) {
12388 return false;
12389 }
12390 }
12391
12392 return true;
12393}
12394
12395bool BytecodeEmitter::emitTree(
12396 ParseNode* pn, ValueUsage valueUsage /* = ValueUsage::WantValue */,
12397 EmitLineNumberNote emitLineNote /* = EMIT_LINENOTE */) {
12398 AutoCheckRecursionLimit recursion(fc);
12399 if (!recursion.check(fc)) {
12400 return false;
12401 }
12402
12403 /* Emit notes to tell the current bytecode's source line number.
12404 However, a couple trees require special treatment; see the
12405 relevant emitter functions for details. */
12406 if (emitLineNote == EMIT_LINENOTE &&
12407 !ParseNodeRequiresSpecialLineNumberNotes(pn)) {
12408 if (!updateLineNumberNotes(pn->pn_pos.begin)) {
12409 return false;
12410 }
12411 }
12412
12413 switch (pn->getKind()) {
12414 case ParseNodeKind::Function:
12415 if (!emitFunction(&pn->as<FunctionNode>())) {
12416 return false;
12417 }
12418 break;
12419
12420 case ParseNodeKind::ParamsBody:
12421 MOZ_ASSERT_UNREACHABLE(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"ParamsBody should be handled in emitFunctionScript." ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12422); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "ParamsBody should be handled in emitFunctionScript."
")"); do { *((volatile int*)__null) = 12422; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12422 "ParamsBody should be handled in emitFunctionScript.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"ParamsBody should be handled in emitFunctionScript." ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 12422); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "ParamsBody should be handled in emitFunctionScript."
")"); do { *((volatile int*)__null) = 12422; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12423 break;
12424
12425 case ParseNodeKind::IfStmt:
12426 if (!emitIf(&pn->as<TernaryNode>())) {
12427 return false;
12428 }
12429 break;
12430
12431 case ParseNodeKind::SwitchStmt:
12432 if (!emitSwitch(&pn->as<SwitchStatement>())) {
12433 return false;
12434 }
12435 break;
12436
12437 case ParseNodeKind::WhileStmt:
12438 if (!emitWhile(&pn->as<BinaryNode>())) {
12439 return false;
12440 }
12441 break;
12442
12443 case ParseNodeKind::DoWhileStmt:
12444 if (!emitDo(&pn->as<BinaryNode>())) {
12445 return false;
12446 }
12447 break;
12448
12449 case ParseNodeKind::ForStmt:
12450 if (!emitFor(&pn->as<ForNode>())) {
12451 return false;
12452 }
12453 break;
12454
12455 case ParseNodeKind::BreakStmt:
12456 // Ensure that the column of the 'break' is set properly.
12457 if (!updateSourceCoordNotes(pn->pn_pos.begin)) {
12458 return false;
12459 }
12460 if (!markStepBreakpoint()) {
12461 return false;
12462 }
12463
12464 if (!emitBreak(pn->as<BreakStatement>().label())) {
12465 return false;
12466 }
12467 break;
12468
12469 case ParseNodeKind::ContinueStmt:
12470 // Ensure that the column of the 'continue' is set properly.
12471 if (!updateSourceCoordNotes(pn->pn_pos.begin)) {
12472 return false;
12473 }
12474 if (!markStepBreakpoint()) {
12475 return false;
12476 }
12477
12478 if (!emitContinue(pn->as<ContinueStatement>().label())) {
12479 return false;
12480 }
12481 break;
12482
12483 case ParseNodeKind::WithStmt:
12484 if (!emitWith(&pn->as<BinaryNode>())) {
12485 return false;
12486 }
12487 break;
12488
12489 case ParseNodeKind::TryStmt:
12490 if (!emitTry(&pn->as<TryNode>())) {
12491 return false;
12492 }
12493 break;
12494
12495 case ParseNodeKind::Catch:
12496 if (!emitCatch(&pn->as<BinaryNode>())) {
12497 return false;
12498 }
12499 break;
12500
12501 case ParseNodeKind::VarStmt:
12502 if (!emitDeclarationList(&pn->as<ListNode>())) {
12503 return false;
12504 }
12505 break;
12506
12507 case ParseNodeKind::ReturnStmt:
12508 if (!emitReturn(&pn->as<UnaryNode>())) {
12509 return false;
12510 }
12511 break;
12512
12513 case ParseNodeKind::YieldStarExpr:
12514 if (!emitYieldStar(pn->as<UnaryNode>().kid())) {
12515 return false;
12516 }
12517 break;
12518
12519 case ParseNodeKind::Generator:
12520 if (!emit1(JSOp::Generator)) {
12521 return false;
12522 }
12523 break;
12524
12525 case ParseNodeKind::InitialYield:
12526 if (!emitInitialYield(&pn->as<UnaryNode>())) {
12527 return false;
12528 }
12529 break;
12530
12531 case ParseNodeKind::YieldExpr:
12532 if (!emitYield(&pn->as<UnaryNode>())) {
12533 return false;
12534 }
12535 break;
12536
12537 case ParseNodeKind::AwaitExpr:
12538 if (!emitAwaitInInnermostScope(&pn->as<UnaryNode>())) {
12539 return false;
12540 }
12541 break;
12542
12543 case ParseNodeKind::StatementList:
12544 if (!emitStatementList(&pn->as<ListNode>())) {
12545 return false;
12546 }
12547 break;
12548
12549 case ParseNodeKind::EmptyStmt:
12550 break;
12551
12552 case ParseNodeKind::ExpressionStmt:
12553 if (!emitExpressionStatement(&pn->as<UnaryNode>())) {
12554 return false;
12555 }
12556 break;
12557
12558 case ParseNodeKind::LabelStmt:
12559 if (!emitLabeledStatement(&pn->as<LabeledStatement>())) {
12560 return false;
12561 }
12562 break;
12563
12564 case ParseNodeKind::CommaExpr:
12565 if (!emitSequenceExpr(&pn->as<ListNode>(), valueUsage)) {
12566 return false;
12567 }
12568 break;
12569
12570 case ParseNodeKind::InitExpr:
12571 case ParseNodeKind::AssignExpr:
12572 case ParseNodeKind::AddAssignExpr:
12573 case ParseNodeKind::SubAssignExpr:
12574 case ParseNodeKind::BitOrAssignExpr:
12575 case ParseNodeKind::BitXorAssignExpr:
12576 case ParseNodeKind::BitAndAssignExpr:
12577 case ParseNodeKind::LshAssignExpr:
12578 case ParseNodeKind::RshAssignExpr:
12579 case ParseNodeKind::UrshAssignExpr:
12580 case ParseNodeKind::MulAssignExpr:
12581 case ParseNodeKind::DivAssignExpr:
12582 case ParseNodeKind::ModAssignExpr:
12583 case ParseNodeKind::PowAssignExpr: {
12584 BinaryNode* assignNode = &pn->as<BinaryNode>();
12585 if (!emitAssignmentOrInit(assignNode->getKind(), assignNode->left(),
12586 assignNode->right())) {
12587 return false;
12588 }
12589 break;
12590 }
12591
12592 case ParseNodeKind::CoalesceAssignExpr:
12593 case ParseNodeKind::OrAssignExpr:
12594 case ParseNodeKind::AndAssignExpr:
12595 if (!emitShortCircuitAssignment(&pn->as<AssignmentNode>())) {
12596 return false;
12597 }
12598 break;
12599
12600 case ParseNodeKind::ConditionalExpr:
12601 if (!emitConditionalExpression(pn->as<ConditionalExpression>(),
12602 valueUsage)) {
12603 return false;
12604 }
12605 break;
12606
12607 case ParseNodeKind::OrExpr:
12608 case ParseNodeKind::CoalesceExpr:
12609 case ParseNodeKind::AndExpr:
12610 if (!emitShortCircuit(&pn->as<ListNode>(), valueUsage)) {
12611 return false;
12612 }
12613 break;
12614
12615 case ParseNodeKind::StrictEqExpr:
12616 case ParseNodeKind::EqExpr:
12617 case ParseNodeKind::StrictNeExpr:
12618 case ParseNodeKind::NeExpr: {
12619 bool emitted;
12620 if (!tryEmitTypeofEq(&pn->as<ListNode>(), &emitted)) {
12621 return false;
12622 }
12623 if (emitted) {
12624 return true;
12625 }
12626 }
12627 [[fallthrough]];
12628
12629 case ParseNodeKind::AddExpr:
12630 case ParseNodeKind::SubExpr:
12631 case ParseNodeKind::BitOrExpr:
12632 case ParseNodeKind::BitXorExpr:
12633 case ParseNodeKind::BitAndExpr:
12634 case ParseNodeKind::LtExpr:
12635 case ParseNodeKind::LeExpr:
12636 case ParseNodeKind::GtExpr:
12637 case ParseNodeKind::GeExpr:
12638 case ParseNodeKind::InExpr:
12639 case ParseNodeKind::InstanceOfExpr:
12640 case ParseNodeKind::LshExpr:
12641 case ParseNodeKind::RshExpr:
12642 case ParseNodeKind::UrshExpr:
12643 case ParseNodeKind::MulExpr:
12644 case ParseNodeKind::DivExpr:
12645 case ParseNodeKind::ModExpr:
12646 if (!emitLeftAssociative(&pn->as<ListNode>())) {
12647 return false;
12648 }
12649 break;
12650
12651 case ParseNodeKind::PrivateInExpr:
12652 if (!emitPrivateInExpr(&pn->as<ListNode>())) {
12653 return false;
12654 }
12655 break;
12656
12657 case ParseNodeKind::PowExpr:
12658 if (!emitRightAssociative(&pn->as<ListNode>())) {
12659 return false;
12660 }
12661 break;
12662
12663 case ParseNodeKind::TypeOfNameExpr:
12664 if (!emitTypeof(&pn->as<UnaryNode>(), JSOp::Typeof)) {
12665 return false;
12666 }
12667 break;
12668
12669 case ParseNodeKind::TypeOfExpr:
12670 if (!emitTypeof(&pn->as<UnaryNode>(), JSOp::TypeofExpr)) {
12671 return false;
12672 }
12673 break;
12674
12675 case ParseNodeKind::ThrowStmt:
12676 if (!updateSourceCoordNotes(pn->pn_pos.begin)) {
12677 return false;
12678 }
12679 if (!markStepBreakpoint()) {
12680 return false;
12681 }
12682 [[fallthrough]];
12683 case ParseNodeKind::VoidExpr:
12684 case ParseNodeKind::NotExpr:
12685 case ParseNodeKind::BitNotExpr:
12686 case ParseNodeKind::PosExpr:
12687 case ParseNodeKind::NegExpr:
12688 if (!emitUnary(&pn->as<UnaryNode>())) {
12689 return false;
12690 }
12691 break;
12692
12693 case ParseNodeKind::PreIncrementExpr:
12694 case ParseNodeKind::PreDecrementExpr:
12695 case ParseNodeKind::PostIncrementExpr:
12696 case ParseNodeKind::PostDecrementExpr:
12697 if (!emitIncOrDec(&pn->as<UnaryNode>(), valueUsage)) {
12698 return false;
12699 }
12700 break;
12701
12702 case ParseNodeKind::DeleteNameExpr:
12703 if (!emitDeleteName(&pn->as<UnaryNode>())) {
12704 return false;
12705 }
12706 break;
12707
12708 case ParseNodeKind::DeletePropExpr:
12709 if (!emitDeleteProperty(&pn->as<UnaryNode>())) {
12710 return false;
12711 }
12712 break;
12713
12714 case ParseNodeKind::DeleteElemExpr:
12715 if (!emitDeleteElement(&pn->as<UnaryNode>())) {
12716 return false;
12717 }
12718 break;
12719
12720 case ParseNodeKind::DeleteExpr:
12721 if (!emitDeleteExpression(&pn->as<UnaryNode>())) {
12722 return false;
12723 }
12724 break;
12725
12726 case ParseNodeKind::DeleteOptionalChainExpr:
12727 if (!emitDeleteOptionalChain(&pn->as<UnaryNode>())) {
12728 return false;
12729 }
12730 break;
12731
12732 case ParseNodeKind::OptionalChain:
12733 if (!emitOptionalChain(&pn->as<UnaryNode>(), valueUsage)) {
12734 return false;
12735 }
12736 break;
12737
12738 case ParseNodeKind::DotExpr: {
12739 PropertyAccess* prop = &pn->as<PropertyAccess>();
12740 bool isSuper = prop->isSuper();
12741 PropOpEmitter poe(this, PropOpEmitter::Kind::Get,
12742 isSuper ? PropOpEmitter::ObjKind::Super
12743 : PropOpEmitter::ObjKind::Other);
12744 if (!poe.prepareForObj()) {
12745 return false;
12746 }
12747 if (isSuper) {
12748 UnaryNode* base = &prop->expression().as<UnaryNode>();
12749 if (!emitGetThisForSuperBase(base)) {
12750 // [stack] THIS
12751 return false;
12752 }
12753 } else {
12754 if (!emitPropLHS(prop)) {
12755 // [stack] OBJ
12756 return false;
12757 }
12758 }
12759 if (!poe.emitGet(prop->key().atom())) {
12760 // [stack] PROP
12761 return false;
12762 }
12763 break;
12764 }
12765
12766 case ParseNodeKind::ArgumentsLength: {
12767 if (sc->isFunctionBox() &&
12768 sc->asFunctionBox()->isEligibleForArgumentsLength() &&
12769 !sc->asFunctionBox()->needsArgsObj()) {
12770 if (!emit1(JSOp::ArgumentsLength)) {
12771 return false;
12772 }
12773 } else {
12774 PropOpEmitter poe(this, PropOpEmitter::Kind::Get,
12775 PropOpEmitter::ObjKind::Other);
12776 if (!poe.prepareForObj()) {
12777 return false;
12778 }
12779
12780 NameOpEmitter noe(this, TaggedParserAtomIndex::WellKnown::arguments(),
12781 NameOpEmitter::Kind::Get);
12782 if (!noe.emitGet()) {
12783 return false;
12784 }
12785 if (!poe.emitGet(TaggedParserAtomIndex::WellKnown::length())) {
12786 return false;
12787 }
12788 }
12789 break;
12790 }
12791
12792 case ParseNodeKind::ElemExpr: {
12793 PropertyByValue* elem = &pn->as<PropertyByValue>();
12794 bool isSuper = elem->isSuper();
12795 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"
, 12795); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 12795; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12796 ElemOpEmitter eoe(this, ElemOpEmitter::Kind::Get,
12797 isSuper ? ElemOpEmitter::ObjKind::Super
12798 : ElemOpEmitter::ObjKind::Other);
12799 if (!emitElemObjAndKey(elem, eoe)) {
12800 // [stack] # if Super
12801 // [stack] THIS KEY
12802 // [stack] # otherwise
12803 // [stack] OBJ KEY
12804 return false;
12805 }
12806 if (!eoe.emitGet()) {
12807 // [stack] ELEM
12808 return false;
12809 }
12810
12811 break;
12812 }
12813
12814 case ParseNodeKind::PrivateMemberExpr: {
12815 PrivateMemberAccess* privateExpr = &pn->as<PrivateMemberAccess>();
12816 PrivateOpEmitter xoe(this, PrivateOpEmitter::Kind::Get,
12817 privateExpr->privateName().name());
12818 if (!emitTree(&privateExpr->expression())) {
12819 // [stack] OBJ
12820 return false;
12821 }
12822 if (!xoe.emitReference()) {
12823 // [stack] OBJ NAME
12824 return false;
12825 }
12826 if (!xoe.emitGet()) {
12827 // [stack] VALUE
12828 return false;
12829 }
12830
12831 break;
12832 }
12833
12834 case ParseNodeKind::NewExpr:
12835 case ParseNodeKind::TaggedTemplateExpr:
12836 case ParseNodeKind::CallExpr:
12837 case ParseNodeKind::SuperCallExpr:
12838 if (!emitCallOrNew(&pn->as<CallNode>(), valueUsage)) {
12839 return false;
12840 }
12841 break;
12842
12843 case ParseNodeKind::LexicalScope:
12844 if (!emitLexicalScope(&pn->as<LexicalScopeNode>())) {
12845 return false;
12846 }
12847 break;
12848
12849 case ParseNodeKind::ConstDecl:
12850 case ParseNodeKind::LetDecl:
12851 if (!emitDeclarationList(&pn->as<ListNode>())) {
12852 return false;
12853 }
12854 break;
12855#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT1
12856 case ParseNodeKind::AwaitUsingDecl:
12857 case ParseNodeKind::UsingDecl:
12858 if (!emitDeclarationList(&pn->as<ListNode>())) {
12859 return false;
12860 }
12861 break;
12862#endif
12863
12864 case ParseNodeKind::ImportDecl:
12865 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"
, 12865); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isModuleContext()"
")"); do { *((volatile int*)__null) = 12865; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12866 break;
12867
12868 case ParseNodeKind::ExportStmt: {
12869 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"
, 12869); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isModuleContext()"
")"); do { *((volatile int*)__null) = 12869; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12870 UnaryNode* node = &pn->as<UnaryNode>();
12871 ParseNode* decl = node->kid();
12872 if (decl->getKind() != ParseNodeKind::ExportSpecList) {
12873 if (!emitTree(decl)) {
12874 return false;
12875 }
12876 }
12877 break;
12878 }
12879
12880 case ParseNodeKind::ExportDefaultStmt:
12881 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"
, 12881); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isModuleContext()"
")"); do { *((volatile int*)__null) = 12881; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12882 if (!emitExportDefault(&pn->as<BinaryNode>())) {
12883 return false;
12884 }
12885 break;
12886
12887 case ParseNodeKind::ExportFromStmt:
12888 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"
, 12888); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isModuleContext()"
")"); do { *((volatile int*)__null) = 12888; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12889 break;
12890
12891 case ParseNodeKind::CallSiteObj:
12892 if (!emitCallSiteObject(&pn->as<CallSiteNode>())) {
12893 return false;
12894 }
12895 break;
12896
12897 case ParseNodeKind::ArrayExpr:
12898 if (!emitArrayLiteral(&pn->as<ListNode>())) {
12899 return false;
12900 }
12901 break;
12902
12903 case ParseNodeKind::ObjectExpr:
12904 if (!emitObject(&pn->as<ListNode>())) {
12905 return false;
12906 }
12907 break;
12908
12909 case ParseNodeKind::Name:
12910 if (!emitGetName(&pn->as<NameNode>())) {
12911 return false;
12912 }
12913 break;
12914
12915 case ParseNodeKind::PrivateName:
12916 if (!emitGetPrivateName(&pn->as<NameNode>())) {
12917 return false;
12918 }
12919 break;
12920
12921 case ParseNodeKind::TemplateStringListExpr:
12922 if (!emitTemplateString(&pn->as<ListNode>())) {
12923 return false;
12924 }
12925 break;
12926
12927 case ParseNodeKind::TemplateStringExpr:
12928 case ParseNodeKind::StringExpr:
12929 if (!emitStringOp(JSOp::String, pn->as<NameNode>().atom())) {
12930 return false;
12931 }
12932 break;
12933
12934 case ParseNodeKind::NumberExpr:
12935 if (!emitNumberOp(pn->as<NumericLiteral>().value())) {
12936 return false;
12937 }
12938 break;
12939
12940 case ParseNodeKind::BigIntExpr:
12941 if (!emitBigIntOp(&pn->as<BigIntLiteral>())) {
12942 return false;
12943 }
12944 break;
12945
12946 case ParseNodeKind::RegExpExpr: {
12947 GCThingIndex index;
12948 if (!perScriptData().gcThingList().append(&pn->as<RegExpLiteral>(),
12949 &index)) {
12950 return false;
12951 }
12952 if (!emitRegExp(index)) {
12953 return false;
12954 }
12955 break;
12956 }
12957
12958 case ParseNodeKind::TrueExpr:
12959 if (!emit1(JSOp::True)) {
12960 return false;
12961 }
12962 break;
12963 case ParseNodeKind::FalseExpr:
12964 if (!emit1(JSOp::False)) {
12965 return false;
12966 }
12967 break;
12968 case ParseNodeKind::NullExpr:
12969 if (!emit1(JSOp::Null)) {
12970 return false;
12971 }
12972 break;
12973 case ParseNodeKind::RawUndefinedExpr:
12974 if (!emit1(JSOp::Undefined)) {
12975 return false;
12976 }
12977 break;
12978
12979 case ParseNodeKind::ThisExpr:
12980 if (!emitThisLiteral(&pn->as<ThisLiteral>())) {
12981 return false;
12982 }
12983 break;
12984
12985 case ParseNodeKind::DebuggerStmt:
12986 if (!updateSourceCoordNotes(pn->pn_pos.begin)) {
12987 return false;
12988 }
12989 if (!markStepBreakpoint()) {
12990 return false;
12991 }
12992 if (!emit1(JSOp::Debugger)) {
12993 return false;
12994 }
12995 break;
12996
12997 case ParseNodeKind::ClassDecl:
12998 if (!emitClass(&pn->as<ClassNode>())) {
12999 return false;
13000 }
13001 break;
13002
13003 case ParseNodeKind::NewTargetExpr:
13004 if (!emitNewTarget(&pn->as<NewTargetNode>())) {
13005 return false;
13006 }
13007 break;
13008
13009 case ParseNodeKind::ImportMetaExpr:
13010 if (!emit1(JSOp::ImportMeta)) {
13011 return false;
13012 }
13013 break;
13014
13015 case ParseNodeKind::CallImportExpr: {
13016 BinaryNode* spec = &pn->as<BinaryNode>().right()->as<BinaryNode>();
13017
13018 if (!emitTree(spec->left())) {
13019 // [stack] specifier
13020 return false;
13021 }
13022
13023 if (!spec->right()->isKind(ParseNodeKind::PosHolder)) {
13024 // [stack] specifier options
13025 if (!emitTree(spec->right())) {
13026 return false;
13027 }
13028 } else {
13029 // [stack] specifier undefined
13030 if (!emit1(JSOp::Undefined)) {
13031 return false;
13032 }
13033 }
13034
13035 if (!emit1(JSOp::DynamicImport)) {
13036 return false;
13037 }
13038
13039 break;
13040 }
13041
13042 case ParseNodeKind::SetThis:
13043 if (!emitSetThis(&pn->as<BinaryNode>())) {
13044 return false;
13045 }
13046 break;
13047
13048#ifdef ENABLE_RECORD_TUPLE
13049 case ParseNodeKind::RecordExpr:
13050 if (!emitRecordLiteral(&pn->as<ListNode>())) {
13051 return false;
13052 }
13053 break;
13054
13055 case ParseNodeKind::TupleExpr:
13056 if (!emitTupleLiteral(&pn->as<ListNode>())) {
13057 return false;
13058 }
13059 break;
13060#endif
13061
13062 case ParseNodeKind::PropertyNameExpr:
13063 case ParseNodeKind::PosHolder:
13064 MOZ_FALLTHROUGH_ASSERT(do { do { } while (false); MOZ_ReportCrash("" "MOZ_FALLTHROUGH_ASSERT: "
"Should never try to emit ParseNodeKind::PosHolder or ::Property"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 13065); AnnotateMozCrashReason("MOZ_CRASH(" "MOZ_FALLTHROUGH_ASSERT: "
"Should never try to emit ParseNodeKind::PosHolder or ::Property"
")"); do { *((volatile int*)__null) = 13065; __attribute__((
nomerge)) ::abort(); } while (false); } while (false)
13065 "Should never try to emit ParseNodeKind::PosHolder or ::Property")do { do { } while (false); MOZ_ReportCrash("" "MOZ_FALLTHROUGH_ASSERT: "
"Should never try to emit ParseNodeKind::PosHolder or ::Property"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 13065); AnnotateMozCrashReason("MOZ_CRASH(" "MOZ_FALLTHROUGH_ASSERT: "
"Should never try to emit ParseNodeKind::PosHolder or ::Property"
")"); do { *((volatile int*)__null) = 13065; __attribute__((
nomerge)) ::abort(); } while (false); } while (false)
;
13066
13067 default:
13068 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"
, 13068); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0" ")"); do
{ *((volatile int*)__null) = 13068; __attribute__((nomerge))
::abort(); } while (false); } } while (false)
;
13069 }
13070
13071 return true;
13072}
13073
13074static bool AllocSrcNote(FrontendContext* fc, SrcNotesVector& notes,
13075 unsigned size, unsigned* index) {
13076 size_t oldLength = notes.length();
13077
13078 if (MOZ_UNLIKELY(oldLength + size > MaxSrcNotesLength)(__builtin_expect(!!(oldLength + size > MaxSrcNotesLength)
, 0))
) {
13079 ReportAllocationOverflow(fc);
13080 return false;
13081 }
13082
13083 if (!notes.growByUninitialized(size)) {
13084 return false;
13085 }
13086
13087 *index = oldLength;
13088 return true;
13089}
13090
13091bool BytecodeEmitter::addTryNote(TryNoteKind kind, uint32_t stackDepth,
13092 BytecodeOffset start, BytecodeOffset end) {
13093 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"
, 13093); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inPrologue()"
")"); do { *((volatile int*)__null) = 13093; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13094 return bytecodeSection().tryNoteList().append(kind, stackDepth, start, end);
13095}
13096
13097bool BytecodeEmitter::newSrcNote(SrcNoteType type, unsigned* indexp) {
13098 SrcNotesVector& notes = bytecodeSection().notes();
13099 unsigned index;
13100
13101 /*
13102 * Compute delta from the last annotated bytecode's offset. If it's too
13103 * big to fit in sn, allocate one or more xdelta notes and reset sn.
13104 */
13105 BytecodeOffset offset = bytecodeSection().offset();
13106 ptrdiff_t delta = (offset - bytecodeSection().lastNoteOffset()).value();
13107 bytecodeSection().setLastNoteOffset(offset);
13108
13109 auto allocator = [&](unsigned size) -> SrcNote* {
13110 if (!AllocSrcNote(fc, notes, size, &index)) {
13111 return nullptr;
13112 }
13113 return &notes[index];
13114 };
13115
13116 if (!SrcNoteWriter::writeNote(type, delta, allocator)) {
13117 return false;
13118 }
13119
13120 if (indexp) {
13121 *indexp = index;
13122 }
13123
13124 if (type == SrcNoteType::NewLine || type == SrcNoteType::SetLine) {
13125 lastLineOnlySrcNoteIndex = index;
13126 } else {
13127 lastLineOnlySrcNoteIndex = LastSrcNoteIsNotLineOnly;
13128 }
13129
13130 return true;
13131}
13132
13133bool BytecodeEmitter::newSrcNote2(SrcNoteType type, ptrdiff_t offset,
13134 unsigned* indexp) {
13135 unsigned index;
13136 if (!newSrcNote(type, &index)) {
13137 return false;
13138 }
13139 if (!newSrcNoteOperand(offset)) {
13140 return false;
13141 }
13142 if (indexp) {
13143 *indexp = index;
13144 }
13145 return true;
13146}
13147
13148bool BytecodeEmitter::convertLastNewLineToNewLineColumn(
13149 JS::LimitedColumnNumberOneOrigin column) {
13150 SrcNotesVector& notes = bytecodeSection().notes();
13151 MOZ_ASSERT(lastLineOnlySrcNoteIndex == notes.length() - 1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(lastLineOnlySrcNoteIndex == notes.length() - 1)>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(lastLineOnlySrcNoteIndex == notes.length() - 1))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("lastLineOnlySrcNoteIndex == notes.length() - 1"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 13151); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lastLineOnlySrcNoteIndex == notes.length() - 1"
")"); do { *((volatile int*)__null) = 13151; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13152 SrcNote* sn = &notes[lastLineOnlySrcNoteIndex];
13153 MOZ_ASSERT(sn->type() == SrcNoteType::NewLine)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sn->type() == SrcNoteType::NewLine)>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(sn->type() == SrcNoteType::NewLine))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("sn->type() == SrcNoteType::NewLine"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 13153); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sn->type() == SrcNoteType::NewLine"
")"); do { *((volatile int*)__null) = 13153; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13154
13155 SrcNoteWriter::convertNote(sn, SrcNoteType::NewLineColumn);
13156 if (!newSrcNoteOperand(SrcNote::NewLineColumn::toOperand(column))) {
13157 return false;
13158 }
13159
13160 lastLineOnlySrcNoteIndex = LastSrcNoteIsNotLineOnly;
13161 return true;
13162}
13163
13164bool BytecodeEmitter::convertLastSetLineToSetLineColumn(
13165 JS::LimitedColumnNumberOneOrigin column) {
13166 SrcNotesVector& notes = bytecodeSection().notes();
13167 // The Line operand is either 1 byte or 4 bytes.
13168 MOZ_ASSERT(lastLineOnlySrcNoteIndex == notes.length() - 1 - 1 ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(lastLineOnlySrcNoteIndex == notes.length() - 1 - 1 ||
lastLineOnlySrcNoteIndex == notes.length() - 1 - 4)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(lastLineOnlySrcNoteIndex == notes.length() - 1 - 1 || lastLineOnlySrcNoteIndex
== notes.length() - 1 - 4))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("lastLineOnlySrcNoteIndex == notes.length() - 1 - 1 || lastLineOnlySrcNoteIndex == notes.length() - 1 - 4"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 13169); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lastLineOnlySrcNoteIndex == notes.length() - 1 - 1 || lastLineOnlySrcNoteIndex == notes.length() - 1 - 4"
")"); do { *((volatile int*)__null) = 13169; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
13169 lastLineOnlySrcNoteIndex == notes.length() - 1 - 4)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(lastLineOnlySrcNoteIndex == notes.length() - 1 - 1 ||
lastLineOnlySrcNoteIndex == notes.length() - 1 - 4)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(lastLineOnlySrcNoteIndex == notes.length() - 1 - 1 || lastLineOnlySrcNoteIndex
== notes.length() - 1 - 4))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("lastLineOnlySrcNoteIndex == notes.length() - 1 - 1 || lastLineOnlySrcNoteIndex == notes.length() - 1 - 4"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 13169); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lastLineOnlySrcNoteIndex == notes.length() - 1 - 1 || lastLineOnlySrcNoteIndex == notes.length() - 1 - 4"
")"); do { *((volatile int*)__null) = 13169; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13170 SrcNote* sn = &notes[lastLineOnlySrcNoteIndex];
13171 MOZ_ASSERT(sn->type() == SrcNoteType::SetLine)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sn->type() == SrcNoteType::SetLine)>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(sn->type() == SrcNoteType::SetLine))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("sn->type() == SrcNoteType::SetLine"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 13171); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sn->type() == SrcNoteType::SetLine"
")"); do { *((volatile int*)__null) = 13171; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13172
13173 SrcNoteWriter::convertNote(sn, SrcNoteType::SetLineColumn);
13174 if (!newSrcNoteOperand(SrcNote::SetLineColumn::columnToOperand(column))) {
13175 return false;
13176 }
13177
13178 lastLineOnlySrcNoteIndex = LastSrcNoteIsNotLineOnly;
13179 return true;
13180}
13181
13182bool BytecodeEmitter::newSrcNoteOperand(ptrdiff_t operand) {
13183 if (!SrcNote::isRepresentableOperand(operand)) {
13184 reportError(nullptr, JSMSG_NEED_DIET, "script");
13185 return false;
13186 }
13187
13188 SrcNotesVector& notes = bytecodeSection().notes();
13189
13190 auto allocator = [&](unsigned size) -> SrcNote* {
13191 unsigned index;
13192 if (!AllocSrcNote(fc, notes, size, &index)) {
13193 return nullptr;
13194 }
13195 return &notes[index];
13196 };
13197
13198 return SrcNoteWriter::writeOperand(operand, allocator);
13199}
13200
13201bool BytecodeEmitter::intoScriptStencil(ScriptIndex scriptIndex) {
13202 js::UniquePtr<ImmutableScriptData> immutableScriptData =
13203 createImmutableScriptData();
13204 if (!immutableScriptData) {
13205 return false;
13206 }
13207
13208 MOZ_ASSERT(outermostScope().hasNonSyntacticScopeOnChain() ==do { static_assert( mozilla::detail::AssertionConditionType<
decltype(outermostScope().hasNonSyntacticScopeOnChain() == sc
->hasNonSyntacticScope())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(outermostScope().hasNonSyntacticScopeOnChain
() == sc->hasNonSyntacticScope()))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("outermostScope().hasNonSyntacticScopeOnChain() == sc->hasNonSyntacticScope()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 13209); AnnotateMozCrashReason("MOZ_ASSERT" "(" "outermostScope().hasNonSyntacticScopeOnChain() == sc->hasNonSyntacticScope()"
")"); do { *((volatile int*)__null) = 13209; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
13209 sc->hasNonSyntacticScope())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(outermostScope().hasNonSyntacticScopeOnChain() == sc
->hasNonSyntacticScope())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(outermostScope().hasNonSyntacticScopeOnChain
() == sc->hasNonSyntacticScope()))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("outermostScope().hasNonSyntacticScopeOnChain() == sc->hasNonSyntacticScope()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 13209); AnnotateMozCrashReason("MOZ_ASSERT" "(" "outermostScope().hasNonSyntacticScopeOnChain() == sc->hasNonSyntacticScope()"
")"); do { *((volatile int*)__null) = 13209; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13210
13211 auto& things = perScriptData().gcThingList().objects();
13212 if (!compilationState.appendGCThings(fc, scriptIndex, things)) {
13213 return false;
13214 }
13215
13216 // Hand over the ImmutableScriptData instance generated by BCE.
13217 auto* sharedData =
13218 SharedImmutableScriptData::createWith(fc, std::move(immutableScriptData));
13219 if (!sharedData) {
13220 return false;
13221 }
13222
13223 // De-duplicate the bytecode within the runtime.
13224 if (!compilationState.sharedData.addAndShare(fc, scriptIndex, sharedData)) {
13225 return false;
13226 }
13227
13228 ScriptStencil& script = compilationState.scriptData[scriptIndex];
13229 script.setHasSharedData();
13230
13231 // Update flags specific to functions.
13232 if (sc->isFunctionBox()) {
13233 FunctionBox* funbox = sc->asFunctionBox();
13234 MOZ_ASSERT(&script == &funbox->functionStencil())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(&script == &funbox->functionStencil())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(&script == &funbox->functionStencil()))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("&script == &funbox->functionStencil()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 13234); AnnotateMozCrashReason("MOZ_ASSERT" "(" "&script == &funbox->functionStencil()"
")"); do { *((volatile int*)__null) = 13234; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13235 funbox->copyUpdatedImmutableFlags();
13236 MOZ_ASSERT(script.isFunction())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(script.isFunction())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(script.isFunction()))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("script.isFunction()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 13236); AnnotateMozCrashReason("MOZ_ASSERT" "(" "script.isFunction()"
")"); do { *((volatile int*)__null) = 13236; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13237 } else {
13238 ScriptStencilExtra& scriptExtra = compilationState.scriptExtra[scriptIndex];
13239 sc->copyScriptExtraFields(scriptExtra);
13240 }
13241
13242 return true;
13243}
13244
13245SelfHostedIter BytecodeEmitter::getSelfHostedIterFor(
13246 ParseNode* parseNode) const {
13247 if (emitterMode == BytecodeEmitter::SelfHosting &&
13248 parseNode->isKind(ParseNodeKind::CallExpr)) {
13249 auto* callee = parseNode->as<CallNode>().callee();
13250 if (callee->isName(TaggedParserAtomIndex::WellKnown::allowContentIter())) {
13251 return SelfHostedIter::AllowContent;
13252 }
13253 if (callee->isName(
13254 TaggedParserAtomIndex::WellKnown::allowContentIterWith())) {
13255 return SelfHostedIter::AllowContentWith;
13256 }
13257 if (callee->isName(
13258 TaggedParserAtomIndex::WellKnown::allowContentIterWithNext())) {
13259 return SelfHostedIter::AllowContentWithNext;
13260 }
13261 }
13262
13263 return SelfHostedIter::Deny;
13264}
13265
13266#if defined(DEBUG1) || defined(JS_JITSPEW1)
13267void BytecodeEmitter::dumpAtom(TaggedParserAtomIndex index) const {
13268 parserAtoms().dump(index);
13269}
13270#endif