Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name Unified_cpp_js_src_frontend0.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/js/src/frontend -fcoverage-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/js/src/frontend -resource-dir /usr/lib/llvm-18/lib/clang/18 -include /var/lib/jenkins/workspace/firefox-scan-build/config/gcc_hidden.h -include /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D WASM_SUPPORTS_HUGE_MEMORY -D JS_CACHEIR_SPEW -D JS_STRUCTURED_SPEW -D JS_HAS_CTYPES -D FFI_BUILDING -D EXPORT_JS_API -D MOZ_HAS_MOZGLUE -D MOZ_SUPPORT_LEAKCHECKING -I /var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/js/src/frontend -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/js/src -I /var/lib/jenkins/workspace/firefox-scan-build/js/src -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/backward -internal-isystem /usr/lib/llvm-18/lib/clang/18/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 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fno-aligned-allocation -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2024-07-21-021012-413605-1 -x c++ Unified_cpp_js_src_frontend0.cpp
1/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=8 sts=2 et sw=2 tw=80:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7/*
8 * JS bytecode generation.
9 */
10
11#include "frontend/BytecodeEmitter.h"
12
13#include "mozilla/Casting.h" // mozilla::AssertedCast
14#include "mozilla/DebugOnly.h" // mozilla::DebugOnly
15#include "mozilla/FloatingPoint.h" // mozilla::NumberEqualsInt32, mozilla::NumberIsInt32
16#include "mozilla/HashTable.h" // mozilla::HashSet
17#include "mozilla/Maybe.h" // mozilla::{Maybe,Nothing,Some}
18#include "mozilla/PodOperations.h" // mozilla::PodCopy
19#include "mozilla/Saturate.h"
20#include "mozilla/Variant.h" // mozilla::AsVariant
21
22#include <algorithm>
23#include <iterator>
24#include <string.h>
25
26#include "jstypes.h" // JS_BIT
27
28#include "frontend/AbstractScopePtr.h" // ScopeIndex
29#include "frontend/BytecodeControlStructures.h" // NestableControl, BreakableControl, LabelControl, LoopControl, TryFinallyControl
30#include "frontend/CallOrNewEmitter.h" // CallOrNewEmitter
31#include "frontend/CForEmitter.h" // CForEmitter
32#include "frontend/DecoratorEmitter.h" // DecoratorEmitter
33#include "frontend/DefaultEmitter.h" // DefaultEmitter
34#include "frontend/DoWhileEmitter.h" // DoWhileEmitter
35#include "frontend/ElemOpEmitter.h" // ElemOpEmitter
36#include "frontend/EmitterScope.h" // EmitterScope
37#include "frontend/ExpressionStatementEmitter.h" // ExpressionStatementEmitter
38#include "frontend/ForInEmitter.h" // ForInEmitter
39#include "frontend/ForOfEmitter.h" // ForOfEmitter
40#include "frontend/FunctionEmitter.h" // FunctionEmitter, FunctionScriptEmitter, FunctionParamsEmitter
41#include "frontend/IfEmitter.h" // IfEmitter, InternalIfEmitter, CondEmitter
42#include "frontend/LabelEmitter.h" // LabelEmitter
43#include "frontend/LexicalScopeEmitter.h" // LexicalScopeEmitter
44#include "frontend/ModuleSharedContext.h" // ModuleSharedContext
45#include "frontend/NameAnalysisTypes.h" // PrivateNameKind
46#include "frontend/NameFunctions.h" // NameFunctions
47#include "frontend/NameOpEmitter.h" // NameOpEmitter
48#include "frontend/ObjectEmitter.h" // PropertyEmitter, ObjectEmitter, ClassEmitter
49#include "frontend/OptionalEmitter.h" // OptionalEmitter
50#include "frontend/ParseContext.h" // ParseContext::Scope
51#include "frontend/ParseNode.h" // ParseNodeKind, ParseNode and subclasses
52#include "frontend/Parser.h" // Parser
53#include "frontend/ParserAtom.h" // ParserAtomsTable, ParserAtom
54#include "frontend/PrivateOpEmitter.h" // PrivateOpEmitter
55#include "frontend/PropOpEmitter.h" // PropOpEmitter
56#include "frontend/SourceNotes.h" // SrcNote, SrcNoteType, SrcNoteWriter
57#include "frontend/SwitchEmitter.h" // SwitchEmitter
58#include "frontend/TaggedParserAtomIndexHasher.h" // TaggedParserAtomIndexHasher
59#include "frontend/TDZCheckCache.h" // TDZCheckCache
60#include "frontend/TryEmitter.h" // TryEmitter
61#include "frontend/UsingEmitter.h" // UsingEmitter
62#include "frontend/WhileEmitter.h" // WhileEmitter
63#include "js/ColumnNumber.h" // JS::LimitedColumnNumberOneOrigin, JS::ColumnNumberOffset
64#include "js/friend/ErrorMessages.h" // JSMSG_*
65#include "js/friend/StackLimits.h" // AutoCheckRecursionLimit
66#include "util/StringBuffer.h" // StringBuffer
67#include "vm/BytecodeUtil.h" // JOF_*, IsArgOp, IsLocalOp, SET_UINT24, SET_ICINDEX, BytecodeFallsThrough, BytecodeIsJumpTarget
68#include "vm/CompletionKind.h" // CompletionKind
69#include "vm/FunctionPrefixKind.h" // FunctionPrefixKind
70#include "vm/GeneratorObject.h" // AbstractGeneratorObject
71#include "vm/Opcodes.h" // JSOp, JSOpLength_*
72#include "vm/PropMap.h" // SharedPropMap::MaxPropsForNonDictionary
73#include "vm/Scope.h" // GetScopeDataTrailingNames
74#include "vm/SharedStencil.h" // ScopeNote
75#include "vm/ThrowMsgKind.h" // ThrowMsgKind
76#include "vm/TypeofEqOperand.h" // TypeofEqOperand
77
78using namespace js;
79using namespace js::frontend;
80
81using mozilla::AssertedCast;
82using mozilla::AsVariant;
83using mozilla::DebugOnly;
84using mozilla::Maybe;
85using mozilla::Nothing;
86using mozilla::NumberEqualsInt32;
87using mozilla::NumberIsInt32;
88using mozilla::PodCopy;
89using mozilla::Some;
90
91static bool ParseNodeRequiresSpecialLineNumberNotes(ParseNode* pn) {
92 // The few node types listed below are exceptions to the usual
93 // location-source-note-emitting code in BytecodeEmitter::emitTree().
94 // Single-line `while` loops and C-style `for` loops require careful
95 // handling to avoid strange stepping behavior.
96 // Functions usually shouldn't have location information (bug 1431202).
97
98 ParseNodeKind kind = pn->getKind();
99 return kind == ParseNodeKind::WhileStmt || kind == ParseNodeKind::ForStmt ||
100 kind == ParseNodeKind::Function;
101}
102
103static bool NeedsFieldInitializer(ParseNode* member, bool inStaticContext) {
104 // For the purposes of bytecode emission, StaticClassBlocks are treated as if
105 // they were static initializers.
106 return (member->is<StaticClassBlock>() && inStaticContext) ||
107 (member->is<ClassField>() &&
108 member->as<ClassField>().isStatic() == inStaticContext);
109}
110
111static bool NeedsAccessorInitializer(ParseNode* member, bool isStatic) {
112 if (isStatic) {
113 return false;
114 }
115 return member->is<ClassMethod>() &&
116 member->as<ClassMethod>().name().isKind(ParseNodeKind::PrivateName) &&
117 !member->as<ClassMethod>().isStatic() &&
118 member->as<ClassMethod>().accessorType() != AccessorType::None;
119}
120
121static bool ShouldSuppressBreakpointsAndSourceNotes(
122 SharedContext* sc, BytecodeEmitter::EmitterMode emitterMode) {
123 // Suppress for all self-hosting code.
124 if (emitterMode == BytecodeEmitter::EmitterMode::SelfHosting) {
125 return true;
126 }
127
128 // Suppress for synthesized class constructors.
129 if (sc->isFunctionBox()) {
130 FunctionBox* funbox = sc->asFunctionBox();
131 return funbox->isSyntheticFunction() && funbox->isClassConstructor();
132 }
133
134 return false;
135}
136
137BytecodeEmitter::BytecodeEmitter(BytecodeEmitter* parent, FrontendContext* fc,
138 SharedContext* sc,
139 const ErrorReporter& errorReporter,
140 CompilationState& compilationState,
141 EmitterMode emitterMode)
142 : sc(sc),
143 fc(fc),
144 parent(parent),
145 bytecodeSection_(fc, sc->extent().lineno,
146 JS::LimitedColumnNumberOneOrigin(sc->extent().column)),
147 perScriptData_(fc, compilationState),
148 errorReporter_(errorReporter),
149 compilationState(compilationState),
150 suppressBreakpointsAndSourceNotes(
151 ShouldSuppressBreakpointsAndSourceNotes(sc, emitterMode)),
152 emitterMode(emitterMode) {
153 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"
, 153); AnnotateMozCrashReason("MOZ_ASSERT" "(" "fc == parent->fc"
")"); do { *((volatile int*)__null) = 153; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
154}
155
156BytecodeEmitter::BytecodeEmitter(BytecodeEmitter* parent, SharedContext* sc)
157 : BytecodeEmitter(parent, parent->fc, sc, parent->errorReporter_,
158 parent->compilationState, parent->emitterMode) {}
159
160BytecodeEmitter::BytecodeEmitter(FrontendContext* fc,
161 const EitherParser& parser, SharedContext* sc,
162 CompilationState& compilationState,
163 EmitterMode emitterMode)
164 : BytecodeEmitter(nullptr, fc, sc, parser.errorReporter(), compilationState,
165 emitterMode) {
166 ep_.emplace(parser);
167}
168
169void BytecodeEmitter::initFromBodyPosition(TokenPos bodyPosition) {
170 setScriptStartOffsetIfUnset(bodyPosition.begin);
171 setFunctionBodyEndPos(bodyPosition.end);
172}
173
174bool BytecodeEmitter::init() {
175 if (!parent) {
176 if (!compilationState.prepareSharedDataStorage(fc)) {
177 return false;
178 }
179 }
180 return perScriptData_.init(fc);
181}
182
183bool BytecodeEmitter::init(TokenPos bodyPosition) {
184 initFromBodyPosition(bodyPosition);
185 return init();
186}
187
188template <typename T>
189T* BytecodeEmitter::findInnermostNestableControl() const {
190 return NestableControl::findNearest<T>(innermostNestableControl);
191}
192
193template <typename T, typename Predicate /* (T*) -> bool */>
194T* BytecodeEmitter::findInnermostNestableControl(Predicate predicate) const {
195 return NestableControl::findNearest<T>(innermostNestableControl, predicate);
196}
197
198NameLocation BytecodeEmitter::lookupName(TaggedParserAtomIndex name) {
199 return innermostEmitterScope()->lookup(this, name);
200}
201
202void BytecodeEmitter::lookupPrivate(TaggedParserAtomIndex name,
203 NameLocation& loc,
204 Maybe<NameLocation>& brandLoc) {
205 innermostEmitterScope()->lookupPrivate(this, name, loc, brandLoc);
206}
207
208Maybe<NameLocation> BytecodeEmitter::locationOfNameBoundInScope(
209 TaggedParserAtomIndex name, EmitterScope* target) {
210 return innermostEmitterScope()->locationBoundInScope(name, target);
211}
212
213template <typename T>
214Maybe<NameLocation> BytecodeEmitter::locationOfNameBoundInScopeType(
215 TaggedParserAtomIndex name, EmitterScope* source) {
216 EmitterScope* aScope = source;
217 while (!aScope->scope(this).is<T>()) {
218 aScope = aScope->enclosingInFrame();
219 }
220 return source->locationBoundInScope(name, aScope);
221}
222
223bool BytecodeEmitter::markStepBreakpoint() {
224 if (skipBreakpointSrcNotes()) {
225 return true;
226 }
227
228 if (!newSrcNote(SrcNoteType::BreakpointStepSep)) {
229 return false;
230 }
231
232 // We track the location of the most recent separator for use in
233 // markSimpleBreakpoint. Note that this means that the position must already
234 // be set before markStepBreakpoint is called.
235 bytecodeSection().updateSeparatorPosition();
236
237 return true;
238}
239
240bool BytecodeEmitter::markSimpleBreakpoint() {
241 if (skipBreakpointSrcNotes()) {
242 return true;
243 }
244
245 // If a breakable call ends up being the same location as the most recent
246 // expression start, we need to skip marking it breakable in order to avoid
247 // having two breakpoints with the same line/column position.
248 // Note: This assumes that the position for the call has already been set.
249 if (!bytecodeSection().isDuplicateLocation()) {
250 if (!newSrcNote(SrcNoteType::Breakpoint)) {
251 return false;
252 }
253 }
254
255 return true;
256}
257
258bool BytecodeEmitter::emitCheck(JSOp op, ptrdiff_t delta,
259 BytecodeOffset* offset) {
260 size_t oldLength = bytecodeSection().code().length();
261 *offset = BytecodeOffset(oldLength);
262
263 size_t newLength = oldLength + size_t(delta);
264 if (MOZ_UNLIKELY(newLength > MaxBytecodeLength)(__builtin_expect(!!(newLength > MaxBytecodeLength), 0))) {
265 ReportAllocationOverflow(fc);
266 return false;
267 }
268
269 if (!bytecodeSection().code().growByUninitialized(delta)) {
270 return false;
271 }
272
273 if (BytecodeOpHasIC(op)) {
274 // Even if every bytecode op is a JOF_IC op and the function has ARGC_LIMIT
275 // arguments, numICEntries cannot overflow.
276 static_assert(MaxBytecodeLength + 1 /* this */ + ARGC_LIMIT <= UINT32_MAX(4294967295U),
277 "numICEntries must not overflow");
278 bytecodeSection().incrementNumICEntries();
279 }
280
281 return true;
282}
283
284#ifdef DEBUG1
285bool BytecodeEmitter::checkStrictOrSloppy(JSOp op) {
286 if (IsCheckStrictOp(op) && !sc->strict()) {
287 return false;
288 }
289 if (IsCheckSloppyOp(op) && sc->strict()) {
290 return false;
291 }
292 return true;
293}
294#endif
295
296bool BytecodeEmitter::emit1(JSOp op) {
297 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"
, 297); AnnotateMozCrashReason("MOZ_ASSERT" "(" "checkStrictOrSloppy(op)"
")"); do { *((volatile int*)__null) = 297; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
298
299 BytecodeOffset offset;
300 if (!emitCheck(op, 1, &offset)) {
301 return false;
302 }
303
304 jsbytecode* code = bytecodeSection().code(offset);
305 code[0] = jsbytecode(op);
306 bytecodeSection().updateDepth(op, offset);
307 return true;
308}
309
310bool BytecodeEmitter::emit2(JSOp op, uint8_t op1) {
311 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"
, 311); AnnotateMozCrashReason("MOZ_ASSERT" "(" "checkStrictOrSloppy(op)"
")"); do { *((volatile int*)__null) = 311; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
312
313 BytecodeOffset offset;
314 if (!emitCheck(op, 2, &offset)) {
315 return false;
316 }
317
318 jsbytecode* code = bytecodeSection().code(offset);
319 code[0] = jsbytecode(op);
320 code[1] = jsbytecode(op1);
321 bytecodeSection().updateDepth(op, offset);
322 return true;
323}
324
325bool BytecodeEmitter::emit3(JSOp op, jsbytecode op1, jsbytecode op2) {
326 MOZ_ASSERT(checkStrictOrSloppy(op))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(checkStrictOrSloppy(op))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(checkStrictOrSloppy(op)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("checkStrictOrSloppy(op)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 326); AnnotateMozCrashReason("MOZ_ASSERT" "(" "checkStrictOrSloppy(op)"
")"); do { *((volatile int*)__null) = 326; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
327
328 /* These should filter through emitVarOp. */
329 MOZ_ASSERT(!IsArgOp(op))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsArgOp(op))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!IsArgOp(op)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!IsArgOp(op)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 329); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsArgOp(op)"
")"); do { *((volatile int*)__null) = 329; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
330 MOZ_ASSERT(!IsLocalOp(op))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsLocalOp(op))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!IsLocalOp(op)))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("!IsLocalOp(op)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 330); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsLocalOp(op)"
")"); do { *((volatile int*)__null) = 330; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
331
332 BytecodeOffset offset;
333 if (!emitCheck(op, 3, &offset)) {
334 return false;
335 }
336
337 jsbytecode* code = bytecodeSection().code(offset);
338 code[0] = jsbytecode(op);
339 code[1] = op1;
340 code[2] = op2;
341 bytecodeSection().updateDepth(op, offset);
342 return true;
343}
344
345bool BytecodeEmitter::emitN(JSOp op, size_t extra, BytecodeOffset* offset) {
346 MOZ_ASSERT(checkStrictOrSloppy(op))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(checkStrictOrSloppy(op))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(checkStrictOrSloppy(op)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("checkStrictOrSloppy(op)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 346); AnnotateMozCrashReason("MOZ_ASSERT" "(" "checkStrictOrSloppy(op)"
")"); do { *((volatile int*)__null) = 346; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
347 ptrdiff_t length = 1 + ptrdiff_t(extra);
348
349 BytecodeOffset off;
350 if (!emitCheck(op, length, &off)) {
351 return false;
352 }
353
354 jsbytecode* code = bytecodeSection().code(off);
355 code[0] = jsbytecode(op);
356 /* The remaining |extra| bytes are set by the caller */
357
358 /*
359 * Don't updateDepth if op's use-count comes from the immediate
360 * operand yet to be stored in the extra bytes after op.
361 */
362 if (CodeSpec(op).nuses >= 0) {
363 bytecodeSection().updateDepth(op, off);
364 }
365
366 if (offset) {
367 *offset = off;
368 }
369 return true;
370}
371
372bool BytecodeEmitter::emitJumpTargetOp(JSOp op, BytecodeOffset* off) {
373 MOZ_ASSERT(BytecodeIsJumpTarget(op))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(BytecodeIsJumpTarget(op))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(BytecodeIsJumpTarget(op)))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("BytecodeIsJumpTarget(op)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 373); AnnotateMozCrashReason("MOZ_ASSERT" "(" "BytecodeIsJumpTarget(op)"
")"); do { *((volatile int*)__null) = 373; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
374
375 // Record the current IC-entry index at start of this op.
376 uint32_t numEntries = bytecodeSection().numICEntries();
377
378 size_t n = GetOpLength(op) - 1;
379 MOZ_ASSERT(GetOpLength(op) >= 1 + ICINDEX_LEN)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(GetOpLength(op) >= 1 + ICINDEX_LEN)>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(GetOpLength(op) >= 1 + ICINDEX_LEN))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("GetOpLength(op) >= 1 + ICINDEX_LEN"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 379); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetOpLength(op) >= 1 + ICINDEX_LEN"
")"); do { *((volatile int*)__null) = 379; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
380
381 if (!emitN(op, n, off)) {
382 return false;
383 }
384
385 SET_ICINDEX(bytecodeSection().code(*off), numEntries);
386 return true;
387}
388
389bool BytecodeEmitter::emitJumpTarget(JumpTarget* target) {
390 BytecodeOffset off = bytecodeSection().offset();
391
392 // Alias consecutive jump targets.
393 if (bytecodeSection().lastTargetOffset().valid() &&
394 off == bytecodeSection().lastTargetOffset() +
395 BytecodeOffsetDiff(JSOpLength_JumpTarget)) {
396 target->offset = bytecodeSection().lastTargetOffset();
397 return true;
398 }
399
400 target->offset = off;
401 bytecodeSection().setLastTargetOffset(off);
402
403 BytecodeOffset opOff;
404 return emitJumpTargetOp(JSOp::JumpTarget, &opOff);
405}
406
407bool BytecodeEmitter::emitJumpNoFallthrough(JSOp op, JumpList* jump) {
408 BytecodeOffset offset;
409 if (!emitCheck(op, 5, &offset)) {
410 return false;
411 }
412
413 jsbytecode* code = bytecodeSection().code(offset);
414 code[0] = jsbytecode(op);
415 MOZ_ASSERT(!jump->offset.valid() ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!jump->offset.valid() || (0 <= jump->offset
.value() && jump->offset < offset))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!jump->offset.valid() || (0 <= jump->offset.value
() && jump->offset < offset)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!jump->offset.valid() || (0 <= jump->offset.value() && jump->offset < offset)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 416); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!jump->offset.valid() || (0 <= jump->offset.value() && jump->offset < offset)"
")"); do { *((volatile int*)__null) = 416; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
416 (0 <= jump->offset.value() && jump->offset < offset))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!jump->offset.valid() || (0 <= jump->offset
.value() && jump->offset < offset))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!jump->offset.valid() || (0 <= jump->offset.value
() && jump->offset < offset)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!jump->offset.valid() || (0 <= jump->offset.value() && jump->offset < offset)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 416); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!jump->offset.valid() || (0 <= jump->offset.value() && jump->offset < offset)"
")"); do { *((volatile int*)__null) = 416; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
417 jump->push(bytecodeSection().code(BytecodeOffset(0)), offset);
418 bytecodeSection().updateDepth(op, offset);
419 return true;
420}
421
422bool BytecodeEmitter::emitJump(JSOp op, JumpList* jump) {
423 if (!emitJumpNoFallthrough(op, jump)) {
424 return false;
425 }
426 if (BytecodeFallsThrough(op)) {
427 JumpTarget fallthrough;
428 if (!emitJumpTarget(&fallthrough)) {
429 return false;
430 }
431 }
432 return true;
433}
434
435void BytecodeEmitter::patchJumpsToTarget(JumpList jump, JumpTarget target) {
436 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!jump.offset.valid() || (0 <= jump.offset.value()
&& jump.offset <= bytecodeSection().offset()))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!jump.offset.valid() || (0 <= jump.offset.value()
&& jump.offset <= bytecodeSection().offset())))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset())"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 438); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset())"
")"); do { *((volatile int*)__null) = 438; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
437 !jump.offset.valid() ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!jump.offset.valid() || (0 <= jump.offset.value()
&& jump.offset <= bytecodeSection().offset()))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!jump.offset.valid() || (0 <= jump.offset.value()
&& jump.offset <= bytecodeSection().offset())))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset())"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 438); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset())"
")"); do { *((volatile int*)__null) = 438; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
438 (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset()))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!jump.offset.valid() || (0 <= jump.offset.value()
&& jump.offset <= bytecodeSection().offset()))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!jump.offset.valid() || (0 <= jump.offset.value()
&& jump.offset <= bytecodeSection().offset())))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset())"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 438); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset())"
")"); do { *((volatile int*)__null) = 438; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
439 MOZ_ASSERT(0 <= target.offset.value() &&do { static_assert( mozilla::detail::AssertionConditionType<
decltype(0 <= target.offset.value() && target.offset
<= bytecodeSection().offset())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(0 <= target.offset.value(
) && target.offset <= bytecodeSection().offset()))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("0 <= target.offset.value() && target.offset <= bytecodeSection().offset()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 440); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0 <= target.offset.value() && target.offset <= bytecodeSection().offset()"
")"); do { *((volatile int*)__null) = 440; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
440 target.offset <= bytecodeSection().offset())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(0 <= target.offset.value() && target.offset
<= bytecodeSection().offset())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(0 <= target.offset.value(
) && target.offset <= bytecodeSection().offset()))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("0 <= target.offset.value() && target.offset <= bytecodeSection().offset()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 440); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0 <= target.offset.value() && target.offset <= bytecodeSection().offset()"
")"); do { *((volatile int*)__null) = 440; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
441 MOZ_ASSERT_IF(do { if (jump.offset.valid() && target.offset + BytecodeOffsetDiff
(4) <= bytecodeSection().offset()) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(BytecodeIsJumpTarget
(JSOp(*bytecodeSection().code(target.offset))))>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset
)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 444); AnnotateMozCrashReason("MOZ_ASSERT" "(" "BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))"
")"); do { *((volatile int*)__null) = 444; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
442 jump.offset.valid() &&do { if (jump.offset.valid() && target.offset + BytecodeOffsetDiff
(4) <= bytecodeSection().offset()) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(BytecodeIsJumpTarget
(JSOp(*bytecodeSection().code(target.offset))))>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset
)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 444); AnnotateMozCrashReason("MOZ_ASSERT" "(" "BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))"
")"); do { *((volatile int*)__null) = 444; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
443 target.offset + BytecodeOffsetDiff(4) <= bytecodeSection().offset(),do { if (jump.offset.valid() && target.offset + BytecodeOffsetDiff
(4) <= bytecodeSection().offset()) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(BytecodeIsJumpTarget
(JSOp(*bytecodeSection().code(target.offset))))>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset
)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 444); AnnotateMozCrashReason("MOZ_ASSERT" "(" "BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))"
")"); do { *((volatile int*)__null) = 444; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
444 BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset))))do { if (jump.offset.valid() && target.offset + BytecodeOffsetDiff
(4) <= bytecodeSection().offset()) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(BytecodeIsJumpTarget
(JSOp(*bytecodeSection().code(target.offset))))>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset
)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 444); AnnotateMozCrashReason("MOZ_ASSERT" "(" "BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))"
")"); do { *((volatile int*)__null) = 444; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
445 jump.patchAll(bytecodeSection().code(BytecodeOffset(0)), target);
446}
447
448bool BytecodeEmitter::emitJumpTargetAndPatch(JumpList jump) {
449 if (!jump.offset.valid()) {
450 return true;
451 }
452 JumpTarget target;
453 if (!emitJumpTarget(&target)) {
454 return false;
455 }
456 patchJumpsToTarget(jump, target);
457 return true;
458}
459
460bool BytecodeEmitter::emitCall(JSOp op, uint16_t argc,
461 const Maybe<uint32_t>& sourceCoordOffset) {
462 if (sourceCoordOffset.isSome()) {
463 if (!updateSourceCoordNotes(*sourceCoordOffset)) {
464 return false;
465 }
466 }
467 return emit3(op, ARGC_LO(argc), ARGC_HI(argc));
468}
469
470bool BytecodeEmitter::emitCall(JSOp op, uint16_t argc, ParseNode* pn) {
471 return emitCall(op, argc, pn ? Some(pn->pn_pos.begin) : Nothing());
472}
473
474bool BytecodeEmitter::emitDupAt(unsigned slotFromTop, unsigned count) {
475 MOZ_ASSERT(slotFromTop < unsigned(bytecodeSection().stackDepth()))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(slotFromTop < unsigned(bytecodeSection().stackDepth
()))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(slotFromTop < unsigned(bytecodeSection().stackDepth
())))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("slotFromTop < unsigned(bytecodeSection().stackDepth())",
"/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 475); AnnotateMozCrashReason("MOZ_ASSERT" "(" "slotFromTop < unsigned(bytecodeSection().stackDepth())"
")"); do { *((volatile int*)__null) = 475; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
476 MOZ_ASSERT(slotFromTop + 1 >= count)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(slotFromTop + 1 >= count)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(slotFromTop + 1 >= count)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("slotFromTop + 1 >= count"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 476); AnnotateMozCrashReason("MOZ_ASSERT" "(" "slotFromTop + 1 >= count"
")"); do { *((volatile int*)__null) = 476; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
477
478 if (slotFromTop == 0 && count == 1) {
479 return emit1(JSOp::Dup);
480 }
481
482 if (slotFromTop == 1 && count == 2) {
483 return emit1(JSOp::Dup2);
484 }
485
486 if (slotFromTop >= Bit(24)) {
487 reportError(nullptr, JSMSG_TOO_MANY_LOCALS);
488 return false;
489 }
490
491 for (unsigned i = 0; i < count; i++) {
492 BytecodeOffset off;
493 if (!emitN(JSOp::DupAt, 3, &off)) {
494 return false;
495 }
496
497 jsbytecode* pc = bytecodeSection().code(off);
498 SET_UINT24(pc, slotFromTop);
499 }
500
501 return true;
502}
503
504bool BytecodeEmitter::emitPopN(unsigned n) {
505 MOZ_ASSERT(n != 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(n != 0)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(n != 0))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("n != 0", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 505); AnnotateMozCrashReason("MOZ_ASSERT" "(" "n != 0" ")")
; do { *((volatile int*)__null) = 505; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
506
507 if (n == 1) {
508 return emit1(JSOp::Pop);
509 }
510
511 // 2 JSOp::Pop instructions (2 bytes) are shorter than JSOp::PopN (3 bytes).
512 if (n == 2) {
513 return emit1(JSOp::Pop) && emit1(JSOp::Pop);
514 }
515
516 return emitUint16Operand(JSOp::PopN, n);
517}
518
519bool BytecodeEmitter::emitPickN(uint8_t n) {
520 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"
, 520); AnnotateMozCrashReason("MOZ_ASSERT" "(" "n != 0" ")")
; do { *((volatile int*)__null) = 520; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
521
522 if (n == 1) {
523 return emit1(JSOp::Swap);
524 }
525
526 return emit2(JSOp::Pick, n);
527}
528
529bool BytecodeEmitter::emitUnpickN(uint8_t n) {
530 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"
, 530); AnnotateMozCrashReason("MOZ_ASSERT" "(" "n != 0" ")")
; do { *((volatile int*)__null) = 530; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
531
532 if (n == 1) {
533 return emit1(JSOp::Swap);
534 }
535
536 return emit2(JSOp::Unpick, n);
537}
538
539bool BytecodeEmitter::emitCheckIsObj(CheckIsObjectKind kind) {
540 return emit2(JSOp::CheckIsObj, uint8_t(kind));
541}
542
543bool BytecodeEmitter::emitBuiltinObject(BuiltinObjectKind kind) {
544 return emit2(JSOp::BuiltinObject, uint8_t(kind));
545}
546
547/* Updates line number notes, not column notes. */
548bool BytecodeEmitter::updateLineNumberNotes(uint32_t offset) {
549 if (skipLocationSrcNotes()) {
550 return true;
551 }
552
553 const ErrorReporter& er = errorReporter();
554 std::optional<bool> onThisLineStatus =
555 er.isOnThisLine(offset, bytecodeSection().currentLine());
556 if (!onThisLineStatus.has_value()) {
557 er.errorNoOffset(JSMSG_OUT_OF_MEMORY);
558 return false;
559 }
560
561 bool onThisLine = *onThisLineStatus;
562
563 if (!onThisLine) {
564 unsigned line = er.lineAt(offset);
565 unsigned delta = line - bytecodeSection().currentLine();
566
567 // If we use a `SetLine` note below, we want it to be relative to the
568 // scripts initial line number for better chance of sharing.
569 unsigned initialLine = sc->extent().lineno;
570 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"
, 570); AnnotateMozCrashReason("MOZ_ASSERT" "(" "line >= initialLine"
")"); do { *((volatile int*)__null) = 570; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
571
572 /*
573 * Encode any change in the current source line number by using
574 * either several SrcNoteType::NewLine notes or just one
575 * SrcNoteType::SetLine note, whichever consumes less space.
576 *
577 * NB: We handle backward line number deltas (possible with for
578 * loops where the update part is emitted after the body, but its
579 * line number is <= any line number in the body) here by letting
580 * unsigned delta_ wrap to a very large number, which triggers a
581 * SrcNoteType::SetLine.
582 */
583 bytecodeSection().setCurrentLine(line, offset);
584 if (delta >= SrcNote::SetLine::lengthFor(line, initialLine)) {
585 if (!newSrcNote2(SrcNoteType::SetLine,
586 SrcNote::SetLine::toOperand(line, initialLine))) {
587 return false;
588 }
589 } else {
590 do {
591 if (!newSrcNote(SrcNoteType::NewLine)) {
592 return false;
593 }
594 } while (--delta != 0);
595 }
596
597 bytecodeSection().updateSeparatorPositionIfPresent();
598 }
599 return true;
600}
601
602/* Updates the line number and column number information in the source notes. */
603bool BytecodeEmitter::updateSourceCoordNotes(uint32_t offset) {
604 if (skipLocationSrcNotes()) {
605 return true;
606 }
607
608 if (!updateLineNumberNotes(offset)) {
609 return false;
610 }
611
612 JS::LimitedColumnNumberOneOrigin columnIndex =
613 errorReporter().columnAt(offset);
614
615 // Assert colspan is always representable.
616 static_assert((0 - ptrdiff_t(JS::LimitedColumnNumberOneOrigin::Limit)) >=
617 SrcNote::ColSpan::MinColSpan);
618 static_assert((ptrdiff_t(JS::LimitedColumnNumberOneOrigin::Limit) - 0) <=
619 SrcNote::ColSpan::MaxColSpan);
620
621 JS::ColumnNumberOffset colspan = columnIndex - bytecodeSection().lastColumn();
622
623 if (colspan != JS::ColumnNumberOffset::zero()) {
624 if (lastLineOnlySrcNoteIndex != LastSrcNoteIsNotLineOnly) {
625 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"
, 626); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().lastColumn() == JS::LimitedColumnNumberOneOrigin()"
")"); do { *((volatile int*)__null) = 626; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
626 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"
, 626); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().lastColumn() == JS::LimitedColumnNumberOneOrigin()"
")"); do { *((volatile int*)__null) = 626; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
627
628 const SrcNotesVector& notes = bytecodeSection().notes();
629 SrcNoteType type = notes[lastLineOnlySrcNoteIndex].type();
630 if (type == SrcNoteType::NewLine) {
631 if (!convertLastNewLineToNewLineColumn(columnIndex)) {
632 return false;
633 }
634 } else {
635 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"
, 635); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == SrcNoteType::SetLine"
")"); do { *((volatile int*)__null) = 635; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
636 if (!convertLastSetLineToSetLineColumn(columnIndex)) {
637 return false;
638 }
639 }
640 } else {
641 if (!newSrcNote2(SrcNoteType::ColSpan,
642 SrcNote::ColSpan::toOperand(colspan))) {
643 return false;
644 }
645 }
646 bytecodeSection().setLastColumn(columnIndex, offset);
647 bytecodeSection().updateSeparatorPositionIfPresent();
648 }
649 return true;
650}
651
652bool BytecodeEmitter::updateSourceCoordNotesIfNonLiteral(ParseNode* node) {
653 if (node->isLiteral()) {
654 return true;
655 }
656 return updateSourceCoordNotes(node->pn_pos.begin);
657}
658
659uint32_t BytecodeEmitter::getOffsetForLoop(ParseNode* nextpn) {
660 // Try to give the JSOp::LoopHead the same line number as the next
661 // instruction. nextpn is often a block, in which case the next instruction
662 // typically comes from the first statement inside.
663 if (nextpn->is<LexicalScopeNode>()) {
664 nextpn = nextpn->as<LexicalScopeNode>().scopeBody();
665 }
666 if (nextpn->isKind(ParseNodeKind::StatementList)) {
667 if (ParseNode* firstStatement = nextpn->as<ListNode>().head()) {
668 nextpn = firstStatement;
669 }
670 }
671
672 return nextpn->pn_pos.begin;
673}
674
675bool BytecodeEmitter::emitUint16Operand(JSOp op, uint32_t operand) {
676 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"
, 676); AnnotateMozCrashReason("MOZ_ASSERT" "(" "operand <= (65535)"
")"); do { *((volatile int*)__null) = 676; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
677 if (!emit3(op, UINT16_LO(operand), UINT16_HI(operand))) {
678 return false;
679 }
680 return true;
681}
682
683bool BytecodeEmitter::emitUint32Operand(JSOp op, uint32_t operand) {
684 BytecodeOffset off;
685 if (!emitN(op, 4, &off)) {
686 return false;
687 }
688 SET_UINT32(bytecodeSection().code(off), operand);
689 return true;
690}
691
692bool BytecodeEmitter::emitGoto(NestableControl* target, GotoKind kind) {
693 NonLocalExitControl nle(this, kind == GotoKind::Continue
694 ? NonLocalExitKind::Continue
695 : NonLocalExitKind::Break);
696 return nle.emitNonLocalJump(target);
697}
698
699AbstractScopePtr BytecodeEmitter::innermostScope() const {
700 return innermostEmitterScope()->scope(this);
701}
702
703ScopeIndex BytecodeEmitter::innermostScopeIndex() const {
704 return *innermostEmitterScope()->scopeIndex(this);
705}
706
707bool BytecodeEmitter::emitGCIndexOp(JSOp op, GCThingIndex index) {
708 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"
, 708); AnnotateMozCrashReason("MOZ_ASSERT" "(" "checkStrictOrSloppy(op)"
")"); do { *((volatile int*)__null) = 708; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
709
710 constexpr size_t OpLength = 1 + GCTHING_INDEX_LEN;
711 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"
, 711); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetOpLength(op) == OpLength"
")"); do { *((volatile int*)__null) = 711; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
712
713 BytecodeOffset offset;
714 if (!emitCheck(op, OpLength, &offset)) {
715 return false;
716 }
717
718 jsbytecode* code = bytecodeSection().code(offset);
719 code[0] = jsbytecode(op);
720 SET_GCTHING_INDEX(code, index);
721 bytecodeSection().updateDepth(op, offset);
722 return true;
723}
724
725bool BytecodeEmitter::emitAtomOp(JSOp op, TaggedParserAtomIndex atom) {
726 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"
, 726); AnnotateMozCrashReason("MOZ_ASSERT" "(" "atom" ")"); do
{ *((volatile int*)__null) = 726; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
727
728 // .generator lookups should be emitted as JSOp::GetAliasedVar instead of
729 // JSOp::GetName etc, to bypass |with| objects on the scope chain.
730 // It's safe to emit .this lookups though because |with| objects skip
731 // those.
732 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"
, 733); AnnotateMozCrashReason("MOZ_ASSERT" "(" "atom != TaggedParserAtomIndex::WellKnown::dot_generator_()"
")"); do { *((volatile int*)__null) = 733; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
733 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"
, 733); AnnotateMozCrashReason("MOZ_ASSERT" "(" "atom != TaggedParserAtomIndex::WellKnown::dot_generator_()"
")"); do { *((volatile int*)__null) = 733; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
734
735 GCThingIndex index;
736 if (!makeAtomIndex(atom, ParserAtom::Atomize::Yes, &index)) {
737 return false;
738 }
739
740 return emitAtomOp(op, index);
741}
742
743bool BytecodeEmitter::emitAtomOp(JSOp op, GCThingIndex atomIndex) {
744 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"
, 744); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JOF_OPTYPE(op) == JOF_ATOM"
")"); do { *((volatile int*)__null) = 744; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
745#ifdef DEBUG1
746 auto atom = perScriptData().gcThingList().getAtom(atomIndex);
747 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"
, 747); AnnotateMozCrashReason("MOZ_ASSERT" "(" "compilationState.parserAtoms.isInstantiatedAsJSAtom(atom)"
")"); do { *((volatile int*)__null) = 747; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
748#endif
749 return emitGCIndexOp(op, atomIndex);
750}
751
752bool BytecodeEmitter::emitStringOp(JSOp op, TaggedParserAtomIndex atom) {
753 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"
, 753); AnnotateMozCrashReason("MOZ_ASSERT" "(" "atom" ")"); do
{ *((volatile int*)__null) = 753; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
754 GCThingIndex index;
755 if (!makeAtomIndex(atom, ParserAtom::Atomize::No, &index)) {
756 return false;
757 }
758
759 return emitStringOp(op, index);
760}
761
762bool BytecodeEmitter::emitStringOp(JSOp op, GCThingIndex atomIndex) {
763 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"
, 763); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JOF_OPTYPE(op) == JOF_STRING"
")"); do { *((volatile int*)__null) = 763; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
764 return emitGCIndexOp(op, atomIndex);
765}
766
767bool BytecodeEmitter::emitInternedScopeOp(GCThingIndex index, JSOp op) {
768 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"
, 768); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JOF_OPTYPE(op) == JOF_SCOPE"
")"); do { *((volatile int*)__null) = 768; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
769 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"
, 769); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index < perScriptData().gcThingList().length()"
")"); do { *((volatile int*)__null) = 769; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
770 return emitGCIndexOp(op, index);
771}
772
773bool BytecodeEmitter::emitInternedObjectOp(GCThingIndex index, JSOp op) {
774 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"
, 774); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JOF_OPTYPE(op) == JOF_OBJECT"
")"); do { *((volatile int*)__null) = 774; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
775 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"
, 775); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index < perScriptData().gcThingList().length()"
")"); do { *((volatile int*)__null) = 775; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
776 return emitGCIndexOp(op, index);
777}
778
779bool BytecodeEmitter::emitRegExp(GCThingIndex index) {
780 return emitGCIndexOp(JSOp::RegExp, index);
781}
782
783bool BytecodeEmitter::emitLocalOp(JSOp op, uint32_t slot) {
784 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"
, 784); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JOF_OPTYPE(op) != JOF_ENVCOORD"
")"); do { *((volatile int*)__null) = 784; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
785 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"
, 785); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsLocalOp(op)"
")"); do { *((volatile int*)__null) = 785; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
786
787 BytecodeOffset off;
788 if (!emitN(op, LOCALNO_LEN, &off)) {
789 return false;
790 }
791
792 SET_LOCALNO(bytecodeSection().code(off), slot);
793 return true;
794}
795
796bool BytecodeEmitter::emitArgOp(JSOp op, uint16_t slot) {
797 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"
, 797); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsArgOp(op)"
")"); do { *((volatile int*)__null) = 797; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
798 BytecodeOffset off;
799 if (!emitN(op, ARGNO_LEN, &off)) {
800 return false;
801 }
802
803 SET_ARGNO(bytecodeSection().code(off), slot);
804 return true;
805}
806
807bool BytecodeEmitter::emitEnvCoordOp(JSOp op, EnvironmentCoordinate ec) {
808 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"
, 809); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JOF_OPTYPE(op) == JOF_ENVCOORD || JOF_OPTYPE(op) == JOF_DEBUGCOORD"
")"); do { *((volatile int*)__null) = 809; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
809 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"
, 809); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JOF_OPTYPE(op) == JOF_ENVCOORD || JOF_OPTYPE(op) == JOF_DEBUGCOORD"
")"); do { *((volatile int*)__null) = 809; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
810
811 constexpr size_t N = ENVCOORD_HOPS_LEN + ENVCOORD_SLOT_LEN;
812 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"
, 812); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetOpLength(op) == 1 + N"
")"); do { *((volatile int*)__null) = 812; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
813
814 BytecodeOffset off;
815 if (!emitN(op, N, &off)) {
816 return false;
817 }
818
819 jsbytecode* pc = bytecodeSection().code(off);
820 SET_ENVCOORD_HOPS(pc, ec.hops());
821 pc += ENVCOORD_HOPS_LEN;
822 SET_ENVCOORD_SLOT(pc, ec.slot());
823 pc += ENVCOORD_SLOT_LEN;
Value stored to 'pc' is never read
824 return true;
825}
826
827JSOp BytecodeEmitter::strictifySetNameOp(JSOp op) {
828 switch (op) {
829 case JSOp::SetName:
830 if (sc->strict()) {
831 op = JSOp::StrictSetName;
832 }
833 break;
834 case JSOp::SetGName:
835 if (sc->strict()) {
836 op = JSOp::StrictSetGName;
837 }
838 break;
839 default:;
840 }
841 return op;
842}
843
844bool BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer) {
845 AutoCheckRecursionLimit recursion(fc);
846 if (!recursion.check(fc)) {
847 return false;
848 }
849
850restart:
851
852 switch (pn->getKind()) {
853 // Trivial cases with no side effects.
854 case ParseNodeKind::EmptyStmt:
855 case ParseNodeKind::TrueExpr:
856 case ParseNodeKind::FalseExpr:
857 case ParseNodeKind::NullExpr:
858 case ParseNodeKind::RawUndefinedExpr:
859 case ParseNodeKind::Elision:
860 case ParseNodeKind::Generator:
861 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"
, 861); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<NullaryNode>()"
")"); do { *((volatile int*)__null) = 861; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
862 *answer = false;
863 return true;
864
865 case ParseNodeKind::ObjectPropertyName:
866 case ParseNodeKind::PrivateName: // no side effects, unlike
867 // ParseNodeKind::Name
868 case ParseNodeKind::StringExpr:
869 case ParseNodeKind::TemplateStringExpr:
870 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"
, 870); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<NameNode>()"
")"); do { *((volatile int*)__null) = 870; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
871 *answer = false;
872 return true;
873
874 case ParseNodeKind::RegExpExpr:
875 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"
, 875); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<RegExpLiteral>()"
")"); do { *((volatile int*)__null) = 875; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
876 *answer = false;
877 return true;
878
879 case ParseNodeKind::NumberExpr:
880 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"
, 880); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<NumericLiteral>()"
")"); do { *((volatile int*)__null) = 880; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
881 *answer = false;
882 return true;
883
884 case ParseNodeKind::BigIntExpr:
885 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"
, 885); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BigIntLiteral>()"
")"); do { *((volatile int*)__null) = 885; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
886 *answer = false;
887 return true;
888
889 // |this| can throw in derived class constructors, including nested arrow
890 // functions or eval.
891 case ParseNodeKind::ThisExpr:
892 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"
, 892); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { *((volatile int*)__null) = 892; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
893 *answer = sc->needsThisTDZChecks();
894 return true;
895
896 // |new.target| doesn't have any side-effects.
897 case ParseNodeKind::NewTargetExpr: {
898 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"
, 898); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<NewTargetNode>()"
")"); do { *((volatile int*)__null) = 898; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
899 *answer = false;
900 return true;
901 }
902
903 // Trivial binary nodes with more token pos holders.
904 case ParseNodeKind::ImportMetaExpr: {
905 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"
, 905); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->as<BinaryNode>().left()->isKind(ParseNodeKind::PosHolder)"
")"); do { *((volatile int*)__null) = 905; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
906 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"
, 907); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->as<BinaryNode>().right()->isKind(ParseNodeKind::PosHolder)"
")"); do { *((volatile int*)__null) = 907; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
907 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"
, 907); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->as<BinaryNode>().right()->isKind(ParseNodeKind::PosHolder)"
")"); do { *((volatile int*)__null) = 907; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
908 *answer = false;
909 return true;
910 }
911
912 case ParseNodeKind::BreakStmt:
913 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"
, 913); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BreakStatement>()"
")"); do { *((volatile int*)__null) = 913; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
914 *answer = true;
915 return true;
916
917 case ParseNodeKind::ContinueStmt:
918 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"
, 918); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<ContinueStatement>()"
")"); do { *((volatile int*)__null) = 918; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
919 *answer = true;
920 return true;
921
922 case ParseNodeKind::DebuggerStmt:
923 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"
, 923); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<DebuggerStatement>()"
")"); do { *((volatile int*)__null) = 923; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
924 *answer = true;
925 return true;
926
927 // Watch out for getters!
928 case ParseNodeKind::OptionalDotExpr:
929 case ParseNodeKind::DotExpr:
930 case ParseNodeKind::ArgumentsLength:
931 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"
, 931); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { *((volatile int*)__null) = 931; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
932 *answer = true;
933 return true;
934
935 // Unary cases with side effects only if the child has them.
936 case ParseNodeKind::TypeOfExpr:
937 case ParseNodeKind::VoidExpr:
938 case ParseNodeKind::NotExpr:
939 return checkSideEffects(pn->as<UnaryNode>().kid(), answer);
940
941 // Even if the name expression is effect-free, performing ToPropertyKey on
942 // it might not be effect-free:
943 //
944 // RegExp.prototype.toString = () => { throw 42; };
945 // ({ [/regex/]: 0 }); // ToPropertyKey(/regex/) throws 42
946 //
947 // function Q() {
948 // ({ [new.target]: 0 });
949 // }
950 // Q.toString = () => { throw 17; };
951 // new Q; // new.target will be Q, ToPropertyKey(Q) throws 17
952 case ParseNodeKind::ComputedName:
953 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"
, 953); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { *((volatile int*)__null) = 953; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
954 *answer = true;
955 return true;
956
957 // Looking up or evaluating the associated name could throw.
958 case ParseNodeKind::TypeOfNameExpr:
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 // This unary case has side effects on the enclosing object, sure. But
964 // that's not the question this function answers: it's whether the
965 // operation may have a side effect on something *other* than the result
966 // of the overall operation in which it's embedded. The answer to that
967 // is no, because an object literal having a mutated prototype only
968 // produces a value, without affecting anything else.
969 case ParseNodeKind::MutateProto:
970 return checkSideEffects(pn->as<UnaryNode>().kid(), answer);
971
972 // Unary cases with obvious side effects.
973 case ParseNodeKind::PreIncrementExpr:
974 case ParseNodeKind::PostIncrementExpr:
975 case ParseNodeKind::PreDecrementExpr:
976 case ParseNodeKind::PostDecrementExpr:
977 case ParseNodeKind::ThrowStmt:
978 MOZ_ASSERT(pn->is<UnaryNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<UnaryNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<UnaryNode>()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"pn->is<UnaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 978); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { *((volatile int*)__null) = 978; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
979 *answer = true;
980 return true;
981
982 // These might invoke valueOf/toString, even with a subexpression without
983 // side effects! Consider |+{ valueOf: null, toString: null }|.
984 case ParseNodeKind::BitNotExpr:
985 case ParseNodeKind::PosExpr:
986 case ParseNodeKind::NegExpr:
987 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"
, 987); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { *((volatile int*)__null) = 987; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
988 *answer = true;
989 return true;
990
991 // This invokes the (user-controllable) iterator protocol.
992 case ParseNodeKind::Spread:
993 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"
, 993); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { *((volatile int*)__null) = 993; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
994 *answer = true;
995 return true;
996
997 case ParseNodeKind::InitialYield:
998 case ParseNodeKind::YieldStarExpr:
999 case ParseNodeKind::YieldExpr:
1000 case ParseNodeKind::AwaitExpr:
1001 MOZ_ASSERT(pn->is<UnaryNode>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pn->is<UnaryNode>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pn->is<UnaryNode>()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"pn->is<UnaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1001); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { *((volatile int*)__null) = 1001; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1002 *answer = true;
1003 return true;
1004
1005 // Deletion generally has side effects, even if isolated cases have none.
1006 case ParseNodeKind::DeleteNameExpr:
1007 case ParseNodeKind::DeletePropExpr:
1008 case ParseNodeKind::DeleteElemExpr:
1009 case ParseNodeKind::DeleteOptionalChainExpr:
1010 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"
, 1010); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { *((volatile int*)__null) = 1010; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1011 *answer = true;
1012 return true;
1013
1014 // Deletion of a non-Reference expression has side effects only through
1015 // evaluating the expression.
1016 case ParseNodeKind::DeleteExpr: {
1017 ParseNode* expr = pn->as<UnaryNode>().kid();
1018 return checkSideEffects(expr, answer);
1019 }
1020
1021 case ParseNodeKind::ExpressionStmt:
1022 return checkSideEffects(pn->as<UnaryNode>().kid(), answer);
1023
1024 // Binary cases with obvious side effects.
1025 case ParseNodeKind::InitExpr:
1026 *answer = true;
1027 return true;
1028
1029 case ParseNodeKind::AssignExpr:
1030 case ParseNodeKind::AddAssignExpr:
1031 case ParseNodeKind::SubAssignExpr:
1032 case ParseNodeKind::CoalesceAssignExpr:
1033 case ParseNodeKind::OrAssignExpr:
1034 case ParseNodeKind::AndAssignExpr:
1035 case ParseNodeKind::BitOrAssignExpr:
1036 case ParseNodeKind::BitXorAssignExpr:
1037 case ParseNodeKind::BitAndAssignExpr:
1038 case ParseNodeKind::LshAssignExpr:
1039 case ParseNodeKind::RshAssignExpr:
1040 case ParseNodeKind::UrshAssignExpr:
1041 case ParseNodeKind::MulAssignExpr:
1042 case ParseNodeKind::DivAssignExpr:
1043 case ParseNodeKind::ModAssignExpr:
1044 case ParseNodeKind::PowAssignExpr:
1045 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"
, 1045); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<AssignmentNode>()"
")"); do { *((volatile int*)__null) = 1045; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1046 *answer = true;
1047 return true;
1048
1049 case ParseNodeKind::SetThis:
1050 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"
, 1050); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { *((volatile int*)__null) = 1050; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1051 *answer = true;
1052 return true;
1053
1054 case ParseNodeKind::StatementList:
1055 // Strict equality operations and short circuit operators are well-behaved
1056 // and perform no conversions.
1057 case ParseNodeKind::CoalesceExpr:
1058 case ParseNodeKind::OrExpr:
1059 case ParseNodeKind::AndExpr:
1060 case ParseNodeKind::StrictEqExpr:
1061 case ParseNodeKind::StrictNeExpr:
1062 // Any subexpression of a comma expression could be effectful.
1063 case ParseNodeKind::CommaExpr:
1064 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"
, 1064); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!pn->as<ListNode>().empty()"
")"); do { *((volatile int*)__null) = 1064; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1065 [[fallthrough]];
1066 // Subcomponents of a literal may be effectful.
1067 case ParseNodeKind::ArrayExpr:
1068 case ParseNodeKind::ObjectExpr:
1069 for (ParseNode* item : pn->as<ListNode>().contents()) {
1070 if (!checkSideEffects(item, answer)) {
1071 return false;
1072 }
1073 if (*answer) {
1074 return true;
1075 }
1076 }
1077 return true;
1078
1079#ifdef ENABLE_RECORD_TUPLE
1080 case ParseNodeKind::RecordExpr:
1081 case ParseNodeKind::TupleExpr:
1082 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"
, 1082); AnnotateMozCrashReason("MOZ_CRASH(" "Record and Tuple are not supported yet"
")"); do { *((volatile int*)__null) = 1082; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
1083#endif
1084
1085#ifdef ENABLE_DECORATORS
1086 case ParseNodeKind::DecoratorList:
1087 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"
, 1087); AnnotateMozCrashReason("MOZ_CRASH(" "Decorators are not supported yet"
")"); do { *((volatile int*)__null) = 1087; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
1088#endif
1089
1090#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
1091 case ParseNodeKind::UsingDecl:
1092 case ParseNodeKind::AwaitUsingDecl:
1093 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"
, 1093); AnnotateMozCrashReason("MOZ_CRASH(" "Using declarations are not supported yet"
")"); do { *((volatile int*)__null) = 1093; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
1094#endif
1095
1096 // Most other binary operations (parsed as lists in SpiderMonkey) may
1097 // perform conversions triggering side effects. Math operations perform
1098 // ToNumber and may fail invoking invalid user-defined toString/valueOf:
1099 // |5 < { toString: null }|. |instanceof| throws if provided a
1100 // non-object constructor: |null instanceof null|. |in| throws if given
1101 // a non-object RHS: |5 in null|.
1102 case ParseNodeKind::BitOrExpr:
1103 case ParseNodeKind::BitXorExpr:
1104 case ParseNodeKind::BitAndExpr:
1105 case ParseNodeKind::EqExpr:
1106 case ParseNodeKind::NeExpr:
1107 case ParseNodeKind::LtExpr:
1108 case ParseNodeKind::LeExpr:
1109 case ParseNodeKind::GtExpr:
1110 case ParseNodeKind::GeExpr:
1111 case ParseNodeKind::InstanceOfExpr:
1112 case ParseNodeKind::InExpr:
1113 case ParseNodeKind::PrivateInExpr:
1114 case ParseNodeKind::LshExpr:
1115 case ParseNodeKind::RshExpr:
1116 case ParseNodeKind::UrshExpr:
1117 case ParseNodeKind::AddExpr:
1118 case ParseNodeKind::SubExpr:
1119 case ParseNodeKind::MulExpr:
1120 case ParseNodeKind::DivExpr:
1121 case ParseNodeKind::ModExpr:
1122 case ParseNodeKind::PowExpr:
1123 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"
, 1123); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->as<ListNode>().count() >= 2"
")"); do { *((volatile int*)__null) = 1123; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1124 *answer = true;
1125 return true;
1126
1127 case ParseNodeKind::PropertyDefinition:
1128 case ParseNodeKind::Case: {
1129 BinaryNode* node = &pn->as<BinaryNode>();
1130 if (!checkSideEffects(node->left(), answer)) {
1131 return false;
1132 }
1133 if (*answer) {
1134 return true;
1135 }
1136 return checkSideEffects(node->right(), answer);
1137 }
1138
1139 // More getters.
1140 case ParseNodeKind::ElemExpr:
1141 case ParseNodeKind::OptionalElemExpr:
1142 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"
, 1142); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { *((volatile int*)__null) = 1142; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1143 *answer = true;
1144 return true;
1145
1146 // Throws if the operand is not of the right class. Can also call a private
1147 // getter.
1148 case ParseNodeKind::PrivateMemberExpr:
1149 case ParseNodeKind::OptionalPrivateMemberExpr:
1150 *answer = true;
1151 return true;
1152
1153 // These affect visible names in this code, or in other code.
1154 case ParseNodeKind::ImportDecl:
1155 case ParseNodeKind::ExportFromStmt:
1156 case ParseNodeKind::ExportDefaultStmt:
1157 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"
, 1157); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { *((volatile int*)__null) = 1157; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1158 *answer = true;
1159 return true;
1160
1161 // Likewise.
1162 case ParseNodeKind::ExportStmt:
1163 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"
, 1163); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { *((volatile int*)__null) = 1163; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1164 *answer = true;
1165 return true;
1166
1167 case ParseNodeKind::CallImportExpr:
1168 case ParseNodeKind::CallImportSpec:
1169 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"
, 1169); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { *((volatile int*)__null) = 1169; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1170 *answer = true;
1171 return true;
1172
1173 // Every part of a loop might be effect-free, but looping infinitely *is*
1174 // an effect. (Language lawyer trivia: C++ says threads can be assumed
1175 // to exit or have side effects, C++14 [intro.multithread]p27, so a C++
1176 // implementation's equivalent of the below could set |*answer = false;|
1177 // if all loop sub-nodes set |*answer = false|!)
1178 case ParseNodeKind::DoWhileStmt:
1179 case ParseNodeKind::WhileStmt:
1180 case ParseNodeKind::ForStmt:
1181 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"
, 1181); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { *((volatile int*)__null) = 1181; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1182 *answer = true;
1183 return true;
1184
1185 // Declarations affect the name set of the relevant scope.
1186 case ParseNodeKind::VarStmt:
1187 case ParseNodeKind::ConstDecl:
1188 case ParseNodeKind::LetDecl:
1189 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"
, 1189); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<ListNode>()"
")"); do { *((volatile int*)__null) = 1189; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1190 *answer = true;
1191 return true;
1192
1193 case ParseNodeKind::IfStmt:
1194 case ParseNodeKind::ConditionalExpr: {
1195 TernaryNode* node = &pn->as<TernaryNode>();
1196 if (!checkSideEffects(node->kid1(), answer)) {
1197 return false;
1198 }
1199 if (*answer) {
1200 return true;
1201 }
1202 if (!checkSideEffects(node->kid2(), answer)) {
1203 return false;
1204 }
1205 if (*answer) {
1206 return true;
1207 }
1208 if ((pn = node->kid3())) {
1209 goto restart;
1210 }
1211 return true;
1212 }
1213
1214 // Function calls can invoke non-local code.
1215 case ParseNodeKind::NewExpr:
1216 case ParseNodeKind::CallExpr:
1217 case ParseNodeKind::OptionalCallExpr:
1218 case ParseNodeKind::TaggedTemplateExpr:
1219 case ParseNodeKind::SuperCallExpr:
1220 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"
, 1220); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { *((volatile int*)__null) = 1220; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1221 *answer = true;
1222 return true;
1223
1224 // Function arg lists can contain arbitrary expressions. Technically
1225 // this only causes side-effects if one of the arguments does, but since
1226 // the call being made will always trigger side-effects, it isn't needed.
1227 case ParseNodeKind::Arguments:
1228 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"
, 1228); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<ListNode>()"
")"); do { *((volatile int*)__null) = 1228; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1229 *answer = true;
1230 return true;
1231
1232 case ParseNodeKind::OptionalChain:
1233 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"
, 1233); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()"
")"); do { *((volatile int*)__null) = 1233; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1234 *answer = true;
1235 return true;
1236
1237 // Classes typically introduce names. Even if no name is introduced,
1238 // the heritage and/or class body (through computed property names)
1239 // usually have effects.
1240 case ParseNodeKind::ClassDecl:
1241 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"
, 1241); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<ClassNode>()"
")"); do { *((volatile int*)__null) = 1241; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1242 *answer = true;
1243 return true;
1244
1245 // |with| calls |ToObject| on its expression and so throws if that value
1246 // is null/undefined.
1247 case ParseNodeKind::WithStmt:
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::ReturnStmt:
1253 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"
, 1253); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { *((volatile int*)__null) = 1253; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1254 *answer = true;
1255 return true;
1256
1257 case ParseNodeKind::Name:
1258 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"
, 1258); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<NameNode>()"
")"); do { *((volatile int*)__null) = 1258; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1259 *answer = true;
1260 return true;
1261
1262 // Shorthands could trigger getters: the |x| in the object literal in
1263 // |with ({ get x() { throw 42; } }) ({ x });|, for example, triggers
1264 // one. (Of course, it isn't necessary to use |with| for a shorthand to
1265 // trigger a getter.)
1266 case ParseNodeKind::Shorthand:
1267 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"
, 1267); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()"
")"); do { *((volatile int*)__null) = 1267; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1268 *answer = true;
1269 return true;
1270
1271 case ParseNodeKind::Function:
1272 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"
, 1272); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<FunctionNode>()"
")"); do { *((volatile int*)__null) = 1272; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1273 /*
1274 * A named function, contrary to ES3, is no longer effectful, because
1275 * we bind its name lexically (using JSOp::Callee) instead of creating
1276 * an Object instance and binding a readonly, permanent property in it
1277 * (the object and binding can be detected and hijacked or captured).
1278 * This is a bug fix to ES3; it is fixed in ES3.1 drafts.
1279 */
1280 *answer = false;
1281 return true;
1282
1283 case ParseNodeKind::Module:
1284 *answer = false;
1285 return true;
1286
1287 case ParseNodeKind::TryStmt: {
1288 TryNode* tryNode = &pn->as<TryNode>();
1289 if (!checkSideEffects(tryNode->body(), answer)) {
1290 return false;
1291 }
1292 if (*answer) {
1293 return true;
1294 }
1295 if (LexicalScopeNode* catchScope = tryNode->catchScope()) {
1296 if (!checkSideEffects(catchScope, answer)) {
1297 return false;
1298 }
1299 if (*answer) {
1300 return true;
1301 }
1302 }
1303 if (ParseNode* finallyBlock = tryNode->finallyBlock()) {
1304 if (!checkSideEffects(finallyBlock, answer)) {
1305 return false;
1306 }
1307 }
1308 return true;
1309 }
1310
1311 case ParseNodeKind::Catch: {
1312 BinaryNode* catchClause = &pn->as<BinaryNode>();
1313 if (ParseNode* name = catchClause->left()) {
1314 if (!checkSideEffects(name, answer)) {
1315 return false;
1316 }
1317 if (*answer) {
1318 return true;
1319 }
1320 }
1321 return checkSideEffects(catchClause->right(), answer);
1322 }
1323
1324 case ParseNodeKind::SwitchStmt: {
1325 SwitchStatement* switchStmt = &pn->as<SwitchStatement>();
1326 if (!checkSideEffects(&switchStmt->discriminant(), answer)) {
1327 return false;
1328 }
1329 return *answer ||
1330 checkSideEffects(&switchStmt->lexicalForCaseList(), answer);
1331 }
1332
1333 case ParseNodeKind::LabelStmt:
1334 return checkSideEffects(pn->as<LabeledStatement>().statement(), answer);
1335
1336 case ParseNodeKind::LexicalScope:
1337 return checkSideEffects(pn->as<LexicalScopeNode>().scopeBody(), answer);
1338
1339 // We could methodically check every interpolated expression, but it's
1340 // probably not worth the trouble. Treat template strings as effect-free
1341 // only if they don't contain any substitutions.
1342 case ParseNodeKind::TemplateStringListExpr: {
1343 ListNode* list = &pn->as<ListNode>();
1344 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"
, 1344); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!list->empty()"
")"); do { *((volatile int*)__null) = 1344; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1345 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"
, 1347); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(list->count() % 2) == 1"
") (" "template strings must alternate template and substitution "
"parts" ")"); do { *((volatile int*)__null) = 1347; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
1346 "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"
, 1347); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(list->count() % 2) == 1"
") (" "template strings must alternate template and substitution "
"parts" ")"); do { *((volatile int*)__null) = 1347; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
1347 "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"
, 1347); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(list->count() % 2) == 1"
") (" "template strings must alternate template and substitution "
"parts" ")"); do { *((volatile int*)__null) = 1347; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
1348 *answer = list->count() > 1;
1349 return true;
1350 }
1351
1352 // This should be unreachable but is left as-is for now.
1353 case ParseNodeKind::ParamsBody:
1354 *answer = true;
1355 return true;
1356
1357 case ParseNodeKind::ForIn: // by ParseNodeKind::For
1358 case ParseNodeKind::ForOf: // by ParseNodeKind::For
1359 case ParseNodeKind::ForHead: // by ParseNodeKind::For
1360 case ParseNodeKind::DefaultConstructor: // by ParseNodeKind::ClassDecl
1361 case ParseNodeKind::ClassBodyScope: // by ParseNodeKind::ClassDecl
1362 case ParseNodeKind::ClassMethod: // by ParseNodeKind::ClassDecl
1363 case ParseNodeKind::ClassField: // by ParseNodeKind::ClassDecl
1364 case ParseNodeKind::ClassNames: // by ParseNodeKind::ClassDecl
1365 case ParseNodeKind::StaticClassBlock: // by ParseNodeKind::ClassDecl
1366 case ParseNodeKind::ClassMemberList: // by ParseNodeKind::ClassDecl
1367 case ParseNodeKind::ImportSpecList: // by ParseNodeKind::Import
1368 case ParseNodeKind::ImportSpec: // by ParseNodeKind::Import
1369 case ParseNodeKind::ImportNamespaceSpec: // by ParseNodeKind::Import
1370 case ParseNodeKind::ImportAttribute: // by ParseNodeKind::Import
1371 case ParseNodeKind::ImportAttributeList: // by ParseNodeKind::Import
1372 case ParseNodeKind::ImportModuleRequest: // by ParseNodeKind::Import
1373 case ParseNodeKind::ExportBatchSpecStmt: // by ParseNodeKind::Export
1374 case ParseNodeKind::ExportSpecList: // by ParseNodeKind::Export
1375 case ParseNodeKind::ExportSpec: // by ParseNodeKind::Export
1376 case ParseNodeKind::ExportNamespaceSpec: // by ParseNodeKind::Export
1377 case ParseNodeKind::CallSiteObj: // by ParseNodeKind::TaggedTemplate
1378 case ParseNodeKind::PosHolder: // by ParseNodeKind::NewTarget
1379 case ParseNodeKind::SuperBase: // by ParseNodeKind::Elem and others
1380 case ParseNodeKind::PropertyNameExpr: // by ParseNodeKind::Dot
1381 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"
, 1381); AnnotateMozCrashReason("MOZ_CRASH(" "handled by parent nodes"
")"); do { *((volatile int*)__null) = 1381; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
1382
1383 case ParseNodeKind::LastUnused:
1384 case ParseNodeKind::Limit:
1385 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"
, 1385); AnnotateMozCrashReason("MOZ_CRASH(" "invalid node kind"
")"); do { *((volatile int*)__null) = 1385; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
1386 }
1387
1388 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"
, 1390); AnnotateMozCrashReason("MOZ_CRASH(" "invalid, unenumerated ParseNodeKind value encountered in "
"BytecodeEmitter::checkSideEffects" ")"); do { *((volatile int
*)__null) = 1390; __attribute__((nomerge)) ::abort(); } while
(false); } while (false)
1389 "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"
, 1390); AnnotateMozCrashReason("MOZ_CRASH(" "invalid, unenumerated ParseNodeKind value encountered in "
"BytecodeEmitter::checkSideEffects" ")"); do { *((volatile int
*)__null) = 1390; __attribute__((nomerge)) ::abort(); } while
(false); } while (false)
1390 "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"
, 1390); AnnotateMozCrashReason("MOZ_CRASH(" "invalid, unenumerated ParseNodeKind value encountered in "
"BytecodeEmitter::checkSideEffects" ")"); do { *((volatile int
*)__null) = 1390; __attribute__((nomerge)) ::abort(); } while
(false); } while (false)
;
1391}
1392
1393bool BytecodeEmitter::isInLoop() {
1394 return findInnermostNestableControl<LoopControl>();
1395}
1396
1397bool BytecodeEmitter::checkSingletonContext() {
1398 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"
, 1398); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isTopLevelContext()"
")"); do { *((volatile int*)__null) = 1398; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
1399 return sc->treatAsRunOnce() && !isInLoop();
1400}
1401
1402bool BytecodeEmitter::needsImplicitThis() {
1403 // Short-circuit if there is an enclosing 'with' scope.
1404 if (sc->inWith()) {
1405 return true;
1406 }
1407
1408 // Otherwise see if the current point is under a 'with'.
1409 for (EmitterScope* es = innermostEmitterScope(); es;
1410 es = es->enclosingInFrame()) {
1411 if (es->scope(this).kind() == ScopeKind::With) {
1412 return true;
1413 }
1414 }
1415
1416 return false;
1417}
1418
1419size_t BytecodeEmitter::countThisEnvironmentHops() {
1420 unsigned numHops = 0;
1421
1422 for (BytecodeEmitter* current = this; current; current = current->parent) {
1423 for (EmitterScope* es = current->innermostEmitterScope(); es;
1424 es = es->enclosingInFrame()) {
1425 if (es->scope(current).is<FunctionScope>()) {
1426 if (!es->scope(current).isArrow()) {
1427 // The Parser is responsible for marking the environment as either
1428 // closed-over or used-by-eval which ensure that is must exist.
1429 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"
, 1429); AnnotateMozCrashReason("MOZ_ASSERT" "(" "es->scope(current).hasEnvironment()"
")"); do { *((volatile int*)__null) = 1429; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1430 return numHops;
1431 }
1432 }
1433 if (es->scope(current).hasEnvironment()) {
1434 numHops++;
1435 }
1436 }
1437 }
1438
1439 // The "this" environment exists outside of the compilation, but the
1440 // `ScopeContext` recorded the number of additional hops needed, so add
1441 // those in now.
1442 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"
, 1442); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->allowSuperProperty()"
")"); do { *((volatile int*)__null) = 1442; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1443 numHops += compilationState.scopeContext.enclosingThisEnvironmentHops;
1444 return numHops;
1445}
1446
1447bool BytecodeEmitter::emitThisEnvironmentCallee() {
1448 // Get the innermost enclosing function that has a |this| binding.
1449
1450 // Directly load callee from the frame if possible.
1451 if (sc->isFunctionBox() && !sc->asFunctionBox()->isArrow()) {
1452 return emit1(JSOp::Callee);
1453 }
1454
1455 // We have to load the callee from the environment chain.
1456 size_t numHops = countThisEnvironmentHops();
1457
1458 static_assert(
1459 ENVCOORD_HOPS_LIMIT - 1 <= UINT8_MAX(255),
1460 "JSOp::EnvCallee operand size should match ENVCOORD_HOPS_LIMIT");
1461
1462 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"
, 1462); AnnotateMozCrashReason("MOZ_ASSERT" "(" "numHops < ENVCOORD_HOPS_LIMIT - 1"
")"); do { *((volatile int*)__null) = 1462; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1463
1464 return emit2(JSOp::EnvCallee, numHops);
1465}
1466
1467bool BytecodeEmitter::emitSuperBase() {
1468 if (!emitThisEnvironmentCallee()) {
1469 return false;
1470 }
1471
1472 return emit1(JSOp::SuperBase);
1473}
1474
1475void BytecodeEmitter::reportError(ParseNode* pn, unsigned errorNumber, ...) {
1476 uint32_t offset = pn ? pn->pn_pos.begin : *scriptStartOffset;
1477
1478 va_list args;
1479 va_start(args, errorNumber)__builtin_va_start(args, errorNumber);
1480
1481 errorReporter().errorWithNotesAtVA(nullptr, AsVariant(offset), errorNumber,
1482 &args);
1483
1484 va_end(args)__builtin_va_end(args);
1485}
1486
1487void BytecodeEmitter::reportError(uint32_t offset, unsigned errorNumber, ...) {
1488 va_list args;
1489 va_start(args, errorNumber)__builtin_va_start(args, errorNumber);
1490
1491 errorReporter().errorWithNotesAtVA(nullptr, AsVariant(offset), errorNumber,
1492 &args);
1493
1494 va_end(args)__builtin_va_end(args);
1495}
1496
1497bool BytecodeEmitter::addObjLiteralData(ObjLiteralWriter& writer,
1498 GCThingIndex* outIndex) {
1499 if (!writer.checkForDuplicatedNames(fc)) {
1500 return false;
1501 }
1502
1503 size_t len = writer.getCode().size();
1504 auto* code = compilationState.alloc.newArrayUninitialized<uint8_t>(len);
1505 if (!code) {
1506 js::ReportOutOfMemory(fc);
1507 return false;
1508 }
1509 memcpy(code, writer.getCode().data(), len);
1510
1511 ObjLiteralIndex objIndex(compilationState.objLiteralData.length());
1512 if (uint32_t(objIndex) >= TaggedScriptThingIndex::IndexLimit) {
1513 ReportAllocationOverflow(fc);
1514 return false;
1515 }
1516 if (!compilationState.objLiteralData.emplaceBack(code, len, writer.getKind(),
1517 writer.getFlags(),
1518 writer.getPropertyCount())) {
1519 js::ReportOutOfMemory(fc);
1520 return false;
1521 }
1522
1523 return perScriptData().gcThingList().append(objIndex, outIndex);
1524}
1525
1526bool BytecodeEmitter::emitPrepareIteratorResult() {
1527 constexpr JSOp op = JSOp::NewObject;
1528
1529 ObjLiteralWriter writer;
1530 writer.beginShape(op);
1531
1532 writer.setPropNameNoDuplicateCheck(parserAtoms(),
1533 TaggedParserAtomIndex::WellKnown::value());
1534 if (!writer.propWithUndefinedValue(fc)) {
1535 return false;
1536 }
1537 writer.setPropNameNoDuplicateCheck(parserAtoms(),
1538 TaggedParserAtomIndex::WellKnown::done());
1539 if (!writer.propWithUndefinedValue(fc)) {
1540 return false;
1541 }
1542
1543 GCThingIndex shape;
1544 if (!addObjLiteralData(writer, &shape)) {
1545 return false;
1546 }
1547
1548 return emitGCIndexOp(op, shape);
1549}
1550
1551bool BytecodeEmitter::emitFinishIteratorResult(bool done) {
1552 if (!emitAtomOp(JSOp::InitProp, TaggedParserAtomIndex::WellKnown::value())) {
1553 return false;
1554 }
1555 if (!emit1(done ? JSOp::True : JSOp::False)) {
1556 return false;
1557 }
1558 if (!emitAtomOp(JSOp::InitProp, TaggedParserAtomIndex::WellKnown::done())) {
1559 return false;
1560 }
1561 return true;
1562}
1563
1564bool BytecodeEmitter::emitGetNameAtLocation(TaggedParserAtomIndex name,
1565 const NameLocation& loc) {
1566 NameOpEmitter noe(this, name, loc, NameOpEmitter::Kind::Get);
1567 if (!noe.emitGet()) {
1568 return false;
1569 }
1570
1571 return true;
1572}
1573
1574bool BytecodeEmitter::emitGetName(NameNode* name) {
1575 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"
, 1575); AnnotateMozCrashReason("MOZ_ASSERT" "(" "name->isKind(ParseNodeKind::Name)"
")"); do { *((volatile int*)__null) = 1575; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1576
1577 return emitGetName(name->name());
1578}
1579
1580bool BytecodeEmitter::emitGetPrivateName(NameNode* name) {
1581 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"
, 1581); AnnotateMozCrashReason("MOZ_ASSERT" "(" "name->isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 1581; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1582 return emitGetPrivateName(name->name());
1583}
1584
1585bool BytecodeEmitter::emitGetPrivateName(TaggedParserAtomIndex nameAtom) {
1586 // The parser ensures the private name is present on the environment chain,
1587 // but its location can be Dynamic or Global when emitting debugger
1588 // eval-in-frame code.
1589 NameLocation location = lookupName(nameAtom);
1590 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"
, 1593); 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) = 1593; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1591 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"
, 1593); 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) = 1593; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1592 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"
, 1593); 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) = 1593; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1593 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"
, 1593); 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) = 1593; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1594
1595 return emitGetNameAtLocation(nameAtom, location);
1596}
1597
1598bool BytecodeEmitter::emitTDZCheckIfNeeded(TaggedParserAtomIndex name,
1599 const NameLocation& loc,
1600 ValueIsOnStack isOnStack) {
1601 // Dynamic accesses have TDZ checks built into their VM code and should
1602 // never emit explicit TDZ checks.
1603 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"
, 1603); AnnotateMozCrashReason("MOZ_ASSERT" "(" "loc.hasKnownSlot()"
")"); do { *((volatile int*)__null) = 1603; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1604 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"
, 1604); AnnotateMozCrashReason("MOZ_ASSERT" "(" "loc.isLexical() || loc.isPrivateMethod() || loc.isSynthetic()"
")"); do { *((volatile int*)__null) = 1604; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1605
1606 // Private names are implemented as lexical bindings, but it's just an
1607 // implementation detail. Per spec there's no TDZ check when using them.
1608 if (parserAtoms().isPrivateName(name)) {
1609 return true;
1610 }
1611
1612 Maybe<MaybeCheckTDZ> check =
1613 innermostTDZCheckCache->needsTDZCheck(this, name);
1614 if (!check) {
1615 return false;
1616 }
1617
1618 // We've already emitted a check in this basic block.
1619 if (*check == DontCheckTDZ) {
1620 return true;
1621 }
1622
1623 // If the value is not on the stack, we have to load it first.
1624 if (isOnStack == ValueIsOnStack::No) {
1625 if (loc.kind() == NameLocation::Kind::FrameSlot) {
1626 if (!emitLocalOp(JSOp::GetLocal, loc.frameSlot())) {
1627 return false;
1628 }
1629 } else {
1630 if (!emitEnvCoordOp(JSOp::GetAliasedVar, loc.environmentCoordinate())) {
1631 return false;
1632 }
1633 }
1634 }
1635
1636 // Emit the lexical check.
1637 if (loc.kind() == NameLocation::Kind::FrameSlot) {
1638 if (!emitLocalOp(JSOp::CheckLexical, loc.frameSlot())) {
1639 return false;
1640 }
1641 } else {
1642 if (!emitEnvCoordOp(JSOp::CheckAliasedLexical,
1643 loc.environmentCoordinate())) {
1644 return false;
1645 }
1646 }
1647
1648 // Pop the value if needed.
1649 if (isOnStack == ValueIsOnStack::No) {
1650 if (!emit1(JSOp::Pop)) {
1651 return false;
1652 }
1653 }
1654
1655 return innermostTDZCheckCache->noteTDZCheck(this, name, DontCheckTDZ);
1656}
1657
1658bool BytecodeEmitter::emitPropLHS(PropertyAccess* prop) {
1659 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"
, 1659); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!prop->isSuper()"
")"); do { *((volatile int*)__null) = 1659; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1660
1661 ParseNode* expr = &prop->expression();
1662
1663 if (!expr->is<PropertyAccess>() || expr->as<PropertyAccess>().isSuper()) {
1664 // The non-optimized case.
1665 return emitTree(expr);
1666 }
1667
1668 // If the object operand is also a dotted property reference, reverse the
1669 // list linked via expression() temporarily so we can iterate over it from
1670 // the bottom up (reversing again as we go), to avoid excessive recursion.
1671 PropertyAccess* pndot = &expr->as<PropertyAccess>();
1672 ParseNode* pnup = nullptr;
1673 ParseNode* pndown;
1674 for (;;) {
1675 // Reverse pndot->expression() to point up, not down.
1676 pndown = &pndot->expression();
1677 pndot->setExpression(pnup);
1678 if (!pndown->is<PropertyAccess>() ||
1679 pndown->as<PropertyAccess>().isSuper()) {
1680 break;
1681 }
1682 pnup = pndot;
1683 pndot = &pndown->as<PropertyAccess>();
1684 }
1685
1686 // pndown is a primary expression, not a dotted property reference.
1687 if (!emitTree(pndown)) {
1688 return false;
1689 }
1690
1691 while (true) {
1692 // Walk back up the list, emitting annotated name ops.
1693 if (!emitAtomOp(JSOp::GetProp, pndot->key().atom())) {
1694 return false;
1695 }
1696
1697 // Reverse the pndot->expression() link again.
1698 pnup = pndot->maybeExpression();
1699 pndot->setExpression(pndown);
1700 pndown = pndot;
1701 if (!pnup) {
1702 break;
1703 }
1704 pndot = &pnup->as<PropertyAccess>();
1705 }
1706 return true;
1707}
1708
1709bool BytecodeEmitter::emitPropIncDec(UnaryNode* incDec, ValueUsage valueUsage) {
1710 PropertyAccess* prop = &incDec->kid()->as<PropertyAccess>();
1711 bool isSuper = prop->isSuper();
1712 ParseNodeKind kind = incDec->getKind();
1713 PropOpEmitter poe(
1714 this,
1715 kind == ParseNodeKind::PostIncrementExpr
1716 ? PropOpEmitter::Kind::PostIncrement
1717 : kind == ParseNodeKind::PreIncrementExpr
1718 ? PropOpEmitter::Kind::PreIncrement
1719 : kind == ParseNodeKind::PostDecrementExpr
1720 ? PropOpEmitter::Kind::PostDecrement
1721 : PropOpEmitter::Kind::PreDecrement,
1722 isSuper ? PropOpEmitter::ObjKind::Super : PropOpEmitter::ObjKind::Other);
1723 if (!poe.prepareForObj()) {
1724 return false;
1725 }
1726 if (isSuper) {
1727 UnaryNode* base = &prop->expression().as<UnaryNode>();
1728 if (!emitGetThisForSuperBase(base)) {
1729 // [stack] THIS
1730 return false;
1731 }
1732 } else {
1733 if (!emitPropLHS(prop)) {
1734 // [stack] OBJ
1735 return false;
1736 }
1737 }
1738 if (!poe.emitIncDec(prop->key().atom(), valueUsage)) {
1739 // [stack] RESULT
1740 return false;
1741 }
1742
1743 return true;
1744}
1745
1746bool BytecodeEmitter::emitNameIncDec(UnaryNode* incDec, ValueUsage valueUsage) {
1747 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"
, 1747); AnnotateMozCrashReason("MOZ_ASSERT" "(" "incDec->kid()->isKind(ParseNodeKind::Name)"
")"); do { *((volatile int*)__null) = 1747; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1748
1749 ParseNodeKind kind = incDec->getKind();
1750 NameNode* name = &incDec->kid()->as<NameNode>();
1751 NameOpEmitter noe(this, name->atom(),
1752 kind == ParseNodeKind::PostIncrementExpr
1753 ? NameOpEmitter::Kind::PostIncrement
1754 : kind == ParseNodeKind::PreIncrementExpr
1755 ? NameOpEmitter::Kind::PreIncrement
1756 : kind == ParseNodeKind::PostDecrementExpr
1757 ? NameOpEmitter::Kind::PostDecrement
1758 : NameOpEmitter::Kind::PreDecrement);
1759 if (!noe.emitIncDec(valueUsage)) {
1760 return false;
1761 }
1762
1763 return true;
1764}
1765
1766bool BytecodeEmitter::emitObjAndKey(ParseNode* exprOrSuper, ParseNode* key,
1767 ElemOpEmitter& eoe) {
1768 if (exprOrSuper->isKind(ParseNodeKind::SuperBase)) {
1769 if (!eoe.prepareForObj()) {
1770 // [stack]
1771 return false;
1772 }
1773 UnaryNode* base = &exprOrSuper->as<UnaryNode>();
1774 if (!emitGetThisForSuperBase(base)) {
1775 // [stack] THIS
1776 return false;
1777 }
1778 if (!eoe.prepareForKey()) {
1779 // [stack] THIS
1780 return false;
1781 }
1782 if (!emitTree(key)) {
1783 // [stack] THIS KEY
1784 return false;
1785 }
1786
1787 return true;
1788 }
1789
1790 if (!eoe.prepareForObj()) {
1791 // [stack]
1792 return false;
1793 }
1794 if (!emitTree(exprOrSuper)) {
1795 // [stack] OBJ
1796 return false;
1797 }
1798 if (!eoe.prepareForKey()) {
1799 // [stack] OBJ? OBJ
1800 return false;
1801 }
1802 if (!emitTree(key)) {
1803 // [stack] OBJ? OBJ KEY
1804 return false;
1805 }
1806
1807 return true;
1808}
1809
1810bool BytecodeEmitter::emitElemOpBase(JSOp op) {
1811 if (!emit1(op)) {
1812 return false;
1813 }
1814
1815 return true;
1816}
1817
1818bool BytecodeEmitter::emitElemObjAndKey(PropertyByValue* elem, bool isSuper,
1819 ElemOpEmitter& eoe) {
1820 MOZ_ASSERT(isSuper == elem->expression().isKind(ParseNodeKind::SuperBase))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(isSuper == elem->expression().isKind(ParseNodeKind
::SuperBase))>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(isSuper == elem->expression().
isKind(ParseNodeKind::SuperBase)))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("isSuper == elem->expression().isKind(ParseNodeKind::SuperBase)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 1820); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isSuper == elem->expression().isKind(ParseNodeKind::SuperBase)"
")"); do { *((volatile int*)__null) = 1820; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1821 return emitObjAndKey(&elem->expression(), &elem->key(), eoe);
1822}
1823
1824static ElemOpEmitter::Kind ConvertIncDecKind(ParseNodeKind kind) {
1825 switch (kind) {
1826 case ParseNodeKind::PostIncrementExpr:
1827 return ElemOpEmitter::Kind::PostIncrement;
1828 case ParseNodeKind::PreIncrementExpr:
1829 return ElemOpEmitter::Kind::PreIncrement;
1830 case ParseNodeKind::PostDecrementExpr:
1831 return ElemOpEmitter::Kind::PostDecrement;
1832 case ParseNodeKind::PreDecrementExpr:
1833 return ElemOpEmitter::Kind::PreDecrement;
1834 default:
1835 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"
, 1835); AnnotateMozCrashReason("MOZ_CRASH(" "unexpected inc/dec node kind"
")"); do { *((volatile int*)__null) = 1835; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
1836 }
1837}
1838
1839static PrivateOpEmitter::Kind PrivateConvertIncDecKind(ParseNodeKind kind) {
1840 switch (kind) {
1841 case ParseNodeKind::PostIncrementExpr:
1842 return PrivateOpEmitter::Kind::PostIncrement;
1843 case ParseNodeKind::PreIncrementExpr:
1844 return PrivateOpEmitter::Kind::PreIncrement;
1845 case ParseNodeKind::PostDecrementExpr:
1846 return PrivateOpEmitter::Kind::PostDecrement;
1847 case ParseNodeKind::PreDecrementExpr:
1848 return PrivateOpEmitter::Kind::PreDecrement;
1849 default:
1850 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"
, 1850); AnnotateMozCrashReason("MOZ_CRASH(" "unexpected inc/dec node kind"
")"); do { *((volatile int*)__null) = 1850; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
1851 }
1852}
1853
1854bool BytecodeEmitter::emitElemIncDec(UnaryNode* incDec, ValueUsage valueUsage) {
1855 PropertyByValue* elemExpr = &incDec->kid()->as<PropertyByValue>();
1856 bool isSuper = elemExpr->isSuper();
1857 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"
, 1857); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elemExpr->key().isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 1857; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1858 ParseNodeKind kind = incDec->getKind();
1859 ElemOpEmitter eoe(
1860 this, ConvertIncDecKind(kind),
1861 isSuper ? ElemOpEmitter::ObjKind::Super : ElemOpEmitter::ObjKind::Other);
1862 if (!emitElemObjAndKey(elemExpr, isSuper, eoe)) {
1863 // [stack] # if Super
1864 // [stack] THIS KEY
1865 // [stack] # otherwise
1866 // [stack] OBJ KEY
1867 return false;
1868 }
1869 if (!eoe.emitIncDec(valueUsage)) {
1870 // [stack] RESULT
1871 return false;
1872 }
1873
1874 return true;
1875}
1876
1877bool BytecodeEmitter::emitCallIncDec(UnaryNode* incDec) {
1878 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"
, 1881); AnnotateMozCrashReason("MOZ_ASSERT" "(" "incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind(ParseNodeKind::PostDecrementExpr)"
")"); do { *((volatile int*)__null) = 1881; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1879 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"
, 1881); AnnotateMozCrashReason("MOZ_ASSERT" "(" "incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind(ParseNodeKind::PostDecrementExpr)"
")"); do { *((volatile int*)__null) = 1881; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1880 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"
, 1881); AnnotateMozCrashReason("MOZ_ASSERT" "(" "incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind(ParseNodeKind::PostDecrementExpr)"
")"); do { *((volatile int*)__null) = 1881; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1881 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"
, 1881); AnnotateMozCrashReason("MOZ_ASSERT" "(" "incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind(ParseNodeKind::PostDecrementExpr)"
")"); do { *((volatile int*)__null) = 1881; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1882
1883 ParseNode* call = incDec->kid();
1884 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"
, 1884); AnnotateMozCrashReason("MOZ_ASSERT" "(" "call->isKind(ParseNodeKind::CallExpr)"
")"); do { *((volatile int*)__null) = 1884; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1885 if (!emitTree(call)) {
1886 // [stack] CALLRESULT
1887 return false;
1888 }
1889 if (!emit1(JSOp::ToNumeric)) {
1890 // [stack] N
1891 return false;
1892 }
1893
1894 // The increment/decrement has no side effects, so proceed to throw for
1895 // invalid assignment target.
1896 return emit2(JSOp::ThrowMsg, uint8_t(ThrowMsgKind::AssignToCall));
1897}
1898
1899bool BytecodeEmitter::emitPrivateIncDec(UnaryNode* incDec,
1900 ValueUsage valueUsage) {
1901 PrivateMemberAccess* privateExpr = &incDec->kid()->as<PrivateMemberAccess>();
1902 ParseNodeKind kind = incDec->getKind();
1903 PrivateOpEmitter xoe(this, PrivateConvertIncDecKind(kind),
1904 privateExpr->privateName().name());
1905 if (!emitTree(&privateExpr->expression())) {
1906 // [stack] OBJ
1907 return false;
1908 }
1909 if (!xoe.emitReference()) {
1910 // [stack] OBJ NAME
1911 return false;
1912 }
1913 if (!xoe.emitIncDec(valueUsage)) {
1914 // [stack] RESULT
1915 return false;
1916 }
1917
1918 return true;
1919}
1920
1921bool BytecodeEmitter::emitDouble(double d) {
1922 BytecodeOffset offset;
1923 if (!emitCheck(JSOp::Double, 9, &offset)) {
1924 return false;
1925 }
1926
1927 jsbytecode* code = bytecodeSection().code(offset);
1928 code[0] = jsbytecode(JSOp::Double);
1929 SET_INLINE_VALUE(code, DoubleValue(d));
1930 bytecodeSection().updateDepth(JSOp::Double, offset);
1931 return true;
1932}
1933
1934bool BytecodeEmitter::emitNumberOp(double dval) {
1935 int32_t ival;
1936 if (NumberIsInt32(dval, &ival)) {
1937 if (ival == 0) {
1938 return emit1(JSOp::Zero);
1939 }
1940 if (ival == 1) {
1941 return emit1(JSOp::One);
1942 }
1943 if ((int)(int8_t)ival == ival) {
1944 return emit2(JSOp::Int8, uint8_t(int8_t(ival)));
1945 }
1946
1947 uint32_t u = uint32_t(ival);
1948 if (u < Bit(16)) {
1949 if (!emitUint16Operand(JSOp::Uint16, u)) {
1950 return false;
1951 }
1952 } else if (u < Bit(24)) {
1953 BytecodeOffset off;
1954 if (!emitN(JSOp::Uint24, 3, &off)) {
1955 return false;
1956 }
1957 SET_UINT24(bytecodeSection().code(off), u);
1958 } else {
1959 BytecodeOffset off;
1960 if (!emitN(JSOp::Int32, 4, &off)) {
1961 return false;
1962 }
1963 SET_INT32(bytecodeSection().code(off), ival);
1964 }
1965 return true;
1966 }
1967
1968 return emitDouble(dval);
1969}
1970
1971/*
1972 * Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047.
1973 * LLVM is deciding to inline this function which uses a lot of stack space
1974 * into emitTree which is recursive and uses relatively little stack space.
1975 */
1976MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitSwitch(SwitchStatement* switchStmt) {
1977 LexicalScopeNode& lexical = switchStmt->lexicalForCaseList();
1978 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"
, 1978); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lexical.isKind(ParseNodeKind::LexicalScope)"
")"); do { *((volatile int*)__null) = 1978; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1979 ListNode* cases = &lexical.scopeBody()->as<ListNode>();
1980 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"
, 1980); AnnotateMozCrashReason("MOZ_ASSERT" "(" "cases->isKind(ParseNodeKind::StatementList)"
")"); do { *((volatile int*)__null) = 1980; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1981
1982 SwitchEmitter se(this);
1983 if (!se.emitDiscriminant(switchStmt->discriminant().pn_pos.begin)) {
1984 return false;
1985 }
1986
1987 if (!markStepBreakpoint()) {
1988 return false;
1989 }
1990 if (!emitTree(&switchStmt->discriminant())) {
1991 return false;
1992 }
1993
1994 // Enter the scope before pushing the switch BreakableControl since all
1995 // breaks are under this scope.
1996
1997 if (!lexical.isEmptyScope()) {
1998 if (!se.emitLexical(lexical.scopeBindings())) {
1999 return false;
2000 }
2001
2002 // A switch statement may contain hoisted functions inside its
2003 // cases. The hasTopLevelFunctionDeclarations flag is propagated from the
2004 // StatementList bodies of the cases to the case list.
2005 if (cases->hasTopLevelFunctionDeclarations()) {
2006 for (ParseNode* item : cases->contents()) {
2007 CaseClause* caseClause = &item->as<CaseClause>();
2008 ListNode* statements = caseClause->statementList();
2009 if (statements->hasTopLevelFunctionDeclarations()) {
2010 if (!emitHoistedFunctionsInList(statements)) {
2011 return false;
2012 }
2013 }
2014 }
2015 }
2016 } else {
2017 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"
, 2017); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!cases->hasTopLevelFunctionDeclarations()"
")"); do { *((volatile int*)__null) = 2017; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2018 }
2019
2020 SwitchEmitter::TableGenerator tableGen(this);
2021 uint32_t caseCount = cases->count() - (switchStmt->hasDefault() ? 1 : 0);
2022 if (caseCount == 0) {
2023 tableGen.finish(0);
2024 } else {
2025 for (ParseNode* item : cases->contents()) {
2026 CaseClause* caseClause = &item->as<CaseClause>();
2027 if (caseClause->isDefault()) {
2028 continue;
2029 }
2030
2031 ParseNode* caseValue = caseClause->caseExpression();
2032
2033 if (caseValue->getKind() != ParseNodeKind::NumberExpr) {
2034 tableGen.setInvalid();
2035 break;
2036 }
2037
2038 int32_t i;
2039 if (!NumberEqualsInt32(caseValue->as<NumericLiteral>().value(), &i)) {
2040 tableGen.setInvalid();
2041 break;
2042 }
2043
2044 if (!tableGen.addNumber(i)) {
2045 return false;
2046 }
2047 }
2048
2049 tableGen.finish(caseCount);
2050 }
2051
2052 if (!se.validateCaseCount(caseCount)) {
2053 return false;
2054 }
2055
2056 bool isTableSwitch = tableGen.isValid();
2057 if (isTableSwitch) {
2058 if (!se.emitTable(tableGen)) {
2059 return false;
2060 }
2061 } else {
2062 if (!se.emitCond()) {
2063 return false;
2064 }
2065
2066 // Emit code for evaluating cases and jumping to case statements.
2067 for (ParseNode* item : cases->contents()) {
2068 CaseClause* caseClause = &item->as<CaseClause>();
2069 if (caseClause->isDefault()) {
2070 continue;
2071 }
2072
2073 if (!se.prepareForCaseValue()) {
2074 return false;
2075 }
2076
2077 ParseNode* caseValue = caseClause->caseExpression();
2078 // If the expression is a literal, suppress line number emission so
2079 // that debugging works more naturally.
2080 if (!emitTree(
2081 caseValue, ValueUsage::WantValue,
2082 caseValue->isLiteral() ? SUPPRESS_LINENOTE : EMIT_LINENOTE)) {
2083 return false;
2084 }
2085
2086 if (!se.emitCaseJump()) {
2087 return false;
2088 }
2089 }
2090 }
2091
2092 // Emit code for each case's statements.
2093 for (ParseNode* item : cases->contents()) {
2094 CaseClause* caseClause = &item->as<CaseClause>();
2095 if (caseClause->isDefault()) {
2096 if (!se.emitDefaultBody()) {
2097 return false;
2098 }
2099 } else {
2100 if (isTableSwitch) {
2101 ParseNode* caseValue = caseClause->caseExpression();
2102 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"
, 2102); AnnotateMozCrashReason("MOZ_ASSERT" "(" "caseValue->isKind(ParseNodeKind::NumberExpr)"
")"); do { *((volatile int*)__null) = 2102; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2103
2104 NumericLiteral* literal = &caseValue->as<NumericLiteral>();
2105#ifdef DEBUG1
2106 // Use NumberEqualsInt32 here because switches compare using
2107 // strict equality, which will equate -0 and +0. In contrast
2108 // NumberIsInt32 would return false for -0.
2109 int32_t v;
2110 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"
, 2110); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mozilla::NumberEqualsInt32(literal->value(), &v)"
")"); do { *((volatile int*)__null) = 2110; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2111#endif
2112 int32_t i = int32_t(literal->value());
2113
2114 if (!se.emitCaseBody(i, tableGen)) {
2115 return false;
2116 }
2117 } else {
2118 if (!se.emitCaseBody()) {
2119 return false;
2120 }
2121 }
2122 }
2123
2124 if (!emitTree(caseClause->statementList())) {
2125 return false;
2126 }
2127 }
2128
2129 if (!se.emitEnd()) {
2130 return false;
2131 }
2132
2133 return true;
2134}
2135
2136bool BytecodeEmitter::allocateResumeIndex(BytecodeOffset offset,
2137 uint32_t* resumeIndex) {
2138 static constexpr uint32_t MaxResumeIndex = BitMask(24);
2139
2140 static_assert(
2141 MaxResumeIndex < uint32_t(AbstractGeneratorObject::RESUME_INDEX_RUNNING),
2142 "resumeIndex should not include magic AbstractGeneratorObject "
2143 "resumeIndex values");
2144 static_assert(
2145 MaxResumeIndex <= INT32_MAX(2147483647) / sizeof(uintptr_t),
2146 "resumeIndex * sizeof(uintptr_t) must fit in an int32. JIT code relies "
2147 "on this when loading resume entries from BaselineScript");
2148
2149 *resumeIndex = bytecodeSection().resumeOffsetList().length();
2150 if (*resumeIndex > MaxResumeIndex) {
2151 reportError(nullptr, JSMSG_TOO_MANY_RESUME_INDEXES);
2152 return false;
2153 }
2154
2155 return bytecodeSection().resumeOffsetList().append(offset.value());
2156}
2157
2158bool BytecodeEmitter::allocateResumeIndexRange(
2159 mozilla::Span<BytecodeOffset> offsets, uint32_t* firstResumeIndex) {
2160 *firstResumeIndex = 0;
2161
2162 for (size_t i = 0, len = offsets.size(); i < len; i++) {
2163 uint32_t resumeIndex;
2164 if (!allocateResumeIndex(offsets[i], &resumeIndex)) {
2165 return false;
2166 }
2167 if (i == 0) {
2168 *firstResumeIndex = resumeIndex;
2169 }
2170 }
2171
2172 return true;
2173}
2174
2175bool BytecodeEmitter::emitYieldOp(JSOp op) {
2176 // ParseContext::Scope::setOwnStackSlotCount should check the fixed slot
2177 // for the following, and it should prevent using fixed slot if there are
2178 // too many bindings:
2179 // * generator or asyn function
2180 // * module code after top-level await
2181 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"
, 2182); AnnotateMozCrashReason("MOZ_ASSERT" "(" "innermostEmitterScopeNoCheck()->frameSlotEnd() <= ParseContext::Scope::FixedSlotLimit"
")"); do { *((volatile int*)__null) = 2182; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2182 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"
, 2182); AnnotateMozCrashReason("MOZ_ASSERT" "(" "innermostEmitterScopeNoCheck()->frameSlotEnd() <= ParseContext::Scope::FixedSlotLimit"
")"); do { *((volatile int*)__null) = 2182; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2183
2184 if (op == JSOp::FinalYieldRval) {
2185 return emit1(JSOp::FinalYieldRval);
2186 }
2187
2188 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"
, 2189); AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::InitialYield || op == JSOp::Yield || op == JSOp::Await"
")"); do { *((volatile int*)__null) = 2189; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2189 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"
, 2189); AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::InitialYield || op == JSOp::Yield || op == JSOp::Await"
")"); do { *((volatile int*)__null) = 2189; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2190
2191 BytecodeOffset off;
2192 if (!emitN(op, 3, &off)) {
2193 return false;
2194 }
2195
2196 if (op == JSOp::InitialYield || op == JSOp::Yield) {
2197 bytecodeSection().addNumYields();
2198 }
2199
2200 uint32_t resumeIndex;
2201 if (!allocateResumeIndex(bytecodeSection().offset(), &resumeIndex)) {
2202 return false;
2203 }
2204
2205 SET_RESUMEINDEX(bytecodeSection().code(off), resumeIndex);
2206
2207 BytecodeOffset unusedOffset;
2208 return emitJumpTargetOp(JSOp::AfterYield, &unusedOffset);
2209}
2210
2211bool BytecodeEmitter::emitPushResumeKind(GeneratorResumeKind kind) {
2212 return emit2(JSOp::ResumeKind, uint8_t(kind));
2213}
2214
2215bool BytecodeEmitter::emitSetThis(BinaryNode* setThisNode) {
2216 // ParseNodeKind::SetThis is used to update |this| after a super() call
2217 // in a derived class constructor.
2218
2219 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"
, 2219); AnnotateMozCrashReason("MOZ_ASSERT" "(" "setThisNode->isKind(ParseNodeKind::SetThis)"
")"); do { *((volatile int*)__null) = 2219; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2220 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"
, 2220); AnnotateMozCrashReason("MOZ_ASSERT" "(" "setThisNode->left()->isKind(ParseNodeKind::Name)"
")"); do { *((volatile int*)__null) = 2220; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2221
2222 auto name = setThisNode->left()->as<NameNode>().name();
2223
2224 // The 'this' binding is not lexical, but due to super() semantics this
2225 // initialization needs to be treated as a lexical one.
2226 NameLocation loc = lookupName(name);
2227 NameLocation lexicalLoc;
2228 if (loc.kind() == NameLocation::Kind::FrameSlot) {
2229 lexicalLoc = NameLocation::FrameSlot(BindingKind::Let, loc.frameSlot());
2230 } else if (loc.kind() == NameLocation::Kind::EnvironmentCoordinate) {
2231 EnvironmentCoordinate coord = loc.environmentCoordinate();
2232 uint8_t hops = AssertedCast<uint8_t>(coord.hops());
2233 lexicalLoc = NameLocation::EnvironmentCoordinate(BindingKind::Let, hops,
2234 coord.slot());
2235 } else {
2236 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"
, 2236); AnnotateMozCrashReason("MOZ_ASSERT" "(" "loc.kind() == NameLocation::Kind::Dynamic"
")"); do { *((volatile int*)__null) = 2236; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2237 lexicalLoc = loc;
2238 }
2239
2240 NameOpEmitter noe(this, name, lexicalLoc, NameOpEmitter::Kind::Initialize);
2241 if (!noe.prepareForRhs()) {
2242 // [stack]
2243 return false;
2244 }
2245
2246 // Emit the new |this| value.
2247 if (!emitTree(setThisNode->right())) {
2248 // [stack] NEWTHIS
2249 return false;
2250 }
2251
2252 // Get the original |this| and throw if we already initialized
2253 // it. Do *not* use the NameLocation argument, as that's the special
2254 // lexical location below to deal with super() semantics.
2255 if (!emitGetName(name)) {
2256 // [stack] NEWTHIS THIS
2257 return false;
2258 }
2259 if (!emit1(JSOp::CheckThisReinit)) {
2260 // [stack] NEWTHIS THIS
2261 return false;
2262 }
2263 if (!emit1(JSOp::Pop)) {
2264 // [stack] NEWTHIS
2265 return false;
2266 }
2267 if (!noe.emitAssignment()) {
2268 // [stack] NEWTHIS
2269 return false;
2270 }
2271
2272 if (!emitInitializeInstanceMembers(true)) {
2273 return false;
2274 }
2275
2276 return true;
2277}
2278
2279bool BytecodeEmitter::defineHoistedTopLevelFunctions(ParseNode* body) {
2280 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"
, 2280); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inPrologue()"
")"); do { *((volatile int*)__null) = 2280; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2281 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"
, 2281); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isGlobalContext() || (sc->isEvalContext() && !sc->strict())"
")"); do { *((volatile int*)__null) = 2281; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2282 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"
, 2282); AnnotateMozCrashReason("MOZ_ASSERT" "(" "body->is<LexicalScopeNode>() || body->is<ListNode>()"
")"); do { *((volatile int*)__null) = 2282; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2283
2284 if (body->is<LexicalScopeNode>()) {
2285 body = body->as<LexicalScopeNode>().scopeBody();
2286 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"
, 2286); AnnotateMozCrashReason("MOZ_ASSERT" "(" "body->is<ListNode>()"
")"); do { *((volatile int*)__null) = 2286; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2287 }
2288
2289 if (!body->as<ListNode>().hasTopLevelFunctionDeclarations()) {
2290 return true;
2291 }
2292
2293 return emitHoistedFunctionsInList(&body->as<ListNode>());
2294}
2295
2296// For Global and sloppy-Eval scripts, this performs most of the steps of the
2297// spec's [GlobalDeclarationInstantiation] and [EvalDeclarationInstantiation]
2298// operations.
2299//
2300// Note that while strict-Eval is handled in the same part of the spec, it never
2301// fails for global-redeclaration checks so those scripts initialize directly in
2302// their bytecode.
2303bool BytecodeEmitter::emitDeclarationInstantiation(ParseNode* body) {
2304 if (sc->isModuleContext()) {
2305 // ES Modules have dedicated variable and lexial environments and therefore
2306 // do not have to perform redeclaration checks. We initialize their bindings
2307 // elsewhere in bytecode.
2308 return true;
2309 }
2310
2311 if (sc->isEvalContext() && sc->strict()) {
2312 // Strict Eval has a dedicated variables (and lexical) environment and
2313 // therefore does not have to perform redeclaration checks. We initialize
2314 // their bindings elsewhere in the bytecode.
2315 return true;
2316 }
2317
2318 // If we have no variables bindings, then we are done!
2319 if (sc->isGlobalContext()) {
2320 if (!sc->asGlobalContext()->bindings) {
2321 return true;
2322 }
2323 } else {
2324 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"
, 2324); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isEvalContext()"
")"); do { *((volatile int*)__null) = 2324; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2325
2326 if (!sc->asEvalContext()->bindings) {
2327 return true;
2328 }
2329 }
2330
2331#if DEBUG1
2332 // There should be no emitted functions yet.
2333 for (const auto& thing : perScriptData().gcThingList().objects()) {
2334 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"
, 2334); AnnotateMozCrashReason("MOZ_ASSERT" "(" "thing.isEmptyGlobalScope() || thing.isScope()"
")"); do { *((volatile int*)__null) = 2334; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2335 }
2336#endif
2337
2338 // Emit the hoisted functions to gc-things list. There is no bytecode
2339 // generated yet to bind them.
2340 if (!defineHoistedTopLevelFunctions(body)) {
2341 return false;
2342 }
2343
2344 // Save the last GCThingIndex emitted. The hoisted functions are contained in
2345 // the gc-things list up until this point. This set of gc-things also contain
2346 // initial scopes (of which there must be at least one).
2347 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"
, 2347); AnnotateMozCrashReason("MOZ_ASSERT" "(" "perScriptData().gcThingList().length() > 0"
")"); do { *((volatile int*)__null) = 2347; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2348 GCThingIndex lastFun =
2349 GCThingIndex(perScriptData().gcThingList().length() - 1);
2350
2351#if DEBUG1
2352 for (const auto& thing : perScriptData().gcThingList().objects()) {
2353 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"
, 2354); AnnotateMozCrashReason("MOZ_ASSERT" "(" "thing.isEmptyGlobalScope() || thing.isScope() || thing.isFunction()"
")"); do { *((volatile int*)__null) = 2354; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2354 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"
, 2354); AnnotateMozCrashReason("MOZ_ASSERT" "(" "thing.isEmptyGlobalScope() || thing.isScope() || thing.isFunction()"
")"); do { *((volatile int*)__null) = 2354; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2355 }
2356#endif
2357
2358 // Check for declaration conflicts and initialize the bindings.
2359 // NOTE: The self-hosting top-level script should not populate the builtins
2360 // directly on the GlobalObject (and instead uses JSOp::GetIntrinsic for
2361 // lookups).
2362 if (emitterMode == BytecodeEmitter::EmitterMode::Normal) {
2363 if (!emitGCIndexOp(JSOp::GlobalOrEvalDeclInstantiation, lastFun)) {
2364 return false;
2365 }
2366 }
2367
2368 return true;
2369}
2370
2371bool BytecodeEmitter::emitScript(ParseNode* body) {
2372 setScriptStartOffsetIfUnset(body->pn_pos.begin);
2373
2374 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"
, 2374); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inPrologue()"
")"); do { *((volatile int*)__null) = 2374; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2375
2376 TDZCheckCache tdzCache(this);
2377 EmitterScope emitterScope(this);
2378 Maybe<AsyncEmitter> topLevelAwait;
2379 if (sc->isGlobalContext()) {
2380 if (!emitterScope.enterGlobal(this, sc->asGlobalContext())) {
2381 return false;
2382 }
2383 } else if (sc->isEvalContext()) {
2384 if (!emitterScope.enterEval(this, sc->asEvalContext())) {
2385 return false;
2386 }
2387 } else {
2388 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"
, 2388); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isModuleContext()"
")"); do { *((volatile int*)__null) = 2388; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2389 if (!emitterScope.enterModule(this, sc->asModuleContext())) {
2390 return false;
2391 }
2392 if (sc->asModuleContext()->isAsync()) {
2393 topLevelAwait.emplace(this);
2394 }
2395 }
2396
2397 setFunctionBodyEndPos(body->pn_pos.end);
2398
2399 bool isSloppyEval = sc->isEvalContext() && !sc->strict();
2400 if (isSloppyEval && body->is<LexicalScopeNode>() &&
2401 !body->as<LexicalScopeNode>().isEmptyScope()) {
2402 // Sloppy eval scripts may emit hoisted functions bindings with a
2403 // `JSOp::GlobalOrEvalDeclInstantiation` opcode below. If this eval needs a
2404 // top-level lexical environment, we must ensure that environment is created
2405 // before those functions are created and bound.
2406 //
2407 // This differs from the global-script case below because the global-lexical
2408 // environment exists outside the script itself. In the case of strict eval
2409 // scripts, the `emitterScope` above is already sufficient.
2410 EmitterScope lexicalEmitterScope(this);
2411 LexicalScopeNode* scope = &body->as<LexicalScopeNode>();
2412
2413 if (!lexicalEmitterScope.enterLexical(this, ScopeKind::Lexical,
2414 scope->scopeBindings())) {
2415 return false;
2416 }
2417
2418 if (!emitDeclarationInstantiation(scope->scopeBody())) {
2419 return false;
2420 }
2421
2422 switchToMain();
2423
2424 ParseNode* scopeBody = scope->scopeBody();
2425 if (!emitLexicalScopeBody(scopeBody)) {
2426 return false;
2427 }
2428
2429 if (!updateSourceCoordNotes(scopeBody->pn_pos.end)) {
2430 return false;
2431 }
2432
2433 if (!lexicalEmitterScope.leave(this)) {
2434 return false;
2435 }
2436 } else {
2437 if (!emitDeclarationInstantiation(body)) {
2438 return false;
2439 }
2440 if (topLevelAwait) {
2441 if (!topLevelAwait->prepareForModule()) {
2442 return false;
2443 }
2444 }
2445
2446 switchToMain();
2447
2448#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
2449 if (!emitterScope.prepareForModuleDisposableScopeBody(this)) {
2450 return false;
2451 }
2452#endif
2453
2454 if (topLevelAwait) {
2455 if (!topLevelAwait->prepareForBody()) {
2456 return false;
2457 }
2458 }
2459
2460 if (!emitTree(body)) {
2461 // [stack]
2462 return false;
2463 }
2464
2465 if (!updateSourceCoordNotes(body->pn_pos.end)) {
2466 return false;
2467 }
2468 }
2469
2470 if (topLevelAwait) {
2471 if (!topLevelAwait->emitEndModule()) {
2472 return false;
2473 }
2474 }
2475
2476#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
2477 if (!emitterScope.emitModuleDisposableScopeBodyEnd(this)) {
2478 return false;
2479 }
2480#endif
2481
2482 if (!markSimpleBreakpoint()) {
2483 return false;
2484 }
2485
2486 if (!emitReturnRval()) {
2487 return false;
2488 }
2489
2490 if (!emitterScope.leave(this)) {
2491 return false;
2492 }
2493
2494 if (!NameFunctions(fc, parserAtoms(), body)) {
2495 return false;
2496 }
2497
2498 // Create a Stencil and convert it into a JSScript.
2499 return intoScriptStencil(CompilationStencil::TopLevelIndex);
2500}
2501
2502js::UniquePtr<ImmutableScriptData>
2503BytecodeEmitter::createImmutableScriptData() {
2504 uint32_t nslots;
2505 if (!getNslots(&nslots)) {
2506 return nullptr;
2507 }
2508
2509 bool isFunction = sc->isFunctionBox();
2510 uint16_t funLength = isFunction ? sc->asFunctionBox()->length() : 0;
2511
2512 mozilla::SaturateUint8 propertyCountEstimate = propertyAdditionEstimate;
2513
2514 // Add fields to the property count estimate.
2515 if (isFunction && sc->asFunctionBox()->useMemberInitializers()) {
2516 propertyCountEstimate +=
2517 sc->asFunctionBox()->memberInitializers().numMemberInitializers;
2518 }
2519
2520 return ImmutableScriptData::new_(
2521 fc, mainOffset(), maxFixedSlots, nslots, bodyScopeIndex,
2522 bytecodeSection().numICEntries(), isFunction, funLength,
2523 propertyCountEstimate.value(), bytecodeSection().code(),
2524 bytecodeSection().notes(), bytecodeSection().resumeOffsetList().span(),
2525 bytecodeSection().scopeNoteList().span(),
2526 bytecodeSection().tryNoteList().span());
2527}
2528
2529#if defined(ENABLE_DECORATORS) || defined(ENABLE_EXPLICIT_RESOURCE_MANAGEMENT)
2530bool BytecodeEmitter::emitCheckIsCallable() {
2531 // This emits code to check if the value at the top of the stack is
2532 // callable. The value is left on the stack.
2533 // [stack] VAL
2534 if (!emitAtomOp(JSOp::GetIntrinsic,
2535 TaggedParserAtomIndex::WellKnown::IsCallable())) {
2536 // [stack] VAL ISCALLABLE
2537 return false;
2538 }
2539 if (!emit1(JSOp::Undefined)) {
2540 // [stack] VAL ISCALLABLE UNDEFINED
2541 return false;
2542 }
2543 if (!emitDupAt(2)) {
2544 // [stack] VAL ISCALLABLE UNDEFINED VAL
2545 return false;
2546 }
2547 return emitCall(JSOp::Call, 1);
2548 // [stack] VAL ISCALLABLE_RESULT
2549}
2550#endif
2551
2552bool BytecodeEmitter::getNslots(uint32_t* nslots) {
2553 uint64_t nslots64 =
2554 maxFixedSlots + static_cast<uint64_t>(bytecodeSection().maxStackDepth());
2555 if (nslots64 > UINT32_MAX(4294967295U)) {
2556 reportError(nullptr, JSMSG_NEED_DIET, "script");
2557 return false;
2558 }
2559 *nslots = nslots64;
2560 return true;
2561}
2562
2563bool BytecodeEmitter::emitFunctionScript(FunctionNode* funNode) {
2564 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"
, 2564); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inPrologue()"
")"); do { *((volatile int*)__null) = 2564; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2565 ParamsBodyNode* paramsBody = funNode->body();
2566 FunctionBox* funbox = sc->asFunctionBox();
2567
2568 setScriptStartOffsetIfUnset(paramsBody->pn_pos.begin);
2569
2570 // [stack]
2571
2572 FunctionScriptEmitter fse(this, funbox, Some(paramsBody->pn_pos.begin),
2573 Some(paramsBody->pn_pos.end));
2574 if (!fse.prepareForParameters()) {
2575 // [stack]
2576 return false;
2577 }
2578
2579 if (!emitFunctionFormalParameters(paramsBody)) {
2580 // [stack]
2581 return false;
2582 }
2583
2584 if (!fse.prepareForBody()) {
2585 // [stack]
2586 return false;
2587 }
2588
2589 if (!emitTree(paramsBody->body())) {
2590 // [stack]
2591 return false;
2592 }
2593
2594 if (!fse.emitEndBody()) {
2595 // [stack]
2596 return false;
2597 }
2598
2599 if (funbox->index() == CompilationStencil::TopLevelIndex) {
2600 if (!NameFunctions(fc, parserAtoms(), funNode)) {
2601 return false;
2602 }
2603 }
2604
2605 return fse.intoStencil();
2606}
2607
2608bool BytecodeEmitter::emitDestructuringLHSRef(ParseNode* target,
2609 size_t* emitted) {
2610#ifdef DEBUG1
2611 int depth = bytecodeSection().stackDepth();
2612#endif
2613
2614 switch (target->getKind()) {
2615 case ParseNodeKind::Name:
2616 case ParseNodeKind::ArrayExpr:
2617 case ParseNodeKind::ObjectExpr:
2618 // No need to recurse into ParseNodeKind::Array and ParseNodeKind::Object
2619 // subpatterns here, since emitSetOrInitializeDestructuring does the
2620 // recursion when setting or initializing the value. Getting reference
2621 // doesn't recurse.
2622 *emitted = 0;
2623 break;
2624
2625 case ParseNodeKind::ArgumentsLength:
2626 case ParseNodeKind::DotExpr: {
2627 PropertyAccess* prop = &target->as<PropertyAccess>();
2628 bool isSuper = prop->isSuper();
2629 PropOpEmitter poe(this, PropOpEmitter::Kind::SimpleAssignment,
2630 isSuper ? PropOpEmitter::ObjKind::Super
2631 : PropOpEmitter::ObjKind::Other);
2632 if (!poe.prepareForObj()) {
2633 return false;
2634 }
2635 if (isSuper) {
2636 UnaryNode* base = &prop->expression().as<UnaryNode>();
2637 if (!emitGetThisForSuperBase(base)) {
2638 // [stack] THIS SUPERBASE
2639 return false;
2640 }
2641 } else {
2642 if (!emitTree(&prop->expression())) {
2643 // [stack] OBJ
2644 return false;
2645 }
2646 }
2647 if (!poe.prepareForRhs()) {
2648 // [stack] # if Super
2649 // [stack] THIS SUPERBASE
2650 // [stack] # otherwise
2651 // [stack] OBJ
2652 return false;
2653 }
2654
2655 // SUPERBASE was pushed onto THIS in poe.prepareForRhs above.
2656 *emitted = 1 + isSuper;
2657 break;
2658 }
2659
2660 case ParseNodeKind::ElemExpr: {
2661 PropertyByValue* elem = &target->as<PropertyByValue>();
2662 bool isSuper = elem->isSuper();
2663 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"
, 2663); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 2663; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2664 ElemOpEmitter eoe(this, ElemOpEmitter::Kind::SimpleAssignment,
2665 isSuper ? ElemOpEmitter::ObjKind::Super
2666 : ElemOpEmitter::ObjKind::Other);
2667 if (!emitElemObjAndKey(elem, isSuper, eoe)) {
2668 // [stack] # if Super
2669 // [stack] THIS KEY
2670 // [stack] # otherwise
2671 // [stack] OBJ KEY
2672 return false;
2673 }
2674 if (!eoe.prepareForRhs()) {
2675 // [stack] # if Super
2676 // [stack] THIS KEY SUPERBASE
2677 // [stack] # otherwise
2678 // [stack] OBJ KEY
2679 return false;
2680 }
2681
2682 // SUPERBASE was pushed onto KEY in eoe.prepareForRhs above.
2683 *emitted = 2 + isSuper;
2684 break;
2685 }
2686
2687 case ParseNodeKind::PrivateMemberExpr: {
2688 PrivateMemberAccess* privateExpr = &target->as<PrivateMemberAccess>();
2689 PrivateOpEmitter xoe(this, PrivateOpEmitter::Kind::SimpleAssignment,
2690 privateExpr->privateName().name());
2691 if (!emitTree(&privateExpr->expression())) {
2692 // [stack] OBJ
2693 return false;
2694 }
2695 if (!xoe.emitReference()) {
2696 // [stack] OBJ NAME
2697 return false;
2698 }
2699 *emitted = xoe.numReferenceSlots();
2700 break;
2701 }
2702
2703 case ParseNodeKind::CallExpr:
2704 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"
, 2707); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget "
"rejects function calls as assignment " "targets in destructuring assignments"
")"); do { *((volatile int*)__null) = 2707; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2705 "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"
, 2707); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget "
"rejects function calls as assignment " "targets in destructuring assignments"
")"); do { *((volatile int*)__null) = 2707; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2706 "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"
, 2707); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget "
"rejects function calls as assignment " "targets in destructuring assignments"
")"); do { *((volatile int*)__null) = 2707; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2707 "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"
, 2707); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget "
"rejects function calls as assignment " "targets in destructuring assignments"
")"); do { *((volatile int*)__null) = 2707; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2708 break;
2709
2710 default:
2711 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"
, 2711); AnnotateMozCrashReason("MOZ_CRASH(" "emitDestructuringLHSRef: bad lhs kind"
")"); do { *((volatile int*)__null) = 2711; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
2712 }
2713
2714 MOZ_ASSERT(bytecodeSection().stackDepth() == depth + int(*emitted))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bytecodeSection().stackDepth() == depth + int(*emitted
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(bytecodeSection().stackDepth() == depth + int(*emitted
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("bytecodeSection().stackDepth() == depth + int(*emitted)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 2714); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == depth + int(*emitted)"
")"); do { *((volatile int*)__null) = 2714; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2715
2716 return true;
2717}
2718
2719bool BytecodeEmitter::emitSetOrInitializeDestructuring(
2720 ParseNode* target, DestructuringFlavor flav) {
2721 // Now emit the lvalue opcode sequence. If the lvalue is a nested
2722 // destructuring initialiser-form, call ourselves to handle it, then pop
2723 // the matched value. Otherwise emit an lvalue bytecode sequence followed
2724 // by an assignment op.
2725
2726 switch (target->getKind()) {
2727 case ParseNodeKind::ArrayExpr:
2728 case ParseNodeKind::ObjectExpr:
2729 if (!emitDestructuringOps(&target->as<ListNode>(), flav)) {
2730 return false;
2731 }
2732 // emitDestructuringOps leaves the assigned (to-be-destructured) value on
2733 // top of the stack.
2734 break;
2735
2736 case ParseNodeKind::Name: {
2737 auto name = target->as<NameNode>().name();
2738 NameLocation loc = lookupName(name);
2739 NameOpEmitter::Kind kind;
2740 switch (flav) {
2741 case DestructuringFlavor::Declaration:
2742 kind = NameOpEmitter::Kind::Initialize;
2743 break;
2744
2745 case DestructuringFlavor::Assignment:
2746 kind = NameOpEmitter::Kind::SimpleAssignment;
2747 break;
2748 }
2749
2750 NameOpEmitter noe(this, name, loc, kind);
2751 if (!noe.prepareForRhs()) {
2752 // [stack] V ENV?
2753 return false;
2754 }
2755 if (noe.emittedBindOp()) {
2756 // This is like ordinary assignment, but with one difference.
2757 //
2758 // In `a = b`, we first determine a binding for `a` (using
2759 // JSOp::BindName or JSOp::BindGName), then we evaluate `b`, then
2760 // a JSOp::SetName instruction.
2761 //
2762 // In `[a] = [b]`, per spec, `b` is evaluated first, then we
2763 // determine a binding for `a`. Then we need to do assignment--
2764 // but the operands are on the stack in the wrong order for
2765 // JSOp::SetProp, so we have to add a JSOp::Swap.
2766 //
2767 // In the cases where we are emitting a name op, emit a swap
2768 // because of this.
2769 if (!emit1(JSOp::Swap)) {
2770 // [stack] ENV V
2771 return false;
2772 }
2773 } else {
2774 // In cases of emitting a frame slot or environment slot,
2775 // nothing needs be done.
2776 }
2777 if (!noe.emitAssignment()) {
2778 // [stack] V
2779 return false;
2780 }
2781
2782 break;
2783 }
2784
2785 case ParseNodeKind::ArgumentsLength:
2786 case ParseNodeKind::DotExpr: {
2787 // The reference is already pushed by emitDestructuringLHSRef.
2788 // [stack] # if Super
2789 // [stack] THIS SUPERBASE VAL
2790 // [stack] # otherwise
2791 // [stack] OBJ VAL
2792 PropertyAccess* prop = &target->as<PropertyAccess>();
2793 bool isSuper = prop->isSuper();
2794 PropOpEmitter poe(this, PropOpEmitter::Kind::SimpleAssignment,
2795 isSuper ? PropOpEmitter::ObjKind::Super
2796 : PropOpEmitter::ObjKind::Other);
2797 if (!poe.skipObjAndRhs()) {
2798 return false;
2799 }
2800 // [stack] # VAL
2801 if (!poe.emitAssignment(prop->key().atom())) {
2802 return false;
2803 }
2804 break;
2805 }
2806
2807 case ParseNodeKind::ElemExpr: {
2808 // The reference is already pushed by emitDestructuringLHSRef.
2809 // [stack] # if Super
2810 // [stack] THIS KEY SUPERBASE VAL
2811 // [stack] # otherwise
2812 // [stack] OBJ KEY VAL
2813 PropertyByValue* elem = &target->as<PropertyByValue>();
2814 bool isSuper = elem->isSuper();
2815 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"
, 2815); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 2815; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2816 ElemOpEmitter eoe(this, ElemOpEmitter::Kind::SimpleAssignment,
2817 isSuper ? ElemOpEmitter::ObjKind::Super
2818 : ElemOpEmitter::ObjKind::Other);
2819 if (!eoe.skipObjAndKeyAndRhs()) {
2820 return false;
2821 }
2822 if (!eoe.emitAssignment()) {
2823 // [stack] VAL
2824 return false;
2825 }
2826 break;
2827 }
2828
2829 case ParseNodeKind::PrivateMemberExpr: {
2830 // The reference is already pushed by emitDestructuringLHSRef.
2831 // [stack] OBJ NAME VAL
2832 PrivateMemberAccess* privateExpr = &target->as<PrivateMemberAccess>();
2833 PrivateOpEmitter xoe(this, PrivateOpEmitter::Kind::SimpleAssignment,
2834 privateExpr->privateName().name());
2835 if (!xoe.skipReference()) {
2836 return false;
2837 }
2838 if (!xoe.emitAssignment()) {
2839 // [stack] VAL
2840 return false;
2841 }
2842 break;
2843 }
2844
2845 case ParseNodeKind::CallExpr:
2846 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"
, 2849); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget "
"rejects function calls as assignment " "targets in destructuring assignments"
")"); do { *((volatile int*)__null) = 2849; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2847 "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"
, 2849); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget "
"rejects function calls as assignment " "targets in destructuring assignments"
")"); do { *((volatile int*)__null) = 2849; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2848 "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"
, 2849); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget "
"rejects function calls as assignment " "targets in destructuring assignments"
")"); do { *((volatile int*)__null) = 2849; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2849 "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"
, 2849); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget "
"rejects function calls as assignment " "targets in destructuring assignments"
")"); do { *((volatile int*)__null) = 2849; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2850 break;
2851
2852 default:
2853 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"
, 2853); AnnotateMozCrashReason("MOZ_CRASH(" "emitSetOrInitializeDestructuring: bad lhs kind"
")"); do { *((volatile int*)__null) = 2853; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
2854 }
2855
2856 // Pop the assigned value.
2857 if (!emit1(JSOp::Pop)) {
2858 // [stack] # empty
2859 return false;
2860 }
2861
2862 return true;
2863}
2864
2865JSOp BytecodeEmitter::getIterCallOp(JSOp callOp,
2866 SelfHostedIter selfHostedIter) {
2867 if (emitterMode == BytecodeEmitter::SelfHosting) {
2868 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"
, 2868); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny"
")"); do { *((volatile int*)__null) = 2868; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2869
2870 switch (callOp) {
2871 case JSOp::Call:
2872 return JSOp::CallContent;
2873 case JSOp::CallIter:
2874 return JSOp::CallContentIter;
2875 default:
2876 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"
, 2876); AnnotateMozCrashReason("MOZ_CRASH(" "Unknown iterator call op"
")"); do { *((volatile int*)__null) = 2876; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
2877 }
2878 }
2879
2880 return callOp;
2881}
2882
2883bool BytecodeEmitter::emitIteratorNext(
2884 const Maybe<uint32_t>& callSourceCoordOffset,
2885 IteratorKind iterKind /* = IteratorKind::Sync */,
2886 SelfHostedIter selfHostedIter /* = SelfHostedIter::Deny */) {
2887 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"
, 2890); 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) = 2890; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
2888 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"
, 2890); 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) = 2890; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
2889 ".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"
, 2890); 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) = 2890; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
2890 "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"
, 2890); 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) = 2890; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
2891
2892 // [stack] ... NEXT ITER
2893 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"
, 2893); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() >= 2"
")"); do { *((volatile int*)__null) = 2893; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2894
2895 if (!emitCall(getIterCallOp(JSOp::Call, selfHostedIter), 0,
2896 callSourceCoordOffset)) {
2897 // [stack] ... RESULT
2898 return false;
2899 }
2900
2901 if (iterKind == IteratorKind::Async) {
2902 if (!emitAwaitInInnermostScope()) {
2903 // [stack] ... RESULT
2904 return false;
2905 }
2906 }
2907
2908 if (!emitCheckIsObj(CheckIsObjectKind::IteratorNext)) {
2909 // [stack] ... RESULT
2910 return false;
2911 }
2912 return true;
2913}
2914
2915bool BytecodeEmitter::emitIteratorCloseInScope(
2916 EmitterScope& currentScope,
2917 IteratorKind iterKind /* = IteratorKind::Sync */,
2918 CompletionKind completionKind /* = CompletionKind::Normal */,
2919 SelfHostedIter selfHostedIter /* = SelfHostedIter::Deny */) {
2920 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"
, 2923); 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) = 2923; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
2921 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"
, 2923); 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) = 2923; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
2922 ".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"
, 2923); 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) = 2923; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
2923 "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"
, 2923); 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) = 2923; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
2924
2925 if (iterKind == IteratorKind::Sync) {
2926 return emit2(JSOp::CloseIter, uint8_t(completionKind));
2927 }
2928
2929 // Generate inline logic corresponding to IteratorClose (ES2021 7.4.6) and
2930 // AsyncIteratorClose (ES2021 7.4.7). Steps numbers apply to both operations.
2931 //
2932 // Callers need to ensure that the iterator object is at the top of the
2933 // stack.
2934
2935 // For non-Throw completions, we emit the equivalent of:
2936 //
2937 // var returnMethod = GetMethod(iterator, "return");
2938 // if (returnMethod !== undefined) {
2939 // var innerResult = [Await] Call(returnMethod, iterator);
2940 // CheckIsObj(innerResult);
2941 // }
2942 //
2943 // Whereas for Throw completions, we emit:
2944 //
2945 // try {
2946 // var returnMethod = GetMethod(iterator, "return");
2947 // if (returnMethod !== undefined) {
2948 // [Await] Call(returnMethod, iterator);
2949 // }
2950 // } catch {}
2951
2952 Maybe<TryEmitter> tryCatch;
2953
2954 if (completionKind == CompletionKind::Throw) {
2955 tryCatch.emplace(this, TryEmitter::Kind::TryCatch,
2956 TryEmitter::ControlKind::NonSyntactic);
2957
2958 if (!tryCatch->emitTry()) {
2959 // [stack] ... ITER
2960 return false;
2961 }
2962 }
2963
2964 if (!emit1(JSOp::Dup)) {
2965 // [stack] ... ITER ITER
2966 return false;
2967 }
2968
2969 // Steps 1-2 are assertions, step 3 is implicit.
2970
2971 // Step 4.
2972 //
2973 // Get the "return" method.
2974 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::return_())) {
2975 // [stack] ... ITER RET
2976 return false;
2977 }
2978
2979 // Step 5.
2980 //
2981 // Do nothing if "return" is undefined or null.
2982 InternalIfEmitter ifReturnMethodIsDefined(this);
2983 if (!emit1(JSOp::IsNullOrUndefined)) {
2984 // [stack] ... ITER RET NULL-OR-UNDEF
2985 return false;
2986 }
2987
2988 if (!ifReturnMethodIsDefined.emitThenElse(
2989 IfEmitter::ConditionKind::Negative)) {
2990 // [stack] ... ITER RET
2991 return false;
2992 }
2993
2994 // Steps 5.c, 7.
2995 //
2996 // Call the "return" method.
2997 if (!emit1(JSOp::Swap)) {
2998 // [stack] ... RET ITER
2999 return false;
3000 }
3001
3002 if (!emitCall(getIterCallOp(JSOp::Call, selfHostedIter), 0)) {
3003 // [stack] ... RESULT
3004 return false;
3005 }
3006
3007 // 7.4.7 AsyncIteratorClose, step 5.d.
3008 if (iterKind == IteratorKind::Async) {
3009 if (completionKind != CompletionKind::Throw) {
3010 // Await clobbers rval, so save the current rval.
3011 if (!emit1(JSOp::GetRval)) {
3012 // [stack] ... RESULT RVAL
3013 return false;
3014 }
3015 if (!emit1(JSOp::Swap)) {
3016 // [stack] ... RVAL RESULT
3017 return false;
3018 }
3019 }
3020
3021 if (!emitAwaitInScope(currentScope)) {
3022 // [stack] ... RVAL? RESULT
3023 return false;
3024 }
3025
3026 if (completionKind != CompletionKind::Throw) {
3027 if (!emit1(JSOp::Swap)) {
3028 // [stack] ... RESULT RVAL
3029 return false;
3030 }
3031 if (!emit1(JSOp::SetRval)) {
3032 // [stack] ... RESULT
3033 return false;
3034 }
3035 }
3036 }
3037
3038 // Step 6 (Handled in caller).
3039
3040 // Step 8.
3041 if (completionKind != CompletionKind::Throw) {
3042 // Check that the "return" result is an object.
3043 if (!emitCheckIsObj(CheckIsObjectKind::IteratorReturn)) {
3044 // [stack] ... RESULT
3045 return false;
3046 }
3047 }
3048
3049 if (!ifReturnMethodIsDefined.emitElse()) {
3050 // [stack] ... ITER RET
3051 return false;
3052 }
3053
3054 if (!emit1(JSOp::Pop)) {
3055 // [stack] ... ITER
3056 return false;
3057 }
3058
3059 if (!ifReturnMethodIsDefined.emitEnd()) {
3060 return false;
3061 }
3062
3063 if (completionKind == CompletionKind::Throw) {
3064 if (!tryCatch->emitCatch()) {
3065 // [stack] ... ITER EXC
3066 return false;
3067 }
3068
3069 // Just ignore the exception thrown by call and await.
3070 if (!emit1(JSOp::Pop)) {
3071 // [stack] ... ITER
3072 return false;
3073 }
3074
3075 if (!tryCatch->emitEnd()) {
3076 // [stack] ... ITER
3077 return false;
3078 }
3079 }
3080
3081 // Step 9 (Handled in caller).
3082
3083 return emit1(JSOp::Pop);
3084 // [stack] ...
3085}
3086
3087template <typename InnerEmitter>
3088bool BytecodeEmitter::wrapWithDestructuringTryNote(int32_t iterDepth,
3089 InnerEmitter emitter) {
3090 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"
, 3090); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() >= iterDepth"
")"); do { *((volatile int*)__null) = 3090; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3091
3092 // Pad a nop at the beginning of the bytecode covered by the trynote so
3093 // that when unwinding environments, we may unwind to the scope
3094 // corresponding to the pc *before* the start, in case the first bytecode
3095 // emitted by |emitter| is the start of an inner scope. See comment above
3096 // UnwindEnvironmentToTryPc.
3097 if (!emit1(JSOp::TryDestructuring)) {
3098 return false;
3099 }
3100
3101 BytecodeOffset start = bytecodeSection().offset();
3102 if (!emitter(this)) {
3103 return false;
3104 }
3105 BytecodeOffset end = bytecodeSection().offset();
3106 if (start != end) {
3107 return addTryNote(TryNoteKind::Destructuring, iterDepth, start, end);
3108 }
3109 return true;
3110}
3111
3112bool BytecodeEmitter::emitDefault(ParseNode* defaultExpr, ParseNode* pattern) {
3113 // [stack] VALUE
3114
3115 DefaultEmitter de(this);
3116 if (!de.prepareForDefault()) {
3117 // [stack]
3118 return false;
3119 }
3120 if (!emitInitializer(defaultExpr, pattern)) {
3121 // [stack] DEFAULTVALUE
3122 return false;
3123 }
3124 if (!de.emitEnd()) {
3125 // [stack] VALUE/DEFAULTVALUE
3126 return false;
3127 }
3128 return true;
3129}
3130
3131bool BytecodeEmitter::emitAnonymousFunctionWithName(
3132 ParseNode* node, TaggedParserAtomIndex name) {
3133 MOZ_ASSERT(node->isDirectRHSAnonFunction())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(node->isDirectRHSAnonFunction())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(node->isDirectRHSAnonFunction
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("node->isDirectRHSAnonFunction()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 3133); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isDirectRHSAnonFunction()"
")"); do { *((volatile int*)__null) = 3133; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3134
3135 if (node->is<FunctionNode>()) {
3136 // Function doesn't have 'name' property at this point.
3137 // Set function's name at compile time.
3138 if (!setFunName(node->as<FunctionNode>().funbox(), name)) {
3139 return false;
3140 }
3141
3142 return emitTree(node);
3143 }
3144
3145 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"
, 3145); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->is<ClassNode>()"
")"); do { *((volatile int*)__null) = 3145; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3146
3147 return emitClass(&node->as<ClassNode>(), ClassNameKind::InferredName, name);
3148}
3149
3150bool BytecodeEmitter::emitAnonymousFunctionWithComputedName(
3151 ParseNode* node, FunctionPrefixKind prefixKind) {
3152 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"
, 3152); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isDirectRHSAnonFunction()"
")"); do { *((volatile int*)__null) = 3152; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3153
3154 if (node->is<FunctionNode>()) {
3155 if (!emitTree(node)) {
3156 // [stack] NAME FUN
3157 return false;
3158 }
3159 if (!emitDupAt(1)) {
3160 // [stack] NAME FUN NAME
3161 return false;
3162 }
3163 if (!emit2(JSOp::SetFunName, uint8_t(prefixKind))) {
3164 // [stack] NAME FUN
3165 return false;
3166 }
3167 return true;
3168 }
3169
3170 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"
, 3170); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->is<ClassNode>()"
")"); do { *((volatile int*)__null) = 3170; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3171 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"
, 3171); AnnotateMozCrashReason("MOZ_ASSERT" "(" "prefixKind == FunctionPrefixKind::None"
")"); do { *((volatile int*)__null) = 3171; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3172
3173 return emitClass(&node->as<ClassNode>(), ClassNameKind::ComputedName);
3174}
3175
3176bool BytecodeEmitter::setFunName(FunctionBox* funbox,
3177 TaggedParserAtomIndex name) {
3178 // The inferred name may already be set if this function is an interpreted
3179 // lazy function and we OOM'ed after we set the inferred name the first
3180 // time.
3181 if (funbox->hasInferredName()) {
3182 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"
, 3182); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!funbox->emitBytecode"
")"); do { *((volatile int*)__null) = 3182; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3183 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"
, 3183); AnnotateMozCrashReason("MOZ_ASSERT" "(" "funbox->displayAtom() == name"
")"); do { *((volatile int*)__null) = 3183; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3184
3185 return true;
3186 }
3187
3188 funbox->setInferredName(name);
3189 return true;
3190}
3191
3192bool BytecodeEmitter::emitInitializer(ParseNode* initializer,
3193 ParseNode* pattern) {
3194 if (initializer->isDirectRHSAnonFunction()) {
3195 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"
, 3195); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!pattern->isInParens()"
")"); do { *((volatile int*)__null) = 3195; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3196 auto name = pattern->as<NameNode>().name();
3197 if (!emitAnonymousFunctionWithName(initializer, name)) {
3198 return false;
3199 }
3200 } else {
3201 if (!emitTree(initializer)) {
3202 return false;
3203 }
3204 }
3205
3206 return true;
3207}
3208
3209bool BytecodeEmitter::emitDestructuringOpsArray(ListNode* pattern,
3210 DestructuringFlavor flav) {
3211 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"
, 3213); 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) = 3213; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
3212 "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"
, 3213); 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) = 3213; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
3213 "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"
, 3213); 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) = 3213; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
3214 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"
, 3214); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pattern->isKind(ParseNodeKind::ArrayExpr)"
")"); do { *((volatile int*)__null) = 3214; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3215 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"
, 3215); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() != 0"
")"); do { *((volatile int*)__null) = 3215; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3216
3217 // Here's pseudo code for |let [a, b, , c=y, ...d] = x;|
3218 //
3219 // Lines that are annotated "covered by trynote" mean that upon throwing
3220 // an exception, IteratorClose is called on iter only if done is false.
3221 //
3222 // let x, y;
3223 // let a, b, c, d;
3224 // let iter, next, lref, result, done, value; // stack values
3225 //
3226 // // NOTE: the fast path for this example is not applicable, because of
3227 // // the spread and the assignment |c=y|, but it is documented here for a
3228 // // simpler example, |let [a,b] = x;|
3229 // //
3230 // // if (IsOptimizableArray(x)) {
3231 // // a = x[0];
3232 // // b = x[1];
3233 // // goto end: // (skip everything below)
3234 // // }
3235 //
3236 // iter = x[Symbol.iterator]();
3237 // next = iter.next;
3238 //
3239 // // ==== emitted by loop for a ====
3240 // lref = GetReference(a); // covered by trynote
3241 //
3242 // result = Call(next, iter);
3243 // done = result.done;
3244 //
3245 // if (done)
3246 // value = undefined;
3247 // else
3248 // value = result.value;
3249 //
3250 // SetOrInitialize(lref, value); // covered by trynote
3251 //
3252 // // ==== emitted by loop for b ====
3253 // lref = GetReference(b); // covered by trynote
3254 //
3255 // if (done) {
3256 // value = undefined;
3257 // } else {
3258 // result = Call(next, iter);
3259 // done = result.done;
3260 // if (done)
3261 // value = undefined;
3262 // else
3263 // value = result.value;
3264 // }
3265 //
3266 // SetOrInitialize(lref, value); // covered by trynote
3267 //
3268 // // ==== emitted by loop for elision ====
3269 // if (done) {
3270 // value = undefined;
3271 // } else {
3272 // result = Call(next, iter);
3273 // done = result.done;
3274 // if (done)
3275 // value = undefined;
3276 // else
3277 // value = result.value;
3278 // }
3279 //
3280 // // ==== emitted by loop for c ====
3281 // lref = GetReference(c); // covered by trynote
3282 //
3283 // if (done) {
3284 // value = undefined;
3285 // } else {
3286 // result = Call(next, iter);
3287 // done = result.done;
3288 // if (done)
3289 // value = undefined;
3290 // else
3291 // value = result.value;
3292 // }
3293 //
3294 // if (value === undefined)
3295 // value = y; // covered by trynote
3296 //
3297 // SetOrInitialize(lref, value); // covered by trynote
3298 //
3299 // // ==== emitted by loop for d ====
3300 // lref = GetReference(d); // covered by trynote
3301 //
3302 // if (done)
3303 // value = [];
3304 // else
3305 // value = [...iter];
3306 //
3307 // SetOrInitialize(lref, value); // covered by trynote
3308 //
3309 // // === emitted after loop ===
3310 // if (!done)
3311 // IteratorClose(iter);
3312 //
3313 // end:
3314
3315 bool isEligibleForArrayOptimizations = true;
3316 for (ParseNode* member : pattern->contents()) {
3317 switch (member->getKind()) {
3318 case ParseNodeKind::Elision:
3319 break;
3320 case ParseNodeKind::Name: {
3321 auto name = member->as<NameNode>().name();
3322 NameLocation loc = lookupName(name);
3323 if (loc.kind() != NameLocation::Kind::ArgumentSlot &&
3324 loc.kind() != NameLocation::Kind::FrameSlot &&
3325 loc.kind() != NameLocation::Kind::EnvironmentCoordinate) {
3326 isEligibleForArrayOptimizations = false;
3327 }
3328 break;
3329 }
3330 default:
3331 // Unfortunately we can't handle any recursive destructuring,
3332 // because we can't guarantee that the recursed-into parts
3333 // won't run code which invalidates our constraints. We also
3334 // cannot handle ParseNodeKind::AssignExpr for similar reasons.
3335 isEligibleForArrayOptimizations = false;
3336 break;
3337 }
3338 if (!isEligibleForArrayOptimizations) {
3339 break;
3340 }
3341 }
3342
3343 // Use an iterator to destructure the RHS, instead of index lookup. We
3344 // must leave the *original* value on the stack.
3345 if (!emit1(JSOp::Dup)) {
3346 // [stack] ... OBJ OBJ
3347 return false;
3348 }
3349
3350 Maybe<InternalIfEmitter> ifArrayOptimizable;
3351
3352 if (isEligibleForArrayOptimizations) {
3353 ifArrayOptimizable.emplace(
3354 this, BranchEmitterBase::LexicalKind::MayContainLexicalAccessInBranch);
3355
3356 if (!emit1(JSOp::Dup)) {
3357 // [stack] OBJ OBJ
3358 return false;
3359 }
3360
3361 if (!emit1(JSOp::OptimizeGetIterator)) {
3362 // [stack] OBJ OBJ IS_OPTIMIZABLE
3363 return false;
3364 }
3365
3366 if (!ifArrayOptimizable->emitThenElse()) {
3367 // [stack] OBJ OBJ
3368 return false;
3369 }
3370
3371 if (!emitAtomOp(JSOp::GetProp,
3372 TaggedParserAtomIndex::WellKnown::length())) {
3373 // [stack] OBJ LENGTH
3374 return false;
3375 }
3376
3377 if (!emit1(JSOp::Swap)) {
3378 // [stack] LENGTH OBJ
3379 return false;
3380 }
3381
3382 uint32_t idx = 0;
3383 for (ParseNode* member : pattern->contents()) {
3384 if (member->isKind(ParseNodeKind::Elision)) {
3385 idx += 1;
3386 continue;
3387 }
3388
3389 if (!emit1(JSOp::Dup)) {
3390 // [stack] LENGTH OBJ OBJ
3391 return false;
3392 }
3393
3394 if (!emitNumberOp(idx)) {
3395 // [stack] LENGTH OBJ OBJ IDX
3396 return false;
3397 }
3398
3399 if (!emit1(JSOp::Dup)) {
3400 // [stack] LENGTH OBJ OBJ IDX IDX
3401 return false;
3402 }
3403
3404 if (!emitDupAt(4)) {
3405 // [stack] LENGTH OBJ OBJ IDX IDX LENGTH
3406 return false;
3407 }
3408
3409 if (!emit1(JSOp::Lt)) {
3410 // [stack] LENGTH OBJ OBJ IDX IS_IN_DENSE_BOUNDS
3411 return false;
3412 }
3413
3414 InternalIfEmitter isInDenseBounds(this);
3415 if (!isInDenseBounds.emitThenElse()) {
3416 // [stack] LENGTH OBJ OBJ IDX
3417 return false;
3418 }
3419
3420 if (!emit1(JSOp::GetElem)) {
3421 // [stack] LENGTH OBJ VALUE
3422 return false;
3423 }
3424
3425 if (!isInDenseBounds.emitElse()) {
3426 // [stack] LENGTH OBJ OBJ IDX
3427 return false;
3428 }
3429
3430 if (!emitPopN(2)) {
3431 // [stack] LENGTH OBJ
3432 return false;
3433 }
3434
3435 if (!emit1(JSOp::Undefined)) {
3436 // [stack] LENGTH OBJ UNDEFINED
3437 return false;
3438 }
3439
3440 if (!isInDenseBounds.emitEnd()) {
3441 // [stack] LENGTH OBJ VALUE|UNDEFINED
3442 return false;
3443 }
3444
3445 if (!emitSetOrInitializeDestructuring(member, flav)) {
3446 // [stack] LENGTH OBJ
3447 return false;
3448 }
3449
3450 idx += 1;
3451 }
3452
3453 if (!emit1(JSOp::Swap)) {
3454 // [stack] OBJ LENGTH
3455 return false;
3456 }
3457
3458 if (!emit1(JSOp::Pop)) {
3459 // [stack] OBJ
3460 return false;
3461 }
3462
3463 if (!ifArrayOptimizable->emitElse()) {
3464 // [stack] OBJ OBJ
3465 return false;
3466 }
3467 }
3468
3469 if (!emitIterator(SelfHostedIter::Deny)) {
3470 // [stack] ... OBJ NEXT ITER
3471 return false;
3472 }
3473
3474 // For an empty pattern [], call IteratorClose unconditionally. Nothing
3475 // else needs to be done.
3476 if (!pattern->head()) {
3477 if (!emit1(JSOp::Swap)) {
3478 // [stack] ... OBJ ITER NEXT
3479 return false;
3480 }
3481 if (!emit1(JSOp::Pop)) {
3482 // [stack] ... OBJ ITER
3483 return false;
3484 }
3485
3486 if (!emitIteratorCloseInInnermostScope()) {
3487 // [stack] ... OBJ
3488 return false;
3489 }
3490
3491 if (ifArrayOptimizable.isSome()) {
3492 if (!ifArrayOptimizable->emitEnd()) {
3493 // [stack] OBJ
3494 return false;
3495 }
3496 }
3497
3498 return true;
3499 }
3500
3501 // Push an initial FALSE value for DONE.
3502 if (!emit1(JSOp::False)) {
3503 // [stack] ... OBJ NEXT ITER FALSE
3504 return false;
3505 }
3506
3507 // TryNoteKind::Destructuring expects the iterator and the done value
3508 // to be the second to top and the top of the stack, respectively.
3509 // IteratorClose is called upon exception only if done is false.
3510 int32_t tryNoteDepth = bytecodeSection().stackDepth();
3511
3512 for (ParseNode* member : pattern->contents()) {
3513 bool isFirst = member == pattern->head();
3514 DebugOnly<bool> hasNext = !!member->pn_next;
3515
3516 ParseNode* subpattern;
3517 if (member->isKind(ParseNodeKind::Spread)) {
3518 subpattern = member->as<UnaryNode>().kid();
3519
3520 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"
, 3520); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!subpattern->isKind(ParseNodeKind::AssignExpr)"
")"); do { *((volatile int*)__null) = 3520; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3521 } else {
3522 subpattern = member;
3523 }
3524
3525 ParseNode* lhsPattern = subpattern;
3526 ParseNode* pndefault = nullptr;
3527 if (subpattern->isKind(ParseNodeKind::AssignExpr)) {
3528 lhsPattern = subpattern->as<AssignmentNode>().left();
3529 pndefault = subpattern->as<AssignmentNode>().right();
3530 }
3531
3532 // Number of stack slots emitted for the LHS reference.
3533 size_t emitted = 0;
3534
3535 // Spec requires LHS reference to be evaluated first.
3536 bool isElision = lhsPattern->isKind(ParseNodeKind::Elision);
3537 if (!isElision) {
3538 auto emitLHSRef = [lhsPattern, &emitted](BytecodeEmitter* bce) {
3539 return bce->emitDestructuringLHSRef(lhsPattern, &emitted);
3540 // [stack] ... OBJ NEXT ITER DONE LREF*
3541 };
3542 if (!wrapWithDestructuringTryNote(tryNoteDepth, emitLHSRef)) {
3543 return false;
3544 }
3545 }
3546
3547 // Pick the DONE value to the top of the stack.
3548 if (emitted) {
3549 if (!emitPickN(emitted)) {
3550 // [stack] ... OBJ NEXT ITER LREF* DONE
3551 return false;
3552 }
3553 }
3554
3555 if (isFirst) {
3556 // If this element is the first, DONE is always FALSE, so pop it.
3557 //
3558 // Non-first elements should emit if-else depending on the
3559 // member pattern, below.
3560 if (!emit1(JSOp::Pop)) {
3561 // [stack] ... OBJ NEXT ITER LREF*
3562 return false;
3563 }
3564 }
3565
3566 if (member->isKind(ParseNodeKind::Spread)) {
3567 InternalIfEmitter ifThenElse(this);
3568 if (!isFirst) {
3569 // If spread is not the first element of the pattern,
3570 // iterator can already be completed.
3571 // [stack] ... OBJ NEXT ITER LREF* DONE
3572
3573 if (!ifThenElse.emitThenElse()) {
3574 // [stack] ... OBJ NEXT ITER LREF*
3575 return false;
3576 }
3577
3578 if (!emitUint32Operand(JSOp::NewArray, 0)) {
3579 // [stack] ... OBJ NEXT ITER LREF* ARRAY
3580 return false;
3581 }
3582 if (!ifThenElse.emitElse()) {
3583 // [stack] ... OBJ NEXT ITER LREF*
3584 return false;
3585 }
3586 }
3587
3588 // If iterator is not completed, create a new array with the rest
3589 // of the iterator.
3590 if (!emitDupAt(emitted + 1, 2)) {
3591 // [stack] ... OBJ NEXT ITER LREF* NEXT ITER
3592 return false;
3593 }
3594 if (!emitUint32Operand(JSOp::NewArray, 0)) {
3595 // [stack] ... OBJ NEXT ITER LREF* NEXT ITER ARRAY
3596 return false;
3597 }
3598 if (!emitNumberOp(0)) {
3599 // [stack] ... OBJ NEXT ITER LREF* NEXT ITER ARRAY INDEX
3600 return false;
3601 }
3602 if (!emitSpread(SelfHostedIter::Deny)) {
3603 // [stack] ... OBJ NEXT ITER LREF* ARRAY INDEX
3604 return false;
3605 }
3606 if (!emit1(JSOp::Pop)) {
3607 // [stack] ... OBJ NEXT ITER LREF* ARRAY
3608 return false;
3609 }
3610
3611 if (!isFirst) {
3612 if (!ifThenElse.emitEnd()) {
3613 return false;
3614 }
3615 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"
, 3615); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ifThenElse.pushed() == 1"
")"); do { *((volatile int*)__null) = 3615; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3616 }
3617
3618 // At this point the iterator is done. Unpick a TRUE value for DONE above
3619 // ITER.
3620 if (!emit1(JSOp::True)) {
3621 // [stack] ... OBJ NEXT ITER LREF* ARRAY TRUE
3622 return false;
3623 }
3624 if (!emitUnpickN(emitted + 1)) {
3625 // [stack] ... OBJ NEXT ITER TRUE LREF* ARRAY
3626 return false;
3627 }
3628
3629 auto emitAssignment = [lhsPattern, flav](BytecodeEmitter* bce) {
3630 return bce->emitSetOrInitializeDestructuring(lhsPattern, flav);
3631 // [stack] ... OBJ NEXT ITER TRUE
3632 };
3633 if (!wrapWithDestructuringTryNote(tryNoteDepth, emitAssignment)) {
3634 return false;
3635 }
3636
3637 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"
, 3637); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!hasNext" ")"
); do { *((volatile int*)__null) = 3637; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3638 break;
3639 }
3640
3641 InternalIfEmitter ifAlreadyDone(this);
3642 if (!isFirst) {
3643 // [stack] ... OBJ NEXT ITER LREF* DONE
3644
3645 if (!ifAlreadyDone.emitThenElse()) {
3646 // [stack] ... OBJ NEXT ITER LREF*
3647 return false;
3648 }
3649
3650 if (!emit1(JSOp::Undefined)) {
3651 // [stack] ... OBJ NEXT ITER LREF* UNDEF
3652 return false;
3653 }
3654 if (!emit1(JSOp::NopDestructuring)) {
3655 // [stack] ... OBJ NEXT ITER LREF* UNDEF
3656 return false;
3657 }
3658
3659 // The iterator is done. Unpick a TRUE value for DONE above ITER.
3660 if (!emit1(JSOp::True)) {
3661 // [stack] ... OBJ NEXT ITER LREF* UNDEF TRUE
3662 return false;
3663 }
3664 if (!emitUnpickN(emitted + 1)) {
3665 // [stack] ... OBJ NEXT ITER TRUE LREF* UNDEF
3666 return false;
3667 }
3668
3669 if (!ifAlreadyDone.emitElse()) {
3670 // [stack] ... OBJ NEXT ITER LREF*
3671 return false;
3672 }
3673 }
3674
3675 if (!emitDupAt(emitted + 1, 2)) {
3676 // [stack] ... OBJ NEXT ITER LREF* NEXT
3677 return false;
3678 }
3679 if (!emitIteratorNext(Some(pattern->pn_pos.begin))) {
3680 // [stack] ... OBJ NEXT ITER LREF* RESULT
3681 return false;
3682 }
3683 if (!emit1(JSOp::Dup)) {
3684 // [stack] ... OBJ NEXT ITER LREF* RESULT RESULT
3685 return false;
3686 }
3687 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::done())) {
3688 // [stack] ... OBJ NEXT ITER LREF* RESULT DONE
3689 return false;
3690 }
3691
3692 if (!emit1(JSOp::Dup)) {
3693 // [stack] ... OBJ NEXT ITER LREF* RESULT DONE DONE
3694 return false;
3695 }
3696 if (!emitUnpickN(emitted + 2)) {
3697 // [stack] ... OBJ NEXT ITER DONE LREF* RESULT DONE
3698 return false;
3699 }
3700
3701 InternalIfEmitter ifDone(this);
3702 if (!ifDone.emitThenElse()) {
3703 // [stack] ... OBJ NEXT ITER DONE LREF* RESULT
3704 return false;
3705 }
3706
3707 if (!emit1(JSOp::Pop)) {
3708 // [stack] ... OBJ NEXT ITER DONE LREF*
3709 return false;
3710 }
3711 if (!emit1(JSOp::Undefined)) {
3712 // [stack] ... OBJ NEXT ITER DONE LREF* UNDEF
3713 return false;
3714 }
3715 if (!emit1(JSOp::NopDestructuring)) {
3716 // [stack] ... OBJ NEXT ITER DONE LREF* UNDEF
3717 return false;
3718 }
3719
3720 if (!ifDone.emitElse()) {
3721 // [stack] ... OBJ NEXT ITER DONE LREF* RESULT
3722 return false;
3723 }
3724
3725 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::value())) {
3726 // [stack] ... OBJ NEXT ITER DONE LREF* VALUE
3727 return false;
3728 }
3729
3730 if (!ifDone.emitEnd()) {
3731 return false;
3732 }
3733 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"
, 3733); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ifDone.pushed() == 0"
")"); do { *((volatile int*)__null) = 3733; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3734
3735 if (!isFirst) {
3736 if (!ifAlreadyDone.emitEnd()) {
3737 return false;
3738 }
3739 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"
, 3739); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ifAlreadyDone.pushed() == 2"
")"); do { *((volatile int*)__null) = 3739; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3740 }
3741
3742 if (pndefault) {
3743 auto emitDefault = [pndefault, lhsPattern](BytecodeEmitter* bce) {
3744 return bce->emitDefault(pndefault, lhsPattern);
3745 // [stack] ... OBJ NEXT ITER DONE LREF* VALUE
3746 };
3747
3748 if (!wrapWithDestructuringTryNote(tryNoteDepth, emitDefault)) {
3749 return false;
3750 }
3751 }
3752
3753 if (!isElision) {
3754 auto emitAssignment = [lhsPattern, flav](BytecodeEmitter* bce) {
3755 return bce->emitSetOrInitializeDestructuring(lhsPattern, flav);
3756 // [stack] ... OBJ NEXT ITER DONE
3757 };
3758
3759 if (!wrapWithDestructuringTryNote(tryNoteDepth, emitAssignment)) {
3760 return false;
3761 }
3762 } else {
3763 if (!emit1(JSOp::Pop)) {
3764 // [stack] ... OBJ NEXT ITER DONE
3765 return false;
3766 }
3767 }
3768 }
3769
3770 // The last DONE value is on top of the stack. If not DONE, call
3771 // IteratorClose.
3772 // [stack] ... OBJ NEXT ITER DONE
3773
3774 InternalIfEmitter ifDone(this);
3775 if (!ifDone.emitThenElse()) {
3776 // [stack] ... OBJ NEXT ITER
3777 return false;
3778 }
3779 if (!emitPopN(2)) {
3780 // [stack] ... OBJ
3781 return false;
3782 }
3783 if (!ifDone.emitElse()) {
3784 // [stack] ... OBJ NEXT ITER
3785 return false;
3786 }
3787 if (!emit1(JSOp::Swap)) {
3788 // [stack] ... OBJ ITER NEXT
3789 return false;
3790 }
3791 if (!emit1(JSOp::Pop)) {
3792 // [stack] ... OBJ ITER
3793 return false;
3794 }
3795 if (!emitIteratorCloseInInnermostScope()) {
3796 // [stack] ... OBJ
3797 return false;
3798 }
3799 if (!ifDone.emitEnd()) {
3800 return false;
3801 }
3802
3803 if (ifArrayOptimizable.isSome()) {
3804 if (!ifArrayOptimizable->emitEnd()) {
3805 // [stack] OBJ
3806 return false;
3807 }
3808 }
3809
3810 return true;
3811}
3812
3813bool BytecodeEmitter::emitComputedPropertyName(UnaryNode* computedPropName) {
3814 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"
, 3814); AnnotateMozCrashReason("MOZ_ASSERT" "(" "computedPropName->isKind(ParseNodeKind::ComputedName)"
")"); do { *((volatile int*)__null) = 3814; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3815 return emitTree(computedPropName->kid()) && emit1(JSOp::ToPropertyKey);
3816}
3817
3818bool BytecodeEmitter::emitDestructuringOpsObject(ListNode* pattern,
3819 DestructuringFlavor flav) {
3820 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"
, 3820); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pattern->isKind(ParseNodeKind::ObjectExpr)"
")"); do { *((volatile int*)__null) = 3820; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3821
3822 // [stack] ... RHS
3823 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"
, 3823); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() > 0"
")"); do { *((volatile int*)__null) = 3823; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3824
3825 if (!emit1(JSOp::CheckObjCoercible)) {
3826 // [stack] ... RHS
3827 return false;
3828 }
3829
3830 bool needsRestPropertyExcludedSet =
3831 pattern->count() > 1 && pattern->last()->isKind(ParseNodeKind::Spread);
3832 if (needsRestPropertyExcludedSet) {
3833 if (!emitDestructuringObjRestExclusionSet(pattern)) {
3834 // [stack] ... RHS SET
3835 return false;
3836 }
3837
3838 if (!emit1(JSOp::Swap)) {
3839 // [stack] ... SET RHS
3840 return false;
3841 }
3842 }
3843
3844 for (ParseNode* member : pattern->contents()) {
3845 ParseNode* subpattern;
3846 if (member->isKind(ParseNodeKind::MutateProto) ||
3847 member->isKind(ParseNodeKind::Spread)) {
3848 subpattern = member->as<UnaryNode>().kid();
3849
3850 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"
, 3851); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!subpattern->isKind(ParseNodeKind::AssignExpr)"
")"); do { *((volatile int*)__null) = 3851; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3851 !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"
, 3851); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!subpattern->isKind(ParseNodeKind::AssignExpr)"
")"); do { *((volatile int*)__null) = 3851; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
3852 } else {
3853 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"
, 3854); AnnotateMozCrashReason("MOZ_ASSERT" "(" "member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)"
")"); do { *((volatile int*)__null) = 3854; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3854 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"
, 3854); AnnotateMozCrashReason("MOZ_ASSERT" "(" "member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)"
")"); do { *((volatile int*)__null) = 3854; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3855 subpattern = member->as<BinaryNode>().right();
3856 }
3857
3858 ParseNode* lhs = subpattern;
3859 ParseNode* pndefault = nullptr;
3860 if (subpattern->isKind(ParseNodeKind::AssignExpr)) {
3861 lhs = subpattern->as<AssignmentNode>().left();
3862 pndefault = subpattern->as<AssignmentNode>().right();
3863 }
3864
3865 // Number of stack slots emitted for the LHS reference.
3866 size_t emitted = 0;
3867
3868 // Spec requires LHS reference to be evaluated first.
3869 if (!emitDestructuringLHSRef(lhs, &emitted)) {
3870 // [stack] ... SET? RHS LREF*
3871 return false;
3872 }
3873
3874 // Duplicate the value being destructured to use as a reference base.
3875 if (!emitDupAt(emitted)) {
3876 // [stack] ... SET? RHS LREF* RHS
3877 return false;
3878 }
3879
3880 if (member->isKind(ParseNodeKind::Spread)) {
3881 if (!updateSourceCoordNotes(member->pn_pos.begin)) {
3882 return false;
3883 }
3884
3885 if (!emit1(JSOp::NewInit)) {
3886 // [stack] ... SET? RHS LREF* RHS TARGET
3887 return false;
3888 }
3889 if (!emit1(JSOp::Dup)) {
3890 // [stack] ... SET? RHS LREF* RHS TARGET TARGET
3891 return false;
3892 }
3893 if (!emit2(JSOp::Pick, 2)) {
3894 // [stack] ... SET? RHS LREF* TARGET TARGET RHS
3895 return false;
3896 }
3897
3898 if (needsRestPropertyExcludedSet) {
3899 if (!emit2(JSOp::Pick, emitted + 4)) {
3900 // [stack] ... RHS LREF* TARGET TARGET RHS SET
3901 return false;
3902 }
3903 }
3904
3905 CopyOption option = needsRestPropertyExcludedSet ? CopyOption::Filtered
3906 : CopyOption::Unfiltered;
3907 if (!emitCopyDataProperties(option)) {
3908 // [stack] ... RHS LREF* TARGET
3909 return false;
3910 }
3911
3912 // Destructure TARGET per this member's lhs.
3913 if (!emitSetOrInitializeDestructuring(lhs, flav)) {
3914 // [stack] ... RHS
3915 return false;
3916 }
3917
3918 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"
, 3918); AnnotateMozCrashReason("MOZ_ASSERT" "(" "member == pattern->last()"
") (" "Rest property is always last" ")"); do { *((volatile int
*)__null) = 3918; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
3919 break;
3920 }
3921
3922 // Now push the property value currently being matched, which is the value
3923 // of the current property name "label" on the left of a colon in the object
3924 // initialiser.
3925 if (member->isKind(ParseNodeKind::MutateProto)) {
3926 if (!emitAtomOp(JSOp::GetProp,
3927 TaggedParserAtomIndex::WellKnown::proto_())) {
3928 // [stack] ... SET? RHS LREF* PROP
3929 return false;
3930 }
3931 } else {
3932 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"
, 3933); AnnotateMozCrashReason("MOZ_ASSERT" "(" "member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)"
")"); do { *((volatile int*)__null) = 3933; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3933 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"
, 3933); AnnotateMozCrashReason("MOZ_ASSERT" "(" "member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)"
")"); do { *((volatile int*)__null) = 3933; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3934
3935 ParseNode* key = member->as<BinaryNode>().left();
3936 if (key->isKind(ParseNodeKind::ObjectPropertyName) ||
3937 key->isKind(ParseNodeKind::StringExpr)) {
3938 if (!emitAtomOp(JSOp::GetProp, key->as<NameNode>().atom())) {
3939 // [stack] ... SET? RHS LREF* PROP
3940 return false;
3941 }
3942 } else {
3943 if (key->isKind(ParseNodeKind::NumberExpr)) {
3944 if (!emitNumberOp(key->as<NumericLiteral>().value())) {
3945 // [stack]... SET? RHS LREF* RHS KEY
3946 return false;
3947 }
3948 } else {
3949 // Otherwise this is a computed property name. BigInt keys are parsed
3950 // as (synthetic) computed property names, too.
3951 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"
, 3951); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::ComputedName)"
")"); do { *((volatile int*)__null) = 3951; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3952
3953 if (!emitComputedPropertyName(&key->as<UnaryNode>())) {
3954 // [stack] ... SET? RHS LREF* RHS KEY
3955 return false;
3956 }
3957
3958 // Add the computed property key to the exclusion set.
3959 if (needsRestPropertyExcludedSet) {
3960 if (!emitDupAt(emitted + 3)) {
3961 // [stack] ... SET RHS LREF* RHS KEY SET
3962 return false;
3963 }
3964 if (!emitDupAt(1)) {
3965 // [stack] ... SET RHS LREF* RHS KEY SET KEY
3966 return false;
3967 }
3968 if (!emit1(JSOp::Undefined)) {
3969 // [stack] ... SET RHS LREF* RHS KEY SET KEY UNDEFINED
3970 return false;
3971 }
3972 if (!emit1(JSOp::InitElem)) {
3973 // [stack] ... SET RHS LREF* RHS KEY SET
3974 return false;
3975 }
3976 if (!emit1(JSOp::Pop)) {
3977 // [stack] ... SET RHS LREF* RHS KEY
3978 return false;
3979 }
3980 }
3981 }
3982
3983 // Get the property value.
3984 if (!emitElemOpBase(JSOp::GetElem)) {
3985 // [stack] ... SET? RHS LREF* PROP
3986 return false;
3987 }
3988 }
3989 }
3990
3991 if (pndefault) {
3992 if (!emitDefault(pndefault, lhs)) {
3993 // [stack] ... SET? RHS LREF* VALUE
3994 return false;
3995 }
3996 }
3997
3998 // Destructure PROP per this member's lhs.
3999 if (!emitSetOrInitializeDestructuring(lhs, flav)) {
4000 // [stack] ... SET? RHS
4001 return false;
4002 }
4003 }
4004
4005 return true;
4006}
4007
4008static bool IsDestructuringRestExclusionSetObjLiteralCompatible(
4009 ListNode* pattern) {
4010 uint32_t propCount = 0;
4011 for (ParseNode* member : pattern->contents()) {
4012 if (member->isKind(ParseNodeKind::Spread)) {
4013 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"
, 4013); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!member->pn_next"
") (" "unexpected trailing element after spread" ")"); do { *
((volatile int*)__null) = 4013; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
4014 break;
4015 }
4016
4017 propCount++;
4018
4019 if (member->isKind(ParseNodeKind::MutateProto)) {
4020 continue;
4021 }
4022
4023 ParseNode* key = member->as<BinaryNode>().left();
4024 if (key->isKind(ParseNodeKind::ObjectPropertyName) ||
4025 key->isKind(ParseNodeKind::StringExpr)) {
4026 continue;
4027 }
4028
4029 // Number and BigInt keys aren't yet supported. Computed property names need
4030 // to be added dynamically.
4031 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"
, 4033); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr) || key->isKind(ParseNodeKind::ComputedName)"
")"); do { *((volatile int*)__null) = 4033; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4032 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"
, 4033); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr) || key->isKind(ParseNodeKind::ComputedName)"
")"); do { *((volatile int*)__null) = 4033; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4033 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"
, 4033); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr) || key->isKind(ParseNodeKind::ComputedName)"
")"); do { *((volatile int*)__null) = 4033; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4034 return false;
4035 }
4036
4037 if (propCount > SharedPropMap::MaxPropsForNonDictionary) {
4038 // JSOp::NewObject cannot accept dictionary-mode objects.
4039 return false;
4040 }
4041
4042 return true;
4043}
4044
4045bool BytecodeEmitter::emitDestructuringObjRestExclusionSet(ListNode* pattern) {
4046 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"
, 4046); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pattern->isKind(ParseNodeKind::ObjectExpr)"
")"); do { *((volatile int*)__null) = 4046; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4047 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"
, 4047); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pattern->last()->isKind(ParseNodeKind::Spread)"
")"); do { *((volatile int*)__null) = 4047; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4048
4049 // See if we can use ObjLiteral to construct the exclusion set object.
4050 if (IsDestructuringRestExclusionSetObjLiteralCompatible(pattern)) {
4051 if (!emitDestructuringRestExclusionSetObjLiteral(pattern)) {
4052 // [stack] OBJ
4053 return false;
4054 }
4055 } else {
4056 // Take the slow but sure way and start off with a blank object.
4057 if (!emit1(JSOp::NewInit)) {
4058 // [stack] OBJ
4059 return false;
4060 }
4061 }
4062
4063 for (ParseNode* member : pattern->contents()) {
4064 if (member->isKind(ParseNodeKind::Spread)) {
4065 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"
, 4065); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!member->pn_next"
") (" "unexpected trailing element after spread" ")"); do { *
((volatile int*)__null) = 4065; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
4066 break;
4067 }
4068
4069 TaggedParserAtomIndex pnatom;
4070 if (member->isKind(ParseNodeKind::MutateProto)) {
4071 pnatom = TaggedParserAtomIndex::WellKnown::proto_();
4072 } else {
4073 ParseNode* key = member->as<BinaryNode>().left();
4074 if (key->isKind(ParseNodeKind::ObjectPropertyName) ||
4075 key->isKind(ParseNodeKind::StringExpr)) {
4076 pnatom = key->as<NameNode>().atom();
4077 } else if (key->isKind(ParseNodeKind::NumberExpr)) {
4078 if (!emitNumberOp(key->as<NumericLiteral>().value())) {
4079 return false;
4080 }
4081 } else {
4082 // Otherwise this is a computed property name which needs to be added
4083 // dynamically. BigInt keys are parsed as (synthetic) computed property
4084 // names, too.
4085 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"
, 4085); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::ComputedName)"
")"); do { *((volatile int*)__null) = 4085; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4086 continue;
4087 }
4088 }
4089
4090 // Initialize elements with |undefined|.
4091 if (!emit1(JSOp::Undefined)) {
4092 return false;
4093 }
4094
4095 if (!pnatom) {
4096 if (!emit1(JSOp::InitElem)) {
4097 return false;
4098 }
4099 } else {
4100 if (!emitAtomOp(JSOp::InitProp, pnatom)) {
4101 return false;
4102 }
4103 }
4104 }
4105
4106 return true;
4107}
4108
4109bool BytecodeEmitter::emitDestructuringOps(ListNode* pattern,
4110 DestructuringFlavor flav) {
4111 if (pattern->isKind(ParseNodeKind::ArrayExpr)) {
4112 return emitDestructuringOpsArray(pattern, flav);
4113 }
4114 return emitDestructuringOpsObject(pattern, flav);
4115}
4116
4117bool BytecodeEmitter::emitTemplateString(ListNode* templateString) {
4118 bool pushedString = false;
4119
4120 for (ParseNode* item : templateString->contents()) {
4121 bool isString = (item->getKind() == ParseNodeKind::StringExpr ||
4122 item->getKind() == ParseNodeKind::TemplateStringExpr);
4123
4124 // Skip empty strings. These are very common: a template string like
4125 // `${a}${b}` has three empty strings and without this optimization
4126 // we'd emit four JSOp::Add operations instead of just one.
4127 if (isString && item->as<NameNode>().atom() ==
4128 TaggedParserAtomIndex::WellKnown::empty()) {
4129 continue;
4130 }
4131
4132 if (!isString) {
4133 // We update source notes before emitting the expression
4134 if (!updateSourceCoordNotes(item->pn_pos.begin)) {
4135 return false;
4136 }
4137 }
4138
4139 if (!emitTree(item)) {
4140 return false;
4141 }
4142
4143 if (!isString) {
4144 // We need to convert the expression to a string
4145 if (!emit1(JSOp::ToString)) {
4146 return false;
4147 }
4148 }
4149
4150 if (pushedString) {
4151 // We've pushed two strings onto the stack. Add them together, leaving
4152 // just one.
4153 if (!emit1(JSOp::Add)) {
4154 return false;
4155 }
4156 } else {
4157 pushedString = true;
4158 }
4159 }
4160
4161 if (!pushedString) {
4162 // All strings were empty, this can happen for something like `${""}`.
4163 // Just push an empty string.
4164 if (!emitStringOp(JSOp::String,
4165 TaggedParserAtomIndex::WellKnown::empty())) {
4166 return false;
4167 }
4168 }
4169
4170 return true;
4171}
4172
4173bool BytecodeEmitter::emitDeclarationList(ListNode* declList) {
4174 for (ParseNode* decl : declList->contents()) {
4175 ParseNode* pattern;
4176 ParseNode* initializer;
4177 if (decl->isKind(ParseNodeKind::Name)) {
4178 pattern = decl;
4179 initializer = nullptr;
4180 } else {
4181 AssignmentNode* assignNode = &decl->as<AssignmentNode>();
4182 pattern = assignNode->left();
4183 initializer = assignNode->right();
4184 }
4185
4186 if (pattern->isKind(ParseNodeKind::Name)) {
4187 // initializer can be null here.
4188 if (!emitSingleDeclaration(declList, &pattern->as<NameNode>(),
4189 initializer)) {
4190 return false;
4191 }
4192 } else {
4193 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"
, 4194); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pattern->isKind(ParseNodeKind::ArrayExpr) || pattern->isKind(ParseNodeKind::ObjectExpr)"
")"); do { *((volatile int*)__null) = 4194; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4194 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"
, 4194); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pattern->isKind(ParseNodeKind::ArrayExpr) || pattern->isKind(ParseNodeKind::ObjectExpr)"
")"); do { *((volatile int*)__null) = 4194; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4195 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"
, 4195); AnnotateMozCrashReason("MOZ_ASSERT" "(" "initializer != nullptr"
")"); do { *((volatile int*)__null) = 4195; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4196
4197 if (!updateSourceCoordNotes(initializer->pn_pos.begin)) {
4198 return false;
4199 }
4200 if (!markStepBreakpoint()) {
4201 return false;
4202 }
4203 if (!emitTree(initializer)) {
4204 return false;
4205 }
4206
4207 if (!emitDestructuringOps(&pattern->as<ListNode>(),
4208 DestructuringFlavor::Declaration)) {
4209 return false;
4210 }
4211
4212 if (!emit1(JSOp::Pop)) {
4213 return false;
4214 }
4215 }
4216 }
4217 return true;
4218}
4219
4220bool BytecodeEmitter::emitSingleDeclaration(ListNode* declList, NameNode* decl,
4221 ParseNode* initializer) {
4222 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"
, 4222); AnnotateMozCrashReason("MOZ_ASSERT" "(" "decl->isKind(ParseNodeKind::Name)"
")"); do { *((volatile int*)__null) = 4222; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4223
4224 // Nothing to do for initializer-less 'var' declarations, as there's no TDZ.
4225 if (!initializer && declList->isKind(ParseNodeKind::VarStmt)) {
4226 return true;
4227 }
4228
4229 auto nameAtom = decl->name();
4230 NameOpEmitter noe(this, nameAtom, NameOpEmitter::Kind::Initialize);
4231 if (!noe.prepareForRhs()) {
4232 // [stack] ENV?
4233 return false;
4234 }
4235 if (!initializer) {
4236 // Lexical declarations are initialized to undefined without an
4237 // initializer.
4238 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"
, 4240); AnnotateMozCrashReason("MOZ_ASSERT" "(" "declList->isKind(ParseNodeKind::LetDecl)"
") (" "var declarations without initializers handled above, "
"and const declarations must have initializers" ")"); do { *
((volatile int*)__null) = 4240; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
4239 "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"
, 4240); AnnotateMozCrashReason("MOZ_ASSERT" "(" "declList->isKind(ParseNodeKind::LetDecl)"
") (" "var declarations without initializers handled above, "
"and const declarations must have initializers" ")"); do { *
((volatile int*)__null) = 4240; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
4240 "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"
, 4240); AnnotateMozCrashReason("MOZ_ASSERT" "(" "declList->isKind(ParseNodeKind::LetDecl)"
") (" "var declarations without initializers handled above, "
"and const declarations must have initializers" ")"); do { *
((volatile int*)__null) = 4240; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
4241 if (!emit1(JSOp::Undefined)) {
4242 // [stack] ENV? UNDEF
4243 return false;
4244 }
4245 } else {
4246 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"
, 4246); AnnotateMozCrashReason("MOZ_ASSERT" "(" "initializer"
")"); do { *((volatile int*)__null) = 4246; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4247
4248 if (!updateSourceCoordNotes(initializer->pn_pos.begin)) {
4249 return false;
4250 }
4251 if (!markStepBreakpoint()) {
4252 return false;
4253 }
4254 if (!emitInitializer(initializer, decl)) {
4255 // [stack] ENV? V
4256 return false;
4257 }
4258 }
4259
4260#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
4261 if (declList->isKind(ParseNodeKind::UsingDecl)) {
4262 if (!innermostEmitterScope()->prepareForDisposableAssignment(
4263 UsingHint::Sync)) {
4264 // [stack] ENV? V
4265 return false;
4266 }
4267 }
4268#endif
4269
4270 if (!noe.emitAssignment()) {
4271 // [stack] V
4272 return false;
4273 }
4274
4275 if (!emit1(JSOp::Pop)) {
4276 // [stack]
4277 return false;
4278 }
4279
4280 return true;
4281}
4282
4283bool BytecodeEmitter::emitAssignmentRhs(
4284 ParseNode* rhs, TaggedParserAtomIndex anonFunctionName) {
4285 if (rhs->isDirectRHSAnonFunction()) {
4286 if (anonFunctionName) {
4287 return emitAnonymousFunctionWithName(rhs, anonFunctionName);
4288 }
4289 return emitAnonymousFunctionWithComputedName(rhs, FunctionPrefixKind::None);
4290 }
4291 return emitTree(rhs);
4292}
4293
4294// The RHS value to assign is already on the stack, i.e., the next enumeration
4295// value in a for-in or for-of loop. Offset is the location in the stack of the
4296// already-emitted rhs. If we emitted a JSOp::BindName or JSOp::BindGName, then
4297// the scope is on the top of the stack and we need to dig one deeper to get
4298// the right RHS value.
4299bool BytecodeEmitter::emitAssignmentRhs(uint8_t offset) {
4300 if (offset != 1) {
4301 return emitPickN(offset - 1);
4302 }
4303
4304 return true;
4305}
4306
4307static inline JSOp CompoundAssignmentParseNodeKindToJSOp(ParseNodeKind pnk) {
4308 switch (pnk) {
4309 case ParseNodeKind::InitExpr:
4310 return JSOp::Nop;
4311 case ParseNodeKind::AssignExpr:
4312 return JSOp::Nop;
4313 case ParseNodeKind::AddAssignExpr:
4314 return JSOp::Add;
4315 case ParseNodeKind::SubAssignExpr:
4316 return JSOp::Sub;
4317 case ParseNodeKind::BitOrAssignExpr:
4318 return JSOp::BitOr;
4319 case ParseNodeKind::BitXorAssignExpr:
4320 return JSOp::BitXor;
4321 case ParseNodeKind::BitAndAssignExpr:
4322 return JSOp::BitAnd;
4323 case ParseNodeKind::LshAssignExpr:
4324 return JSOp::Lsh;
4325 case ParseNodeKind::RshAssignExpr:
4326 return JSOp::Rsh;
4327 case ParseNodeKind::UrshAssignExpr:
4328 return JSOp::Ursh;
4329 case ParseNodeKind::MulAssignExpr:
4330 return JSOp::Mul;
4331 case ParseNodeKind::DivAssignExpr:
4332 return JSOp::Div;
4333 case ParseNodeKind::ModAssignExpr:
4334 return JSOp::Mod;
4335 case ParseNodeKind::PowAssignExpr:
4336 return JSOp::Pow;
4337 case ParseNodeKind::CoalesceAssignExpr:
4338 case ParseNodeKind::OrAssignExpr:
4339 case ParseNodeKind::AndAssignExpr:
4340 // Short-circuit assignment operators are handled elsewhere.
4341 [[fallthrough]];
4342 default:
4343 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"
, 4343); AnnotateMozCrashReason("MOZ_CRASH(" "unexpected compound assignment op"
")"); do { *((volatile int*)__null) = 4343; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
4344 }
4345}
4346
4347bool BytecodeEmitter::emitAssignmentOrInit(ParseNodeKind kind, ParseNode* lhs,
4348 ParseNode* rhs) {
4349 JSOp compoundOp = CompoundAssignmentParseNodeKindToJSOp(kind);
4350 bool isCompound = compoundOp != JSOp::Nop;
4351 bool isInit = kind == ParseNodeKind::InitExpr;
4352
4353 // We estimate the number of properties this could create
4354 // if used as constructor merely by counting this.foo = assignment
4355 // or init expressions;
4356 //
4357 // This currently doesn't handle this[x] = foo;
4358 if (isInit || kind == ParseNodeKind::AssignExpr) {
4359 if (lhs->isKind(ParseNodeKind::DotExpr)) {
4360 if (lhs->as<PropertyAccess>().expression().isKind(
4361 ParseNodeKind::ThisExpr)) {
4362 propertyAdditionEstimate++;
4363 }
4364 }
4365 }
4366
4367 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"
, 4369); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lhs->isKind(ParseNodeKind::DotExpr) || lhs->isKind(ParseNodeKind::ElemExpr) || lhs->isKind(ParseNodeKind::PrivateMemberExpr)"
")"); do { *((volatile int*)__null) = 4369; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4368 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"
, 4369); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lhs->isKind(ParseNodeKind::DotExpr) || lhs->isKind(ParseNodeKind::ElemExpr) || lhs->isKind(ParseNodeKind::PrivateMemberExpr)"
")"); do { *((volatile int*)__null) = 4369; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4369 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"
, 4369); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lhs->isKind(ParseNodeKind::DotExpr) || lhs->isKind(ParseNodeKind::ElemExpr) || lhs->isKind(ParseNodeKind::PrivateMemberExpr)"
")"); do { *((volatile int*)__null) = 4369; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4370
4371 // |name| is used within NameOpEmitter, so its lifetime must surpass |noe|.
4372 TaggedParserAtomIndex name;
4373
4374 Maybe<NameOpEmitter> noe;
4375 Maybe<PropOpEmitter> poe;
4376 Maybe<ElemOpEmitter> eoe;
4377 Maybe<PrivateOpEmitter> xoe;
4378
4379 // Deal with non-name assignments.
4380 uint8_t offset = 1;
4381
4382 // Purpose of anonFunctionName:
4383 //
4384 // In normal name assignments (`f = function(){}`), an anonymous function gets
4385 // an inferred name based on the left-hand side name node.
4386 //
4387 // In normal property assignments (`obj.x = function(){}`), the anonymous
4388 // function does not have a computed name, and rhs->isDirectRHSAnonFunction()
4389 // will be false (and anonFunctionName will not be used). However, in field
4390 // initializers (`class C { x = function(){} }`), field initialization is
4391 // implemented via a property or elem assignment (where we are now), and
4392 // rhs->isDirectRHSAnonFunction() is set - so we'll assign the name of the
4393 // function.
4394 TaggedParserAtomIndex anonFunctionName;
4395
4396 switch (lhs->getKind()) {
4397 case ParseNodeKind::Name: {
4398 name = lhs->as<NameNode>().name();
4399 anonFunctionName = name;
4400 noe.emplace(this, name,
4401 isCompound ? NameOpEmitter::Kind::CompoundAssignment
4402 : NameOpEmitter::Kind::SimpleAssignment);
4403 break;
4404 }
4405 case ParseNodeKind::ArgumentsLength:
4406 case ParseNodeKind::DotExpr: {
4407 PropertyAccess* prop = &lhs->as<PropertyAccess>();
4408 bool isSuper = prop->isSuper();
4409 poe.emplace(this,
4410 isCompound ? PropOpEmitter::Kind::CompoundAssignment
4411 : isInit ? PropOpEmitter::Kind::PropInit
4412 : PropOpEmitter::Kind::SimpleAssignment,
4413 isSuper ? PropOpEmitter::ObjKind::Super
4414 : PropOpEmitter::ObjKind::Other);
4415 if (!poe->prepareForObj()) {
4416 return false;
4417 }
4418 anonFunctionName = prop->name();
4419 if (isSuper) {
4420 UnaryNode* base = &prop->expression().as<UnaryNode>();
4421 if (!emitGetThisForSuperBase(base)) {
4422 // [stack] THIS SUPERBASE
4423 return false;
4424 }
4425 // SUPERBASE is pushed onto THIS later in poe->emitGet below.
4426 offset += 2;
4427 } else {
4428 if (!emitTree(&prop->expression())) {
4429 // [stack] OBJ
4430 return false;
4431 }
4432 offset += 1;
4433 }
4434 break;
4435 }
4436 case ParseNodeKind::ElemExpr: {
4437 PropertyByValue* elem = &lhs->as<PropertyByValue>();
4438 bool isSuper = elem->isSuper();
4439 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"
, 4439); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 4439; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4440 eoe.emplace(this,
4441 isCompound ? ElemOpEmitter::Kind::CompoundAssignment
4442 : isInit ? ElemOpEmitter::Kind::PropInit
4443 : ElemOpEmitter::Kind::SimpleAssignment,
4444 isSuper ? ElemOpEmitter::ObjKind::Super
4445 : ElemOpEmitter::ObjKind::Other);
4446 if (!emitElemObjAndKey(elem, isSuper, *eoe)) {
4447 // [stack] # if Super
4448 // [stack] THIS KEY
4449 // [stack] # otherwise
4450 // [stack] OBJ KEY
4451 return false;
4452 }
4453 if (isSuper) {
4454 // SUPERBASE is pushed onto KEY in eoe->emitGet below.
4455 offset += 3;
4456 } else {
4457 offset += 2;
4458 }
4459 break;
4460 }
4461 case ParseNodeKind::PrivateMemberExpr: {
4462 PrivateMemberAccess* privateExpr = &lhs->as<PrivateMemberAccess>();
4463 xoe.emplace(this,
4464 isCompound ? PrivateOpEmitter::Kind::CompoundAssignment
4465 : isInit ? PrivateOpEmitter::Kind::PropInit
4466 : PrivateOpEmitter::Kind::SimpleAssignment,
4467 privateExpr->privateName().name());
4468 if (!emitTree(&privateExpr->expression())) {
4469 // [stack] OBJ
4470 return false;
4471 }
4472 if (!xoe->emitReference()) {
4473 // [stack] OBJ KEY
4474 return false;
4475 }
4476 offset += xoe->numReferenceSlots();
4477 break;
4478 }
4479 case ParseNodeKind::ArrayExpr:
4480 case ParseNodeKind::ObjectExpr:
4481 break;
4482 case ParseNodeKind::CallExpr:
4483 if (!emitTree(lhs)) {
4484 return false;
4485 }
4486
4487 // Assignment to function calls is forbidden, but we have to make the
4488 // call first. Now we can throw.
4489 if (!emit2(JSOp::ThrowMsg, uint8_t(ThrowMsgKind::AssignToCall))) {
4490 return false;
4491 }
4492
4493 // Rebalance the stack to placate stack-depth assertions.
4494 if (!emit1(JSOp::Pop)) {
4495 return false;
4496 }
4497 break;
4498 default:
4499 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"
, 4499); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0" ")"); do
{ *((volatile int*)__null) = 4499; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
4500 }
4501
4502 if (isCompound) {
4503 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"
, 4503); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rhs" ")"); do
{ *((volatile int*)__null) = 4503; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
4504 switch (lhs->getKind()) {
4505 case ParseNodeKind::ArgumentsLength:
4506 case ParseNodeKind::DotExpr: {
4507 PropertyAccess* prop = &lhs->as<PropertyAccess>();
4508 if (!poe->emitGet(prop->key().atom())) {
4509 // [stack] # if Super
4510 // [stack] THIS SUPERBASE PROP
4511 // [stack] # otherwise
4512 // [stack] OBJ PROP
4513 return false;
4514 }
4515 break;
4516 }
4517 case ParseNodeKind::ElemExpr: {
4518 if (!eoe->emitGet()) {
4519 // [stack] KEY THIS OBJ ELEM
4520 return false;
4521 }
4522 break;
4523 }
4524 case ParseNodeKind::PrivateMemberExpr: {
4525 if (!xoe->emitGet()) {
4526 // [stack] OBJ KEY VALUE
4527 return false;
4528 }
4529 break;
4530 }
4531 case ParseNodeKind::CallExpr:
4532 // We just emitted a JSOp::ThrowMsg and popped the call's return
4533 // value. Push a random value to make sure the stack depth is
4534 // correct.
4535 if (!emit1(JSOp::Null)) {
4536 // [stack] NULL
4537 return false;
4538 }
4539 break;
4540 default:;
4541 }
4542 }
4543
4544 switch (lhs->getKind()) {
4545 case ParseNodeKind::Name:
4546 if (!noe->prepareForRhs()) {
4547 // [stack] ENV? VAL?
4548 return false;
4549 }
4550 offset += noe->emittedBindOp();
4551 break;
4552 case ParseNodeKind::ArgumentsLength:
4553 case ParseNodeKind::DotExpr:
4554 if (!poe->prepareForRhs()) {
4555 // [stack] # if Simple Assignment with Super
4556 // [stack] THIS SUPERBASE
4557 // [stack] # if Simple Assignment with other
4558 // [stack] OBJ
4559 // [stack] # if Compound Assignment with Super
4560 // [stack] THIS SUPERBASE PROP
4561 // [stack] # if Compound Assignment with other
4562 // [stack] OBJ PROP
4563 return false;
4564 }
4565 break;
4566 case ParseNodeKind::ElemExpr:
4567 if (!eoe->prepareForRhs()) {
4568 // [stack] # if Simple Assignment with Super
4569 // [stack] THIS KEY SUPERBASE
4570 // [stack] # if Simple Assignment with other
4571 // [stack] OBJ KEY
4572 // [stack] # if Compound Assignment with Super
4573 // [stack] THIS KEY SUPERBASE ELEM
4574 // [stack] # if Compound Assignment with other
4575 // [stack] OBJ KEY ELEM
4576 return false;
4577 }
4578 break;
4579 case ParseNodeKind::PrivateMemberExpr:
4580 // no stack adjustment needed
4581 break;
4582 default:
4583 break;
4584 }
4585
4586 if (rhs) {
4587 if (!emitAssignmentRhs(rhs, anonFunctionName)) {
4588 // [stack] ... VAL? RHS
4589 return false;
4590 }
4591 } else {
4592 // Assumption: Things with pre-emitted RHS values never need to be named.
4593 if (!emitAssignmentRhs(offset)) {
4594 // [stack] ... VAL? RHS
4595 return false;
4596 }
4597 }
4598
4599 /* If += etc., emit the binary operator with a hint for the decompiler. */
4600 if (isCompound) {
4601 if (!emit1(compoundOp)) {
4602 // [stack] ... VAL
4603 return false;
4604 }
4605 if (!emit1(JSOp::NopIsAssignOp)) {
4606 // [stack] ... VAL
4607 return false;
4608 }
4609 }
4610
4611 /* Finally, emit the specialized assignment bytecode. */
4612 switch (lhs->getKind()) {
4613 case ParseNodeKind::Name: {
4614 if (!noe->emitAssignment()) {
4615 // [stack] VAL
4616 return false;
4617 }
4618 break;
4619 }
4620 case ParseNodeKind::ArgumentsLength:
4621 case ParseNodeKind::DotExpr: {
4622 PropertyAccess* prop = &lhs->as<PropertyAccess>();
4623 if (!poe->emitAssignment(prop->key().atom())) {
4624 // [stack] VAL
4625 return false;
4626 }
4627 break;
4628 }
4629 case ParseNodeKind::CallExpr:
4630 // We threw above, so nothing to do here.
4631 break;
4632 case ParseNodeKind::ElemExpr: {
4633 if (!eoe->emitAssignment()) {
4634 // [stack] VAL
4635 return false;
4636 }
4637 break;
4638 }
4639 case ParseNodeKind::PrivateMemberExpr:
4640 if (!xoe->emitAssignment()) {
4641 // [stack] VAL
4642 return false;
4643 }
4644 break;
4645 case ParseNodeKind::ArrayExpr:
4646 case ParseNodeKind::ObjectExpr:
4647 if (!emitDestructuringOps(&lhs->as<ListNode>(),
4648 DestructuringFlavor::Assignment)) {
4649 return false;
4650 }
4651 break;
4652 default:
4653 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"
, 4653); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0" ")"); do
{ *((volatile int*)__null) = 4653; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
4654 }
4655 return true;
4656}
4657
4658bool BytecodeEmitter::emitShortCircuitAssignment(AssignmentNode* node) {
4659 TDZCheckCache tdzCache(this);
4660
4661 JSOp op;
4662 switch (node->getKind()) {
4663 case ParseNodeKind::CoalesceAssignExpr:
4664 op = JSOp::Coalesce;
4665 break;
4666 case ParseNodeKind::OrAssignExpr:
4667 op = JSOp::Or;
4668 break;
4669 case ParseNodeKind::AndAssignExpr:
4670 op = JSOp::And;
4671 break;
4672 default:
4673 MOZ_CRASH("Unexpected ParseNodeKind")do { do { } while (false); MOZ_ReportCrash("" "Unexpected ParseNodeKind"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4673); AnnotateMozCrashReason("MOZ_CRASH(" "Unexpected ParseNodeKind"
")"); do { *((volatile int*)__null) = 4673; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
4674 }
4675
4676 ParseNode* lhs = node->left();
4677 ParseNode* rhs = node->right();
4678
4679 // |name| is used within NameOpEmitter, so its lifetime must surpass |noe|.
4680 TaggedParserAtomIndex name;
4681
4682 // Select the appropriate emitter based on the left-hand side.
4683 Maybe<NameOpEmitter> noe;
4684 Maybe<PropOpEmitter> poe;
4685 Maybe<ElemOpEmitter> eoe;
4686 Maybe<PrivateOpEmitter> xoe;
4687
4688 int32_t depth = bytecodeSection().stackDepth();
4689
4690 // Number of values pushed onto the stack in addition to the lhs value.
4691 int32_t numPushed;
4692
4693 // Evaluate the left-hand side expression and compute any stack values needed
4694 // for the assignment.
4695 switch (lhs->getKind()) {
4696 case ParseNodeKind::Name: {
4697 name = lhs->as<NameNode>().name();
4698 noe.emplace(this, name, NameOpEmitter::Kind::CompoundAssignment);
4699
4700 if (!noe->prepareForRhs()) {
4701 // [stack] ENV? LHS
4702 return false;
4703 }
4704
4705 numPushed = noe->emittedBindOp();
4706 break;
4707 }
4708 case ParseNodeKind::ArgumentsLength:
4709 case ParseNodeKind::DotExpr: {
4710 PropertyAccess* prop = &lhs->as<PropertyAccess>();
4711 bool isSuper = prop->isSuper();
4712
4713 poe.emplace(this, PropOpEmitter::Kind::CompoundAssignment,
4714 isSuper ? PropOpEmitter::ObjKind::Super
4715 : PropOpEmitter::ObjKind::Other);
4716
4717 if (!poe->prepareForObj()) {
4718 return false;
4719 }
4720
4721 if (isSuper) {
4722 UnaryNode* base = &prop->expression().as<UnaryNode>();
4723 if (!emitGetThisForSuperBase(base)) {
4724 // [stack] THIS SUPERBASE
4725 return false;
4726 }
4727 } else {
4728 if (!emitTree(&prop->expression())) {
4729 // [stack] OBJ
4730 return false;
4731 }
4732 }
4733
4734 if (!poe->emitGet(prop->key().atom())) {
4735 // [stack] # if Super
4736 // [stack] THIS SUPERBASE LHS
4737 // [stack] # otherwise
4738 // [stack] OBJ LHS
4739 return false;
4740 }
4741
4742 if (!poe->prepareForRhs()) {
4743 // [stack] # if Super
4744 // [stack] THIS SUPERBASE LHS
4745 // [stack] # otherwise
4746 // [stack] OBJ LHS
4747 return false;
4748 }
4749
4750 numPushed = 1 + isSuper;
4751 break;
4752 }
4753
4754 case ParseNodeKind::ElemExpr: {
4755 PropertyByValue* elem = &lhs->as<PropertyByValue>();
4756 bool isSuper = elem->isSuper();
4757 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"
, 4757); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 4757; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4758 eoe.emplace(this, ElemOpEmitter::Kind::CompoundAssignment,
4759 isSuper ? ElemOpEmitter::ObjKind::Super
4760 : ElemOpEmitter::ObjKind::Other);
4761
4762 if (!emitElemObjAndKey(elem, isSuper, *eoe)) {
4763 // [stack] # if Super
4764 // [stack] THIS KEY
4765 // [stack] # otherwise
4766 // [stack] OBJ KEY
4767 return false;
4768 }
4769
4770 if (!eoe->emitGet()) {
4771 // [stack] # if Super
4772 // [stack] THIS KEY SUPERBASE LHS
4773 // [stack] # otherwise
4774 // [stack] OBJ KEY LHS
4775 return false;
4776 }
4777
4778 if (!eoe->prepareForRhs()) {
4779 // [stack] # if Super
4780 // [stack] THIS KEY SUPERBASE LHS
4781 // [stack] # otherwise
4782 // [stack] OBJ KEY LHS
4783 return false;
4784 }
4785
4786 numPushed = 2 + isSuper;
4787 break;
4788 }
4789
4790 case ParseNodeKind::PrivateMemberExpr: {
4791 PrivateMemberAccess* privateExpr = &lhs->as<PrivateMemberAccess>();
4792 xoe.emplace(this, PrivateOpEmitter::Kind::CompoundAssignment,
4793 privateExpr->privateName().name());
4794 if (!emitTree(&privateExpr->expression())) {
4795 // [stack] OBJ
4796 return false;
4797 }
4798 if (!xoe->emitReference()) {
4799 // [stack] OBJ NAME
4800 return false;
4801 }
4802 if (!xoe->emitGet()) {
4803 // [stack] OBJ NAME LHS
4804 return false;
4805 }
4806 numPushed = xoe->numReferenceSlots();
4807 break;
4808 }
4809
4810 default:
4811 MOZ_CRASH()do { do { } while (false); MOZ_ReportCrash("" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4811); AnnotateMozCrashReason("MOZ_CRASH(" ")"); do { *((volatile
int*)__null) = 4811; __attribute__((nomerge)) ::abort(); } while
(false); } while (false)
;
4812 }
4813
4814 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"
, 4814); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == depth + numPushed + 1"
")"); do { *((volatile int*)__null) = 4814; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4815
4816 // Test for the short-circuit condition.
4817 JumpList jump;
4818 if (!emitJump(op, &jump)) {
4819 // [stack] ... LHS
4820 return false;
4821 }
4822
4823 // The short-circuit condition wasn't fulfilled, pop the left-hand side value
4824 // which was kept on the stack.
4825 if (!emit1(JSOp::Pop)) {
4826 // [stack] ...
4827 return false;
4828 }
4829
4830 if (!emitAssignmentRhs(rhs, name)) {
4831 // [stack] ... RHS
4832 return false;
4833 }
4834
4835 // Perform the actual assignment.
4836 switch (lhs->getKind()) {
4837 case ParseNodeKind::Name: {
4838 if (!noe->emitAssignment()) {
4839 // [stack] RHS
4840 return false;
4841 }
4842 break;
4843 }
4844 case ParseNodeKind::ArgumentsLength:
4845 case ParseNodeKind::DotExpr: {
4846 PropertyAccess* prop = &lhs->as<PropertyAccess>();
4847
4848 if (!poe->emitAssignment(prop->key().atom())) {
4849 // [stack] RHS
4850 return false;
4851 }
4852 break;
4853 }
4854
4855 case ParseNodeKind::ElemExpr: {
4856 if (!eoe->emitAssignment()) {
4857 // [stack] RHS
4858 return false;
4859 }
4860 break;
4861 }
4862
4863 case ParseNodeKind::PrivateMemberExpr:
4864 if (!xoe->emitAssignment()) {
4865 // [stack] RHS
4866 return false;
4867 }
4868 break;
4869
4870 default:
4871 MOZ_CRASH()do { do { } while (false); MOZ_ReportCrash("" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 4871); AnnotateMozCrashReason("MOZ_CRASH(" ")"); do { *((volatile
int*)__null) = 4871; __attribute__((nomerge)) ::abort(); } while
(false); } while (false)
;
4872 }
4873
4874 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"
, 4874); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == depth + 1"
")"); do { *((volatile int*)__null) = 4874; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4875
4876 // Join with the short-circuit jump and pop anything left on the stack.
4877 if (numPushed > 0) {
4878 JumpList jumpAroundPop;
4879 if (!emitJump(JSOp::Goto, &jumpAroundPop)) {
4880 // [stack] RHS
4881 return false;
4882 }
4883
4884 if (!emitJumpTargetAndPatch(jump)) {
4885 // [stack] ... LHS
4886 return false;
4887 }
4888
4889 // Reconstruct the stack depth after the jump.
4890 bytecodeSection().setStackDepth(depth + 1 + numPushed);
4891
4892 // Move the left-hand side value to the bottom and pop the rest.
4893 if (!emitUnpickN(numPushed)) {
4894 // [stack] LHS ...
4895 return false;
4896 }
4897 if (!emitPopN(numPushed)) {
4898 // [stack] LHS
4899 return false;
4900 }
4901
4902 if (!emitJumpTargetAndPatch(jumpAroundPop)) {
4903 // [stack] LHS | RHS
4904 return false;
4905 }
4906 } else {
4907 if (!emitJumpTargetAndPatch(jump)) {
4908 // [stack] LHS | RHS
4909 return false;
4910 }
4911 }
4912
4913 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"
, 4913); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == depth + 1"
")"); do { *((volatile int*)__null) = 4913; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4914
4915 return true;
4916}
4917
4918bool BytecodeEmitter::emitCallSiteObjectArray(ObjLiteralWriter& writer,
4919 ListNode* cookedOrRaw,
4920 ParseNode* head, uint32_t count) {
4921 DebugOnly<size_t> idx = 0;
4922 for (ParseNode* pn : cookedOrRaw->contentsFrom(head)) {
4923 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"
, 4924); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->isKind(ParseNodeKind::TemplateStringExpr) || pn->isKind(ParseNodeKind::RawUndefinedExpr)"
")"); do { *((volatile int*)__null) = 4924; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4924 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"
, 4924); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->isKind(ParseNodeKind::TemplateStringExpr) || pn->isKind(ParseNodeKind::RawUndefinedExpr)"
")"); do { *((volatile int*)__null) = 4924; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4925
4926 if (!emitObjLiteralValue(writer, pn)) {
4927 return false;
4928 }
4929 idx++;
4930 }
4931 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"
, 4931); AnnotateMozCrashReason("MOZ_ASSERT" "(" "idx == count"
")"); do { *((volatile int*)__null) = 4931; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4932
4933 return true;
4934}
4935
4936bool BytecodeEmitter::emitCallSiteObject(CallSiteNode* callSiteObj) {
4937 constexpr JSOp op = JSOp::CallSiteObj;
4938
4939 // The first element of a call-site node is the raw-values list. Skip over it.
4940 ListNode* raw = callSiteObj->rawNodes();
4941 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"
, 4941); AnnotateMozCrashReason("MOZ_ASSERT" "(" "raw->isKind(ParseNodeKind::ArrayExpr)"
")"); do { *((volatile int*)__null) = 4941; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4942 ParseNode* head = callSiteObj->head()->pn_next;
4943
4944 uint32_t count = callSiteObj->count() - 1;
4945 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"
, 4945); AnnotateMozCrashReason("MOZ_ASSERT" "(" "count == raw->count()"
")"); do { *((volatile int*)__null) = 4945; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4946
4947 ObjLiteralWriter writer;
4948 writer.beginCallSiteObj(op);
4949 writer.beginDenseArrayElements();
4950
4951 // Write elements of the two arrays: the 'cooked' values followed by the
4952 // 'raw' values.
4953 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"
, 4954); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "count < (4294967295U) / 2"
") (" "Number of elements for both arrays must fit in uint32_t"
")"); do { *((volatile int*)__null) = 4954; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4954 "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"
, 4954); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "count < (4294967295U) / 2"
") (" "Number of elements for both arrays must fit in uint32_t"
")"); do { *((volatile int*)__null) = 4954; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4955 if (!emitCallSiteObjectArray(writer, callSiteObj, head, count)) {
4956 return false;
4957 }
4958 if (!emitCallSiteObjectArray(writer, raw, raw->head(), count)) {
4959 return false;
4960 }
4961
4962 GCThingIndex cookedIndex;
4963 if (!addObjLiteralData(writer, &cookedIndex)) {
4964 return false;
4965 }
4966
4967 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"
, 4967); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->hasCallSiteObj()"
")"); do { *((volatile int*)__null) = 4967; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4968
4969 return emitInternedObjectOp(cookedIndex, op);
4970}
4971
4972bool BytecodeEmitter::emitCatch(BinaryNode* catchClause) {
4973 // We must be nested under a try-finally statement.
4974 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"
, 4974); AnnotateMozCrashReason("MOZ_ASSERT" "(" "innermostNestableControl->is<TryFinallyControl>()"
")"); do { *((volatile int*)__null) = 4974; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4975
4976 ParseNode* param = catchClause->left();
4977 if (!param) {
4978 // Catch parameter was omitted; just discard the exception.
4979 if (!emit1(JSOp::Pop)) {
4980 return false;
4981 }
4982 } else {
4983 switch (param->getKind()) {
4984 case ParseNodeKind::ArrayExpr:
4985 case ParseNodeKind::ObjectExpr:
4986 if (!emitDestructuringOps(&param->as<ListNode>(),
4987 DestructuringFlavor::Declaration)) {
4988 return false;
4989 }
4990 if (!emit1(JSOp::Pop)) {
4991 return false;
4992 }
4993 break;
4994
4995 case ParseNodeKind::Name:
4996 if (!emitLexicalInitialization(&param->as<NameNode>())) {
4997 return false;
4998 }
4999 if (!emit1(JSOp::Pop)) {
5000 return false;
5001 }
5002 break;
5003
5004 default:
5005 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"
, 5005); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0" ")"); do
{ *((volatile int*)__null) = 5005; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
5006 }
5007 }
5008
5009 /* Emit the catch body. */
5010 return emitTree(catchClause->right());
5011}
5012
5013// Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See the
5014// comment on EmitSwitch.
5015MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitTry(TryNode* tryNode) {
5016 LexicalScopeNode* catchScope = tryNode->catchScope();
5017 ParseNode* finallyNode = tryNode->finallyBlock();
5018
5019 TryEmitter::Kind kind;
5020 if (catchScope) {
5021 if (finallyNode) {
5022 kind = TryEmitter::Kind::TryCatchFinally;
5023 } else {
5024 kind = TryEmitter::Kind::TryCatch;
5025 }
5026 } else {
5027 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"
, 5027); AnnotateMozCrashReason("MOZ_ASSERT" "(" "finallyNode"
")"); do { *((volatile int*)__null) = 5027; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5028 kind = TryEmitter::Kind::TryFinally;
5029 }
5030 TryEmitter tryCatch(this, kind, TryEmitter::ControlKind::Syntactic);
5031
5032 if (!tryCatch.emitTry()) {
5033 return false;
5034 }
5035
5036 if (!emitTree(tryNode->body())) {
5037 return false;
5038 }
5039
5040 // If this try has a catch block, emit it.
5041 if (catchScope) {
5042 // The emitted code for a catch block looks like:
5043 //
5044 // [pushlexicalenv] only if any local aliased
5045 // exception
5046 // setlocal 0; pop assign or possibly destructure exception
5047 // < catch block contents >
5048 // debugleaveblock
5049 // [poplexicalenv] only if any local aliased
5050 // if there is a finally block:
5051 // goto <finally>
5052 // [jump target for returning from finally]
5053 // goto <after finally>
5054 if (!tryCatch.emitCatch()) {
5055 return false;
5056 }
5057
5058 // Emit the lexical scope and catch body.
5059 if (!emitTree(catchScope)) {
5060 return false;
5061 }
5062 }
5063
5064 // Emit the finally handler, if there is one.
5065 if (finallyNode) {
5066 if (!tryCatch.emitFinally(Some(finallyNode->pn_pos.begin))) {
5067 return false;
5068 }
5069
5070 if (!emitTree(finallyNode)) {
5071 return false;
5072 }
5073 }
5074
5075 if (!tryCatch.emitEnd()) {
5076 return false;
5077 }
5078
5079 return true;
5080}
5081
5082[[nodiscard]] bool BytecodeEmitter::emitJumpToFinally(JumpList* jump,
5083 uint32_t idx) {
5084 // Push the continuation index.
5085 if (!emitNumberOp(idx)) {
5086 return false;
5087 }
5088
5089 // Push |exception_stack|.
5090 if (!emit1(JSOp::Null)) {
5091 return false;
5092 }
5093
5094 // Push |throwing|.
5095 if (!emit1(JSOp::False)) {
5096 return false;
5097 }
5098
5099 // Jump to the finally block.
5100 if (!emitJumpNoFallthrough(JSOp::Goto, jump)) {
5101 return false;
5102 }
5103
5104 return true;
5105}
5106
5107bool BytecodeEmitter::emitIf(TernaryNode* ifNode) {
5108 IfEmitter ifThenElse(this);
5109
5110 if (!ifThenElse.emitIf(Some(ifNode->kid1()->pn_pos.begin))) {
5111 return false;
5112 }
5113
5114if_again:
5115 ParseNode* testNode = ifNode->kid1();
5116 auto conditionKind = IfEmitter::ConditionKind::Positive;
5117 if (testNode->isKind(ParseNodeKind::NotExpr)) {
5118 testNode = testNode->as<UnaryNode>().kid();
5119 conditionKind = IfEmitter::ConditionKind::Negative;
5120 }
5121
5122 if (!markStepBreakpoint()) {
5123 return false;
5124 }
5125
5126 // Emit code for the condition before pushing stmtInfo.
5127 // NOTE: NotExpr of testNode may be unwrapped, and in that case the negation
5128 // is handled by conditionKind.
5129 if (!emitTree(testNode)) {
5130 return false;
5131 }
5132
5133 ParseNode* elseNode = ifNode->kid3();
5134 if (elseNode) {
5135 if (!ifThenElse.emitThenElse(conditionKind)) {
5136 return false;
5137 }
5138 } else {
5139 if (!ifThenElse.emitThen(conditionKind)) {
5140 return false;
5141 }
5142 }
5143
5144 /* Emit code for the then part. */
5145 if (!emitTree(ifNode->kid2())) {
5146 return false;
5147 }
5148
5149 if (elseNode) {
5150 if (elseNode->isKind(ParseNodeKind::IfStmt)) {
5151 ifNode = &elseNode->as<TernaryNode>();
5152
5153 if (!ifThenElse.emitElseIf(Some(ifNode->kid1()->pn_pos.begin))) {
5154 return false;
5155 }
5156
5157 goto if_again;
5158 }
5159
5160 if (!ifThenElse.emitElse()) {
5161 return false;
5162 }
5163
5164 /* Emit code for the else part. */
5165 if (!emitTree(elseNode)) {
5166 return false;
5167 }
5168 }
5169
5170 if (!ifThenElse.emitEnd()) {
5171 return false;
5172 }
5173
5174 return true;
5175}
5176
5177bool BytecodeEmitter::emitHoistedFunctionsInList(ListNode* stmtList) {
5178 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"
, 5178); AnnotateMozCrashReason("MOZ_ASSERT" "(" "stmtList->hasTopLevelFunctionDeclarations()"
")"); do { *((volatile int*)__null) = 5178; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5179
5180 // We can call this multiple times for sloppy eval scopes.
5181 if (stmtList->emittedTopLevelFunctionDeclarations()) {
5182 return true;
5183 }
5184
5185 stmtList->setEmittedTopLevelFunctionDeclarations();
5186
5187 for (ParseNode* stmt : stmtList->contents()) {
5188 ParseNode* maybeFun = stmt;
5189
5190 if (!sc->strict()) {
5191 while (maybeFun->isKind(ParseNodeKind::LabelStmt)) {
5192 maybeFun = maybeFun->as<LabeledStatement>().statement();
5193 }
5194 }
5195
5196 if (maybeFun->is<FunctionNode>() &&
5197 maybeFun->as<FunctionNode>().functionIsHoisted()) {
5198 if (!emitTree(maybeFun)) {
5199 return false;
5200 }
5201 }
5202 }
5203
5204 return true;
5205}
5206
5207bool BytecodeEmitter::emitLexicalScopeBody(
5208 ParseNode* body, EmitLineNumberNote emitLineNote /* = EMIT_LINENOTE */) {
5209 if (body->isKind(ParseNodeKind::StatementList) &&
5210 body->as<ListNode>().hasTopLevelFunctionDeclarations()) {
5211 // This block contains function statements whose definitions are
5212 // hoisted to the top of the block. Emit these as a separate pass
5213 // before the rest of the block.
5214 if (!emitHoistedFunctionsInList(&body->as<ListNode>())) {
5215 return false;
5216 }
5217 }
5218
5219 // Line notes were updated by emitLexicalScope or emitScript.
5220 return emitTree(body, ValueUsage::WantValue, emitLineNote);
5221}
5222
5223// Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See
5224// the comment on emitSwitch.
5225MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitLexicalScope(
5226 LexicalScopeNode* lexicalScope) {
5227 LexicalScopeEmitter lse(this);
5228
5229 ParseNode* body = lexicalScope->scopeBody();
5230 if (lexicalScope->isEmptyScope()) {
5231 if (!lse.emitEmptyScope()) {
5232 return false;
5233 }
5234
5235 if (!emitLexicalScopeBody(body)) {
5236 return false;
5237 }
5238
5239 if (!lse.emitEnd()) {
5240 return false;
5241 }
5242
5243 return true;
5244 }
5245
5246 // We are about to emit some bytecode for what the spec calls "declaration
5247 // instantiation". Assign these instructions to the opening `{` of the
5248 // block. (Using the location of each declaration we're instantiating is
5249 // too weird when stepping in the debugger.)
5250 if (!ParseNodeRequiresSpecialLineNumberNotes(body)) {
5251 if (!updateSourceCoordNotes(lexicalScope->pn_pos.begin)) {
5252 return false;
5253 }
5254 }
5255
5256 ScopeKind kind;
5257 if (body->isKind(ParseNodeKind::Catch)) {
5258 BinaryNode* catchNode = &body->as<BinaryNode>();
5259 kind =
5260 (!catchNode->left() || catchNode->left()->isKind(ParseNodeKind::Name))
5261 ? ScopeKind::SimpleCatch
5262 : ScopeKind::Catch;
5263 } else {
5264 kind = lexicalScope->kind();
5265 }
5266
5267 if (!lse.emitScope(kind, lexicalScope->scopeBindings())) {
5268 return false;
5269 }
5270
5271 if (body->isKind(ParseNodeKind::ForStmt)) {
5272 // for loops need to emit JSOp::FreshenLexicalEnv/JSOp::RecreateLexicalEnv
5273 // if there are lexical declarations in the head. Signal this by passing a
5274 // non-nullptr lexical scope.
5275 if (!emitFor(&body->as<ForNode>(), &lse.emitterScope())) {
5276 return false;
5277 }
5278 } else {
5279 if (!emitLexicalScopeBody(body, SUPPRESS_LINENOTE)) {
5280 return false;
5281 }
5282 }
5283
5284 if (!lse.emitEnd()) {
5285 return false;
5286 }
5287 return true;
5288}
5289
5290bool BytecodeEmitter::emitWith(BinaryNode* withNode) {
5291 // Ensure that the column of the 'with' is set properly.
5292 if (!updateSourceCoordNotes(withNode->left()->pn_pos.begin)) {
5293 return false;
5294 }
5295
5296 if (!markStepBreakpoint()) {
5297 return false;
5298 }
5299
5300 if (!emitTree(withNode->left())) {
5301 return false;
5302 }
5303
5304 EmitterScope emitterScope(this);
5305 if (!emitterScope.enterWith(this)) {
5306 return false;
5307 }
5308
5309 if (!emitTree(withNode->right())) {
5310 return false;
5311 }
5312
5313 return emitterScope.leave(this);
5314}
5315
5316bool BytecodeEmitter::emitCopyDataProperties(CopyOption option) {
5317 DebugOnly<int32_t> depth = bytecodeSection().stackDepth();
5318
5319 uint32_t argc;
5320 if (option == CopyOption::Filtered) {
5321 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"
, 5321); AnnotateMozCrashReason("MOZ_ASSERT" "(" "depth > 2"
")"); do { *((volatile int*)__null) = 5321; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5322 // [stack] TARGET SOURCE SET
5323 argc = 3;
5324
5325 if (!emitAtomOp(JSOp::GetIntrinsic,
5326 TaggedParserAtomIndex::WellKnown::CopyDataProperties())) {
5327 // [stack] TARGET SOURCE SET COPYDATAPROPERTIES
5328 return false;
5329 }
5330 } else {
5331 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"
, 5331); AnnotateMozCrashReason("MOZ_ASSERT" "(" "depth > 1"
")"); do { *((volatile int*)__null) = 5331; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5332 // [stack] TARGET SOURCE
5333 argc = 2;
5334
5335 if (!emitAtomOp(
5336 JSOp::GetIntrinsic,
5337 TaggedParserAtomIndex::WellKnown::CopyDataPropertiesUnfiltered())) {
5338 // [stack] TARGET SOURCE COPYDATAPROPERTIES
5339 return false;
5340 }
5341 }
5342
5343 if (!emit1(JSOp::Undefined)) {
5344 // [stack] TARGET SOURCE SET? COPYDATAPROPERTIES
5345 // UNDEFINED
5346 return false;
5347 }
5348 if (!emit2(JSOp::Pick, argc + 1)) {
5349 // [stack] SOURCE SET? COPYDATAPROPERTIES UNDEFINED
5350 // TARGET
5351 return false;
5352 }
5353 if (!emit2(JSOp::Pick, argc + 1)) {
5354 // [stack] SET? COPYDATAPROPERTIES UNDEFINED TARGET
5355 // SOURCE
5356 return false;
5357 }
5358 if (option == CopyOption::Filtered) {
5359 if (!emit2(JSOp::Pick, argc + 1)) {
5360 // [stack] COPYDATAPROPERTIES UNDEFINED TARGET SOURCE SET
5361 return false;
5362 }
5363 }
5364 // Callee is always self-hosted instrinsic, and cannot be content function.
5365 if (!emitCall(JSOp::CallIgnoresRv, argc)) {
5366 // [stack] IGNORED
5367 return false;
5368 }
5369
5370 if (!emit1(JSOp::Pop)) {
5371 // [stack]
5372 return false;
5373 }
5374
5375 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"
, 5375); AnnotateMozCrashReason("MOZ_ASSERT" "(" "depth - int(argc) == bytecodeSection().stackDepth()"
")"); do { *((volatile int*)__null) = 5375; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5376 return true;
5377}
5378
5379bool BytecodeEmitter::emitBigIntOp(BigIntLiteral* bigint) {
5380 GCThingIndex index;
5381 if (!perScriptData().gcThingList().append(bigint, &index)) {
5382 return false;
5383 }
5384 return emitGCIndexOp(JSOp::BigInt, index);
5385}
5386
5387bool BytecodeEmitter::emitIterable(ParseNode* value,
5388 SelfHostedIter selfHostedIter,
5389 IteratorKind iterKind) {
5390 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"
, 5390); AnnotateMozCrashReason("MOZ_ASSERT" "(" "getSelfHostedIterFor(value) == selfHostedIter"
")"); do { *((volatile int*)__null) = 5390; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5391
5392 if (!emitTree(value)) {
5393 // [stack] ITERABLE
5394 return false;
5395 }
5396
5397 switch (selfHostedIter) {
5398 case SelfHostedIter::Deny:
5399 case SelfHostedIter::AllowContent:
5400 // [stack] ITERABLE
5401 return true;
5402
5403 case SelfHostedIter::AllowContentWith: {
5404 // This is the following case:
5405 //
5406 // for (const nextValue of allowContentIterWith(items, usingIterator)) {
5407 //
5408 // `items` is emitted by `emitTree(value)` above, and the result is on the
5409 // stack as ITERABLE.
5410 // `usingIterator` is the value of `items[Symbol.iterator]`, that's
5411 // already retrieved.
5412 ListNode* argsList = value->as<CallNode>().args();
5413 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"
, 5413); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2"
")"); do { *((volatile int*)__null) = 5413; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
5414 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"
, 5414); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 3"
")"); do { *((volatile int*)__null) = 5414; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
5415
5416 if (!emitTree(argsList->head()->pn_next)) {
5417 // [stack] ITERABLE ITERFN
5418 return false;
5419 }
5420
5421 // Async iterator has two possible iterators: An async iterator and a sync
5422 // iterator.
5423 if (iterKind == IteratorKind::Async) {
5424 if (!emitTree(argsList->head()->pn_next->pn_next)) {
5425 // [stack] ITERABLE ASYNC_ITERFN SYNC_ITERFN
5426 return false;
5427 }
5428 }
5429
5430 // [stack] ITERABLE ASYNC_ITERFN? SYNC_ITERFN
5431 return true;
5432 }
5433
5434 case SelfHostedIter::AllowContentWithNext: {
5435 // This is the following case:
5436 //
5437 // for (const nextValue of allowContentIterWithNext(iterator, next)) {
5438 //
5439 // `iterator` is emitted by `emitTree(value)` above, and the result is on
5440 // the stack as ITER.
5441 // `next` is the value of `iterator.next`, that's already retrieved.
5442 ListNode* argsList = value->as<CallNode>().args();
5443 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"
, 5443); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2"
")"); do { *((volatile int*)__null) = 5443; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5444
5445 if (!emitTree(argsList->head()->pn_next)) {
5446 // [stack] ITER NEXT
5447 return false;
5448 }
5449
5450 if (!emit1(JSOp::Swap)) {
5451 // [stack] NEXT ITER
5452 return false;
5453 }
5454
5455 // [stack] NEXT ITER
5456 return true;
5457 }
5458 }
5459
5460 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"
, 5460); AnnotateMozCrashReason("MOZ_CRASH(" "invalid self-hosted iteration kind"
")"); do { *((volatile int*)__null) = 5460; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
5461}
5462
5463bool BytecodeEmitter::emitIterator(SelfHostedIter selfHostedIter) {
5464 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"
, 5467); 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) = 5467; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
5465 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"
, 5467); 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) = 5467; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
5466 "[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"
, 5467); 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) = 5467; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
5467 "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"
, 5467); 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) = 5467; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
5468
5469 if (selfHostedIter == SelfHostedIter::AllowContentWithNext) {
5470 // [stack] NEXT ITER
5471
5472 // Nothing to do, stack already contains the iterator and its `next` method.
5473 return true;
5474 }
5475
5476 if (selfHostedIter != SelfHostedIter::AllowContentWith) {
5477 // [stack] OBJ
5478
5479 // Convert iterable to iterator.
5480 if (!emit1(JSOp::Dup)) {
5481 // [stack] OBJ OBJ
5482 return false;
5483 }
5484 if (!emit2(JSOp::Symbol, uint8_t(JS::SymbolCode::iterator))) {
5485 // [stack] OBJ OBJ @@ITERATOR
5486 return false;
5487 }
5488 if (!emitElemOpBase(JSOp::GetElem)) {
5489 // [stack] OBJ ITERFN
5490 return false;
5491 }
5492 }
5493
5494 if (!emit1(JSOp::Swap)) {
5495 // [stack] ITERFN OBJ
5496 return false;
5497 }
5498 if (!emitCall(getIterCallOp(JSOp::CallIter, selfHostedIter), 0)) {
5499 // [stack] ITER
5500 return false;
5501 }
5502 if (!emitCheckIsObj(CheckIsObjectKind::GetIterator)) {
5503 // [stack] ITER
5504 return false;
5505 }
5506 if (!emit1(JSOp::Dup)) {
5507 // [stack] ITER ITER
5508 return false;
5509 }
5510 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::next())) {
5511 // [stack] ITER NEXT
5512 return false;
5513 }
5514 if (!emit1(JSOp::Swap)) {
5515 // [stack] NEXT ITER
5516 return false;
5517 }
5518 return true;
5519}
5520
5521bool BytecodeEmitter::emitAsyncIterator(SelfHostedIter selfHostedIter) {
5522 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"
, 5522); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::AllowContentWithNext"
")"); do { *((volatile int*)__null) = 5522; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5523 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"
, 5526); 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) = 5526; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
5524 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"
, 5526); 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) = 5526; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
5525 "[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"
, 5526); 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) = 5526; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
5526 "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"
, 5526); 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) = 5526; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
5527
5528 if (selfHostedIter != SelfHostedIter::AllowContentWith) {
5529 // [stack] OBJ
5530
5531 // Convert iterable to iterator.
5532 if (!emit1(JSOp::Dup)) {
5533 // [stack] OBJ OBJ
5534 return false;
5535 }
5536 if (!emit2(JSOp::Symbol, uint8_t(JS::SymbolCode::asyncIterator))) {
5537 // [stack] OBJ OBJ @@ASYNCITERATOR
5538 return false;
5539 }
5540 if (!emitElemOpBase(JSOp::GetElem)) {
5541 // [stack] OBJ ASYNC_ITERFN
5542 return false;
5543 }
5544 } else {
5545 // [stack] OBJ ASYNC_ITERFN SYNC_ITERFN
5546
5547 if (!emitElemOpBase(JSOp::Swap)) {
5548 // [stack] OBJ SYNC_ITERFN ASYNC_ITERFN
5549 return false;
5550 }
5551 }
5552
5553 InternalIfEmitter ifAsyncIterIsUndefined(this);
5554 if (!emit1(JSOp::IsNullOrUndefined)) {
5555 // [stack] OBJ SYNC_ITERFN? ASYNC_ITERFN NULL-OR-UNDEF
5556 return false;
5557 }
5558 if (!ifAsyncIterIsUndefined.emitThenElse()) {
5559 // [stack] OBJ SYNC_ITERFN? ASYNC_ITERFN
5560 return false;
5561 }
5562
5563 if (!emit1(JSOp::Pop)) {
5564 // [stack] OBJ SYNC_ITERFN?
5565 return false;
5566 }
5567
5568 if (selfHostedIter != SelfHostedIter::AllowContentWith) {
5569 if (!emit1(JSOp::Dup)) {
5570 // [stack] OBJ OBJ
5571 return false;
5572 }
5573 if (!emit2(JSOp::Symbol, uint8_t(JS::SymbolCode::iterator))) {
5574 // [stack] OBJ OBJ @@ITERATOR
5575 return false;
5576 }
5577 if (!emitElemOpBase(JSOp::GetElem)) {
5578 // [stack] OBJ SYNC_ITERFN
5579 return false;
5580 }
5581 } else {
5582 // [stack] OBJ SYNC_ITERFN
5583 }
5584
5585 if (!emit1(JSOp::Swap)) {
5586 // [stack] SYNC_ITERFN OBJ
5587 return false;
5588 }
5589 if (!emitCall(getIterCallOp(JSOp::CallIter, selfHostedIter), 0)) {
5590 // [stack] ITER
5591 return false;
5592 }
5593 if (!emitCheckIsObj(CheckIsObjectKind::GetIterator)) {
5594 // [stack] ITER
5595 return false;
5596 }
5597
5598 if (!emit1(JSOp::Dup)) {
5599 // [stack] ITER ITER
5600 return false;
5601 }
5602 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::next())) {
5603 // [stack] ITER SYNCNEXT
5604 return false;
5605 }
5606
5607 if (!emit1(JSOp::ToAsyncIter)) {
5608 // [stack] ITER
5609 return false;
5610 }
5611
5612 if (!ifAsyncIterIsUndefined.emitElse()) {
5613 // [stack] OBJ SYNC_ITERFN? ASYNC_ITERFN
5614 return false;
5615 }
5616
5617 if (selfHostedIter == SelfHostedIter::AllowContentWith) {
5618 if (!emit1(JSOp::Swap)) {
5619 // [stack] OBJ ASYNC_ITERFN SYNC_ITERFN
5620 return false;
5621 }
5622 if (!emit1(JSOp::Pop)) {
5623 // [stack] OBJ ASYNC_ITERFN
5624 return false;
5625 }
5626 }
5627
5628 if (!emit1(JSOp::Swap)) {
5629 // [stack] ASYNC_ITERFN OBJ
5630 return false;
5631 }
5632 if (!emitCall(getIterCallOp(JSOp::CallIter, selfHostedIter), 0)) {
5633 // [stack] ITER
5634 return false;
5635 }
5636 if (!emitCheckIsObj(CheckIsObjectKind::GetAsyncIterator)) {
5637 // [stack] ITER
5638 return false;
5639 }
5640
5641 if (!ifAsyncIterIsUndefined.emitEnd()) {
5642 // [stack] ITER
5643 return false;
5644 }
5645
5646 if (!emit1(JSOp::Dup)) {
5647 // [stack] ITER ITER
5648 return false;
5649 }
5650 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::next())) {
5651 // [stack] ITER NEXT
5652 return false;
5653 }
5654 if (!emit1(JSOp::Swap)) {
5655 // [stack] NEXT ITER
5656 return false;
5657 }
5658
5659 return true;
5660}
5661
5662bool BytecodeEmitter::emitSpread(SelfHostedIter selfHostedIter) {
5663 // [stack] NEXT ITER ARR I
5664 return emitSpread(selfHostedIter, 2, JSOp::InitElemInc);
5665 // [stack] ARR FINAL_INDEX
5666}
5667
5668bool BytecodeEmitter::emitSpread(SelfHostedIter selfHostedIter,
5669 int spreadeeStackItems, JSOp storeElementOp) {
5670 LoopControl loopInfo(this, StatementKind::Spread);
5671 // In the [stack] annotations, (spreadee) can be "ARR I" (when spreading
5672 // into an array or into call parameters, or "TUPLE" (when spreading into a
5673 // tuple)
5674
5675 if (!loopInfo.emitLoopHead(this, Nothing())) {
5676 // [stack] NEXT ITER (spreadee)
5677 return false;
5678 }
5679
5680 {
5681#ifdef DEBUG1
5682 auto loopDepth = bytecodeSection().stackDepth();
5683#endif
5684
5685 // Spread operations can't contain |continue|, so don't bother setting loop
5686 // and enclosing "update" offsets, as we do with for-loops.
5687
5688 if (!emitDupAt(spreadeeStackItems + 1, 2)) {
5689 // [stack] NEXT ITER (spreadee) NEXT ITER
5690 return false;
5691 }
5692 if (!emitIteratorNext(Nothing(), IteratorKind::Sync, selfHostedIter)) {
5693 // [stack] NEXT ITER (spreadee) RESULT
5694 return false;
5695 }
5696 if (!emit1(JSOp::Dup)) {
5697 // [stack] NEXT ITER (spreadee) RESULT RESULT
5698 return false;
5699 }
5700 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::done())) {
5701 // [stack] NEXT ITER (spreadee) RESULT DONE
5702 return false;
5703 }
5704 if (!emitJump(JSOp::JumpIfTrue, &loopInfo.breaks)) {
5705 // [stack] NEXT ITER (spreadee) RESULT
5706 return false;
5707 }
5708
5709 // Emit code to assign result.value to the iteration variable.
5710 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::value())) {
5711 // [stack] NEXT ITER (spreadee) VALUE
5712 return false;
5713 }
5714 if (!emit1(storeElementOp)) {
5715 // [stack] NEXT ITER (spreadee)
5716 return false;
5717 }
5718
5719 if (!loopInfo.emitLoopEnd(this, JSOp::Goto, TryNoteKind::ForOf)) {
5720 // [stack] NEXT ITER (spreadee)
5721 return false;
5722 }
5723
5724 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"
, 5724); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == loopDepth"
")"); do { *((volatile int*)__null) = 5724; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5725 }
5726
5727 // When we leave the loop body and jump to this point, the result value is
5728 // still on the stack. Account for that by updating the stack depth
5729 // manually.
5730 bytecodeSection().setStackDepth(bytecodeSection().stackDepth() + 1);
5731
5732 // No continues should occur in spreads.
5733 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"
, 5733); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!loopInfo.continues.offset.valid()"
")"); do { *((volatile int*)__null) = 5733; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5734
5735 if (!emit2(JSOp::Pick, spreadeeStackItems + 2)) {
5736 // [stack] ITER (spreadee) RESULT NEXT
5737 return false;
5738 }
5739 if (!emit2(JSOp::Pick, spreadeeStackItems + 2)) {
5740 // [stack] (spreadee) RESULT NEXT ITER
5741 return false;
5742 }
5743
5744 return emitPopN(3);
5745 // [stack] (spreadee)
5746}
5747
5748bool BytecodeEmitter::emitInitializeForInOrOfTarget(TernaryNode* forHead) {
5749 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"
, 5750); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forHead->isKind(ParseNodeKind::ForIn) || forHead->isKind(ParseNodeKind::ForOf)"
")"); do { *((volatile int*)__null) = 5750; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5750 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"
, 5750); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forHead->isKind(ParseNodeKind::ForIn) || forHead->isKind(ParseNodeKind::ForOf)"
")"); do { *((volatile int*)__null) = 5750; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5751
5752 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"
, 5753); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() >= 1"
") (" "must have a per-iteration value for initializing" ")"
); do { *((volatile int*)__null) = 5753; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5753 "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"
, 5753); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() >= 1"
") (" "must have a per-iteration value for initializing" ")"
); do { *((volatile int*)__null) = 5753; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5754
5755 ParseNode* target = forHead->kid1();
5756 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"
, 5756); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!forHead->kid2()"
")"); do { *((volatile int*)__null) = 5756; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5757
5758 // If the for-in/of loop didn't have a variable declaration, per-loop
5759 // initialization is just assigning the iteration value to a target
5760 // expression.
5761 if (!target->is<DeclarationListNode>()) {
5762 return emitAssignmentOrInit(ParseNodeKind::AssignExpr, target, nullptr);
5763 // [stack] ... ITERVAL
5764 }
5765
5766 // Otherwise, per-loop initialization is (possibly) declaration
5767 // initialization. If the declaration is a lexical declaration, it must be
5768 // initialized. If the declaration is a variable declaration, an
5769 // assignment to that name (which does *not* necessarily assign to the
5770 // variable!) must be generated.
5771
5772 auto* declarationList = &target->as<DeclarationListNode>();
5773 if (!updateSourceCoordNotes(declarationList->pn_pos.begin)) {
5774 return false;
5775 }
5776
5777 target = declarationList->singleBinding();
5778
5779 NameNode* nameNode = nullptr;
5780 if (target->isKind(ParseNodeKind::Name)) {
5781 nameNode = &target->as<NameNode>();
5782 } else if (target->isKind(ParseNodeKind::AssignExpr)) {
5783 BinaryNode* assignNode = &target->as<BinaryNode>();
5784 if (assignNode->left()->is<NameNode>()) {
5785 nameNode = &assignNode->left()->as<NameNode>();
5786 }
5787 }
5788
5789 if (nameNode) {
5790 auto nameAtom = nameNode->name();
5791 NameOpEmitter noe(this, nameAtom, NameOpEmitter::Kind::Initialize);
5792 if (!noe.prepareForRhs()) {
5793 return false;
5794 }
5795 if (noe.emittedBindOp()) {
5796 // Per-iteration initialization in for-in/of loops computes the
5797 // iteration value *before* initializing. Thus the initializing
5798 // value may be buried under a bind-specific value on the stack.
5799 // Swap it to the top of the stack.
5800 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"
, 5800); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() >= 2"
")"); do { *((volatile int*)__null) = 5800; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5801 if (!emit1(JSOp::Swap)) {
5802 return false;
5803 }
5804 } else {
5805 // In cases of emitting a frame slot or environment slot,
5806 // nothing needs be done.
5807 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"
, 5807); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() >= 1"
")"); do { *((volatile int*)__null) = 5807; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5808 }
5809
5810#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
5811 if (declarationList->isKind(ParseNodeKind::UsingDecl)) {
5812 if (!innermostEmitterScope()->prepareForDisposableAssignment(
5813 UsingHint::Sync)) {
5814 // [stack] ENV? V
5815 return false;
5816 }
5817 }
5818#endif
5819
5820 if (!noe.emitAssignment()) {
5821 return false;
5822 }
5823
5824 // The caller handles removing the iteration value from the stack.
5825 return true;
5826 }
5827
5828 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"
, 5830); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!target->isKind(ParseNodeKind::AssignExpr)"
") (" "for-in/of loop destructuring declarations can't have initializers"
")"); do { *((volatile int*)__null) = 5830; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5829 !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"
, 5830); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!target->isKind(ParseNodeKind::AssignExpr)"
") (" "for-in/of loop destructuring declarations can't have initializers"
")"); do { *((volatile int*)__null) = 5830; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5830 "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"
, 5830); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!target->isKind(ParseNodeKind::AssignExpr)"
") (" "for-in/of loop destructuring declarations can't have initializers"
")"); do { *((volatile int*)__null) = 5830; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5831
5832 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"
, 5833); AnnotateMozCrashReason("MOZ_ASSERT" "(" "target->isKind(ParseNodeKind::ArrayExpr) || target->isKind(ParseNodeKind::ObjectExpr)"
")"); do { *((volatile int*)__null) = 5833; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5833 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"
, 5833); AnnotateMozCrashReason("MOZ_ASSERT" "(" "target->isKind(ParseNodeKind::ArrayExpr) || target->isKind(ParseNodeKind::ObjectExpr)"
")"); do { *((volatile int*)__null) = 5833; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5834 return emitDestructuringOps(&target->as<ListNode>(),
5835 DestructuringFlavor::Declaration);
5836}
5837
5838bool BytecodeEmitter::emitForOf(ForNode* forOfLoop,
5839 const EmitterScope* headLexicalEmitterScope) {
5840 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"
, 5840); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfLoop->isKind(ParseNodeKind::ForStmt)"
")"); do { *((volatile int*)__null) = 5840; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5841
5842 TernaryNode* forOfHead = forOfLoop->head();
5843 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"
, 5843); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfHead->isKind(ParseNodeKind::ForOf)"
")"); do { *((volatile int*)__null) = 5843; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5844
5845 unsigned iflags = forOfLoop->iflags();
5846 IteratorKind iterKind =
5847 (iflags & JSITER_FORAWAITOF0x80) ? IteratorKind::Async : IteratorKind::Sync;
5848 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"
, 5848); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isSuspendableContext()"
")"); do { *((volatile int*)__null) = 5848; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
5849 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"
, 5850); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->asSuspendableContext()->isAsync()"
")"); do { *((volatile int*)__null) = 5850; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
5850 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"
, 5850); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->asSuspendableContext()->isAsync()"
")"); do { *((volatile int*)__null) = 5850; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
5851
5852 ParseNode* forHeadExpr = forOfHead->kid3();
5853
5854 // Certain builtins (e.g. Array.from) are implemented in self-hosting
5855 // as for-of loops.
5856 auto selfHostedIter = getSelfHostedIterFor(forHeadExpr);
5857 ForOfEmitter forOf(this, headLexicalEmitterScope, selfHostedIter, iterKind
5858#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
5859 ,
5860 forOfHead->kid1()->isKind(ParseNodeKind::UsingDecl)
5861 ? ForOfEmitter::HasUsingDeclarationInHead::Yes
5862 : ForOfEmitter::HasUsingDeclarationInHead::No
5863#endif
5864 );
5865
5866 if (!forOf.emitIterated()) {
5867 // [stack]
5868 return false;
5869 }
5870
5871 if (!updateSourceCoordNotes(forHeadExpr->pn_pos.begin)) {
5872 return false;
5873 }
5874 if (!markStepBreakpoint()) {
5875 return false;
5876 }
5877 if (!emitIterable(forHeadExpr, selfHostedIter, iterKind)) {
5878 // [stack] ITERABLE
5879 return false;
5880 }
5881
5882 if (headLexicalEmitterScope) {
5883 DebugOnly<ParseNode*> forOfTarget = forOfHead->kid1();
5884 MOZ_ASSERT(forOfTarget->isKind(ParseNodeKind::LetDecl) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget
->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
|| forOfTarget->isKind(ParseNodeKind::UsingDecl)endif)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget
->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
|| forOfTarget->isKind(ParseNodeKind::UsingDecl)endif))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl)endif"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5889); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl)endif"
")"); do { *((volatile int*)__null) = 5889; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5885 forOfTarget->isKind(ParseNodeKind::ConstDecl)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget
->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
|| forOfTarget->isKind(ParseNodeKind::UsingDecl)endif)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget
->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
|| forOfTarget->isKind(ParseNodeKind::UsingDecl)endif))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl)endif"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5889); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl)endif"
")"); do { *((volatile int*)__null) = 5889; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5886#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENTdo { static_assert( mozilla::detail::AssertionConditionType<
decltype(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget
->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
|| forOfTarget->isKind(ParseNodeKind::UsingDecl)endif)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget
->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
|| forOfTarget->isKind(ParseNodeKind::UsingDecl)endif))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl)endif"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5889); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl)endif"
")"); do { *((volatile int*)__null) = 5889; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5887 || forOfTarget->isKind(ParseNodeKind::UsingDecl)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget
->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
|| forOfTarget->isKind(ParseNodeKind::UsingDecl)endif)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget
->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
|| forOfTarget->isKind(ParseNodeKind::UsingDecl)endif))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl)endif"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5889); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl)endif"
")"); do { *((volatile int*)__null) = 5889; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5888#endifdo { static_assert( mozilla::detail::AssertionConditionType<
decltype(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget
->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
|| forOfTarget->isKind(ParseNodeKind::UsingDecl)endif)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget
->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
|| forOfTarget->isKind(ParseNodeKind::UsingDecl)endif))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl)endif"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5889); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl)endif"
")"); do { *((volatile int*)__null) = 5889; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5889 )do { static_assert( mozilla::detail::AssertionConditionType<
decltype(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget
->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
|| forOfTarget->isKind(ParseNodeKind::UsingDecl)endif)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget
->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
|| forOfTarget->isKind(ParseNodeKind::UsingDecl)endif))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl)endif"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 5889); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl)endif"
")"); do { *((volatile int*)__null) = 5889; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5890 }
5891
5892 if (!forOf.emitInitialize(forOfHead->pn_pos.begin)) {
5893 // [stack] NEXT ITER VALUE
5894 return false;
5895 }
5896
5897 if (!emitInitializeForInOrOfTarget(forOfHead)) {
5898 // [stack] NEXT ITER VALUE
5899 return false;
5900 }
5901
5902 if (!forOf.emitBody()) {
5903 // [stack] NEXT ITER UNDEF
5904 return false;
5905 }
5906
5907 // Perform the loop body.
5908 ParseNode* forBody = forOfLoop->body();
5909 if (!emitTree(forBody)) {
5910 // [stack] NEXT ITER UNDEF
5911 return false;
5912 }
5913
5914 if (!forOf.emitEnd(forHeadExpr->pn_pos.begin)) {
5915 // [stack]
5916 return false;
5917 }
5918
5919 return true;
5920}
5921
5922bool BytecodeEmitter::emitForIn(ForNode* forInLoop,
5923 const EmitterScope* headLexicalEmitterScope) {
5924 TernaryNode* forInHead = forInLoop->head();
5925 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"
, 5925); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInHead->isKind(ParseNodeKind::ForIn)"
")"); do { *((volatile int*)__null) = 5925; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5926
5927 ForInEmitter forIn(this, headLexicalEmitterScope);
5928
5929 // Annex B: Evaluate the var-initializer expression if present.
5930 // |for (var i = initializer in expr) { ... }|
5931 ParseNode* forInTarget = forInHead->kid1();
5932 if (forInTarget->is<DeclarationListNode>()) {
5933 auto* declarationList = &forInTarget->as<DeclarationListNode>();
5934
5935 ParseNode* decl = declarationList->singleBinding();
5936 if (decl->isKind(ParseNodeKind::AssignExpr)) {
5937 BinaryNode* assignNode = &decl->as<BinaryNode>();
5938 if (assignNode->left()->is<NameNode>()) {
5939 NameNode* nameNode = &assignNode->left()->as<NameNode>();
5940 ParseNode* initializer = assignNode->right();
5941 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"
, 5943); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInTarget->isKind(ParseNodeKind::VarStmt)"
") (" "for-in initializers are only permitted for |var| declarations"
")"); do { *((volatile int*)__null) = 5943; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5942 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"
, 5943); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInTarget->isKind(ParseNodeKind::VarStmt)"
") (" "for-in initializers are only permitted for |var| declarations"
")"); do { *((volatile int*)__null) = 5943; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5943 "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"
, 5943); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInTarget->isKind(ParseNodeKind::VarStmt)"
") (" "for-in initializers are only permitted for |var| declarations"
")"); do { *((volatile int*)__null) = 5943; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5944
5945 if (!updateSourceCoordNotes(decl->pn_pos.begin)) {
5946 return false;
5947 }
5948
5949 auto nameAtom = nameNode->name();
5950 NameOpEmitter noe(this, nameAtom, NameOpEmitter::Kind::Initialize);
5951 if (!noe.prepareForRhs()) {
5952 return false;
5953 }
5954 if (!emitInitializer(initializer, nameNode)) {
5955 return false;
5956 }
5957 if (!noe.emitAssignment()) {
5958 return false;
5959 }
5960
5961 // Pop the initializer.
5962 if (!emit1(JSOp::Pop)) {
5963 return false;
5964 }
5965 }
5966 }
5967 }
5968
5969 if (!forIn.emitIterated()) {
5970 // [stack]
5971 return false;
5972 }
5973
5974 // Evaluate the expression being iterated.
5975 ParseNode* expr = forInHead->kid3();
5976
5977 if (!updateSourceCoordNotes(expr->pn_pos.begin)) {
5978 return false;
5979 }
5980 if (!markStepBreakpoint()) {
5981 return false;
5982 }
5983 if (!emitTree(expr)) {
5984 // [stack] EXPR
5985 return false;
5986 }
5987
5988 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"
, 5988); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInLoop->iflags() == 0"
")"); do { *((volatile int*)__null) = 5988; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5989
5990 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"
, 5992); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInTarget->isKind(ParseNodeKind::LetDecl) || forInTarget->isKind(ParseNodeKind::ConstDecl)"
")"); do { *((volatile int*)__null) = 5992; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
5991 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"
, 5992); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInTarget->isKind(ParseNodeKind::LetDecl) || forInTarget->isKind(ParseNodeKind::ConstDecl)"
")"); do { *((volatile int*)__null) = 5992; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
5992 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"
, 5992); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInTarget->isKind(ParseNodeKind::LetDecl) || forInTarget->isKind(ParseNodeKind::ConstDecl)"
")"); do { *((volatile int*)__null) = 5992; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
5993
5994 if (!forIn.emitInitialize()) {
5995 // [stack] ITER ITERVAL
5996 return false;
5997 }
5998
5999 if (!emitInitializeForInOrOfTarget(forInHead)) {
6000 // [stack] ITER ITERVAL
6001 return false;
6002 }
6003
6004 if (!forIn.emitBody()) {
6005 // [stack] ITER ITERVAL
6006 return false;
6007 }
6008
6009 // Perform the loop body.
6010 ParseNode* forBody = forInLoop->body();
6011 if (!emitTree(forBody)) {
6012 // [stack] ITER ITERVAL
6013 return false;
6014 }
6015
6016 if (!forIn.emitEnd(forInHead->pn_pos.begin)) {
6017 // [stack]
6018 return false;
6019 }
6020
6021 return true;
6022}
6023
6024/* C-style `for (init; cond; update) ...` loop. */
6025bool BytecodeEmitter::emitCStyleFor(
6026 ForNode* forNode, const EmitterScope* headLexicalEmitterScope) {
6027 TernaryNode* forHead = forNode->head();
6028 ParseNode* forBody = forNode->body();
6029 ParseNode* init = forHead->kid1();
6030 ParseNode* cond = forHead->kid2();
6031 ParseNode* update = forHead->kid3();
6032 bool isLet = init && init->isKind(ParseNodeKind::LetDecl);
6033
6034 CForEmitter cfor(this, isLet ? headLexicalEmitterScope : nullptr);
6035
6036 if (!cfor.emitInit(init ? Some(init->pn_pos.begin) : Nothing())) {
6037 // [stack]
6038 return false;
6039 }
6040
6041 // If the head of this for-loop declared any lexical variables, the parser
6042 // wrapped this ParseNodeKind::For node in a ParseNodeKind::LexicalScope
6043 // representing the implicit scope of those variables. By the time we get
6044 // here, we have already entered that scope. So far, so good.
6045 if (init) {
6046 // Emit the `init` clause, whether it's an expression or a variable
6047 // declaration. (The loop variables were hoisted into an enclosing
6048 // scope, but we still need to emit code for the initializers.)
6049 if (init->is<DeclarationListNode>()) {
6050 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"
, 6050); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!init->as<DeclarationListNode>().empty()"
")"); do { *((volatile int*)__null) = 6050; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6051
6052 if (!emitTree(init)) {
6053 // [stack]
6054 return false;
6055 }
6056 } else {
6057 if (!updateSourceCoordNotes(init->pn_pos.begin)) {
6058 return false;
6059 }
6060 if (!markStepBreakpoint()) {
6061 return false;
6062 }
6063
6064 // 'init' is an expression, not a declaration. emitTree left its
6065 // value on the stack.
6066 if (!emitTree(init, ValueUsage::IgnoreValue)) {
6067 // [stack] VAL
6068 return false;
6069 }
6070 if (!emit1(JSOp::Pop)) {
6071 // [stack]
6072 return false;
6073 }
6074 }
6075 }
6076
6077 if (!cfor.emitCond(cond ? Some(cond->pn_pos.begin) : Nothing())) {
6078 // [stack]
6079 return false;
6080 }
6081
6082 if (cond) {
6083 if (!updateSourceCoordNotes(cond->pn_pos.begin)) {
6084 return false;
6085 }
6086 if (!markStepBreakpoint()) {
6087 return false;
6088 }
6089 if (!emitTree(cond)) {
6090 // [stack] VAL
6091 return false;
6092 }
6093 }
6094
6095 if (!cfor.emitBody(cond ? CForEmitter::Cond::Present
6096 : CForEmitter::Cond::Missing)) {
6097 // [stack]
6098 return false;
6099 }
6100
6101 if (!emitTree(forBody)) {
6102 // [stack]
6103 return false;
6104 }
6105
6106 if (!cfor.emitUpdate(
6107 update ? CForEmitter::Update::Present : CForEmitter::Update::Missing,
6108 update ? Some(update->pn_pos.begin) : Nothing())) {
6109 // [stack]
6110 return false;
6111 }
6112
6113 // Check for update code to do before the condition (if any).
6114 if (update) {
6115 if (!updateSourceCoordNotes(update->pn_pos.begin)) {
6116 return false;
6117 }
6118 if (!markStepBreakpoint()) {
6119 return false;
6120 }
6121 if (!emitTree(update, ValueUsage::IgnoreValue)) {
6122 // [stack] VAL
6123 return false;
6124 }
6125 }
6126
6127 if (!cfor.emitEnd(forNode->pn_pos.begin)) {
6128 // [stack]
6129 return false;
6130 }
6131
6132 return true;
6133}
6134
6135bool BytecodeEmitter::emitFor(ForNode* forNode,
6136 const EmitterScope* headLexicalEmitterScope) {
6137 if (forNode->head()->isKind(ParseNodeKind::ForHead)) {
6138 return emitCStyleFor(forNode, headLexicalEmitterScope);
6139 }
6140
6141 if (!updateLineNumberNotes(forNode->pn_pos.begin)) {
6142 return false;
6143 }
6144
6145 if (forNode->head()->isKind(ParseNodeKind::ForIn)) {
6146 return emitForIn(forNode, headLexicalEmitterScope);
6147 }
6148
6149 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"
, 6149); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forNode->head()->isKind(ParseNodeKind::ForOf)"
")"); do { *((volatile int*)__null) = 6149; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6150 return emitForOf(forNode, headLexicalEmitterScope);
6151}
6152
6153MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitFunction(
6154 FunctionNode* funNode, bool needsProto /* = false */) {
6155 FunctionBox* funbox = funNode->funbox();
6156
6157 // [stack]
6158
6159 FunctionEmitter fe(this, funbox, funNode->syntaxKind(),
6160 funNode->functionIsHoisted()
6161 ? FunctionEmitter::IsHoisted::Yes
6162 : FunctionEmitter::IsHoisted::No);
6163
6164 // |wasEmittedByEnclosingScript| flag is set to true once the function has
6165 // been emitted. Function definitions that need hoisting to the top of the
6166 // function will be seen by emitFunction in two places.
6167 if (funbox->wasEmittedByEnclosingScript()) {
6168 if (!fe.emitAgain()) {
6169 // [stack]
6170 return false;
6171 }
6172 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"
, 6172); AnnotateMozCrashReason("MOZ_ASSERT" "(" "funNode->functionIsHoisted()"
")"); do { *((volatile int*)__null) = 6172; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6173 } else if (funbox->isInterpreted()) {
6174 if (!funbox->emitBytecode) {
6175 return fe.emitLazy();
6176 // [stack] FUN?
6177 }
6178
6179 if (!fe.prepareForNonLazy()) {
6180 // [stack]
6181 return false;
6182 }
6183
6184 BytecodeEmitter bce2(this, funbox);
6185 if (!bce2.init(funNode->pn_pos)) {
6186 return false;
6187 }
6188
6189 /* We measured the max scope depth when we parsed the function. */
6190 if (!bce2.emitFunctionScript(funNode)) {
6191 return false;
6192 }
6193
6194 if (!fe.emitNonLazyEnd()) {
6195 // [stack] FUN?
6196 return false;
6197 }
6198 } else {
6199 if (!fe.emitAsmJSModule()) {
6200 // [stack]
6201 return false;
6202 }
6203 }
6204
6205 // Track the last emitted top-level self-hosted function, so that intrinsics
6206 // can adjust attributes at parse time.
6207 //
6208 // NOTE: We also disallow lambda functions in the top-level body. This is done
6209 // to simplify handling of the self-hosted stencil. Within normal function
6210 // declarations there are no such restrictions.
6211 if (emitterMode == EmitterMode::SelfHosting) {
6212 if (sc->isTopLevelContext()) {
6213 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"
, 6213); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!funbox->isLambda()"
")"); do { *((volatile int*)__null) = 6213; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6214 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"
, 6214); AnnotateMozCrashReason("MOZ_ASSERT" "(" "funbox->explicitName()"
")"); do { *((volatile int*)__null) = 6214; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6215 prevSelfHostedTopLevelFunction = funbox;
6216 }
6217 }
6218
6219 return true;
6220}
6221
6222bool BytecodeEmitter::emitDo(BinaryNode* doNode) {
6223 ParseNode* bodyNode = doNode->left();
6224
6225 DoWhileEmitter doWhile(this);
6226 if (!doWhile.emitBody(doNode->pn_pos.begin, getOffsetForLoop(bodyNode))) {
6227 return false;
6228 }
6229
6230 if (!emitTree(bodyNode)) {
6231 return false;
6232 }
6233
6234 if (!doWhile.emitCond()) {
6235 return false;
6236 }
6237
6238 ParseNode* condNode = doNode->right();
6239 if (!updateSourceCoordNotes(condNode->pn_pos.begin)) {
6240 return false;
6241 }
6242 if (!markStepBreakpoint()) {
6243 return false;
6244 }
6245 if (!emitTree(condNode)) {
6246 return false;
6247 }
6248
6249 if (!doWhile.emitEnd()) {
6250 return false;
6251 }
6252
6253 return true;
6254}
6255
6256bool BytecodeEmitter::emitWhile(BinaryNode* whileNode) {
6257 ParseNode* bodyNode = whileNode->right();
6258
6259 WhileEmitter wh(this);
6260
6261 ParseNode* condNode = whileNode->left();
6262 if (!wh.emitCond(whileNode->pn_pos.begin, getOffsetForLoop(condNode),
6263 whileNode->pn_pos.end)) {
6264 return false;
6265 }
6266
6267 if (!updateSourceCoordNotes(condNode->pn_pos.begin)) {
6268 return false;
6269 }
6270 if (!markStepBreakpoint()) {
6271 return false;
6272 }
6273 if (!emitTree(condNode)) {
6274 return false;
6275 }
6276
6277 if (!wh.emitBody()) {
6278 return false;
6279 }
6280 if (!emitTree(bodyNode)) {
6281 return false;
6282 }
6283
6284 if (!wh.emitEnd()) {
6285 return false;
6286 }
6287
6288 return true;
6289}
6290
6291bool BytecodeEmitter::emitBreak(TaggedParserAtomIndex label) {
6292 BreakableControl* target;
6293 if (label) {
6294 // Any statement with the matching label may be the break target.
6295 auto hasSameLabel = [label](LabelControl* labelControl) {
6296 return labelControl->label() == label;
6297 };
6298 target = findInnermostNestableControl<LabelControl>(hasSameLabel);
6299 } else {
6300 auto isNotLabel = [](BreakableControl* control) {
6301 return !control->is<LabelControl>();
6302 };
6303 target = findInnermostNestableControl<BreakableControl>(isNotLabel);
6304 }
6305
6306 return emitGoto(target, GotoKind::Break);
6307}
6308
6309bool BytecodeEmitter::emitContinue(TaggedParserAtomIndex label) {
6310 LoopControl* target = nullptr;
6311 if (label) {
6312 // Find the loop statement enclosed by the matching label.
6313 NestableControl* control = innermostNestableControl;
6314 while (!control->is<LabelControl>() ||
6315 control->as<LabelControl>().label() != label) {
6316 if (control->is<LoopControl>()) {
6317 target = &control->as<LoopControl>();
6318 }
6319 control = control->enclosing();
6320 }
6321 } else {
6322 target = findInnermostNestableControl<LoopControl>();
6323 }
6324 return emitGoto(target, GotoKind::Continue);
6325}
6326
6327bool BytecodeEmitter::emitGetFunctionThis(NameNode* thisName) {
6328 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"
, 6328); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->hasFunctionThisBinding()"
")"); do { *((volatile int*)__null) = 6328; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6329 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"
, 6329); AnnotateMozCrashReason("MOZ_ASSERT" "(" "thisName->isName(TaggedParserAtomIndex::WellKnown::dot_this_())"
")"); do { *((volatile int*)__null) = 6329; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6330
6331 if (!updateLineNumberNotes(thisName->pn_pos.begin)) {
6332 return false;
6333 }
6334
6335 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_this_())) {
6336 // [stack] THIS
6337 return false;
6338 }
6339 if (sc->needsThisTDZChecks()) {
6340 if (!emit1(JSOp::CheckThis)) {
6341 // [stack] THIS
6342 return false;
6343 }
6344 }
6345
6346 return true;
6347}
6348
6349bool BytecodeEmitter::emitGetThisForSuperBase(UnaryNode* superBase) {
6350 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"
, 6350); AnnotateMozCrashReason("MOZ_ASSERT" "(" "superBase->isKind(ParseNodeKind::SuperBase)"
")"); do { *((volatile int*)__null) = 6350; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6351 NameNode* nameNode = &superBase->kid()->as<NameNode>();
6352 return emitGetFunctionThis(nameNode);
6353 // [stack] THIS
6354}
6355
6356bool BytecodeEmitter::emitThisLiteral(ThisLiteral* pn) {
6357 if (ParseNode* kid = pn->kid()) {
6358 NameNode* thisName = &kid->as<NameNode>();
6359 return emitGetFunctionThis(thisName);
6360 // [stack] THIS
6361 }
6362
6363 if (sc->thisBinding() == ThisBinding::Module) {
6364 return emit1(JSOp::Undefined);
6365 // [stack] UNDEF
6366 }
6367
6368 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"
, 6368); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->thisBinding() == ThisBinding::Global"
")"); do { *((volatile int*)__null) = 6368; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6369
6370 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"
, 6371); AnnotateMozCrashReason("MOZ_ASSERT" "(" "outermostScope().hasNonSyntacticScopeOnChain() == sc->hasNonSyntacticScope()"
")"); do { *((volatile int*)__null) = 6371; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6371 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"
, 6371); AnnotateMozCrashReason("MOZ_ASSERT" "(" "outermostScope().hasNonSyntacticScopeOnChain() == sc->hasNonSyntacticScope()"
")"); do { *((volatile int*)__null) = 6371; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6372 if (sc->hasNonSyntacticScope()) {
6373 return emit1(JSOp::NonSyntacticGlobalThis);
6374 // [stack] THIS
6375 }
6376
6377 return emit1(JSOp::GlobalThis);
6378 // [stack] THIS
6379}
6380
6381bool BytecodeEmitter::emitCheckDerivedClassConstructorReturn() {
6382 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"
, 6383); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lookupName(TaggedParserAtomIndex::WellKnown::dot_this_()).hasKnownSlot()"
")"); do { *((volatile int*)__null) = 6383; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6383 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"
, 6383); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lookupName(TaggedParserAtomIndex::WellKnown::dot_this_()).hasKnownSlot()"
")"); do { *((volatile int*)__null) = 6383; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6384 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_this_())) {
6385 return false;
6386 }
6387 if (!emit1(JSOp::CheckReturn)) {
6388 return false;
6389 }
6390 if (!emit1(JSOp::SetRval)) {
6391 return false;
6392 }
6393 return true;
6394}
6395
6396bool BytecodeEmitter::emitNewTarget() {
6397 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"
, 6397); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->allowNewTarget()"
")"); do { *((volatile int*)__null) = 6397; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6398
6399 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_newTarget_())) {
6400 // [stack] NEW.TARGET
6401 return false;
6402 }
6403 return true;
6404}
6405
6406bool BytecodeEmitter::emitNewTarget(NewTargetNode* pn) {
6407 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"
, 6408); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->newTargetName()->isName( TaggedParserAtomIndex::WellKnown::dot_newTarget_())"
")"); do { *((volatile int*)__null) = 6408; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6408 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"
, 6408); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->newTargetName()->isName( TaggedParserAtomIndex::WellKnown::dot_newTarget_())"
")"); do { *((volatile int*)__null) = 6408; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6409
6410 return emitNewTarget();
6411}
6412
6413bool BytecodeEmitter::emitNewTarget(CallNode* pn) {
6414 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"
, 6415); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->callOp() == JSOp::SuperCall || pn->callOp() == JSOp::SpreadSuperCall"
")"); do { *((volatile int*)__null) = 6415; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6415 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"
, 6415); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->callOp() == JSOp::SuperCall || pn->callOp() == JSOp::SpreadSuperCall"
")"); do { *((volatile int*)__null) = 6415; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6416
6417 // The parser is responsible for marking the "new.target" binding as being
6418 // implicitly used in super() calls.
6419 return emitNewTarget();
6420}
6421
6422bool BytecodeEmitter::emitReturn(UnaryNode* returnNode) {
6423 if (!updateSourceCoordNotes(returnNode->pn_pos.begin)) {
6424 return false;
6425 }
6426
6427 if (!markStepBreakpoint()) {
6428 return false;
6429 }
6430
6431 /* Push a return value */
6432 if (ParseNode* expr = returnNode->kid()) {
6433 if (!emitTree(expr)) {
6434 return false;
6435 }
6436
6437 if (sc->asSuspendableContext()->isAsync() &&
6438 sc->asSuspendableContext()->isGenerator()) {
6439 if (!emitAwaitInInnermostScope()) {
6440 return false;
6441 }
6442 }
6443 } else {
6444 /* No explicit return value provided */
6445 if (!emit1(JSOp::Undefined)) {
6446 return false;
6447 }
6448 }
6449
6450 // We know functionBodyEndPos is set because "return" is only
6451 // valid in a function, and so we've passed through
6452 // emitFunctionScript.
6453 if (!updateSourceCoordNotes(*functionBodyEndPos)) {
6454 return false;
6455 }
6456
6457 /*
6458 * The return value is currently on the stack. We would like to
6459 * generate JSOp::Return, but if we have work to do before returning,
6460 * we will instead generate JSOp::SetRval / JSOp::RetRval.
6461 *
6462 * We don't know whether we will need fixup code until after calling
6463 * prepareForNonLocalJumpToOutermost, so we start by generating
6464 * JSOp::SetRval, then mutate it to JSOp::Return in finishReturn if it
6465 * wasn't needed.
6466 */
6467 BytecodeOffset setRvalOffset = bytecodeSection().offset();
6468 if (!emit1(JSOp::SetRval)) {
6469 return false;
6470 }
6471
6472 NonLocalExitControl nle(this, NonLocalExitKind::Return);
6473 return nle.emitReturn(setRvalOffset);
6474}
6475
6476bool BytecodeEmitter::finishReturn(BytecodeOffset setRvalOffset) {
6477 // The return value is currently in rval. Depending on the current function,
6478 // we may have to do additional work before returning:
6479 // - Derived class constructors must check if the return value is an object.
6480 // - Generators and async functions must do a final yield.
6481 // - Non-async generators must return the value as an iterator result:
6482 // { value: <rval>, done: true }
6483 // - Non-generator async functions must resolve the function's result promise
6484 // with the value.
6485 //
6486 // If we have not generated any code since the SetRval that stored the return
6487 // value, we can also optimize the bytecode by rewriting that SetRval as a
6488 // JSOp::Return. See |emitReturn| above.
6489
6490 bool isDerivedClassConstructor =
6491 sc->isFunctionBox() && sc->asFunctionBox()->isDerivedClassConstructor();
6492 bool needsFinalYield =
6493 sc->isFunctionBox() && sc->asFunctionBox()->needsFinalYield();
6494 bool isSimpleReturn =
6495 setRvalOffset.valid() &&
6496 setRvalOffset + BytecodeOffsetDiff(JSOpLength_SetRval) ==
6497 bytecodeSection().offset();
6498
6499 if (isDerivedClassConstructor) {
6500 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"
, 6500); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!needsFinalYield"
")"); do { *((volatile int*)__null) = 6500; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6501 if (!emitJump(JSOp::Goto, &endOfDerivedClassConstructorBody)) {
6502 return false;
6503 }
6504 return true;
6505 }
6506
6507 if (needsFinalYield) {
6508 if (!emitJump(JSOp::Goto, &finalYields)) {
6509 return false;
6510 }
6511 return true;
6512 }
6513
6514 if (isSimpleReturn) {
6515 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"
, 6516); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JSOp(bytecodeSection().code()[setRvalOffset.value()]) == JSOp::SetRval"
")"); do { *((volatile int*)__null) = 6516; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6516 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"
, 6516); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JSOp(bytecodeSection().code()[setRvalOffset.value()]) == JSOp::SetRval"
")"); do { *((volatile int*)__null) = 6516; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6517 bytecodeSection().code()[setRvalOffset.value()] = jsbytecode(JSOp::Return);
6518 return true;
6519 }
6520
6521 // Nothing special needs to be done.
6522 return emitReturnRval();
6523}
6524
6525bool BytecodeEmitter::emitGetDotGeneratorInScope(EmitterScope& currentScope) {
6526 if (!sc->isFunction() && sc->isModuleContext() &&
6527 sc->asModuleContext()->isAsync()) {
6528 NameLocation loc = *locationOfNameBoundInScopeType<ModuleScope>(
6529 TaggedParserAtomIndex::WellKnown::dot_generator_(), &currentScope);
6530 return emitGetNameAtLocation(
6531 TaggedParserAtomIndex::WellKnown::dot_generator_(), loc);
6532 }
6533 NameLocation loc = *locationOfNameBoundInScopeType<FunctionScope>(
6534 TaggedParserAtomIndex::WellKnown::dot_generator_(), &currentScope);
6535 return emitGetNameAtLocation(
6536 TaggedParserAtomIndex::WellKnown::dot_generator_(), loc);
6537}
6538
6539bool BytecodeEmitter::emitInitialYield(UnaryNode* yieldNode) {
6540 if (!emitTree(yieldNode->kid())) {
6541 return false;
6542 }
6543
6544 if (!emitYieldOp(JSOp::InitialYield)) {
6545 // [stack] RVAL GENERATOR RESUMEKIND
6546 return false;
6547 }
6548 if (!emit1(JSOp::CheckResumeKind)) {
6549 // [stack] RVAL
6550 return false;
6551 }
6552 if (!emit1(JSOp::Pop)) {
6553 // [stack]
6554 return false;
6555 }
6556
6557 return true;
6558}
6559
6560bool BytecodeEmitter::emitYield(UnaryNode* yieldNode) {
6561 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"
, 6561); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isFunctionBox()"
")"); do { *((volatile int*)__null) = 6561; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6562 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"
, 6562); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->asFunctionBox()->isGenerator()"
")"); do { *((volatile int*)__null) = 6562; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6563 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"
, 6563); AnnotateMozCrashReason("MOZ_ASSERT" "(" "yieldNode->isKind(ParseNodeKind::YieldExpr)"
")"); do { *((volatile int*)__null) = 6563; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6564
6565 bool needsIteratorResult = sc->asFunctionBox()->needsIteratorResult();
6566 if (needsIteratorResult) {
6567 if (!emitPrepareIteratorResult()) {
6568 // [stack] ITEROBJ
6569 return false;
6570 }
6571 }
6572 if (ParseNode* expr = yieldNode->kid()) {
6573 if (!emitTree(expr)) {
6574 // [stack] ITEROBJ? VAL
6575 return false;
6576 }
6577 } else {
6578 if (!emit1(JSOp::Undefined)) {
6579 // [stack] ITEROBJ? UNDEFINED
6580 return false;
6581 }
6582 }
6583
6584 if (sc->asSuspendableContext()->isAsync()) {
6585 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"
, 6585); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!needsIteratorResult"
")"); do { *((volatile int*)__null) = 6585; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6586 if (!emitAwaitInInnermostScope()) {
6587 // [stack] RESULT
6588 return false;
6589 }
6590 }
6591
6592 if (needsIteratorResult) {
6593 if (!emitFinishIteratorResult(false)) {
6594 // [stack] ITEROBJ
6595 return false;
6596 }
6597 }
6598
6599 if (!emitGetDotGeneratorInInnermostScope()) {
6600 // [stack] # if needsIteratorResult
6601 // [stack] ITEROBJ .GENERATOR
6602 // [stack] # else
6603 // [stack] RESULT .GENERATOR
6604 return false;
6605 }
6606
6607 if (!emitYieldOp(JSOp::Yield)) {
6608 // [stack] YIELDRESULT GENERATOR RESUMEKIND
6609 return false;
6610 }
6611
6612 if (!emit1(JSOp::CheckResumeKind)) {
6613 // [stack] YIELDRESULT
6614 return false;
6615 }
6616
6617 return true;
6618}
6619
6620bool BytecodeEmitter::emitAwaitInInnermostScope(UnaryNode* awaitNode) {
6621 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"
, 6621); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isSuspendableContext()"
")"); do { *((volatile int*)__null) = 6621; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6622 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"
, 6622); AnnotateMozCrashReason("MOZ_ASSERT" "(" "awaitNode->isKind(ParseNodeKind::AwaitExpr)"
")"); do { *((volatile int*)__null) = 6622; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6623
6624 if (!emitTree(awaitNode->kid())) {
6625 return false;
6626 }
6627 return emitAwaitInInnermostScope();
6628}
6629
6630bool BytecodeEmitter::emitAwaitInScope(EmitterScope& currentScope) {
6631 if (!emit1(JSOp::CanSkipAwait)) {
6632 // [stack] VALUE CANSKIP
6633 return false;
6634 }
6635
6636 if (!emit1(JSOp::MaybeExtractAwaitValue)) {
6637 // [stack] VALUE_OR_RESOLVED CANSKIP
6638 return false;
6639 }
6640
6641 InternalIfEmitter ifCanSkip(this);
6642 if (!ifCanSkip.emitThen(IfEmitter::ConditionKind::Negative)) {
6643 // [stack] VALUE_OR_RESOLVED
6644 return false;
6645 }
6646
6647 if (sc->asSuspendableContext()->needsPromiseResult()) {
6648 if (!emitGetDotGeneratorInScope(currentScope)) {
6649 // [stack] VALUE GENERATOR
6650 return false;
6651 }
6652 if (!emit1(JSOp::AsyncAwait)) {
6653 // [stack] PROMISE
6654 return false;
6655 }
6656 }
6657
6658 if (!emitGetDotGeneratorInScope(currentScope)) {
6659 // [stack] VALUE|PROMISE GENERATOR
6660 return false;
6661 }
6662 if (!emitYieldOp(JSOp::Await)) {
6663 // [stack] RESOLVED GENERATOR RESUMEKIND
6664 return false;
6665 }
6666 if (!emit1(JSOp::CheckResumeKind)) {
6667 // [stack] RESOLVED
6668 return false;
6669 }
6670
6671 if (!ifCanSkip.emitEnd()) {
6672 return false;
6673 }
6674
6675 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"
, 6675); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ifCanSkip.popped() == 0"
")"); do { *((volatile int*)__null) = 6675; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6676
6677 return true;
6678}
6679
6680// ES2019 draft rev 49b781ec80117b60f73327ef3054703a3111e40c
6681// 14.4.14 Runtime Semantics: Evaluation
6682// YieldExpression : yield* AssignmentExpression
6683bool BytecodeEmitter::emitYieldStar(ParseNode* iter) {
6684 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"
, 6686); 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) = 6686; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
6685 "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"
, 6686); 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) = 6686; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
6686 "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"
, 6686); 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) = 6686; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6687
6688 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"
, 6688); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isSuspendableContext()"
")"); do { *((volatile int*)__null) = 6688; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6689 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"
, 6689); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->asSuspendableContext()->isGenerator()"
")"); do { *((volatile int*)__null) = 6689; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6690
6691 // Step 1.
6692 IteratorKind iterKind = sc->asSuspendableContext()->isAsync()
6693 ? IteratorKind::Async
6694 : IteratorKind::Sync;
6695 bool needsIteratorResult = sc->asSuspendableContext()->needsIteratorResult();
6696
6697 // Steps 2-5.
6698 if (!emitTree(iter)) {
6699 // [stack] ITERABLE
6700 return false;
6701 }
6702 if (iterKind == IteratorKind::Async) {
6703 if (!emitAsyncIterator(SelfHostedIter::Deny)) {
6704 // [stack] NEXT ITER
6705 return false;
6706 }
6707 } else {
6708 if (!emitIterator(SelfHostedIter::Deny)) {
6709 // [stack] NEXT ITER
6710 return false;
6711 }
6712 }
6713
6714 // Step 6.
6715 // Start with NormalCompletion(undefined).
6716 if (!emit1(JSOp::Undefined)) {
6717 // [stack] NEXT ITER RECEIVED
6718 return false;
6719 }
6720 if (!emitPushResumeKind(GeneratorResumeKind::Next)) {
6721 // [stack] NEXT ITER RECEIVED RESUMEKIND
6722 return false;
6723 }
6724
6725 const int32_t startDepth = bytecodeSection().stackDepth();
6726 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"
, 6726); AnnotateMozCrashReason("MOZ_ASSERT" "(" "startDepth >= 4"
")"); do { *((volatile int*)__null) = 6726; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6727
6728 // Step 7 is a loop.
6729 LoopControl loopInfo(this, StatementKind::YieldStar);
6730 if (!loopInfo.emitLoopHead(this, Nothing())) {
6731 // [stack] NEXT ITER RECEIVED RESUMEKIND
6732 return false;
6733 }
6734
6735 // Step 7.a. Check for Normal completion.
6736 if (!emit1(JSOp::Dup)) {
6737 // [stack] NEXT ITER RECEIVED RESUMEKIND RESUMEKIND
6738 return false;
6739 }
6740 if (!emitPushResumeKind(GeneratorResumeKind::Next)) {
6741 // [stack] NEXT ITER RECEIVED RESUMEKIND RESUMEKIND NORMAL
6742 return false;
6743 }
6744 if (!emit1(JSOp::StrictEq)) {
6745 // [stack] NEXT ITER RECEIVED RESUMEKIND IS_NORMAL
6746 return false;
6747 }
6748
6749 InternalIfEmitter ifKind(this);
6750 if (!ifKind.emitThenElse()) {
6751 // [stack] NEXT ITER RECEIVED RESUMEKIND
6752 return false;
6753 }
6754 {
6755 if (!emit1(JSOp::Pop)) {
6756 // [stack] NEXT ITER RECEIVED
6757 return false;
6758 }
6759
6760 // Step 7.a.i.
6761 // result = iter.next(received)
6762 if (!emit2(JSOp::Unpick, 2)) {
6763 // [stack] RECEIVED NEXT ITER
6764 return false;
6765 }
6766 if (!emit1(JSOp::Dup2)) {
6767 // [stack] RECEIVED NEXT ITER NEXT ITER
6768 return false;
6769 }
6770 if (!emit2(JSOp::Pick, 4)) {
6771 // [stack] NEXT ITER NEXT ITER RECEIVED
6772 return false;
6773 }
6774 if (!emitCall(JSOp::Call, 1, iter)) {
6775 // [stack] NEXT ITER RESULT
6776 return false;
6777 }
6778
6779 // Step 7.a.ii.
6780 if (iterKind == IteratorKind::Async) {
6781 if (!emitAwaitInInnermostScope()) {
6782 // [stack] NEXT ITER RESULT
6783 return false;
6784 }
6785 }
6786
6787 // Step 7.a.iii.
6788 if (!emitCheckIsObj(CheckIsObjectKind::IteratorNext)) {
6789 // [stack] NEXT ITER RESULT
6790 return false;
6791 }
6792
6793 // Bytecode for steps 7.a.iv-vii is emitted after the ifKind if-else because
6794 // it's shared with other branches.
6795 }
6796
6797 // Step 7.b. Check for Throw completion.
6798 if (!ifKind.emitElseIf(Nothing())) {
6799 // [stack] NEXT ITER RECEIVED RESUMEKIND
6800 return false;
6801 }
6802 if (!emit1(JSOp::Dup)) {
6803 // [stack] NEXT ITER RECEIVED RESUMEKIND RESUMEKIND
6804 return false;
6805 }
6806 if (!emitPushResumeKind(GeneratorResumeKind::Throw)) {
6807 // [stack] NEXT ITER RECEIVED RESUMEKIND RESUMEKIND THROW
6808 return false;
6809 }
6810 if (!emit1(JSOp::StrictEq)) {
6811 // [stack] NEXT ITER RECEIVED RESUMEKIND IS_THROW
6812 return false;
6813 }
6814 if (!ifKind.emitThenElse()) {
6815 // [stack] NEXT ITER RECEIVED RESUMEKIND
6816 return false;
6817 }
6818 {
6819 if (!emit1(JSOp::Pop)) {
6820 // [stack] NEXT ITER RECEIVED
6821 return false;
6822 }
6823 // Step 7.b.i.
6824 if (!emitDupAt(1)) {
6825 // [stack] NEXT ITER RECEIVED ITER
6826 return false;
6827 }
6828 if (!emit1(JSOp::Dup)) {
6829 // [stack] NEXT ITER RECEIVED ITER ITER
6830 return false;
6831 }
6832 if (!emitAtomOp(JSOp::GetProp,
6833 TaggedParserAtomIndex::WellKnown::throw_())) {
6834 // [stack] NEXT ITER RECEIVED ITER THROW
6835 return false;
6836 }
6837
6838 // Step 7.b.ii.
6839 InternalIfEmitter ifThrowMethodIsNotDefined(this);
6840 if (!emit1(JSOp::IsNullOrUndefined)) {
6841 // [stack] NEXT ITER RECEIVED ITER THROW NULL-OR-UNDEF
6842 return false;
6843 }
6844
6845 if (!ifThrowMethodIsNotDefined.emitThenElse(
6846 IfEmitter::ConditionKind::Negative)) {
6847 // [stack] NEXT ITER RECEIVED ITER THROW
6848 return false;
6849 }
6850
6851 // Step 7.b.ii.1.
6852 // RESULT = ITER.throw(EXCEPTION)
6853 if (!emit1(JSOp::Swap)) {
6854 // [stack] NEXT ITER RECEIVED THROW ITER
6855 return false;
6856 }
6857 if (!emit2(JSOp::Pick, 2)) {
6858 // [stack] NEXT ITER THROW ITER RECEIVED
6859 return false;
6860 }
6861 if (!emitCall(JSOp::Call, 1, iter)) {
6862 // [stack] NEXT ITER RESULT
6863 return false;
6864 }
6865
6866 // Step 7.b.ii.2.
6867 if (iterKind == IteratorKind::Async) {
6868 if (!emitAwaitInInnermostScope()) {
6869 // [stack] NEXT ITER RESULT
6870 return false;
6871 }
6872 }
6873
6874 // Step 7.b.ii.4.
6875 if (!emitCheckIsObj(CheckIsObjectKind::IteratorThrow)) {
6876 // [stack] NEXT ITER RESULT
6877 return false;
6878 }
6879
6880 // Bytecode for steps 7.b.ii.5-8 is emitted after the ifKind if-else because
6881 // it's shared with other branches.
6882
6883 // Step 7.b.iii.
6884 if (!ifThrowMethodIsNotDefined.emitElse()) {
6885 // [stack] NEXT ITER RECEIVED ITER THROW
6886 return false;
6887 }
6888 if (!emit1(JSOp::Pop)) {
6889 // [stack] NEXT ITER RECEIVED ITER
6890 return false;
6891 }
6892
6893 // Steps 7.b.iii.1-4.
6894 //
6895 // If the iterator does not have a "throw" method, it calls IteratorClose
6896 // and then throws a TypeError.
6897 if (!emitIteratorCloseInInnermostScope(iterKind, CompletionKind::Normal)) {
6898 // [stack] NEXT ITER RECEIVED ITER
6899 return false;
6900 }
6901 // Steps 7.b.iii.5-6.
6902 if (!emit2(JSOp::ThrowMsg, uint8_t(ThrowMsgKind::IteratorNoThrow))) {
6903 // [stack] NEXT ITER RECEIVED ITER
6904 // [stack] # throw
6905 return false;
6906 }
6907
6908 if (!ifThrowMethodIsNotDefined.emitEnd()) {
6909 return false;
6910 }
6911 }
6912
6913 // Step 7.c. It must be a Return completion.
6914 if (!ifKind.emitElse()) {
6915 // [stack] NEXT ITER RECEIVED RESUMEKIND
6916 return false;
6917 }
6918 {
6919 if (!emit1(JSOp::Pop)) {
6920 // [stack] NEXT ITER RECEIVED
6921 return false;
6922 }
6923
6924 // Step 7.c.i.
6925 //
6926 // Call iterator.return() for receiving a "forced return" completion from
6927 // the generator.
6928
6929 // Step 7.c.ii.
6930 //
6931 // Get the "return" method.
6932 if (!emitDupAt(1)) {
6933 // [stack] NEXT ITER RECEIVED ITER
6934 return false;
6935 }
6936 if (!emit1(JSOp::Dup)) {
6937 // [stack] NEXT ITER RECEIVED ITER ITER
6938 return false;
6939 }
6940 if (!emitAtomOp(JSOp::GetProp,
6941 TaggedParserAtomIndex::WellKnown::return_())) {
6942 // [stack] NEXT ITER RECEIVED ITER RET
6943 return false;
6944 }
6945
6946 // Step 7.c.iii.
6947 //
6948 // Do nothing if "return" is undefined or null.
6949 InternalIfEmitter ifReturnMethodIsDefined(this);
6950 if (!emit1(JSOp::IsNullOrUndefined)) {
6951 // [stack] NEXT ITER RECEIVED ITER RET NULL-OR-UNDEF
6952 return false;
6953 }
6954
6955 // Step 7.c.iv.
6956 //
6957 // Call "return" with the argument passed to Generator.prototype.return.
6958 if (!ifReturnMethodIsDefined.emitThenElse(
6959 IfEmitter::ConditionKind::Negative)) {
6960 // [stack] NEXT ITER RECEIVED ITER RET
6961 return false;
6962 }
6963 if (!emit1(JSOp::Swap)) {
6964 // [stack] NEXT ITER RECEIVED RET ITER
6965 return false;
6966 }
6967 if (!emit2(JSOp::Pick, 2)) {
6968 // [stack] NEXT ITER RET ITER RECEIVED
6969 return false;
6970 }
6971 if (needsIteratorResult) {
6972 if (!emitAtomOp(JSOp::GetProp,
6973 TaggedParserAtomIndex::WellKnown::value())) {
6974 // [stack] NEXT ITER RET ITER VAL
6975 return false;
6976 }
6977 }
6978 if (!emitCall(JSOp::Call, 1)) {
6979 // [stack] NEXT ITER RESULT
6980 return false;
6981 }
6982
6983 // Step 7.c.v.
6984 if (iterKind == IteratorKind::Async) {
6985 if (!emitAwaitInInnermostScope()) {
6986 // [stack] NEXT ITER RESULT
6987 return false;
6988 }
6989 }
6990
6991 // Step 7.c.vi.
6992 if (!emitCheckIsObj(CheckIsObjectKind::IteratorReturn)) {
6993 // [stack] NEXT ITER RESULT
6994 return false;
6995 }
6996
6997 // Check if the returned object from iterator.return() is done. If not,
6998 // continue yielding.
6999
7000 // Steps 7.c.vii-viii.
7001 InternalIfEmitter ifReturnDone(this);
7002 if (!emit1(JSOp::Dup)) {
7003 // [stack] NEXT ITER RESULT RESULT
7004 return false;
7005 }
7006 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::done())) {
7007 // [stack] NEXT ITER RESULT DONE
7008 return false;
7009 }
7010 if (!ifReturnDone.emitThenElse()) {
7011 // [stack] NEXT ITER RESULT
7012 return false;
7013 }
7014
7015 // Step 7.c.viii.1.
7016 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::value())) {
7017 // [stack] NEXT ITER VALUE
7018 return false;
7019 }
7020 if (needsIteratorResult) {
7021 if (!emitPrepareIteratorResult()) {
7022 // [stack] NEXT ITER VALUE RESULT
7023 return false;
7024 }
7025 if (!emit1(JSOp::Swap)) {
7026 // [stack] NEXT ITER RESULT VALUE
7027 return false;
7028 }
7029 if (!emitFinishIteratorResult(true)) {
7030 // [stack] NEXT ITER RESULT
7031 return false;
7032 }
7033 }
7034
7035 if (!ifReturnDone.emitElse()) {
7036 // [stack] NEXT ITER RESULT
7037 return false;
7038 }
7039
7040 // Jump to continue label for steps 7.c.ix-x.
7041 if (!emitJump(JSOp::Goto, &loopInfo.continues)) {
7042 // [stack] NEXT ITER RESULT
7043 return false;
7044 }
7045
7046 if (!ifReturnDone.emitEnd()) {
7047 // [stack] NEXT ITER RESULT
7048 return false;
7049 }
7050
7051 // Step 7.c.iii.
7052 if (!ifReturnMethodIsDefined.emitElse()) {
7053 // [stack] NEXT ITER RECEIVED ITER RET
7054 return false;
7055 }
7056 if (!emitPopN(2)) {
7057 // [stack] NEXT ITER RECEIVED
7058 return false;
7059 }
7060 if (iterKind == IteratorKind::Async) {
7061 // Step 7.c.iii.1.
7062 if (!emitAwaitInInnermostScope()) {
7063 // [stack] NEXT ITER RECEIVED
7064 return false;
7065 }
7066 }
7067 if (!ifReturnMethodIsDefined.emitEnd()) {
7068 // [stack] NEXT ITER RECEIVED
7069 return false;
7070 }
7071
7072 // Perform a "forced generator return".
7073 //
7074 // Step 7.c.iii.2.
7075 // Step 7.c.viii.2.
7076 if (!emitGetDotGeneratorInInnermostScope()) {
7077 // [stack] NEXT ITER RESULT GENOBJ
7078 return false;
7079 }
7080 if (!emitPushResumeKind(GeneratorResumeKind::Return)) {
7081 // [stack] NEXT ITER RESULT GENOBJ RESUMEKIND
7082 return false;
7083 }
7084 if (!emit1(JSOp::CheckResumeKind)) {
7085 // [stack] NEXT ITER RESULT GENOBJ RESUMEKIND
7086 return false;
7087 }
7088 }
7089
7090 if (!ifKind.emitEnd()) {
7091 // [stack] NEXT ITER RESULT
7092 return false;
7093 }
7094
7095 // Shared tail for Normal/Throw completions.
7096 //
7097 // Steps 7.a.iv-v.
7098 // Steps 7.b.ii.5-6.
7099 //
7100 // [stack] NEXT ITER RESULT
7101
7102 // if (result.done) break;
7103 if (!emit1(JSOp::Dup)) {
7104 // [stack] NEXT ITER RESULT RESULT
7105 return false;
7106 }
7107 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::done())) {
7108 // [stack] NEXT ITER RESULT DONE
7109 return false;
7110 }
7111 if (!emitJump(JSOp::JumpIfTrue, &loopInfo.breaks)) {
7112 // [stack] NEXT ITER RESULT
7113 return false;
7114 }
7115
7116 // Steps 7.a.vi-vii.
7117 // Steps 7.b.ii.7-8.
7118 // Steps 7.c.ix-x.
7119 if (!loopInfo.emitContinueTarget(this)) {
7120 // [stack] NEXT ITER RESULT
7121 return false;
7122 }
7123 if (iterKind == IteratorKind::Async) {
7124 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::value())) {
7125 // [stack] NEXT ITER RESULT
7126 return false;
7127 }
7128 }
7129 if (!emitGetDotGeneratorInInnermostScope()) {
7130 // [stack] NEXT ITER RESULT GENOBJ
7131 return false;
7132 }
7133 if (!emitYieldOp(JSOp::Yield)) {
7134 // [stack] NEXT ITER RVAL GENOBJ RESUMEKIND
7135 return false;
7136 }
7137 if (!emit1(JSOp::Swap)) {
7138 // [stack] NEXT ITER RVAL RESUMEKIND GENOBJ
7139 return false;
7140 }
7141 if (!emit1(JSOp::Pop)) {
7142 // [stack] NEXT ITER RVAL RESUMEKIND
7143 return false;
7144 }
7145 if (!loopInfo.emitLoopEnd(this, JSOp::Goto, TryNoteKind::Loop)) {
7146 // [stack] NEXT ITER RVAL RESUMEKIND
7147 return false;
7148 }
7149
7150 // Jumps to this point have 3 (instead of 4) values on the stack.
7151 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"
, 7151); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == startDepth"
")"); do { *((volatile int*)__null) = 7151; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7152 bytecodeSection().setStackDepth(startDepth - 1);
7153
7154 // [stack] NEXT ITER RESULT
7155
7156 // Step 7.a.v.1.
7157 // Step 7.b.ii.6.a.
7158 //
7159 // result.value
7160 if (!emit2(JSOp::Unpick, 2)) {
7161 // [stack] RESULT NEXT ITER
7162 return false;
7163 }
7164 if (!emitPopN(2)) {
7165 // [stack] RESULT
7166 return false;
7167 }
7168 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::value())) {
7169 // [stack] VALUE
7170 return false;
7171 }
7172
7173 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"
, 7173); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == startDepth - 3"
")"); do { *((volatile int*)__null) = 7173; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7174
7175 return true;
7176}
7177
7178bool BytecodeEmitter::emitStatementList(ListNode* stmtList) {
7179 for (ParseNode* stmt : stmtList->contents()) {
7180 if (!emitTree(stmt)) {
7181 return false;
7182 }
7183 }
7184 return true;
7185}
7186
7187bool BytecodeEmitter::emitExpressionStatement(UnaryNode* exprStmt) {
7188 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"
, 7188); AnnotateMozCrashReason("MOZ_ASSERT" "(" "exprStmt->isKind(ParseNodeKind::ExpressionStmt)"
")"); do { *((volatile int*)__null) = 7188; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7189
7190 /*
7191 * Top-level or called-from-a-native JS_Execute/EvaluateScript,
7192 * debugger, and eval frames may need the value of the ultimate
7193 * expression statement as the script's result, despite the fact
7194 * that it appears useless to the compiler.
7195 *
7196 * API users may also set the ReadOnlyCompileOptions::noScriptRval option when
7197 * calling JS_Compile* to suppress JSOp::SetRval.
7198 */
7199 bool wantval = false;
7200 bool useful = false;
7201 if (sc->isTopLevelContext()) {
7202 useful = wantval = !sc->noScriptRval();
7203 }
7204
7205 /* Don't eliminate expressions with side effects. */
7206 ParseNode* expr = exprStmt->kid();
7207 if (!useful) {
7208 if (!checkSideEffects(expr, &useful)) {
7209 return false;
7210 }
7211
7212 /*
7213 * Don't eliminate apparently useless expressions if they are labeled
7214 * expression statements. The startOffset() test catches the case
7215 * where we are nesting in emitTree for a labeled compound statement.
7216 */
7217 if (innermostNestableControl &&
7218 innermostNestableControl->is<LabelControl>() &&
7219 innermostNestableControl->as<LabelControl>().startOffset() >=
7220 bytecodeSection().offset()) {
7221 useful = true;
7222 }
7223 }
7224
7225 if (useful) {
7226 ValueUsage valueUsage =
7227 wantval ? ValueUsage::WantValue : ValueUsage::IgnoreValue;
7228 ExpressionStatementEmitter ese(this, valueUsage);
7229 if (!ese.prepareForExpr(exprStmt->pn_pos.begin)) {
7230 return false;
7231 }
7232 if (!markStepBreakpoint()) {
7233 return false;
7234 }
7235 if (!emitTree(expr, valueUsage)) {
7236 return false;
7237 }
7238 if (!ese.emitEnd()) {
7239 return false;
7240 }
7241 }
7242
7243 return true;
7244}
7245
7246bool BytecodeEmitter::emitDeleteName(UnaryNode* deleteNode) {
7247 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"
, 7247); AnnotateMozCrashReason("MOZ_ASSERT" "(" "deleteNode->isKind(ParseNodeKind::DeleteNameExpr)"
")"); do { *((volatile int*)__null) = 7247; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7248
7249 NameNode* nameExpr = &deleteNode->kid()->as<NameNode>();
7250 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"
, 7250); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nameExpr->isKind(ParseNodeKind::Name)"
")"); do { *((volatile int*)__null) = 7250; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7251
7252 return emitAtomOp(JSOp::DelName, nameExpr->atom());
7253}
7254
7255bool BytecodeEmitter::emitDeleteProperty(UnaryNode* deleteNode) {
7256 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"
, 7256); AnnotateMozCrashReason("MOZ_ASSERT" "(" "deleteNode->isKind(ParseNodeKind::DeletePropExpr)"
")"); do { *((volatile int*)__null) = 7256; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7257
7258 PropertyAccess* propExpr = &deleteNode->kid()->as<PropertyAccess>();
7259 PropOpEmitter poe(this, PropOpEmitter::Kind::Delete,
7260 propExpr->as<PropertyAccess>().isSuper()
7261 ? PropOpEmitter::ObjKind::Super
7262 : PropOpEmitter::ObjKind::Other);
7263 if (propExpr->isSuper()) {
7264 // The expression |delete super.foo;| has to evaluate |super.foo|,
7265 // which could throw if |this| hasn't yet been set by a |super(...)|
7266 // call or the super-base is not an object, before throwing a
7267 // ReferenceError for attempting to delete a super-reference.
7268 UnaryNode* base = &propExpr->expression().as<UnaryNode>();
7269 if (!emitGetThisForSuperBase(base)) {
7270 // [stack] THIS
7271 return false;
7272 }
7273 } else {
7274 if (!poe.prepareForObj()) {
7275 return false;
7276 }
7277 if (!emitPropLHS(propExpr)) {
7278 // [stack] OBJ
7279 return false;
7280 }
7281 }
7282
7283 if (!poe.emitDelete(propExpr->key().atom())) {
7284 // [stack] # if Super
7285 // [stack] THIS
7286 // [stack] # otherwise
7287 // [stack] SUCCEEDED
7288 return false;
7289 }
7290
7291 return true;
7292}
7293
7294bool BytecodeEmitter::emitDeleteElement(UnaryNode* deleteNode) {
7295 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"
, 7295); AnnotateMozCrashReason("MOZ_ASSERT" "(" "deleteNode->isKind(ParseNodeKind::DeleteElemExpr)"
")"); do { *((volatile int*)__null) = 7295; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7296
7297 PropertyByValue* elemExpr = &deleteNode->kid()->as<PropertyByValue>();
7298 bool isSuper = elemExpr->isSuper();
7299 DebugOnly<bool> isPrivate =
7300 elemExpr->key().isKind(ParseNodeKind::PrivateName);
7301 MOZ_ASSERT(!isPrivate)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!isPrivate)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!isPrivate))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("!isPrivate", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 7301); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!isPrivate"
")"); do { *((volatile int*)__null) = 7301; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7302 ElemOpEmitter eoe(
7303 this, ElemOpEmitter::Kind::Delete,
7304 isSuper ? ElemOpEmitter::ObjKind::Super : ElemOpEmitter::ObjKind::Other);
7305 if (isSuper) {
7306 // The expression |delete super[foo];| has to evaluate |super[foo]|,
7307 // which could throw if |this| hasn't yet been set by a |super(...)|
7308 // call, or trigger side-effects when evaluating ToPropertyKey(foo),
7309 // or also throw when the super-base is not an object, before throwing
7310 // a ReferenceError for attempting to delete a super-reference.
7311 if (!eoe.prepareForObj()) {
7312 // [stack]
7313 return false;
7314 }
7315
7316 UnaryNode* base = &elemExpr->expression().as<UnaryNode>();
7317 if (!emitGetThisForSuperBase(base)) {
7318 // [stack] THIS
7319 return false;
7320 }
7321 if (!eoe.prepareForKey()) {
7322 // [stack] THIS
7323 return false;
7324 }
7325 if (!emitTree(&elemExpr->key())) {
7326 // [stack] THIS KEY
7327 return false;
7328 }
7329 } else {
7330 if (!emitElemObjAndKey(elemExpr, false, eoe)) {
7331 // [stack] OBJ KEY
7332 return false;
7333 }
7334 }
7335 if (!eoe.emitDelete()) {
7336 // [stack] # if Super
7337 // [stack] THIS
7338 // [stack] # otherwise
7339 // [stack] SUCCEEDED
7340 return false;
7341 }
7342
7343 return true;
7344}
7345
7346bool BytecodeEmitter::emitDeleteExpression(UnaryNode* deleteNode) {
7347 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"
, 7347); AnnotateMozCrashReason("MOZ_ASSERT" "(" "deleteNode->isKind(ParseNodeKind::DeleteExpr)"
")"); do { *((volatile int*)__null) = 7347; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7348
7349 ParseNode* expression = deleteNode->kid();
7350
7351 // If useless, just emit JSOp::True; otherwise convert |delete <expr>| to
7352 // effectively |<expr>, true|.
7353 bool useful = false;
7354 if (!checkSideEffects(expression, &useful)) {
7355 return false;
7356 }
7357
7358 if (useful) {
7359 if (!emitTree(expression)) {
7360 return false;
7361 }
7362 if (!emit1(JSOp::Pop)) {
7363 return false;
7364 }
7365 }
7366
7367 return emit1(JSOp::True);
7368}
7369
7370bool BytecodeEmitter::emitDeleteOptionalChain(UnaryNode* deleteNode) {
7371 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"
, 7371); AnnotateMozCrashReason("MOZ_ASSERT" "(" "deleteNode->isKind(ParseNodeKind::DeleteOptionalChainExpr)"
")"); do { *((volatile int*)__null) = 7371; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7372
7373 OptionalEmitter oe(this, bytecodeSection().stackDepth());
7374
7375 ParseNode* kid = deleteNode->kid();
7376 switch (kid->getKind()) {
7377 case ParseNodeKind::ElemExpr:
7378 case ParseNodeKind::OptionalElemExpr: {
7379 auto* elemExpr = &kid->as<PropertyByValueBase>();
7380 if (!emitDeleteElementInOptChain(elemExpr, oe)) {
7381 // [stack] # If shortcircuit
7382 // [stack] UNDEFINED-OR-NULL
7383 // [stack] # otherwise
7384 // [stack] SUCCEEDED
7385 return false;
7386 }
7387
7388 break;
7389 }
7390 case ParseNodeKind::ArgumentsLength:
7391 case ParseNodeKind::DotExpr:
7392 case ParseNodeKind::OptionalDotExpr: {
7393 auto* propExpr = &kid->as<PropertyAccessBase>();
7394 if (!emitDeletePropertyInOptChain(propExpr, oe)) {
7395 // [stack] # If shortcircuit
7396 // [stack] UNDEFINED-OR-NULL
7397 // [stack] # otherwise
7398 // [stack] SUCCEEDED
7399 return false;
7400 }
7401 break;
7402 }
7403 default:
7404 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"
, 7404); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Unrecognized optional delete ParseNodeKind"
")"); do { *((volatile int*)__null) = 7404; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7405 }
7406
7407 if (!oe.emitOptionalJumpTarget(JSOp::True)) {
7408 // [stack] # If shortcircuit
7409 // [stack] TRUE
7410 // [stack] # otherwise
7411 // [stack] SUCCEEDED
7412 return false;
7413 }
7414
7415 return true;
7416}
7417
7418bool BytecodeEmitter::emitDeletePropertyInOptChain(PropertyAccessBase* propExpr,
7419 OptionalEmitter& oe) {
7420 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"
, 7421); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!propExpr->as<PropertyAccess>().isSuper()"
")"); do { *((volatile int*)__null) = 7421; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
7421 !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"
, 7421); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!propExpr->as<PropertyAccess>().isSuper()"
")"); do { *((volatile int*)__null) = 7421; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
7422 PropOpEmitter poe(this, PropOpEmitter::Kind::Delete,
7423 PropOpEmitter::ObjKind::Other);
7424
7425 if (!poe.prepareForObj()) {
7426 // [stack]
7427 return false;
7428 }
7429 if (!emitOptionalTree(&propExpr->expression(), oe)) {
7430 // [stack] OBJ
7431 return false;
7432 }
7433 if (propExpr->isKind(ParseNodeKind::OptionalDotExpr)) {
7434 if (!oe.emitJumpShortCircuit()) {
7435 // [stack] # if Jump
7436 // [stack] UNDEFINED-OR-NULL
7437 // [stack] # otherwise
7438 // [stack] OBJ
7439 return false;
7440 }
7441 }
7442
7443 if (!poe.emitDelete(propExpr->key().atom())) {
7444 // [stack] SUCCEEDED
7445 return false;
7446 }
7447
7448 return true;
7449}
7450
7451bool BytecodeEmitter::emitDeleteElementInOptChain(PropertyByValueBase* elemExpr,
7452 OptionalEmitter& oe) {
7453 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"
, 7454); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elemExpr->as<PropertyByValue>().isSuper()"
")"); do { *((volatile int*)__null) = 7454; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
7454 !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"
, 7454); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elemExpr->as<PropertyByValue>().isSuper()"
")"); do { *((volatile int*)__null) = 7454; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
7455 ElemOpEmitter eoe(this, ElemOpEmitter::Kind::Delete,
7456 ElemOpEmitter::ObjKind::Other);
7457
7458 if (!eoe.prepareForObj()) {
7459 // [stack]
7460 return false;
7461 }
7462
7463 if (!emitOptionalTree(&elemExpr->expression(), oe)) {
7464 // [stack] OBJ
7465 return false;
7466 }
7467
7468 if (elemExpr->isKind(ParseNodeKind::OptionalElemExpr)) {
7469 if (!oe.emitJumpShortCircuit()) {
7470 // [stack] # if Jump
7471 // [stack] UNDEFINED-OR-NULL
7472 // [stack] # otherwise
7473 // [stack] OBJ
7474 return false;
7475 }
7476 }
7477
7478 if (!eoe.prepareForKey()) {
7479 // [stack] OBJ
7480 return false;
7481 }
7482
7483 if (!emitTree(&elemExpr->key())) {
7484 // [stack] OBJ KEY
7485 return false;
7486 }
7487
7488 if (!eoe.emitDelete()) {
7489 // [stack] SUCCEEDED
7490 return false;
7491 }
7492
7493 return true;
7494}
7495
7496bool BytecodeEmitter::emitDebugCheckSelfHosted() {
7497 // [stack] CALLEE
7498
7499#ifdef DEBUG1
7500 if (!emit1(JSOp::DebugCheckSelfHosted)) {
7501 // [stack] CALLEE
7502 return false;
7503 }
7504#endif
7505
7506 return true;
7507}
7508
7509bool BytecodeEmitter::emitSelfHostedCallFunction(CallNode* callNode, JSOp op) {
7510 // Special-casing of callFunction to emit bytecode that directly
7511 // invokes the callee with the correct |this| object and arguments.
7512 // callFunction(fun, thisArg, arg0, arg1) thus becomes:
7513 // - emit lookup for fun
7514 // - emit lookup for thisArg
7515 // - emit lookups for arg0, arg1
7516 //
7517 // argc is set to the amount of actually emitted args and the
7518 // emitting of args below is disabled by setting emitArgs to false.
7519 NameNode* calleeNode = &callNode->callee()->as<NameNode>();
7520 ListNode* argsList = callNode->args();
7521
7522 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"
, 7522); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() >= 2"
")"); do { *((volatile int*)__null) = 7522; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7523
7524 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"
, 7524); AnnotateMozCrashReason("MOZ_ASSERT" "(" "callNode->callOp() == JSOp::Call"
")"); do { *((volatile int*)__null) = 7524; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7525
7526 bool constructing =
7527 calleeNode->name() ==
7528 TaggedParserAtomIndex::WellKnown::constructContentFunction();
7529 ParseNode* funNode = argsList->head();
7530
7531 if (!emitTree(funNode)) {
7532 // [stack] CALLEE
7533 return false;
7534 }
7535
7536#ifdef DEBUG1
7537 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"
, 7538); AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::Call || op == JSOp::CallContent || op == JSOp::NewContent"
")"); do { *((volatile int*)__null) = 7538; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7538 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"
, 7538); AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::Call || op == JSOp::CallContent || op == JSOp::NewContent"
")"); do { *((volatile int*)__null) = 7538; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7539 if (op == JSOp::Call) {
7540 if (!emitDebugCheckSelfHosted()) {
7541 // [stack] CALLEE
7542 return false;
7543 }
7544 }
7545#endif
7546
7547 ParseNode* thisOrNewTarget = funNode->pn_next;
7548 if (constructing) {
7549 // Save off the new.target value, but here emit a proper |this| for a
7550 // constructing call.
7551 if (!emit1(JSOp::IsConstructing)) {
7552 // [stack] CALLEE IS_CONSTRUCTING
7553 return false;
7554 }
7555 } else {
7556 // It's |this|, emit it.
7557 if (!emitTree(thisOrNewTarget)) {
7558 // [stack] CALLEE THIS
7559 return false;
7560 }
7561 }
7562
7563 for (ParseNode* argpn : argsList->contentsFrom(thisOrNewTarget->pn_next)) {
7564 if (!emitTree(argpn)) {
7565 // [stack] CALLEE ... ARGS...
7566 return false;
7567 }
7568 }
7569
7570 if (constructing) {
7571 if (!emitTree(thisOrNewTarget)) {
7572 // [stack] CALLEE IS_CONSTRUCTING ARGS... NEW.TARGET
7573 return false;
7574 }
7575 }
7576
7577 uint32_t argc = argsList->count() - 2;
7578 if (!emitCall(op, argc)) {
7579 // [stack] RVAL
7580 return false;
7581 }
7582
7583 return true;
7584}
7585
7586bool BytecodeEmitter::emitSelfHostedResumeGenerator(CallNode* callNode) {
7587 ListNode* argsList = callNode->args();
7588
7589 // Syntax: resumeGenerator(gen, value, 'next'|'throw'|'return')
7590 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"
, 7590); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 3"
")"); do { *((volatile int*)__null) = 7590; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7591
7592 ParseNode* genNode = argsList->head();
7593 if (!emitTree(genNode)) {
7594 // [stack] GENERATOR
7595 return false;
7596 }
7597
7598 ParseNode* valNode = genNode->pn_next;
7599 if (!emitTree(valNode)) {
7600 // [stack] GENERATOR VALUE
7601 return false;
7602 }
7603
7604 ParseNode* kindNode = valNode->pn_next;
7605 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"
, 7605); AnnotateMozCrashReason("MOZ_ASSERT" "(" "kindNode->isKind(ParseNodeKind::StringExpr)"
")"); do { *((volatile int*)__null) = 7605; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7606 GeneratorResumeKind kind =
7607 ParserAtomToResumeKind(kindNode->as<NameNode>().atom());
7608 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"
, 7608); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!kindNode->pn_next"
")"); do { *((volatile int*)__null) = 7608; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7609
7610 if (!emitPushResumeKind(kind)) {
7611 // [stack] GENERATOR VALUE RESUMEKIND
7612 return false;
7613 }
7614
7615 if (!emit1(JSOp::Resume)) {
7616 // [stack] RVAL
7617 return false;
7618 }
7619
7620 return true;
7621}
7622
7623bool BytecodeEmitter::emitSelfHostedForceInterpreter() {
7624 // JSScript::hasForceInterpreterOp() relies on JSOp::ForceInterpreter being
7625 // the first bytecode op in the script.
7626 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"
, 7626); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().code().empty()"
")"); do { *((volatile int*)__null) = 7626; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7627
7628 if (!emit1(JSOp::ForceInterpreter)) {
7629 return false;
7630 }
7631 if (!emit1(JSOp::Undefined)) {
7632 return false;
7633 }
7634
7635 return true;
7636}
7637
7638bool BytecodeEmitter::emitSelfHostedAllowContentIter(CallNode* callNode) {
7639 ListNode* argsList = callNode->args();
7640
7641 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"
, 7641); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1"
")"); do { *((volatile int*)__null) = 7641; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7642
7643 // We're just here as a sentinel. Pass the value through directly.
7644 return emitTree(argsList->head());
7645}
7646
7647bool BytecodeEmitter::emitSelfHostedAllowContentIterWith(CallNode* callNode) {
7648 ListNode* argsList = callNode->args();
7649
7650 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"
, 7650); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2 || argsList->count() == 3"
")"); 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::emitSelfHostedAllowContentIterWithNext(
7657 CallNode* callNode) {
7658 ListNode* argsList = callNode->args();
7659
7660 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"
, 7660); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2"
")"); do { *((volatile int*)__null) = 7660; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7661
7662 // We're just here as a sentinel. Pass the value through directly.
7663 return emitTree(argsList->head());
7664}
7665
7666bool BytecodeEmitter::emitSelfHostedDefineDataProperty(CallNode* callNode) {
7667 ListNode* argsList = callNode->args();
7668
7669 // Only optimize when 3 arguments are passed.
7670 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"
, 7670); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 3"
")"); do { *((volatile int*)__null) = 7670; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7671
7672 ParseNode* objNode = argsList->head();
7673 if (!emitTree(objNode)) {
7674 return false;
7675 }
7676
7677 ParseNode* idNode = objNode->pn_next;
7678 if (!emitTree(idNode)) {
7679 return false;
7680 }
7681
7682 ParseNode* valNode = idNode->pn_next;
7683 if (!emitTree(valNode)) {
7684 return false;
7685 }
7686
7687 // This will leave the object on the stack instead of pushing |undefined|,
7688 // but that's fine because the self-hosted code doesn't use the return
7689 // value.
7690 return emit1(JSOp::InitElem);
7691}
7692
7693bool BytecodeEmitter::emitSelfHostedHasOwn(CallNode* callNode) {
7694 ListNode* argsList = callNode->args();
7695
7696 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"
, 7696); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2"
")"); do { *((volatile int*)__null) = 7696; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7697
7698 ParseNode* idNode = argsList->head();
7699 if (!emitTree(idNode)) {
7700 return false;
7701 }
7702
7703 ParseNode* objNode = idNode->pn_next;
7704 if (!emitTree(objNode)) {
7705 return false;
7706 }
7707
7708 return emit1(JSOp::HasOwn);
7709}
7710
7711bool BytecodeEmitter::emitSelfHostedGetPropertySuper(CallNode* callNode) {
7712 ListNode* argsList = callNode->args();
7713
7714 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"
, 7714); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 3"
")"); do { *((volatile int*)__null) = 7714; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7715
7716 ParseNode* objNode = argsList->head();
7717 ParseNode* idNode = objNode->pn_next;
7718 ParseNode* receiverNode = idNode->pn_next;
7719
7720 if (!emitTree(receiverNode)) {
7721 return false;
7722 }
7723
7724 if (!emitTree(idNode)) {
7725 return false;
7726 }
7727
7728 if (!emitTree(objNode)) {
7729 return false;
7730 }
7731
7732 return emitElemOpBase(JSOp::GetElemSuper);
7733}
7734
7735bool BytecodeEmitter::emitSelfHostedToNumeric(CallNode* callNode) {
7736 ListNode* argsList = callNode->args();
7737
7738 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"
, 7738); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1"
")"); do { *((volatile int*)__null) = 7738; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7739
7740 ParseNode* argNode = argsList->head();
7741
7742 if (!emitTree(argNode)) {
7743 return false;
7744 }
7745
7746 return emit1(JSOp::ToNumeric);
7747}
7748
7749bool BytecodeEmitter::emitSelfHostedToString(CallNode* callNode) {
7750 ListNode* argsList = callNode->args();
7751
7752 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"
, 7752); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1"
")"); do { *((volatile int*)__null) = 7752; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7753
7754 ParseNode* argNode = argsList->head();
7755
7756 if (!emitTree(argNode)) {
7757 return false;
7758 }
7759
7760 return emit1(JSOp::ToString);
7761}
7762
7763bool BytecodeEmitter::emitSelfHostedIsNullOrUndefined(CallNode* callNode) {
7764 ListNode* argsList = callNode->args();
7765
7766 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"
, 7766); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1"
")"); do { *((volatile int*)__null) = 7766; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7767
7768 ParseNode* argNode = argsList->head();
7769
7770 if (!emitTree(argNode)) {
7771 // [stack] ARG
7772 return false;
7773 }
7774 if (!emit1(JSOp::IsNullOrUndefined)) {
7775 // [stack] ARG IS_NULL_OR_UNDEF
7776 return false;
7777 }
7778 if (!emit1(JSOp::Swap)) {
7779 // [stack] IS_NULL_OR_UNDEF ARG
7780 return false;
7781 }
7782 if (!emit1(JSOp::Pop)) {
7783 // [stack] IS_NULL_OR_UNDEF
7784 return false;
7785 }
7786 return true;
7787}
7788
7789bool BytecodeEmitter::emitSelfHostedIteratorClose(CallNode* callNode) {
7790 ListNode* argsList = callNode->args();
7791 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"
, 7791); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1"
")"); do { *((volatile int*)__null) = 7791; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7792
7793 ParseNode* argNode = argsList->head();
7794 if (!emitTree(argNode)) {
7795 // [stack] ARG
7796 return false;
7797 }
7798
7799 if (!emit2(JSOp::CloseIter, uint8_t(CompletionKind::Normal))) {
7800 // [stack]
7801 return false;
7802 }
7803
7804 // This is still a call node, so we must generate a stack value.
7805 if (!emit1(JSOp::Undefined)) {
7806 // [stack] RVAL
7807 return false;
7808 }
7809
7810 return true;
7811}
7812
7813bool BytecodeEmitter::emitSelfHostedGetBuiltinConstructorOrPrototype(
7814 CallNode* callNode, bool isConstructor) {
7815 ListNode* argsList = callNode->args();
7816
7817 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"
, 7817); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1"
")"); do { *((volatile int*)__null) = 7817; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7818
7819 ParseNode* argNode = argsList->head();
7820
7821 if (!argNode->isKind(ParseNodeKind::StringExpr)) {
7822 reportError(callNode, JSMSG_UNEXPECTED_TYPE, "built-in name",
7823 "not a string constant");
7824 return false;
7825 }
7826
7827 auto name = argNode->as<NameNode>().atom();
7828
7829 BuiltinObjectKind kind;
7830 if (isConstructor) {
7831 kind = BuiltinConstructorForName(name);
7832 } else {
7833 kind = BuiltinPrototypeForName(name);
7834 }
7835
7836 if (kind == BuiltinObjectKind::None) {
7837 reportError(callNode, JSMSG_UNEXPECTED_TYPE, "built-in name",
7838 "not a valid built-in");
7839 return false;
7840 }
7841
7842 return emitBuiltinObject(kind);
7843}
7844
7845bool BytecodeEmitter::emitSelfHostedGetBuiltinConstructor(CallNode* callNode) {
7846 return emitSelfHostedGetBuiltinConstructorOrPrototype(
7847 callNode, /* isConstructor = */ true);
7848}
7849
7850bool BytecodeEmitter::emitSelfHostedGetBuiltinPrototype(CallNode* callNode) {
7851 return emitSelfHostedGetBuiltinConstructorOrPrototype(
7852 callNode, /* isConstructor = */ false);
7853}
7854
7855JS::SymbolCode ParserAtomToSymbolCode(TaggedParserAtomIndex atom) {
7856 // NOTE: This is a linear search, but the set of entries is quite small and
7857 // this is only used for initial self-hosted parse.
7858#define MATCH_WELL_KNOWN_SYMBOL(NAME) \
7859 if (atom == TaggedParserAtomIndex::WellKnown::NAME()) { \
7860 return JS::SymbolCode::NAME; \
7861 }
7862 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)
7863#undef MATCH_WELL_KNOWN_SYMBOL
7864
7865 return JS::SymbolCode::Limit;
7866}
7867
7868bool BytecodeEmitter::emitSelfHostedGetBuiltinSymbol(CallNode* callNode) {
7869 ListNode* argsList = callNode->args();
7870
7871 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"
, 7871); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1"
")"); do { *((volatile int*)__null) = 7871; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7872
7873 ParseNode* argNode = argsList->head();
7874
7875 if (!argNode->isKind(ParseNodeKind::StringExpr)) {
7876 reportError(callNode, JSMSG_UNEXPECTED_TYPE, "built-in name",
7877 "not a string constant");
7878 return false;
7879 }
7880
7881 auto name = argNode->as<NameNode>().atom();
7882
7883 JS::SymbolCode code = ParserAtomToSymbolCode(name);
7884 if (code == JS::SymbolCode::Limit) {
7885 reportError(callNode, JSMSG_UNEXPECTED_TYPE, "built-in name",
7886 "not a valid built-in");
7887 return false;
7888 }
7889
7890 return emit2(JSOp::Symbol, uint8_t(code));
7891}
7892
7893bool BytecodeEmitter::emitSelfHostedArgumentsLength(CallNode* callNode) {
7894 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"
, 7894); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sc->asFunctionBox()->needsArgsObj()"
")"); do { *((volatile int*)__null) = 7894; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7895 sc->asFunctionBox()->setUsesArgumentsIntrinsics();
7896
7897 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"
, 7897); AnnotateMozCrashReason("MOZ_ASSERT" "(" "callNode->args()->count() == 0"
")"); do { *((volatile int*)__null) = 7897; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7898
7899 return emit1(JSOp::ArgumentsLength);
7900}
7901
7902bool BytecodeEmitter::emitSelfHostedGetArgument(CallNode* callNode) {
7903 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"
, 7903); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sc->asFunctionBox()->needsArgsObj()"
")"); do { *((volatile int*)__null) = 7903; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7904 sc->asFunctionBox()->setUsesArgumentsIntrinsics();
7905
7906 ListNode* argsList = callNode->args();
7907 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"
, 7907); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1"
")"); do { *((volatile int*)__null) = 7907; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7908
7909 ParseNode* argNode = argsList->head();
7910 if (!emitTree(argNode)) {
7911 return false;
7912 }
7913
7914 return emit1(JSOp::GetActualArg);
7915}
7916
7917#ifdef DEBUG1
7918void BytecodeEmitter::assertSelfHostedExpectedTopLevel(ParseNode* node) {
7919 // The function argument is expected to be a simple binding/function name.
7920 // Eg. `function foo() { }; SpecialIntrinsic(foo)`
7921 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"
, 7922); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::Name)"
") (" "argument must be a function name" ")"); do { *((volatile
int*)__null) = 7922; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
7922 "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"
, 7922); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::Name)"
") (" "argument must be a function name" ")"); do { *((volatile
int*)__null) = 7922; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
7923 TaggedParserAtomIndex targetName = node->as<NameNode>().name();
7924
7925 // The special intrinsics must follow the target functions definition. A
7926 // simple assert is fine here since any hoisted function will cause a non-null
7927 // value to be set here.
7928 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"
, 7928); AnnotateMozCrashReason("MOZ_ASSERT" "(" "prevSelfHostedTopLevelFunction"
")"); do { *((volatile int*)__null) = 7928; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7929
7930 // The target function must match the most recently defined top-level
7931 // self-hosted function.
7932 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"
, 7933); AnnotateMozCrashReason("MOZ_ASSERT" "(" "prevSelfHostedTopLevelFunction->explicitName() == targetName"
") (" "selfhost decorator must immediately follow target function"
")"); do { *((volatile int*)__null) = 7933; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7933 "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"
, 7933); AnnotateMozCrashReason("MOZ_ASSERT" "(" "prevSelfHostedTopLevelFunction->explicitName() == targetName"
") (" "selfhost decorator must immediately follow target function"
")"); do { *((volatile int*)__null) = 7933; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7934}
7935#endif
7936
7937bool BytecodeEmitter::emitSelfHostedSetIsInlinableLargeFunction(
7938 CallNode* callNode) {
7939#ifdef DEBUG1
7940 ListNode* argsList = callNode->args();
7941
7942 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"
, 7942); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1"
")"); do { *((volatile int*)__null) = 7942; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7943
7944 assertSelfHostedExpectedTopLevel(argsList->head());
7945#endif
7946
7947 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"
, 7947); AnnotateMozCrashReason("MOZ_ASSERT" "(" "prevSelfHostedTopLevelFunction->isInitialCompilation"
")"); do { *((volatile int*)__null) = 7947; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7948 prevSelfHostedTopLevelFunction->setIsInlinableLargeFunction();
7949
7950 // This is still a call node, so we must generate a stack value.
7951 return emit1(JSOp::Undefined);
7952}
7953
7954bool BytecodeEmitter::emitSelfHostedSetCanonicalName(CallNode* callNode) {
7955 ListNode* argsList = callNode->args();
7956
7957 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"
, 7957); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2"
")"); do { *((volatile int*)__null) = 7957; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7958
7959#ifdef DEBUG1
7960 assertSelfHostedExpectedTopLevel(argsList->head());
7961#endif
7962
7963 ParseNode* nameNode = argsList->last();
7964 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"
, 7964); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nameNode->isKind(ParseNodeKind::StringExpr)"
")"); do { *((volatile int*)__null) = 7964; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7965 TaggedParserAtomIndex specName = nameNode->as<NameNode>().atom();
7966 // Canonical name must be atomized.
7967 compilationState.parserAtoms.markUsedByStencil(specName,
7968 ParserAtom::Atomize::Yes);
7969
7970 // Store the canonical name for instantiation.
7971 prevSelfHostedTopLevelFunction->functionStencil().setSelfHostedCanonicalName(
7972 specName);
7973
7974 return emit1(JSOp::Undefined);
7975}
7976
7977#ifdef DEBUG1
7978void BytecodeEmitter::assertSelfHostedUnsafeGetReservedSlot(
7979 ListNode* argsList) {
7980 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"
, 7980); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2"
")"); do { *((volatile int*)__null) = 7980; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7981
7982 ParseNode* objNode = argsList->head();
7983 ParseNode* slotNode = objNode->pn_next;
7984
7985 // Ensure that the slot argument is fixed, this is required by the JITs.
7986 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"
, 7987); AnnotateMozCrashReason("MOZ_ASSERT" "(" "slotNode->isKind(ParseNodeKind::NumberExpr)"
") (" "slot argument must be a constant" ")"); do { *((volatile
int*)__null) = 7987; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
7987 "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"
, 7987); AnnotateMozCrashReason("MOZ_ASSERT" "(" "slotNode->isKind(ParseNodeKind::NumberExpr)"
") (" "slot argument must be a constant" ")"); do { *((volatile
int*)__null) = 7987; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
7988}
7989
7990void BytecodeEmitter::assertSelfHostedUnsafeSetReservedSlot(
7991 ListNode* argsList) {
7992 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"
, 7992); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 3"
")"); do { *((volatile int*)__null) = 7992; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7993
7994 ParseNode* objNode = argsList->head();
7995 ParseNode* slotNode = objNode->pn_next;
7996
7997 // Ensure that the slot argument is fixed, this is required by the JITs.
7998 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"
, 7999); AnnotateMozCrashReason("MOZ_ASSERT" "(" "slotNode->isKind(ParseNodeKind::NumberExpr)"
") (" "slot argument must be a constant" ")"); do { *((volatile
int*)__null) = 7999; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
7999 "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"
, 7999); AnnotateMozCrashReason("MOZ_ASSERT" "(" "slotNode->isKind(ParseNodeKind::NumberExpr)"
") (" "slot argument must be a constant" ")"); do { *((volatile
int*)__null) = 7999; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
8000}
8001#endif
8002
8003/* A version of emitCalleeAndThis for the optional cases:
8004 * * a?.()
8005 * * a?.b()
8006 * * a?.["b"]()
8007 * * (a?.b)()
8008 * * a?.#b()
8009 *
8010 * See emitCallOrNew and emitOptionalCall for more context.
8011 */
8012bool BytecodeEmitter::emitOptionalCalleeAndThis(ParseNode* callee,
8013 CallNode* call,
8014 CallOrNewEmitter& cone,
8015 OptionalEmitter& oe) {
8016 AutoCheckRecursionLimit recursion(fc);
8017 if (!recursion.check(fc)) {
8018 return false;
8019 }
8020
8021 switch (ParseNodeKind kind = callee->getKind()) {
8022 case ParseNodeKind::Name: {
8023 auto name = callee->as<NameNode>().name();
8024 if (!cone.emitNameCallee(name)) {
8025 // [stack] CALLEE THIS
8026 return false;
8027 }
8028 break;
8029 }
8030
8031 case ParseNodeKind::OptionalDotExpr: {
8032 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"
, 8032); AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode != BytecodeEmitter::SelfHosting"
")"); do { *((volatile int*)__null) = 8032; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8033 OptionalPropertyAccess* prop = &callee->as<OptionalPropertyAccess>();
8034 bool isSuper = false;
8035
8036 PropOpEmitter& poe = cone.prepareForPropCallee(isSuper);
8037 if (!emitOptionalDotExpression(prop, poe, isSuper, oe)) {
8038 // [stack] CALLEE THIS
8039 return false;
8040 }
8041 break;
8042 }
8043 case ParseNodeKind::ArgumentsLength:
8044 case ParseNodeKind::DotExpr: {
8045 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"
, 8045); AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode != BytecodeEmitter::SelfHosting"
")"); do { *((volatile int*)__null) = 8045; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8046 PropertyAccess* prop = &callee->as<PropertyAccess>();
8047 bool isSuper = prop->isSuper();
8048
8049 PropOpEmitter& poe = cone.prepareForPropCallee(isSuper);
8050 if (!emitOptionalDotExpression(prop, poe, isSuper, oe)) {
8051 // [stack] CALLEE THIS
8052 return false;
8053 }
8054 break;
8055 }
8056
8057 case ParseNodeKind::OptionalElemExpr: {
8058 OptionalPropertyByValue* elem = &callee->as<OptionalPropertyByValue>();
8059 bool isSuper = false;
8060 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"
, 8060); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 8060; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8061 ElemOpEmitter& eoe = cone.prepareForElemCallee(isSuper);
8062 if (!emitOptionalElemExpression(elem, eoe, isSuper, oe)) {
8063 // [stack] CALLEE THIS
8064 return false;
8065 }
8066 break;
8067 }
8068 case ParseNodeKind::ElemExpr: {
8069 PropertyByValue* elem = &callee->as<PropertyByValue>();
8070 bool isSuper = elem->isSuper();
8071 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"
, 8071); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 8071; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8072 ElemOpEmitter& eoe = cone.prepareForElemCallee(isSuper);
8073 if (!emitOptionalElemExpression(elem, eoe, isSuper, oe)) {
8074 // [stack] CALLEE THIS
8075 return false;
8076 }
8077 break;
8078 }
8079
8080 case ParseNodeKind::PrivateMemberExpr:
8081 case ParseNodeKind::OptionalPrivateMemberExpr: {
8082 PrivateMemberAccessBase* privateExpr =
8083 &callee->as<PrivateMemberAccessBase>();
8084 PrivateOpEmitter& xoe =
8085 cone.prepareForPrivateCallee(privateExpr->privateName().name());
8086 if (!emitOptionalPrivateExpression(privateExpr, xoe, oe)) {
8087 // [stack] CALLEE THIS
8088 return false;
8089 }
8090 break;
8091 }
8092
8093 case ParseNodeKind::Function:
8094 if (!cone.prepareForFunctionCallee()) {
8095 return false;
8096 }
8097 if (!emitOptionalTree(callee, oe)) {
8098 // [stack] CALLEE
8099 return false;
8100 }
8101 break;
8102
8103 case ParseNodeKind::OptionalChain: {
8104 return emitCalleeAndThisForOptionalChain(&callee->as<UnaryNode>(), call,
8105 cone);
8106 }
8107
8108 default:
8109 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"
, 8109); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "kind != ParseNodeKind::SuperBase"
")"); do { *((volatile int*)__null) = 8109; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8110
8111 if (!cone.prepareForOtherCallee()) {
8112 return false;
8113 }
8114 if (!emitOptionalTree(callee, oe)) {
8115 // [stack] CALLEE
8116 return false;
8117 }
8118 break;
8119 }
8120
8121 if (!cone.emitThis()) {
8122 // [stack] CALLEE THIS
8123 return false;
8124 }
8125
8126 return true;
8127}
8128
8129bool BytecodeEmitter::emitCalleeAndThis(ParseNode* callee, CallNode* maybeCall,
8130 CallOrNewEmitter& cone) {
8131 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"
, 8131); AnnotateMozCrashReason("MOZ_ASSERT" "(" "maybeCall->callee() == callee"
")"); do { *((volatile int*)__null) = 8131; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
8132
8133 switch (callee->getKind()) {
8134 case ParseNodeKind::Name: {
8135 auto name = callee->as<NameNode>().name();
8136 if (!cone.emitNameCallee(name)) {
8137 // [stack] CALLEE THIS?
8138 return false;
8139 }
8140 break;
8141 }
8142 case ParseNodeKind::ArgumentsLength:
8143 case ParseNodeKind::DotExpr: {
8144 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"
, 8144); AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode != BytecodeEmitter::SelfHosting"
")"); do { *((volatile int*)__null) = 8144; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8145 PropertyAccess* prop = &callee->as<PropertyAccess>();
8146 bool isSuper = prop->isSuper();
8147
8148 PropOpEmitter& poe = cone.prepareForPropCallee(isSuper);
8149 if (!poe.prepareForObj()) {
8150 return false;
8151 }
8152 if (isSuper) {
8153 UnaryNode* base = &prop->expression().as<UnaryNode>();
8154 if (!emitGetThisForSuperBase(base)) {
8155 // [stack] THIS
8156 return false;
8157 }
8158 } else {
8159 if (!emitPropLHS(prop)) {
8160 // [stack] OBJ
8161 return false;
8162 }
8163 }
8164 if (!poe.emitGet(prop->key().atom())) {
8165 // [stack] CALLEE THIS?
8166 return false;
8167 }
8168
8169 break;
8170 }
8171 case ParseNodeKind::ElemExpr: {
8172 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"
, 8172); AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode != BytecodeEmitter::SelfHosting"
")"); do { *((volatile int*)__null) = 8172; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8173 PropertyByValue* elem = &callee->as<PropertyByValue>();
8174 bool isSuper = elem->isSuper();
8175 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"
, 8175); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 8175; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8176 ElemOpEmitter& eoe = cone.prepareForElemCallee(isSuper);
8177 if (!emitElemObjAndKey(elem, isSuper, eoe)) {
8178 // [stack] # if Super
8179 // [stack] THIS? THIS KEY
8180 // [stack] # otherwise
8181 // [stack] OBJ? OBJ KEY
8182 return false;
8183 }
8184 if (!eoe.emitGet()) {
8185 // [stack] CALLEE THIS?
8186 return false;
8187 }
8188
8189 break;
8190 }
8191 case ParseNodeKind::PrivateMemberExpr: {
8192 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"
, 8192); AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode != BytecodeEmitter::SelfHosting"
")"); do { *((volatile int*)__null) = 8192; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8193 PrivateMemberAccessBase* privateExpr =
8194 &callee->as<PrivateMemberAccessBase>();
8195 PrivateOpEmitter& xoe =
8196 cone.prepareForPrivateCallee(privateExpr->privateName().name());
8197 if (!emitTree(&privateExpr->expression())) {
8198 // [stack] OBJ
8199 return false;
8200 }
8201 if (!xoe.emitReference()) {
8202 // [stack] OBJ NAME
8203 return false;
8204 }
8205 if (!xoe.emitGetForCallOrNew()) {
8206 // [stack] CALLEE THIS
8207 return false;
8208 }
8209
8210 break;
8211 }
8212 case ParseNodeKind::Function:
8213 if (!cone.prepareForFunctionCallee()) {
8214 return false;
8215 }
8216 if (!emitTree(callee)) {
8217 // [stack] CALLEE
8218 return false;
8219 }
8220 break;
8221 case ParseNodeKind::SuperBase:
8222 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"
, 8222); AnnotateMozCrashReason("MOZ_ASSERT" "(" "maybeCall" ")"
); do { *((volatile int*)__null) = 8222; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8223 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"
, 8223); AnnotateMozCrashReason("MOZ_ASSERT" "(" "maybeCall->isKind(ParseNodeKind::SuperCallExpr)"
")"); do { *((volatile int*)__null) = 8223; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8224 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"
, 8224); AnnotateMozCrashReason("MOZ_ASSERT" "(" "callee->isKind(ParseNodeKind::SuperBase)"
")"); do { *((volatile int*)__null) = 8224; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8225 if (!cone.emitSuperCallee()) {
8226 // [stack] CALLEE IsConstructing
8227 return false;
8228 }
8229 break;
8230 case ParseNodeKind::OptionalChain: {
8231 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"
, 8231); AnnotateMozCrashReason("MOZ_ASSERT" "(" "maybeCall" ")"
); do { *((volatile int*)__null) = 8231; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8232 return emitCalleeAndThisForOptionalChain(&callee->as<UnaryNode>(),
8233 maybeCall, cone);
8234 }
8235 default:
8236 if (!cone.prepareForOtherCallee()) {
8237 return false;
8238 }
8239 if (!emitTree(callee)) {
8240 return false;
8241 }
8242 break;
8243 }
8244
8245 if (!cone.emitThis()) {
8246 // [stack] CALLEE THIS
8247 return false;
8248 }
8249
8250 return true;
8251}
8252
8253ParseNode* BytecodeEmitter::getCoordNode(ParseNode* callNode,
8254 ParseNode* calleeNode, JSOp op,
8255 ListNode* argsList) {
8256 ParseNode* coordNode = callNode;
8257 if (op == JSOp::Call || op == JSOp::SpreadCall) {
8258 // Default to using the location of the `(` itself.
8259 // obj[expr]() // expression
8260 // ^ // column coord
8261 coordNode = argsList;
8262
8263 switch (calleeNode->getKind()) {
8264 case ParseNodeKind::ArgumentsLength:
8265 case ParseNodeKind::DotExpr:
8266 // Use the position of a property access identifier.
8267 //
8268 // obj().aprop() // expression
8269 // ^ // column coord
8270 //
8271 // Note: Because of the constant folding logic in FoldElement,
8272 // this case also applies for constant string properties.
8273 //
8274 // obj()['aprop']() // expression
8275 // ^ // column coord
8276 coordNode = &calleeNode->as<PropertyAccess>().key();
8277 break;
8278 case ParseNodeKind::Name: {
8279 // Use the start of callee name unless it is at a separator
8280 // or has no args.
8281 //
8282 // 2 + obj() // expression
8283 // ^ // column coord
8284 //
8285 if (argsList->empty() ||
8286 !bytecodeSection().atSeparator(calleeNode->pn_pos.begin)) {
8287 // Use the start of callee names.
8288 coordNode = calleeNode;
8289 }
8290 break;
8291 }
8292
8293 default:
8294 break;
8295 }
8296 }
8297 return coordNode;
8298}
8299
8300bool BytecodeEmitter::emitArguments(ListNode* argsList, bool isCall,
8301 bool isSpread, CallOrNewEmitter& cone) {
8302 uint32_t argc = argsList->count();
8303 if (argc >= ARGC_LIMIT) {
8304 reportError(argsList,
8305 isCall ? JSMSG_TOO_MANY_FUN_ARGS : JSMSG_TOO_MANY_CON_ARGS);
8306 return false;
8307 }
8308 if (!isSpread) {
8309 if (!cone.prepareForNonSpreadArguments()) {
8310 // [stack] CALLEE THIS
8311 return false;
8312 }
8313 for (ParseNode* arg : argsList->contents()) {
8314 if (!updateSourceCoordNotesIfNonLiteral(arg)) {
8315 return false;
8316 }
8317 if (!emitTree(arg)) {
8318 // [stack] CALLEE THIS ARG*
8319 return false;
8320 }
8321 }
8322 } else if (cone.wantSpreadOperand()) {
8323 auto* spreadNode = &argsList->head()->as<UnaryNode>();
8324 if (!updateSourceCoordNotesIfNonLiteral(spreadNode->kid())) {
8325 return false;
8326 }
8327 if (!emitTree(spreadNode->kid())) {
8328 // [stack] CALLEE THIS ARG0
8329 return false;
8330 }
8331
8332 if (!cone.emitSpreadArgumentsTest()) {
8333 // [stack] CALLEE THIS ARG0
8334 return false;
8335 }
8336
8337 if (cone.wantSpreadIteration()) {
8338 if (!emitSpreadIntoArray(spreadNode)) {
8339 // [stack] CALLEE THIS ARR
8340 return false;
8341 }
8342 }
8343
8344 if (!cone.emitSpreadArgumentsTestEnd()) {
8345 // [stack] CALLEE THIS ARR
8346 return false;
8347 }
8348 } else {
8349 if (!cone.prepareForSpreadArguments()) {
8350 // [stack] CALLEE THIS
8351 return false;
8352 }
8353 if (!emitArray(argsList)) {
8354 // [stack] CALLEE THIS ARR
8355 return false;
8356 }
8357 }
8358
8359 return true;
8360}
8361
8362bool BytecodeEmitter::emitOptionalCall(CallNode* callNode, OptionalEmitter& oe,
8363 ValueUsage valueUsage) {
8364 /*
8365 * A modified version of emitCallOrNew that handles optional calls.
8366 *
8367 * These include the following:
8368 * a?.()
8369 * a.b?.()
8370 * a.["b"]?.()
8371 * (a?.b)?.()
8372 *
8373 * See CallOrNewEmitter for more context.
8374 */
8375 ParseNode* calleeNode = callNode->callee();
8376 ListNode* argsList = callNode->args();
8377 bool isSpread = IsSpreadOp(callNode->callOp());
8378 JSOp op = callNode->callOp();
8379 uint32_t argc = argsList->count();
8380 bool isOptimizableSpread = isSpread && argc == 1;
8381
8382 CallOrNewEmitter cone(this, op,
8383 isOptimizableSpread
8384 ? CallOrNewEmitter::ArgumentsKind::SingleSpread
8385 : CallOrNewEmitter::ArgumentsKind::Other,
8386 valueUsage);
8387
8388 ParseNode* coordNode = getCoordNode(callNode, calleeNode, op, argsList);
8389
8390 if (!emitOptionalCalleeAndThis(calleeNode, callNode, cone, oe)) {
8391 // [stack] CALLEE THIS
8392 return false;
8393 }
8394
8395 if (callNode->isKind(ParseNodeKind::OptionalCallExpr)) {
8396 if (!oe.emitJumpShortCircuitForCall()) {
8397 // [stack] CALLEE THIS
8398 return false;
8399 }
8400 }
8401
8402 if (!emitArguments(argsList, /* isCall = */ true, isSpread, cone)) {
8403 // [stack] CALLEE THIS ARGS...
8404 return false;
8405 }
8406
8407 if (!cone.emitEnd(argc, coordNode->pn_pos.begin)) {
8408 // [stack] RVAL
8409 return false;
8410 }
8411
8412 return true;
8413}
8414
8415bool BytecodeEmitter::emitCallOrNew(CallNode* callNode, ValueUsage valueUsage) {
8416 /*
8417 * Emit callable invocation or operator new (constructor call) code.
8418 * First, emit code for the left operand to evaluate the callable or
8419 * constructable object expression.
8420 *
8421 * Then (or in a call case that has no explicit reference-base
8422 * object) we emit JSOp::Undefined to produce the undefined |this|
8423 * value required for calls (which non-strict mode functions
8424 * will box into the global object).
8425 */
8426 bool isCall = callNode->isKind(ParseNodeKind::CallExpr) ||
8427 callNode->isKind(ParseNodeKind::TaggedTemplateExpr);
8428 ParseNode* calleeNode = callNode->callee();
8429 ListNode* argsList = callNode->args();
8430 JSOp op = callNode->callOp();
8431
8432 if (calleeNode->isKind(ParseNodeKind::Name) &&
8433 emitterMode == BytecodeEmitter::SelfHosting && op == JSOp::Call) {
8434 // Calls to "forceInterpreter", "callFunction",
8435 // "callContentFunction", or "resumeGenerator" in self-hosted
8436 // code generate inline bytecode.
8437 //
8438 // NOTE: The list of special instruction names has to be kept in sync with
8439 // "js/src/builtin/.eslintrc.js".
8440 auto calleeName = calleeNode->as<NameNode>().name();
8441 if (calleeName == TaggedParserAtomIndex::WellKnown::callFunction()) {
8442 return emitSelfHostedCallFunction(callNode, JSOp::Call);
8443 }
8444 if (calleeName == TaggedParserAtomIndex::WellKnown::callContentFunction()) {
8445 return emitSelfHostedCallFunction(callNode, JSOp::CallContent);
8446 }
8447 if (calleeName ==
8448 TaggedParserAtomIndex::WellKnown::constructContentFunction()) {
8449 return emitSelfHostedCallFunction(callNode, JSOp::NewContent);
8450 }
8451 if (calleeName == TaggedParserAtomIndex::WellKnown::resumeGenerator()) {
8452 return emitSelfHostedResumeGenerator(callNode);
8453 }
8454 if (calleeName == TaggedParserAtomIndex::WellKnown::forceInterpreter()) {
8455 return emitSelfHostedForceInterpreter();
8456 }
8457 if (calleeName == TaggedParserAtomIndex::WellKnown::allowContentIter()) {
8458 return emitSelfHostedAllowContentIter(callNode);
8459 }
8460 if (calleeName ==
8461 TaggedParserAtomIndex::WellKnown::allowContentIterWith()) {
8462 return emitSelfHostedAllowContentIterWith(callNode);
8463 }
8464 if (calleeName ==
8465 TaggedParserAtomIndex::WellKnown::allowContentIterWithNext()) {
8466 return emitSelfHostedAllowContentIterWithNext(callNode);
8467 }
8468 if (calleeName == TaggedParserAtomIndex::WellKnown::DefineDataProperty() &&
8469 argsList->count() == 3) {
8470 return emitSelfHostedDefineDataProperty(callNode);
8471 }
8472 if (calleeName == TaggedParserAtomIndex::WellKnown::hasOwn()) {
8473 return emitSelfHostedHasOwn(callNode);
8474 }
8475 if (calleeName == TaggedParserAtomIndex::WellKnown::getPropertySuper()) {
8476 return emitSelfHostedGetPropertySuper(callNode);
8477 }
8478 if (calleeName == TaggedParserAtomIndex::WellKnown::ToNumeric()) {
8479 return emitSelfHostedToNumeric(callNode);
8480 }
8481 if (calleeName == TaggedParserAtomIndex::WellKnown::ToString()) {
8482 return emitSelfHostedToString(callNode);
8483 }
8484 if (calleeName ==
8485 TaggedParserAtomIndex::WellKnown::GetBuiltinConstructor()) {
8486 return emitSelfHostedGetBuiltinConstructor(callNode);
8487 }
8488 if (calleeName == TaggedParserAtomIndex::WellKnown::GetBuiltinPrototype()) {
8489 return emitSelfHostedGetBuiltinPrototype(callNode);
8490 }
8491 if (calleeName == TaggedParserAtomIndex::WellKnown::GetBuiltinSymbol()) {
8492 return emitSelfHostedGetBuiltinSymbol(callNode);
8493 }
8494 if (calleeName == TaggedParserAtomIndex::WellKnown::ArgumentsLength()) {
8495 return emitSelfHostedArgumentsLength(callNode);
8496 }
8497 if (calleeName == TaggedParserAtomIndex::WellKnown::GetArgument()) {
8498 return emitSelfHostedGetArgument(callNode);
8499 }
8500 if (calleeName ==
8501 TaggedParserAtomIndex::WellKnown::SetIsInlinableLargeFunction()) {
8502 return emitSelfHostedSetIsInlinableLargeFunction(callNode);
8503 }
8504 if (calleeName == TaggedParserAtomIndex::WellKnown::SetCanonicalName()) {
8505 return emitSelfHostedSetCanonicalName(callNode);
8506 }
8507 if (calleeName == TaggedParserAtomIndex::WellKnown::IsNullOrUndefined()) {
8508 return emitSelfHostedIsNullOrUndefined(callNode);
8509 }
8510 if (calleeName == TaggedParserAtomIndex::WellKnown::IteratorClose()) {
8511 return emitSelfHostedIteratorClose(callNode);
8512 }
8513#ifdef DEBUG1
8514 if (calleeName ==
8515 TaggedParserAtomIndex::WellKnown::UnsafeGetReservedSlot() ||
8516 calleeName == TaggedParserAtomIndex::WellKnown::
8517 UnsafeGetObjectFromReservedSlot() ||
8518 calleeName == TaggedParserAtomIndex::WellKnown::
8519 UnsafeGetInt32FromReservedSlot() ||
8520 calleeName == TaggedParserAtomIndex::WellKnown::
8521 UnsafeGetStringFromReservedSlot()) {
8522 // Make sure that this call is correct, but don't emit any special code.
8523 assertSelfHostedUnsafeGetReservedSlot(argsList);
8524 }
8525 if (calleeName ==
8526 TaggedParserAtomIndex::WellKnown::UnsafeSetReservedSlot()) {
8527 // Make sure that this call is correct, but don't emit any special code.
8528 assertSelfHostedUnsafeSetReservedSlot(argsList);
8529 }
8530#endif
8531 // Fall through
8532 }
8533
8534 uint32_t argc = argsList->count();
8535 bool isSpread = IsSpreadOp(op);
8536 bool isOptimizableSpread = isSpread && argc == 1;
8537 bool isDefaultDerivedClassConstructor =
8538 sc->isFunctionBox() && sc->asFunctionBox()->isDerivedClassConstructor() &&
8539 sc->asFunctionBox()->isSyntheticFunction();
8540 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"
, 8540); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isOptimizableSpread"
")"); do { *((volatile int*)__null) = 8540; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
8541 CallOrNewEmitter cone(
8542 this, op,
8543 isOptimizableSpread
8544 ? isDefaultDerivedClassConstructor
8545 ? CallOrNewEmitter::ArgumentsKind::PassthroughRest
8546 : CallOrNewEmitter::ArgumentsKind::SingleSpread
8547 : CallOrNewEmitter::ArgumentsKind::Other,
8548 valueUsage);
8549
8550 if (!emitCalleeAndThis(calleeNode, callNode, cone)) {
8551 // [stack] CALLEE THIS
8552 return false;
8553 }
8554 if (!emitArguments(argsList, isCall, isSpread, cone)) {
8555 // [stack] CALLEE THIS ARGS...
8556 return false;
8557 }
8558
8559 // Push new.target for construct calls.
8560 if (IsConstructOp(op)) {
8561 if (op == JSOp::SuperCall || op == JSOp::SpreadSuperCall) {
8562 if (!emitNewTarget(callNode)) {
8563 // [stack] CALLEE THIS ARGS.. NEW.TARGET
8564 return false;
8565 }
8566 } else {
8567 // Repush the callee as new.target
8568 uint32_t effectiveArgc = isSpread ? 1 : argc;
8569 if (!emitDupAt(effectiveArgc + 1)) {
8570 // [stack] CALLEE THIS ARGS.. CALLEE
8571 return false;
8572 }
8573 }
8574 }
8575
8576 ParseNode* coordNode = getCoordNode(callNode, calleeNode, op, argsList);
8577
8578 if (!cone.emitEnd(argc, coordNode->pn_pos.begin)) {
8579 // [stack] RVAL
8580 return false;
8581 }
8582
8583 return true;
8584}
8585
8586// This list must be kept in the same order in several places:
8587// - The binary operators in ParseNode.h ,
8588// - the binary operators in TokenKind.h
8589// - the precedence list in Parser.cpp
8590static const JSOp ParseNodeKindToJSOp[] = {
8591 // Some binary ops require special code generation (PrivateIn);
8592 // these should not use BinaryOpParseNodeKindToJSOp. This table fills those
8593 // slots with Nops to make the rest of the table lookup work.
8594 JSOp::Coalesce, JSOp::Or, JSOp::And, JSOp::BitOr, JSOp::BitXor,
8595 JSOp::BitAnd, JSOp::StrictEq, JSOp::Eq, JSOp::StrictNe, JSOp::Ne,
8596 JSOp::Lt, JSOp::Le, JSOp::Gt, JSOp::Ge, JSOp::Instanceof,
8597 JSOp::In, JSOp::Nop, JSOp::Lsh, JSOp::Rsh, JSOp::Ursh,
8598 JSOp::Add, JSOp::Sub, JSOp::Mul, JSOp::Div, JSOp::Mod,
8599 JSOp::Pow};
8600
8601static inline JSOp BinaryOpParseNodeKindToJSOp(ParseNodeKind pnk) {
8602 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"
, 8602); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pnk >= ParseNodeKind::BinOpFirst"
")"); do { *((volatile int*)__null) = 8602; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8603 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"
, 8603); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pnk <= ParseNodeKind::BinOpLast"
")"); do { *((volatile int*)__null) = 8603; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8604 int parseNodeFirst = size_t(ParseNodeKind::BinOpFirst);
8605#ifdef DEBUG1
8606 int jsopArraySize = std::size(ParseNodeKindToJSOp);
8607 int parseNodeKindListSize =
8608 size_t(ParseNodeKind::BinOpLast) - parseNodeFirst + 1;
8609 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"
, 8609); AnnotateMozCrashReason("MOZ_ASSERT" "(" "jsopArraySize == parseNodeKindListSize"
")"); do { *((volatile int*)__null) = 8609; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8610 // Ensure we don't use this to find an op for a parse node
8611 // requiring special emission rules.
8612 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"
, 8612); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ParseNodeKindToJSOp[size_t(pnk) - parseNodeFirst] != JSOp::Nop"
")"); do { *((volatile int*)__null) = 8612; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8613#endif
8614 return ParseNodeKindToJSOp[size_t(pnk) - parseNodeFirst];
8615}
8616
8617bool BytecodeEmitter::emitRightAssociative(ListNode* node) {
8618 // ** is the only right-associative operator.
8619 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"
, 8619); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::PowExpr)"
")"); do { *((volatile int*)__null) = 8619; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8620
8621 // Right-associative operator chain.
8622 for (ParseNode* subexpr : node->contents()) {
8623 if (!updateSourceCoordNotesIfNonLiteral(subexpr)) {
8624 return false;
8625 }
8626 if (!emitTree(subexpr)) {
8627 return false;
8628 }
8629 }
8630 for (uint32_t i = 0; i < node->count() - 1; i++) {
8631 if (!emit1(JSOp::Pow)) {
8632 return false;
8633 }
8634 }
8635 return true;
8636}
8637
8638bool BytecodeEmitter::emitLeftAssociative(ListNode* node) {
8639 // Left-associative operator chain.
8640 if (!emitTree(node->head())) {
8641 return false;
8642 }
8643 JSOp op = BinaryOpParseNodeKindToJSOp(node->getKind());
8644 ParseNode* nextExpr = node->head()->pn_next;
8645 do {
8646 if (!updateSourceCoordNotesIfNonLiteral(nextExpr)) {
8647 return false;
8648 }
8649 if (!emitTree(nextExpr)) {
8650 return false;
8651 }
8652 if (!emit1(op)) {
8653 return false;
8654 }
8655 } while ((nextExpr = nextExpr->pn_next));
8656 return true;
8657}
8658
8659bool BytecodeEmitter::emitPrivateInExpr(ListNode* node) {
8660 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"
, 8660); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->head()->isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 8660; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8661
8662 NameNode& privateNameNode = node->head()->as<NameNode>();
8663 TaggedParserAtomIndex privateName = privateNameNode.name();
8664
8665 PrivateOpEmitter xoe(this, PrivateOpEmitter::Kind::ErgonomicBrandCheck,
8666 privateName);
8667
8668 ParseNode* valueNode = node->head()->pn_next;
8669 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"
, 8669); AnnotateMozCrashReason("MOZ_ASSERT" "(" "valueNode->pn_next == nullptr"
")"); do { *((volatile int*)__null) = 8669; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8670
8671 if (!emitTree(valueNode)) {
8672 // [stack] OBJ
8673 return false;
8674 }
8675
8676 if (!xoe.emitReference()) {
8677 // [stack] OBJ BRAND if private method
8678 // [stack] OBJ NAME if private field or accessor.
8679 return false;
8680 }
8681
8682 if (!xoe.emitBrandCheck()) {
8683 // [stack] OBJ BRAND BOOL if private method
8684 // [stack] OBJ NAME BOOL if private field or accessor.
8685 return false;
8686 }
8687
8688 if (!emitUnpickN(2)) {
8689 // [stack] BOOL OBJ BRAND if private method
8690 // [stack] BOOL OBJ NAME if private field or accessor.
8691 return false;
8692 }
8693
8694 if (!emitPopN(2)) {
8695 // [stack] BOOL
8696 return false;
8697 }
8698
8699 return true;
8700}
8701
8702/*
8703 * Special `emitTree` for Optional Chaining case.
8704 * Examples of this are `emitOptionalChain`, `emitDeleteOptionalChain` and
8705 * `emitCalleeAndThisForOptionalChain`.
8706 */
8707bool BytecodeEmitter::emitOptionalTree(
8708 ParseNode* pn, OptionalEmitter& oe,
8709 ValueUsage valueUsage /* = ValueUsage::WantValue */) {
8710 AutoCheckRecursionLimit recursion(fc);
8711 if (!recursion.check(fc)) {
8712 return false;
8713 }
8714 ParseNodeKind kind = pn->getKind();
8715 switch (kind) {
8716 case ParseNodeKind::OptionalDotExpr: {
8717 OptionalPropertyAccess* prop = &pn->as<OptionalPropertyAccess>();
8718 bool isSuper = false;
8719 PropOpEmitter poe(this, PropOpEmitter::Kind::Get,
8720 PropOpEmitter::ObjKind::Other);
8721 if (!emitOptionalDotExpression(prop, poe, isSuper, oe)) {
8722 return false;
8723 }
8724 break;
8725 }
8726 case ParseNodeKind::ArgumentsLength:
8727 case ParseNodeKind::DotExpr: {
8728 PropertyAccess* prop = &pn->as<PropertyAccess>();
8729 bool isSuper = prop->isSuper();
8730 PropOpEmitter poe(this, PropOpEmitter::Kind::Get,
8731 isSuper ? PropOpEmitter::ObjKind::Super
8732 : PropOpEmitter::ObjKind::Other);
8733 if (!emitOptionalDotExpression(prop, poe, isSuper, oe)) {
8734 return false;
8735 }
8736 break;
8737 }
8738
8739 case ParseNodeKind::OptionalElemExpr: {
8740 OptionalPropertyByValue* elem = &pn->as<OptionalPropertyByValue>();
8741 bool isSuper = false;
8742 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"
, 8742); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 8742; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8743 ElemOpEmitter eoe(this, ElemOpEmitter::Kind::Get,
8744 ElemOpEmitter::ObjKind::Other);
8745
8746 if (!emitOptionalElemExpression(elem, eoe, isSuper, oe)) {
8747 return false;
8748 }
8749 break;
8750 }
8751 case ParseNodeKind::ElemExpr: {
8752 PropertyByValue* elem = &pn->as<PropertyByValue>();
8753 bool isSuper = elem->isSuper();
8754 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"
, 8754); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 8754; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8755 ElemOpEmitter eoe(this, ElemOpEmitter::Kind::Get,
8756 isSuper ? ElemOpEmitter::ObjKind::Super
8757 : ElemOpEmitter::ObjKind::Other);
8758
8759 if (!emitOptionalElemExpression(elem, eoe, isSuper, oe)) {
8760 return false;
8761 }
8762 break;
8763 }
8764 case ParseNodeKind::PrivateMemberExpr:
8765 case ParseNodeKind::OptionalPrivateMemberExpr: {
8766 PrivateMemberAccessBase* privateExpr = &pn->as<PrivateMemberAccessBase>();
8767 PrivateOpEmitter xoe(this, PrivateOpEmitter::Kind::Get,
8768 privateExpr->privateName().name());
8769 if (!emitOptionalPrivateExpression(privateExpr, xoe, oe)) {
8770 return false;
8771 }
8772 break;
8773 }
8774 case ParseNodeKind::CallExpr:
8775 case ParseNodeKind::OptionalCallExpr:
8776 if (!emitOptionalCall(&pn->as<CallNode>(), oe, valueUsage)) {
8777 return false;
8778 }
8779 break;
8780 // List of accepted ParseNodeKinds that might appear only at the beginning
8781 // of an Optional Chain.
8782 // For example, a taggedTemplateExpr node might occur if we have
8783 // `test`?.b, with `test` as the taggedTemplateExpr ParseNode.
8784 default:
8785#ifdef DEBUG1
8786 // https://tc39.es/ecma262/#sec-primary-expression
8787 bool isPrimaryExpression =
8788 kind == ParseNodeKind::ThisExpr || kind == ParseNodeKind::Name ||
8789 kind == ParseNodeKind::PrivateName ||
8790 kind == ParseNodeKind::NullExpr || kind == ParseNodeKind::TrueExpr ||
8791 kind == ParseNodeKind::FalseExpr ||
8792 kind == ParseNodeKind::NumberExpr ||
8793 kind == ParseNodeKind::BigIntExpr ||
8794 kind == ParseNodeKind::StringExpr ||
8795 kind == ParseNodeKind::ArrayExpr ||
8796 kind == ParseNodeKind::ObjectExpr ||
8797 kind == ParseNodeKind::Function || kind == ParseNodeKind::ClassDecl ||
8798 kind == ParseNodeKind::RegExpExpr ||
8799 kind == ParseNodeKind::TemplateStringExpr ||
8800 kind == ParseNodeKind::TemplateStringListExpr ||
8801 kind == ParseNodeKind::RawUndefinedExpr || pn->isInParens();
8802
8803 // https://tc39.es/ecma262/#sec-left-hand-side-expressions
8804 bool isMemberExpression = isPrimaryExpression ||
8805 kind == ParseNodeKind::TaggedTemplateExpr ||
8806 kind == ParseNodeKind::NewExpr ||
8807 kind == ParseNodeKind::NewTargetExpr ||
8808 kind == ParseNodeKind::ImportMetaExpr;
8809
8810 bool isCallExpression = kind == ParseNodeKind::SetThis ||
8811 kind == ParseNodeKind::CallImportExpr;
8812
8813 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"
, 8814); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isMemberExpression || isCallExpression"
") (" "Unknown ParseNodeKind for OptionalChain" ")"); do { *
((volatile int*)__null) = 8814; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
8814 "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"
, 8814); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isMemberExpression || isCallExpression"
") (" "Unknown ParseNodeKind for OptionalChain" ")"); do { *
((volatile int*)__null) = 8814; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
8815#endif
8816 return emitTree(pn);
8817 }
8818 return true;
8819}
8820
8821// Handle the case of a call made on a OptionalChainParseNode.
8822// For example `(a?.b)()` and `(a?.b)?.()`.
8823bool BytecodeEmitter::emitCalleeAndThisForOptionalChain(
8824 UnaryNode* optionalChain, CallNode* callNode, CallOrNewEmitter& cone) {
8825 ParseNode* calleeNode = optionalChain->kid();
8826
8827 // Create a new OptionalEmitter, in order to emit the right bytecode
8828 // in isolation.
8829 OptionalEmitter oe(this, bytecodeSection().stackDepth());
8830
8831 if (!emitOptionalCalleeAndThis(calleeNode, callNode, cone, oe)) {
8832 // [stack] CALLEE THIS
8833 return false;
8834 }
8835
8836 // complete the jump if necessary. This will set both the "this" value
8837 // and the "callee" value to undefined, if the callee is undefined. It
8838 // does not matter much what the this value is, the function call will
8839 // fail if it is not optional, and be set to undefined otherwise.
8840 if (!oe.emitOptionalJumpTarget(JSOp::Undefined,
8841 OptionalEmitter::Kind::Reference)) {
8842 // [stack] # If shortcircuit
8843 // [stack] UNDEFINED UNDEFINED
8844 // [stack] # otherwise
8845 // [stack] CALLEE THIS
8846 return false;
8847 }
8848 return true;
8849}
8850
8851bool BytecodeEmitter::emitOptionalChain(UnaryNode* optionalChain,
8852 ValueUsage valueUsage) {
8853 ParseNode* expr = optionalChain->kid();
8854
8855 OptionalEmitter oe(this, bytecodeSection().stackDepth());
8856
8857 if (!emitOptionalTree(expr, oe, valueUsage)) {
8858 // [stack] VAL
8859 return false;
8860 }
8861
8862 if (!oe.emitOptionalJumpTarget(JSOp::Undefined)) {
8863 // [stack] # If shortcircuit
8864 // [stack] UNDEFINED
8865 // [stack] # otherwise
8866 // [stack] VAL
8867 return false;
8868 }
8869
8870 return true;
8871}
8872
8873bool BytecodeEmitter::emitOptionalDotExpression(PropertyAccessBase* prop,
8874 PropOpEmitter& poe,
8875 bool isSuper,
8876 OptionalEmitter& oe) {
8877 if (!poe.prepareForObj()) {
8878 // [stack]
8879 return false;
8880 }
8881
8882 if (isSuper) {
8883 UnaryNode* base = &prop->expression().as<UnaryNode>();
8884 if (!emitGetThisForSuperBase(base)) {
8885 // [stack] OBJ
8886 return false;
8887 }
8888 } else {
8889 if (!emitOptionalTree(&prop->expression(), oe)) {
8890 // [stack] OBJ
8891 return false;
8892 }
8893 }
8894
8895 if (prop->isKind(ParseNodeKind::OptionalDotExpr)) {
8896 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"
, 8896); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!isSuper" ")"
); do { *((volatile int*)__null) = 8896; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8897 if (!oe.emitJumpShortCircuit()) {
8898 // [stack] # if Jump
8899 // [stack] UNDEFINED-OR-NULL
8900 // [stack] # otherwise
8901 // [stack] OBJ
8902 return false;
8903 }
8904 }
8905
8906 if (!poe.emitGet(prop->key().atom())) {
8907 // [stack] PROP
8908 return false;
8909 }
8910
8911 return true;
8912}
8913
8914bool BytecodeEmitter::emitOptionalElemExpression(PropertyByValueBase* elem,
8915 ElemOpEmitter& eoe,
8916 bool isSuper,
8917 OptionalEmitter& oe) {
8918 if (!eoe.prepareForObj()) {
8919 // [stack]
8920 return false;
8921 }
8922
8923 if (isSuper) {
8924 UnaryNode* base = &elem->expression().as<UnaryNode>();
8925 if (!emitGetThisForSuperBase(base)) {
8926 // [stack] OBJ
8927 return false;
8928 }
8929 } else {
8930 if (!emitOptionalTree(&elem->expression(), oe)) {
8931 // [stack] OBJ
8932 return false;
8933 }
8934 }
8935
8936 if (elem->isKind(ParseNodeKind::OptionalElemExpr)) {
8937 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"
, 8937); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!isSuper" ")"
); do { *((volatile int*)__null) = 8937; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8938 if (!oe.emitJumpShortCircuit()) {
8939 // [stack] # if Jump
8940 // [stack] UNDEFINED-OR-NULL
8941 // [stack] # otherwise
8942 // [stack] OBJ
8943 return false;
8944 }
8945 }
8946
8947 if (!eoe.prepareForKey()) {
8948 // [stack] OBJ? OBJ
8949 return false;
8950 }
8951
8952 if (!emitTree(&elem->key())) {
8953 // [stack] OBJ? OBJ KEY
8954 return false;
8955 }
8956
8957 if (!eoe.emitGet()) {
8958 // [stack] ELEM
8959 return false;
8960 }
8961
8962 return true;
8963}
8964
8965bool BytecodeEmitter::emitOptionalPrivateExpression(
8966 PrivateMemberAccessBase* privateExpr, PrivateOpEmitter& xoe,
8967 OptionalEmitter& oe) {
8968 if (!emitOptionalTree(&privateExpr->expression(), oe)) {
8969 // [stack] OBJ
8970 return false;
8971 }
8972
8973 if (privateExpr->isKind(ParseNodeKind::OptionalPrivateMemberExpr)) {
8974 if (!oe.emitJumpShortCircuit()) {
8975 // [stack] # if Jump
8976 // [stack] UNDEFINED-OR-NULL
8977 // [stack] # otherwise
8978 // [stack] OBJ
8979 return false;
8980 }
8981 }
8982
8983 if (!xoe.emitReference()) {
8984 // [stack] OBJ NAME
8985 return false;
8986 }
8987 if (!xoe.emitGet()) {
8988 // [stack] CALLEE THIS # if call
8989 // [stack] VALUE # otherwise
8990 return false;
8991 }
8992
8993 return true;
8994}
8995
8996bool BytecodeEmitter::emitShortCircuit(ListNode* node, ValueUsage valueUsage) {
8997 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"
, 8999); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::OrExpr) || node->isKind(ParseNodeKind::CoalesceExpr) || node->isKind(ParseNodeKind::AndExpr)"
")"); do { *((volatile int*)__null) = 8999; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8998 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"
, 8999); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::OrExpr) || node->isKind(ParseNodeKind::CoalesceExpr) || node->isKind(ParseNodeKind::AndExpr)"
")"); do { *((volatile int*)__null) = 8999; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8999 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"
, 8999); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::OrExpr) || node->isKind(ParseNodeKind::CoalesceExpr) || node->isKind(ParseNodeKind::AndExpr)"
")"); do { *((volatile int*)__null) = 8999; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9000
9001 /*
9002 * JSOp::Or converts the operand on the stack to boolean, leaves the original
9003 * value on the stack and jumps if true; otherwise it falls into the next
9004 * bytecode, which pops the left operand and then evaluates the right operand.
9005 * The jump goes around the right operand evaluation.
9006 *
9007 * JSOp::And converts the operand on the stack to boolean and jumps if false;
9008 * otherwise it falls into the right operand's bytecode.
9009 */
9010
9011 TDZCheckCache tdzCache(this);
9012
9013 JSOp op;
9014 switch (node->getKind()) {
9015 case ParseNodeKind::OrExpr:
9016 op = JSOp::Or;
9017 break;
9018 case ParseNodeKind::CoalesceExpr:
9019 op = JSOp::Coalesce;
9020 break;
9021 case ParseNodeKind::AndExpr:
9022 op = JSOp::And;
9023 break;
9024 default:
9025 MOZ_CRASH("Unexpected ParseNodeKind")do { do { } while (false); MOZ_ReportCrash("" "Unexpected ParseNodeKind"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 9025); AnnotateMozCrashReason("MOZ_CRASH(" "Unexpected ParseNodeKind"
")"); do { *((volatile int*)__null) = 9025; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
9026 }
9027
9028 JumpList jump;
9029
9030 // Left-associative operator chain: avoid too much recursion.
9031 //
9032 // Emit all nodes but the last.
9033 for (ParseNode* expr : node->contentsTo(node->last())) {
9034 if (!emitTree(expr)) {
9035 return false;
9036 }
9037 if (!emitJump(op, &jump)) {
9038 return false;
9039 }
9040 if (!emit1(JSOp::Pop)) {
9041 return false;
9042 }
9043 }
9044
9045 // Emit the last node
9046 if (!emitTree(node->last(), valueUsage)) {
9047 return false;
9048 }
9049
9050 if (!emitJumpTargetAndPatch(jump)) {
9051 return false;
9052 }
9053 return true;
9054}
9055
9056bool BytecodeEmitter::emitSequenceExpr(ListNode* node, ValueUsage valueUsage) {
9057 for (ParseNode* child : node->contentsTo(node->last())) {
9058 if (!updateSourceCoordNotes(child->pn_pos.begin)) {
9059 return false;
9060 }
9061 if (!emitTree(child, ValueUsage::IgnoreValue)) {
9062 return false;
9063 }
9064 if (!emit1(JSOp::Pop)) {
9065 return false;
9066 }
9067 }
9068
9069 ParseNode* child = node->last();
9070 if (!updateSourceCoordNotes(child->pn_pos.begin)) {
9071 return false;
9072 }
9073 if (!emitTree(child, valueUsage)) {
9074 return false;
9075 }
9076 return true;
9077}
9078
9079// Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See
9080// the comment on emitSwitch.
9081MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitIncOrDec(UnaryNode* incDec,
9082 ValueUsage valueUsage) {
9083 switch (incDec->kid()->getKind()) {
9084 case ParseNodeKind::ArgumentsLength:
9085 case ParseNodeKind::DotExpr:
9086 return emitPropIncDec(incDec, valueUsage);
9087 case ParseNodeKind::ElemExpr:
9088 return emitElemIncDec(incDec, valueUsage);
9089 case ParseNodeKind::PrivateMemberExpr:
9090 return emitPrivateIncDec(incDec, valueUsage);
9091 case ParseNodeKind::CallExpr:
9092 return emitCallIncDec(incDec);
9093 default:
9094 return emitNameIncDec(incDec, valueUsage);
9095 }
9096}
9097
9098// Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See
9099// the comment on emitSwitch.
9100MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitLabeledStatement(
9101 const LabeledStatement* labeledStmt) {
9102 auto name = labeledStmt->label();
9103 LabelEmitter label(this);
9104
9105 label.emitLabel(name);
9106
9107 if (!emitTree(labeledStmt->statement())) {
9108 return false;
9109 }
9110 if (!label.emitEnd()) {
9111 return false;
9112 }
9113
9114 return true;
9115}
9116
9117bool BytecodeEmitter::emitConditionalExpression(
9118 ConditionalExpression& conditional, ValueUsage valueUsage) {
9119 CondEmitter cond(this);
9120 if (!cond.emitCond()) {
9121 return false;
9122 }
9123
9124 ParseNode* conditionNode = &conditional.condition();
9125 auto conditionKind = IfEmitter::ConditionKind::Positive;
9126 if (conditionNode->isKind(ParseNodeKind::NotExpr)) {
9127 conditionNode = conditionNode->as<UnaryNode>().kid();
9128 conditionKind = IfEmitter::ConditionKind::Negative;
9129 }
9130
9131 // NOTE: NotExpr of conditionNode may be unwrapped, and in that case the
9132 // negation is handled by conditionKind.
9133 if (!emitTree(conditionNode)) {
9134 return false;
9135 }
9136
9137 if (!cond.emitThenElse(conditionKind)) {
9138 return false;
9139 }
9140
9141 if (!emitTree(&conditional.thenExpression(), valueUsage)) {
9142 return false;
9143 }
9144
9145 if (!cond.emitElse()) {
9146 return false;
9147 }
9148
9149 if (!emitTree(&conditional.elseExpression(), valueUsage)) {
9150 return false;
9151 }
9152
9153 if (!cond.emitEnd()) {
9154 return false;
9155 }
9156 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"
, 9156); AnnotateMozCrashReason("MOZ_ASSERT" "(" "cond.pushed() == 1"
")"); do { *((volatile int*)__null) = 9156; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9157
9158 return true;
9159}
9160
9161// Check for an object-literal property list that can be handled by the
9162// ObjLiteral writer. We ensure that for each `prop: value` pair, the key is a
9163// constant name or numeric index, there is no accessor specified, and the value
9164// can be encoded by an ObjLiteral instruction (constant number, string,
9165// boolean, null/undefined).
9166void BytecodeEmitter::isPropertyListObjLiteralCompatible(ListNode* obj,
9167 bool* withValues,
9168 bool* withoutValues) {
9169 bool keysOK = true;
9170 bool valuesOK = true;
9171 uint32_t propCount = 0;
9172
9173 for (ParseNode* propdef : obj->contents()) {
9174 if (!propdef->is<BinaryNode>()) {
9175 keysOK = false;
9176 break;
9177 }
9178 propCount++;
9179
9180 BinaryNode* prop = &propdef->as<BinaryNode>();
9181 ParseNode* key = prop->left();
9182 ParseNode* value = prop->right();
9183
9184 // Computed keys not OK (ObjLiteral data stores constant keys).
9185 if (key->isKind(ParseNodeKind::ComputedName)) {
9186 keysOK = false;
9187 break;
9188 }
9189
9190 // BigIntExprs should have been lowered to computed names at parse
9191 // time, and so should be excluded above.
9192 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"
, 9192); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!key->isKind(ParseNodeKind::BigIntExpr)"
")"); do { *((volatile int*)__null) = 9192; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9193
9194 // Numeric keys OK as long as they are integers and in range.
9195 if (key->isKind(ParseNodeKind::NumberExpr)) {
9196 double numValue = key->as<NumericLiteral>().value();
9197 int32_t i = 0;
9198 if (!NumberIsInt32(numValue, &i)) {
9199 keysOK = false;
9200 break;
9201 }
9202 if (!ObjLiteralWriter::arrayIndexInRange(i)) {
9203 keysOK = false;
9204 break;
9205 }
9206 }
9207
9208 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"
, 9210); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr)"
")"); do { *((volatile int*)__null) = 9210; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9209 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"
, 9210); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr)"
")"); do { *((volatile int*)__null) = 9210; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9210 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"
, 9210); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr)"
")"); do { *((volatile int*)__null) = 9210; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9211
9212 AccessorType accessorType =
9213 prop->is<PropertyDefinition>()
9214 ? prop->as<PropertyDefinition>().accessorType()
9215 : AccessorType::None;
9216 if (accessorType != AccessorType::None) {
9217 keysOK = false;
9218 break;
9219 }
9220
9221 if (!isRHSObjLiteralCompatible(value)) {
9222 valuesOK = false;
9223 }
9224 }
9225
9226 if (propCount > SharedPropMap::MaxPropsForNonDictionary) {
9227 // JSOp::NewObject cannot accept dictionary-mode objects.
9228 keysOK = false;
9229 }
9230
9231 *withValues = keysOK && valuesOK;
9232 *withoutValues = keysOK;
9233}
9234
9235bool BytecodeEmitter::isArrayObjLiteralCompatible(ListNode* array) {
9236 for (ParseNode* elem : array->contents()) {
9237 if (elem->isKind(ParseNodeKind::Spread)) {
9238 return false;
9239 }
9240 if (!isRHSObjLiteralCompatible(elem)) {
9241 return false;
9242 }
9243 }
9244 return true;
9245}
9246
9247bool BytecodeEmitter::emitPropertyList(ListNode* obj, PropertyEmitter& pe,
9248 PropListType type) {
9249 // [stack] CTOR? OBJ
9250
9251 size_t curFieldKeyIndex = 0;
9252 size_t curStaticFieldKeyIndex = 0;
9253 for (ParseNode* propdef : obj->contents()) {
9254 if (propdef->is<ClassField>()) {
9255 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"
, 9255); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == ClassBody"
")"); do { *((volatile int*)__null) = 9255; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9256 // Only handle computing field keys here: the .initializers lambda array
9257 // is created elsewhere.
9258 ClassField* field = &propdef->as<ClassField>();
9259 if (field->name().getKind() == ParseNodeKind::ComputedName) {
9260 auto fieldKeys =
9261 field->isStatic()
9262 ? TaggedParserAtomIndex::WellKnown::dot_staticFieldKeys_()
9263 : TaggedParserAtomIndex::WellKnown::dot_fieldKeys_();
9264 if (!emitGetName(fieldKeys)) {
9265 // [stack] CTOR OBJ ARRAY
9266 return false;
9267 }
9268
9269 ParseNode* nameExpr = field->name().as<UnaryNode>().kid();
9270
9271 if (!emitTree(nameExpr, ValueUsage::WantValue)) {
9272 // [stack] CTOR OBJ ARRAY KEY
9273 return false;
9274 }
9275
9276 if (!emit1(JSOp::ToPropertyKey)) {
9277 // [stack] CTOR OBJ ARRAY KEY
9278 return false;
9279 }
9280
9281 size_t fieldKeysIndex;
9282 if (field->isStatic()) {
9283 fieldKeysIndex = curStaticFieldKeyIndex++;
9284 } else {
9285 fieldKeysIndex = curFieldKeyIndex++;
9286 }
9287
9288 if (!emitUint32Operand(JSOp::InitElemArray, fieldKeysIndex)) {
9289 // [stack] CTOR OBJ ARRAY
9290 return false;
9291 }
9292
9293 if (!emit1(JSOp::Pop)) {
9294 // [stack] CTOR OBJ
9295 return false;
9296 }
9297 }
9298 continue;
9299 }
9300
9301 if (propdef->isKind(ParseNodeKind::StaticClassBlock)) {
9302 // Static class blocks are emitted as part of
9303 // emitCreateMemberInitializers.
9304 continue;
9305 }
9306
9307 if (propdef->is<LexicalScopeNode>()) {
9308 // Constructors are sometimes wrapped in LexicalScopeNodes. As we
9309 // already handled emitting the constructor, skip it.
9310 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"
, 9311); AnnotateMozCrashReason("MOZ_ASSERT" "(" "propdef->as<LexicalScopeNode>().scopeBody()->is<ClassMethod>()"
")"); do { *((volatile int*)__null) = 9311; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9311 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"
, 9311); AnnotateMozCrashReason("MOZ_ASSERT" "(" "propdef->as<LexicalScopeNode>().scopeBody()->is<ClassMethod>()"
")"); do { *((volatile int*)__null) = 9311; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9312 continue;
9313 }
9314
9315 // Handle __proto__: v specially because *only* this form, and no other
9316 // involving "__proto__", performs [[Prototype]] mutation.
9317 if (propdef->isKind(ParseNodeKind::MutateProto)) {
9318 // [stack] OBJ
9319 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"
, 9319); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == ObjectLiteral"
")"); do { *((volatile int*)__null) = 9319; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9320 if (!pe.prepareForProtoValue(propdef->pn_pos.begin)) {
9321 // [stack] OBJ
9322 return false;
9323 }
9324 if (!emitTree(propdef->as<UnaryNode>().kid())) {
9325 // [stack] OBJ PROTO
9326 return false;
9327 }
9328 if (!pe.emitMutateProto()) {
9329 // [stack] OBJ
9330 return false;
9331 }
9332 continue;
9333 }
9334
9335 if (propdef->isKind(ParseNodeKind::Spread)) {
9336 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"
, 9336); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == ObjectLiteral"
")"); do { *((volatile int*)__null) = 9336; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9337 // [stack] OBJ
9338 if (!pe.prepareForSpreadOperand(propdef->pn_pos.begin)) {
9339 // [stack] OBJ OBJ
9340 return false;
9341 }
9342 if (!emitTree(propdef->as<UnaryNode>().kid())) {
9343 // [stack] OBJ OBJ VAL
9344 return false;
9345 }
9346 if (!pe.emitSpread()) {
9347 // [stack] OBJ
9348 return false;
9349 }
9350 continue;
9351 }
9352
9353 BinaryNode* prop = &propdef->as<BinaryNode>();
9354
9355 ParseNode* key = prop->left();
9356 AccessorType accessorType;
9357 if (prop->is<ClassMethod>()) {
9358 ClassMethod& method = prop->as<ClassMethod>();
9359 accessorType = method.accessorType();
9360
9361 if (!method.isStatic() && key->isKind(ParseNodeKind::PrivateName) &&
9362 accessorType != AccessorType::None) {
9363 // Private non-static accessors are stamped onto instances from
9364 // initializers; see emitCreateMemberInitializers.
9365 continue;
9366 }
9367 } else if (prop->is<PropertyDefinition>()) {
9368 accessorType = prop->as<PropertyDefinition>().accessorType();
9369 } else {
9370 accessorType = AccessorType::None;
9371 }
9372
9373 auto emitValue = [this, &key, &prop, accessorType, &pe]() {
9374 // [stack] CTOR? OBJ CTOR? KEY?
9375
9376 ParseNode* propVal = prop->right();
9377 if (propVal->isDirectRHSAnonFunction()) {
9378 // The following branches except for the last `else` clause emit the
9379 // cases handled in NameResolver::resolveFun (see NameFunctions.cpp)
9380 if (key->isKind(ParseNodeKind::ObjectPropertyName) ||
9381 key->isKind(ParseNodeKind::PrivateName) ||
9382 key->isKind(ParseNodeKind::StringExpr)) {
9383 auto keyAtom = key->as<NameNode>().atom();
9384 if (!emitAnonymousFunctionWithName(propVal, keyAtom)) {
9385 // [stack] CTOR? OBJ CTOR? VAL
9386 return false;
9387 }
9388 } else if (key->isKind(ParseNodeKind::NumberExpr)) {
9389 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"
, 9389); AnnotateMozCrashReason("MOZ_ASSERT" "(" "accessorType == AccessorType::None"
")"); do { *((volatile int*)__null) = 9389; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9390
9391 auto keyAtom = key->as<NumericLiteral>().toAtom(fc, parserAtoms());
9392 if (!keyAtom) {
9393 return false;
9394 }
9395 if (!emitAnonymousFunctionWithName(propVal, keyAtom)) {
9396 // [stack] CTOR? OBJ CTOR? KEY VAL
9397 return false;
9398 }
9399 } else if (key->isKind(ParseNodeKind::ComputedName) &&
9400 (key->as<UnaryNode>().kid()->isKind(
9401 ParseNodeKind::NumberExpr) ||
9402 key->as<UnaryNode>().kid()->isKind(
9403 ParseNodeKind::StringExpr)) &&
9404 accessorType == AccessorType::None) {
9405 ParseNode* keyKid = key->as<UnaryNode>().kid();
9406 if (keyKid->isKind(ParseNodeKind::NumberExpr)) {
9407 auto keyAtom =
9408 keyKid->as<NumericLiteral>().toAtom(fc, parserAtoms());
9409 if (!keyAtom) {
9410 return false;
9411 }
9412 if (!emitAnonymousFunctionWithName(propVal, keyAtom)) {
9413 // [stack] CTOR? OBJ CTOR? KEY VAL
9414 return false;
9415 }
9416 } else {
9417 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"
, 9417); AnnotateMozCrashReason("MOZ_ASSERT" "(" "keyKid->isKind(ParseNodeKind::StringExpr)"
")"); do { *((volatile int*)__null) = 9417; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9418 auto keyAtom = keyKid->as<NameNode>().atom();
9419 if (!emitAnonymousFunctionWithName(propVal, keyAtom)) {
9420 // [stack] CTOR? OBJ CTOR? KEY VAL
9421 return false;
9422 }
9423 }
9424 } else {
9425 // Either a proper computed property name or a synthetic computed
9426 // property name for BigInt keys.
9427 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"
, 9427); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::ComputedName)"
")"); do { *((volatile int*)__null) = 9427; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9428
9429 FunctionPrefixKind prefix =
9430 accessorType == AccessorType::None ? FunctionPrefixKind::None
9431 : accessorType == AccessorType::Getter ? FunctionPrefixKind::Get
9432 : FunctionPrefixKind::Set;
9433
9434 if (!emitAnonymousFunctionWithComputedName(propVal, prefix)) {
9435 // [stack] CTOR? OBJ CTOR? KEY VAL
9436 return false;
9437 }
9438 }
9439 } else {
9440 if (!emitTree(propVal)) {
9441 // [stack] CTOR? OBJ CTOR? KEY? VAL
9442 return false;
9443 }
9444 }
9445
9446 if (propVal->is<FunctionNode>() &&
9447 propVal->as<FunctionNode>().funbox()->needsHomeObject()) {
9448 if (!pe.emitInitHomeObject()) {
9449 // [stack] CTOR? OBJ CTOR? KEY? FUN
9450 return false;
9451 }
9452 }
9453
9454#ifdef ENABLE_DECORATORS
9455 if (prop->is<ClassMethod>()) {
9456 ClassMethod& method = prop->as<ClassMethod>();
9457 if (method.decorators() && !method.decorators()->empty()) {
9458 DecoratorEmitter::Kind kind;
9459 switch (method.accessorType()) {
9460 case AccessorType::Getter:
9461 kind = DecoratorEmitter::Getter;
9462 break;
9463 case AccessorType::Setter:
9464 kind = DecoratorEmitter::Setter;
9465 break;
9466 case AccessorType::None:
9467 kind = DecoratorEmitter::Method;
9468 break;
9469 }
9470
9471 if (!method.isStatic()) {
9472 bool hasKeyOnStack = key->isKind(ParseNodeKind::NumberExpr) ||
9473 key->isKind(ParseNodeKind::ComputedName);
9474 if (!emitDupAt(hasKeyOnStack ? 4 : 3)) {
9475 // [stack] ADDINIT OBJ KEY? VAL ADDINIT
9476 return false;
9477 }
9478 } else {
9479 // TODO: See bug 1868220 for support for static methods.
9480 // Note: Key will be present if this has a private name.
9481 if (!emit1(JSOp::Undefined)) {
9482 // [stack] CTOR OBJ CTOR KEY? VAL ADDINIT
9483 return false;
9484 }
9485 }
9486
9487 if (!emit1(JSOp::Swap)) {
9488 // [stack] ADDINIT CTOR? OBJ CTOR? KEY? ADDINIT VAL
9489 return false;
9490 }
9491
9492 // The decorators are applied to the current value on the stack,
9493 // possibly replacing it.
9494 DecoratorEmitter de(this);
9495 if (!de.emitApplyDecoratorsToElementDefinition(
9496 kind, key, method.decorators(), method.isStatic())) {
9497 // [stack] ADDINIT CTOR? OBJ CTOR? KEY? ADDINIT VAL
9498 return false;
9499 }
9500
9501 if (!emit1(JSOp::Swap)) {
9502 // [stack] ADDINIT CTOR? OBJ CTOR? KEY? VAL ADDINIT
9503 return false;
9504 }
9505
9506 if (!emitPopN(1)) {
9507 // [stack] ADDINIT CTOR? OBJ CTOR? KEY? VAL
9508 return false;
9509 }
9510 }
9511 }
9512#endif
9513
9514 return true;
9515 };
9516
9517 PropertyEmitter::Kind kind =
9518 (type == ClassBody && propdef->as<ClassMethod>().isStatic())
9519 ? PropertyEmitter::Kind::Static
9520 : PropertyEmitter::Kind::Prototype;
9521 if (key->isKind(ParseNodeKind::ObjectPropertyName) ||
9522 key->isKind(ParseNodeKind::StringExpr)) {
9523 // [stack] CTOR? OBJ
9524
9525 auto keyAtom = key->as<NameNode>().atom();
9526
9527 // emitClass took care of constructor already.
9528 if (type == ClassBody &&
9529 keyAtom == TaggedParserAtomIndex::WellKnown::constructor() &&
9530 !propdef->as<ClassMethod>().isStatic()) {
9531 continue;
9532 }
9533
9534 if (!pe.prepareForPropValue(propdef->pn_pos.begin, kind)) {
9535 // [stack] CTOR? OBJ CTOR?
9536 return false;
9537 }
9538
9539 if (!emitValue()) {
9540 // [stack] CTOR? OBJ CTOR? VAL
9541 return false;
9542 }
9543
9544 if (!pe.emitInit(accessorType, keyAtom)) {
9545 // [stack] CTOR? OBJ
9546 return false;
9547 }
9548
9549 continue;
9550 }
9551
9552 if (key->isKind(ParseNodeKind::NumberExpr)) {
9553 // [stack] CTOR? OBJ
9554 if (!pe.prepareForIndexPropKey(propdef->pn_pos.begin, kind)) {
9555 // [stack] CTOR? OBJ CTOR?
9556 return false;
9557 }
9558 if (!emitNumberOp(key->as<NumericLiteral>().value())) {
9559 // [stack] CTOR? OBJ CTOR? KEY
9560 return false;
9561 }
9562 if (!pe.prepareForIndexPropValue()) {
9563 // [stack] CTOR? OBJ CTOR? KEY
9564 return false;
9565 }
9566 if (!emitValue()) {
9567 // [stack] CTOR? OBJ CTOR? KEY VAL
9568 return false;
9569 }
9570
9571 if (!pe.emitInitIndexOrComputed(accessorType)) {
9572 // [stack] CTOR? OBJ
9573 return false;
9574 }
9575
9576 continue;
9577 }
9578
9579 if (key->isKind(ParseNodeKind::ComputedName)) {
9580 // Either a proper computed property name or a synthetic computed property
9581 // name for BigInt keys.
9582
9583 // [stack] CTOR? OBJ
9584
9585 if (!pe.prepareForComputedPropKey(propdef->pn_pos.begin, kind)) {
9586 // [stack] CTOR? OBJ CTOR?
9587 return false;
9588 }
9589 if (!emitTree(key->as<UnaryNode>().kid())) {
9590 // [stack] CTOR? OBJ CTOR? KEY
9591 return false;
9592 }
9593 if (!pe.prepareForComputedPropValue()) {
9594 // [stack] CTOR? OBJ CTOR? KEY
9595 return false;
9596 }
9597 if (!emitValue()) {
9598 // [stack] CTOR? OBJ CTOR? KEY VAL
9599 return false;
9600 }
9601
9602 if (!pe.emitInitIndexOrComputed(accessorType)) {
9603 // [stack] CTOR? OBJ
9604 return false;
9605 }
9606
9607 continue;
9608 }
9609
9610 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"
, 9610); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 9610; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9611 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"
, 9611); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == ClassBody"
")"); do { *((volatile int*)__null) = 9611; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9612
9613 auto* privateName = &key->as<NameNode>();
9614
9615 if (kind == PropertyEmitter::Kind::Prototype) {
9616 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"
, 9616); AnnotateMozCrashReason("MOZ_ASSERT" "(" "accessorType == AccessorType::None"
")"); do { *((volatile int*)__null) = 9616; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9617 if (!pe.prepareForPrivateMethod()) {
9618 // [stack] CTOR OBJ
9619 return false;
9620 }
9621 NameOpEmitter noe(this, privateName->atom(),
9622 NameOpEmitter::Kind::SimpleAssignment);
9623
9624 // Ensure the NameOp emitter doesn't push an environment onto the stack,
9625 // because that would change the stack location of the home object.
9626 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"
, 9627); AnnotateMozCrashReason("MOZ_ASSERT" "(" "noe.loc().kind() == NameLocation::Kind::FrameSlot || noe.loc().kind() == NameLocation::Kind::EnvironmentCoordinate"
")"); do { *((volatile int*)__null) = 9627; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9627 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"
, 9627); AnnotateMozCrashReason("MOZ_ASSERT" "(" "noe.loc().kind() == NameLocation::Kind::FrameSlot || noe.loc().kind() == NameLocation::Kind::EnvironmentCoordinate"
")"); do { *((volatile int*)__null) = 9627; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9628
9629 if (!noe.prepareForRhs()) {
9630 // [stack] CTOR OBJ
9631 return false;
9632 }
9633 if (!emitValue()) {
9634 // [stack] CTOR OBJ METHOD
9635 return false;
9636 }
9637 if (!noe.emitAssignment()) {
9638 // [stack] CTOR OBJ METHOD
9639 return false;
9640 }
9641 if (!emit1(JSOp::Pop)) {
9642 // [stack] CTOR OBJ
9643 return false;
9644 }
9645 if (!pe.skipInit()) {
9646 // [stack] CTOR OBJ
9647 return false;
9648 }
9649 continue;
9650 }
9651
9652 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"
, 9652); AnnotateMozCrashReason("MOZ_ASSERT" "(" "kind == PropertyEmitter::Kind::Static"
")"); do { *((volatile int*)__null) = 9652; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9653
9654 // [stack] CTOR OBJ
9655
9656 if (!pe.prepareForPrivateStaticMethod(propdef->pn_pos.begin)) {
9657 // [stack] CTOR OBJ CTOR
9658 return false;
9659 }
9660 if (!emitGetPrivateName(privateName)) {
9661 // [stack] CTOR OBJ CTOR KEY
9662 return false;
9663 }
9664 if (!emitValue()) {
9665 // [stack] CTOR OBJ CTOR KEY VAL
9666 return false;
9667 }
9668
9669 if (!pe.emitPrivateStaticMethod(accessorType)) {
9670 // [stack] CTOR OBJ
9671 return false;
9672 }
9673
9674 if (privateName->privateNameKind() == PrivateNameKind::Setter) {
9675 if (!emitDupAt(1)) {
9676 // [stack] CTOR OBJ CTOR
9677 return false;
9678 }
9679 if (!emitGetPrivateName(privateName)) {
9680 // [stack] CTOR OBJ CTOR NAME
9681 return false;
9682 }
9683 if (!emitAtomOp(JSOp::GetIntrinsic,
9684 TaggedParserAtomIndex::WellKnown::NoPrivateGetter())) {
9685 // [stack] CTOR OBJ CTOR NAME FUN
9686 return false;
9687 }
9688 if (!emit1(JSOp::InitHiddenElemGetter)) {
9689 // [stack] CTOR OBJ CTOR
9690 return false;
9691 }
9692 if (!emit1(JSOp::Pop)) {
9693 // [stack] CTOR OBJ
9694 return false;
9695 }
9696 }
9697 }
9698
9699 return true;
9700}
9701
9702bool BytecodeEmitter::emitPropertyListObjLiteral(ListNode* obj, JSOp op,
9703 bool useObjLiteralValues) {
9704 ObjLiteralWriter writer;
9705
9706#ifdef DEBUG1
9707 // In self-hosted JS, we check duplication only on debug build.
9708 mozilla::Maybe<mozilla::HashSet<frontend::TaggedParserAtomIndex,
9709 frontend::TaggedParserAtomIndexHasher>>
9710 selfHostedPropNames;
9711 if (emitterMode == BytecodeEmitter::SelfHosting) {
9712 selfHostedPropNames.emplace();
9713 }
9714#endif
9715
9716 if (op == JSOp::Object) {
9717 writer.beginObject(op);
9718 } else {
9719 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"
, 9719); AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::NewObject"
")"); do { *((volatile int*)__null) = 9719; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9720 writer.beginShape(op);
9721 }
9722
9723 for (ParseNode* propdef : obj->contents()) {
9724 BinaryNode* prop = &propdef->as<BinaryNode>();
9725 ParseNode* key = prop->left();
9726
9727 if (key->is<NameNode>()) {
9728 if (emitterMode == BytecodeEmitter::SelfHosting) {
9729 auto propName = key->as<NameNode>().atom();
9730#ifdef DEBUG1
9731 // Self-hosted JS shouldn't contain duplicate properties.
9732 auto p = selfHostedPropNames->lookupForAdd(propName);
9733 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"
, 9733); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!p" ")"); do
{ *((volatile int*)__null) = 9733; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
9734 if (!selfHostedPropNames->add(p, propName)) {
9735 js::ReportOutOfMemory(fc);
9736 return false;
9737 }
9738#endif
9739 writer.setPropNameNoDuplicateCheck(parserAtoms(), propName);
9740 } else {
9741 if (!writer.setPropName(parserAtoms(), key->as<NameNode>().atom())) {
9742 return false;
9743 }
9744 }
9745 } else {
9746 double numValue = key->as<NumericLiteral>().value();
9747 int32_t i = 0;
9748 DebugOnly<bool> numIsInt =
9749 NumberIsInt32(numValue, &i); // checked previously.
9750 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"
, 9750); AnnotateMozCrashReason("MOZ_ASSERT" "(" "numIsInt" ")"
); do { *((volatile int*)__null) = 9750; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9751 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"
, 9752); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ObjLiteralWriter::arrayIndexInRange(i)"
")"); do { *((volatile int*)__null) = 9752; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9752 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"
, 9752); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ObjLiteralWriter::arrayIndexInRange(i)"
")"); do { *((volatile int*)__null) = 9752; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
; // checked previously.
9753
9754 // Ignore indexed properties if we're not storing property values, and
9755 // rely on InitElem ops to define those. These properties will be either
9756 // dense elements (not possible to represent in the literal's shape) or
9757 // sparse elements (enumerated separately, so this doesn't affect property
9758 // iteration order).
9759 if (!useObjLiteralValues) {
9760 continue;
9761 }
9762
9763 writer.setPropIndex(i);
9764 }
9765
9766 if (useObjLiteralValues) {
9767 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"
, 9767); AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::Object"
")"); do { *((volatile int*)__null) = 9767; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9768 ParseNode* value = prop->right();
9769 if (!emitObjLiteralValue(writer, value)) {
9770 return false;
9771 }
9772 } else {
9773 if (!writer.propWithUndefinedValue(fc)) {
9774 return false;
9775 }
9776 }
9777 }
9778
9779 GCThingIndex index;
9780 if (!addObjLiteralData(writer, &index)) {
9781 return false;
9782 }
9783
9784 // JSOp::Object may only be used by (top-level) run-once scripts.
9785 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"
, 9786); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isTopLevelContext() && sc->treatAsRunOnce()"
")"); do { *((volatile int*)__null) = 9786; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
9786 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"
, 9786); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isTopLevelContext() && sc->treatAsRunOnce()"
")"); do { *((volatile int*)__null) = 9786; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
9787
9788 if (!emitGCIndexOp(op, index)) {
9789 // [stack] OBJ
9790 return false;
9791 }
9792
9793 return true;
9794}
9795
9796bool BytecodeEmitter::emitDestructuringRestExclusionSetObjLiteral(
9797 ListNode* pattern) {
9798 // Note: if we want to squeeze out a little more performance, we could switch
9799 // to the `JSOp::Object` opcode, because the exclusion set object is never
9800 // exposed to the user, so it's safe to bake the object into the bytecode.
9801 constexpr JSOp op = JSOp::NewObject;
9802
9803 ObjLiteralWriter writer;
9804 writer.beginShape(op);
9805
9806 for (ParseNode* member : pattern->contents()) {
9807 if (member->isKind(ParseNodeKind::Spread)) {
9808 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"
, 9808); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!member->pn_next"
") (" "unexpected trailing element after spread" ")"); do { *
((volatile int*)__null) = 9808; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
9809 break;
9810 }
9811
9812 TaggedParserAtomIndex atom;
9813 if (member->isKind(ParseNodeKind::MutateProto)) {
9814 atom = TaggedParserAtomIndex::WellKnown::proto_();
9815 } else {
9816 ParseNode* key = member->as<BinaryNode>().left();
9817 atom = key->as<NameNode>().atom();
9818 }
9819
9820 if (!writer.setPropName(parserAtoms(), atom)) {
9821 return false;
9822 }
9823
9824 if (!writer.propWithUndefinedValue(fc)) {
9825 return false;
9826 }
9827 }
9828
9829 GCThingIndex index;
9830 if (!addObjLiteralData(writer, &index)) {
9831 return false;
9832 }
9833
9834 if (!emitGCIndexOp(op, index)) {
9835 // [stack] OBJ
9836 return false;
9837 }
9838
9839 return true;
9840}
9841
9842bool BytecodeEmitter::emitObjLiteralArray(ListNode* array) {
9843 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"
, 9843); AnnotateMozCrashReason("MOZ_ASSERT" "(" "checkSingletonContext()"
")"); do { *((volatile int*)__null) = 9843; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9844
9845 constexpr JSOp op = JSOp::Object;
9846
9847 ObjLiteralWriter writer;
9848 writer.beginArray(op);
9849
9850 writer.beginDenseArrayElements();
9851 for (ParseNode* elem : array->contents()) {
9852 if (!emitObjLiteralValue(writer, elem)) {
9853 return false;
9854 }
9855 }
9856
9857 GCThingIndex index;
9858 if (!addObjLiteralData(writer, &index)) {
9859 return false;
9860 }
9861
9862 if (!emitGCIndexOp(op, index)) {
9863 // [stack] OBJ
9864 return false;
9865 }
9866
9867 return true;
9868}
9869
9870bool BytecodeEmitter::isRHSObjLiteralCompatible(ParseNode* value) {
9871 return value->isKind(ParseNodeKind::NumberExpr) ||
9872 value->isKind(ParseNodeKind::TrueExpr) ||
9873 value->isKind(ParseNodeKind::FalseExpr) ||
9874 value->isKind(ParseNodeKind::NullExpr) ||
9875 value->isKind(ParseNodeKind::RawUndefinedExpr) ||
9876 value->isKind(ParseNodeKind::StringExpr) ||
9877 value->isKind(ParseNodeKind::TemplateStringExpr);
9878}
9879
9880bool BytecodeEmitter::emitObjLiteralValue(ObjLiteralWriter& writer,
9881 ParseNode* value) {
9882 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"
, 9882); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isRHSObjLiteralCompatible(value)"
")"); do { *((volatile int*)__null) = 9882; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9883 if (value->isKind(ParseNodeKind::NumberExpr)) {
9884 double numValue = value->as<NumericLiteral>().value();
9885 int32_t i = 0;
9886 js::Value v;
9887 if (NumberIsInt32(numValue, &i)) {
9888 v.setInt32(i);
9889 } else {
9890 v.setDouble(numValue);
9891 }
9892 if (!writer.propWithConstNumericValue(fc, v)) {
9893 return false;
9894 }
9895 } else if (value->isKind(ParseNodeKind::TrueExpr)) {
9896 if (!writer.propWithTrueValue(fc)) {
9897 return false;
9898 }
9899 } else if (value->isKind(ParseNodeKind::FalseExpr)) {
9900 if (!writer.propWithFalseValue(fc)) {
9901 return false;
9902 }
9903 } else if (value->isKind(ParseNodeKind::NullExpr)) {
9904 if (!writer.propWithNullValue(fc)) {
9905 return false;
9906 }
9907 } else if (value->isKind(ParseNodeKind::RawUndefinedExpr)) {
9908 if (!writer.propWithUndefinedValue(fc)) {
9909 return false;
9910 }
9911 } else if (value->isKind(ParseNodeKind::StringExpr) ||
9912 value->isKind(ParseNodeKind::TemplateStringExpr)) {
9913 if (!writer.propWithAtomValue(fc, parserAtoms(),
9914 value->as<NameNode>().atom())) {
9915 return false;
9916 }
9917 } else {
9918 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"
, 9918); AnnotateMozCrashReason("MOZ_CRASH(" "Unexpected parse node"
")"); do { *((volatile int*)__null) = 9918; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
9919 }
9920 return true;
9921}
9922
9923static bool NeedsPrivateBrand(ParseNode* member) {
9924 return member->is<ClassMethod>() &&
9925 member->as<ClassMethod>().name().isKind(ParseNodeKind::PrivateName) &&
9926 !member->as<ClassMethod>().isStatic();
9927}
9928
9929#ifdef ENABLE_DECORATORS
9930static bool HasDecorators(ParseNode* member) {
9931 return member->is<ClassMethod>() && member->as<ClassMethod>().decorators();
9932}
9933#endif
9934
9935mozilla::Maybe<MemberInitializers> BytecodeEmitter::setupMemberInitializers(
9936 ListNode* classMembers, FieldPlacement placement) {
9937 bool isStatic = placement == FieldPlacement::Static;
9938
9939 size_t numFields = 0;
9940 size_t numPrivateInitializers = 0;
9941 bool hasPrivateBrand = false;
9942#ifdef ENABLE_DECORATORS
9943 bool hasDecorators = false;
9944#endif
9945 for (ParseNode* member : classMembers->contents()) {
9946 if (NeedsFieldInitializer(member, isStatic)) {
9947 numFields++;
9948 } else if (NeedsAccessorInitializer(member, isStatic)) {
9949 numPrivateInitializers++;
9950 hasPrivateBrand = true;
9951 } else if (NeedsPrivateBrand(member)) {
9952 hasPrivateBrand = true;
9953 }
9954#ifdef ENABLE_DECORATORS
9955 if (!hasDecorators && HasDecorators(member)) {
9956 hasDecorators = true;
9957 }
9958#endif
9959 }
9960
9961 // If there are more initializers than can be represented, return invalid.
9962 if (numFields + numPrivateInitializers >
9963 MemberInitializers::MaxInitializers) {
9964 return Nothing();
9965 }
9966 return Some(MemberInitializers(hasPrivateBrand,
9967#ifdef ENABLE_DECORATORS
9968 hasDecorators,
9969#endif
9970 numFields + numPrivateInitializers));
9971}
9972
9973// Purpose of .fieldKeys:
9974// Computed field names (`["x"] = 2;`) must be ran at class-evaluation time,
9975// not object construction time. The transformation to do so is roughly as
9976// follows:
9977//
9978// class C {
9979// [keyExpr] = valueExpr;
9980// }
9981// -->
9982// let .fieldKeys = [keyExpr];
9983// let .initializers = [
9984// () => {
9985// this[.fieldKeys[0]] = valueExpr;
9986// }
9987// ];
9988// class C {
9989// constructor() {
9990// .initializers[0]();
9991// }
9992// }
9993//
9994// BytecodeEmitter::emitCreateFieldKeys does `let .fieldKeys = [...];`
9995// BytecodeEmitter::emitPropertyList fills in the elements of the array.
9996// See GeneralParser::fieldInitializer for the `this[.fieldKeys[0]]` part.
9997bool BytecodeEmitter::emitCreateFieldKeys(ListNode* obj,
9998 FieldPlacement placement) {
9999 bool isStatic = placement == FieldPlacement::Static;
10000 auto isFieldWithComputedName = [isStatic](ParseNode* propdef) {
10001 return propdef->is<ClassField>() &&
10002 propdef->as<ClassField>().isStatic() == isStatic &&
10003 propdef->as<ClassField>().name().getKind() ==
10004 ParseNodeKind::ComputedName;
10005 };
10006
10007 size_t numFieldKeys = std::count_if(
10008 obj->contents().begin(), obj->contents().end(), isFieldWithComputedName);
10009 if (numFieldKeys == 0) {
10010 return true;
10011 }
10012
10013 auto fieldKeys =
10014 isStatic ? TaggedParserAtomIndex::WellKnown::dot_staticFieldKeys_()
10015 : TaggedParserAtomIndex::WellKnown::dot_fieldKeys_();
10016 NameOpEmitter noe(this, fieldKeys, NameOpEmitter::Kind::Initialize);
10017 if (!noe.prepareForRhs()) {
10018 return false;
10019 }
10020
10021 if (!emitUint32Operand(JSOp::NewArray, numFieldKeys)) {
10022 // [stack] ARRAY
10023 return false;
10024 }
10025
10026 if (!noe.emitAssignment()) {
10027 // [stack] ARRAY
10028 return false;
10029 }
10030
10031 if (!emit1(JSOp::Pop)) {
10032 // [stack]
10033 return false;
10034 }
10035
10036 return true;
10037}
10038
10039static bool HasInitializer(ParseNode* node, bool isStaticContext) {
10040 return (node->is<ClassField>() &&
10041 node->as<ClassField>().isStatic() == isStaticContext) ||
10042 (isStaticContext && node->is<StaticClassBlock>());
10043}
10044
10045static FunctionNode* GetInitializer(ParseNode* node, bool isStaticContext) {
10046 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"
, 10046); AnnotateMozCrashReason("MOZ_ASSERT" "(" "HasInitializer(node, isStaticContext)"
")"); do { *((volatile int*)__null) = 10046; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10047 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"
, 10047); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isStaticContext"
")"); do { *((volatile int*)__null) = 10047; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
10048 return node->is<ClassField>() ? node->as<ClassField>().initializer()
10049 : node->as<StaticClassBlock>().function();
10050}
10051
10052static bool IsPrivateInstanceAccessor(const ClassMethod* classMethod) {
10053 return !classMethod->isStatic() &&
10054 classMethod->name().isKind(ParseNodeKind::PrivateName) &&
10055 classMethod->accessorType() != AccessorType::None;
10056}
10057
10058bool BytecodeEmitter::emitCreateMemberInitializers(ClassEmitter& ce,
10059 ListNode* obj,
10060 FieldPlacement placement
10061#ifdef ENABLE_DECORATORS
10062 ,
10063 bool hasHeritage
10064#endif
10065) {
10066 // FieldPlacement::Instance, hasHeritage == false
10067 // [stack] HOME
10068 //
10069 // FieldPlacement::Instance, hasHeritage == true
10070 // [stack] HOME HERIT
10071 //
10072 // FieldPlacement::Static
10073 // [stack] CTOR HOME
10074#ifdef ENABLE_DECORATORS
10075 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"
, 10075); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!hasHeritage"
")"); do { *((volatile int*)__null) = 10075; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
10076#endif
10077 mozilla::Maybe<MemberInitializers> memberInitializers =
10078 setupMemberInitializers(obj, placement);
10079 if (!memberInitializers) {
10080 ReportAllocationOverflow(fc);
10081 return false;
10082 }
10083
10084 size_t numInitializers = memberInitializers->numMemberInitializers;
10085 if (numInitializers == 0) {
10086 return true;
10087 }
10088
10089 bool isStatic = placement == FieldPlacement::Static;
10090 if (!ce.prepareForMemberInitializers(numInitializers, isStatic)) {
10091 // [stack] HOME HERIT? ARR
10092 // or:
10093 // [stack] CTOR HOME ARR
10094 return false;
10095 }
10096
10097 // Private accessors could be used in the field initializers, so make sure
10098 // accessor initializers appear earlier in the .initializers array so they
10099 // run first. Static private methods are not initialized using initializers
10100 // (emitPropertyList emits bytecode to stamp them onto the constructor), so
10101 // skip this step if isStatic.
10102 if (!isStatic) {
10103 if (!emitPrivateMethodInitializers(ce, obj)) {
10104 return false;
10105 }
10106 }
10107
10108 for (ParseNode* propdef : obj->contents()) {
10109 if (!HasInitializer(propdef, isStatic)) {
10110 continue;
10111 }
10112
10113 FunctionNode* initializer = GetInitializer(propdef, isStatic);
10114
10115 if (!ce.prepareForMemberInitializer()) {
10116 return false;
10117 }
10118 if (!emitTree(initializer)) {
10119 // [stack] HOME HERIT? ARR LAMBDA
10120 // or:
10121 // [stack] CTOR HOME ARR LAMBDA
10122 return false;
10123 }
10124 if (initializer->funbox()->needsHomeObject()) {
10125 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"
, 10125); AnnotateMozCrashReason("MOZ_ASSERT" "(" "initializer->funbox()->allowSuperProperty()"
")"); do { *((volatile int*)__null) = 10125; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10126 if (!ce.emitMemberInitializerHomeObject(isStatic)) {
10127 // [stack] HOME HERIT? ARR LAMBDA
10128 // or:
10129 // [stack] CTOR HOME ARR LAMBDA
10130 return false;
10131 }
10132 }
10133 if (!ce.emitStoreMemberInitializer()) {
10134 // [stack] HOME HERIT? ARR
10135 // or:
10136 // [stack] CTOR HOME ARR
10137 return false;
10138 }
10139 }
10140
10141#ifdef ENABLE_DECORATORS
10142 // Index to use to append new initializers returned by decorators to the array
10143 if (!emitNumberOp(numInitializers)) {
10144 // [stack] HOME HERIT? ARR I
10145 // or:
10146 // [stack] CTOR HOME ARR I
10147 return false;
10148 }
10149
10150 for (ParseNode* propdef : obj->contents()) {
10151 if (!propdef->is<ClassField>()) {
10152 continue;
10153 }
10154 ClassField* field = &propdef->as<ClassField>();
10155 if (field->isStatic() != isStatic) {
10156 continue;
10157 }
10158 if (field->decorators() && !field->decorators()->empty()) {
10159 DecoratorEmitter de(this);
10160 if (!field->hasAccessor()) {
10161 if (!emitDupAt((hasHeritage || isStatic) ? 4 : 3)) {
10162 // [stack] ADDINIT HOME HERIT? ARR I ADDINIT
10163 // or:
10164 // [stack] ADDINIT CTOR HOME ARR I ADDINIT
10165 return false;
10166 }
10167 if (!de.emitApplyDecoratorsToFieldDefinition(
10168 &field->name(), field->decorators(), field->isStatic())) {
10169 // [stack] HOME HERIT? ARR I ADDINIT INITS
10170 // or:
10171 // [stack] CTOR HOME ARR I ADDINIT INITS
10172 return false;
10173 }
10174 if (!emit1(JSOp::Swap)) {
10175 // [stack] HOME HERIT? ARR I INITS ADDINIT
10176 // or:
10177 // [stack] CTOR HOME ARR I INITS ADDINIT
10178 return false;
10179 }
10180 if (!emitPopN(1)) {
10181 // [stack] ADDINIT HOME HERIT? ARR I INITS
10182 // or:
10183 // [stack] ADDINIT CTOR HOME ARR I INITS
10184 return false;
10185 }
10186 } else {
10187 ClassMethod* accessorGetterNode = field->accessorGetterNode();
10188 auto accessorGetterKeyAtom =
10189 accessorGetterNode->left()->as<NameNode>().atom();
10190 ClassMethod* accessorSetterNode = field->accessorSetterNode();
10191 auto accessorSetterKeyAtom =
10192 accessorSetterNode->left()->as<NameNode>().atom();
10193 if (!IsPrivateInstanceAccessor(accessorGetterNode)) {
10194 if (!emitTree(&accessorGetterNode->method())) {
10195 // [stack] ADDINIT HOME HERIT? ARR I GET
10196 // or:
10197 // [stack] ADDINIT CTOR HOME ARR I GET
10198 return false;
10199 }
10200 if (!emitTree(&accessorSetterNode->method())) {
10201 // [stack] ADDINIT HOME HERIT? ARR I GET
10202 // SET
10203 // or:
10204 // [stack] ADDINIT CTOR HOME ARR I GET SET
10205 return false;
10206 }
10207 } else {
10208 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"
, 10208); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsPrivateInstanceAccessor(accessorSetterNode)"
")"); do { *((volatile int*)__null) = 10208; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10209 auto getAccessor = [this](
10210 ClassMethod* classMethod,
10211 TaggedParserAtomIndex& updatedAtom) -> bool {
10212 // [stack]
10213
10214 // Synthesize a name for the lexical variable that will store the
10215 // private method body.
10216 TaggedParserAtomIndex name =
10217 classMethod->name().as<NameNode>().atom();
10218 AccessorType accessorType = classMethod->accessorType();
10219 StringBuffer storedMethodName(fc);
10220 if (!storedMethodName.append(parserAtoms(), name)) {
10221 return false;
10222 }
10223 if (!storedMethodName.append(accessorType == AccessorType::Getter
10224 ? ".getter"
10225 : ".setter")) {
10226 return false;
10227 }
10228 updatedAtom = storedMethodName.finishParserAtom(parserAtoms(), fc);
10229 if (!updatedAtom) {
10230 return false;
10231 }
10232
10233 return emitGetName(updatedAtom);
10234 // [stack] ACCESSOR
10235 };
10236
10237 if (!getAccessor(accessorGetterNode, accessorGetterKeyAtom)) {
10238 // [stack] ADDINIT HOME HERIT? ARR I GET
10239 // or:
10240 // [stack] ADDINIT CTOR HOME ARR I GET
10241 return false;
10242 };
10243
10244 if (!getAccessor(accessorSetterNode, accessorSetterKeyAtom)) {
10245 // [stack] ADDINIT HOME HERIT? ARR I GET SET
10246 // or:
10247 // [stack] ADDINIT CTOR HOME ARR I GET SET
10248 return false;
10249 };
10250 }
10251
10252 if (!emitDupAt((hasHeritage || isStatic) ? 6 : 5)) {
10253 // [stack] ADDINIT HOME HERIT? ARR I GET SET ADDINIT
10254 // or:
10255 // [stack] ADDINIT CTOR HOME ARR I GET SET ADDINIT
10256 return false;
10257 }
10258
10259 if (!emitUnpickN(2)) {
10260 // [stack] ADDINIT HOME HERIT? ARR I ADDINIT GET SET
10261 // or:
10262 // [stack] ADDINIT CTOR HOME ARR I ADDINIT GET SET
10263 return false;
10264 }
10265
10266 if (!de.emitApplyDecoratorsToAccessorDefinition(
10267 &field->name(), field->decorators(), field->isStatic())) {
10268 // [stack] ADDINIT HOME HERIT? ARR I ADDINIT GET SET INITS
10269 // or:
10270 // [stack] ADDINIT CTOR HOME ARR I ADDINIT GET SET INITS
10271 return false;
10272 }
10273
10274 if (!emitPickN(3)) {
10275 // [stack] HOME HERIT? ARR I GET SET INITS ADDINIT
10276 // or:
10277 // [stack] CTOR HOME ARR I GET SET INITS ADDINIT
10278 return false;
10279 }
10280
10281 if (!emitPopN(1)) {
10282 // [stack] ADDINIT HOME HERIT? ARR I GET SET INITS
10283 // or:
10284 // [stack] ADDINIT CTOR HOME ARR I GET SET INITS
10285 return false;
10286 }
10287
10288 if (!emitUnpickN(2)) {
10289 // [stack] ADDINIT HOME HERIT? ARR I INITS GET SET
10290 // or:
10291 // [stack] ADDINIT CTOR HOME ARR I INITS GET SET
10292 return false;
10293 }
10294
10295 if (!IsPrivateInstanceAccessor(accessorGetterNode)) {
10296 if (!isStatic) {
10297 if (!emitDupAt(hasHeritage ? 6 : 5)) {
10298 // [stack] ADDINIT HOME HERIT? ARR I INITS GET SET HOME
10299 return false;
10300 }
10301 } else {
10302 if (!emitDupAt(6)) {
10303 // [stack] ADDINIT CTOR HOME ARR I INITS GET SET CTOR
10304 return false;
10305 }
10306 if (!emitDupAt(6)) {
10307 // [stack] ADDINIT CTOR HOME ARR I INITS GET SET CTOR HOME
10308 return false;
10309 }
10310 }
10311
10312 PropertyEmitter::Kind kind = field->isStatic()
10313 ? PropertyEmitter::Kind::Static
10314 : PropertyEmitter::Kind::Prototype;
10315 if (!accessorGetterNode->name().isKind(ParseNodeKind::PrivateName)) {
10316 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"
, 10317); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!accessorSetterNode->name().isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 10317; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10317 !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"
, 10317); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!accessorSetterNode->name().isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 10317; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10318
10319 if (!ce.prepareForPropValue(propdef->pn_pos.begin, kind)) {
10320 // [stack] ADDINIT HOME HERIT? ARR I INITS GET SET HOME
10321 // or:
10322 // [stack] ADDINIT CTOR HOME ARR I INITS GET SET CTOR HOME CTOR
10323 return false;
10324 }
10325 if (!emitPickN(isStatic ? 3 : 1)) {
10326 // [stack] ADDINIT HOME HERIT? ARR I INITS GET HOME SET
10327 // or:
10328 // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME CTOR SET
10329 return false;
10330 }
10331 if (!ce.emitInit(AccessorType::Setter, accessorSetterKeyAtom)) {
10332 // [stack] ADDINIT HOME HERIT? ARR I INITS GET HOME
10333 // or:
10334 // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME
10335 return false;
10336 }
10337
10338 if (!ce.prepareForPropValue(propdef->pn_pos.begin, kind)) {
10339 // [stack] ADDINIT HOME HERIT? ARR I INITS GET HOME
10340 // or:
10341 // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME CTOR
10342 return false;
10343 }
10344 if (!emitPickN(isStatic ? 3 : 1)) {
10345 // [stack] ADDINIT HOME HERIT? ARR I INITS HOME GET
10346 // or:
10347 // [stack] ADDINIT CTOR HOME ARR I INITS CTOR HOME CTOR GET
10348 return false;
10349 }
10350 if (!ce.emitInit(AccessorType::Getter, accessorGetterKeyAtom)) {
10351 // [stack] ADDINIT HOME HERIT? ARR I INITS HOME
10352 // or:
10353 // [stack] ADDINIT CTOR HOME ARR I INITS CTOR HOME
10354 return false;
10355 }
10356 } else {
10357 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"
, 10357); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isStatic" ")"
); do { *((volatile int*)__null) = 10357; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10358 // The getter and setter share the same name.
10359 if (!emitNewPrivateName(accessorSetterKeyAtom,
10360 accessorSetterKeyAtom)) {
10361 return false;
10362 }
10363 if (!ce.prepareForPrivateStaticMethod(propdef->pn_pos.begin)) {
10364 // [stack] ADDINIT CTOR HOME ARR I INITS GET SET CTOR HOME CTOR
10365 return false;
10366 }
10367 if (!emitGetPrivateName(
10368 &accessorSetterNode->name().as<NameNode>())) {
10369 // [stack] ADDINIT CTOR HOME ARR I INITS GET SET CTOR HOME CTOR
10370 // KEY
10371 return false;
10372 }
10373 if (!emitPickN(4)) {
10374 // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME CTOR KEY
10375 // SET
10376 return false;
10377 }
10378 if (!ce.emitPrivateStaticMethod(AccessorType::Setter)) {
10379 // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME
10380 return false;
10381 }
10382
10383 if (!ce.prepareForPrivateStaticMethod(propdef->pn_pos.begin)) {
10384 // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME CTOR
10385 return false;
10386 }
10387 if (!emitGetPrivateName(
10388 &accessorGetterNode->name().as<NameNode>())) {
10389 // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME CTOR KEY
10390 return false;
10391 }
10392 if (!emitPickN(4)) {
10393 // [stack] ADDINIT CTOR HOME ARR I INITS CTOR HOME CTOR KEY GET
10394 return false;
10395 }
10396 if (!ce.emitPrivateStaticMethod(AccessorType::Getter)) {
10397 // [stack] ADDINIT CTOR HOME ARR I INITS CTOR HOME
10398 return false;
10399 }
10400 }
10401
10402 if (!isStatic) {
10403 if (!emitPopN(1)) {
10404 // [stack] ADDINIT HOME HERIT? ARR I INITS
10405 return false;
10406 }
10407 } else {
10408 if (!emitPopN(2)) {
10409 // [stack] ADDINIT CTOR HOME ARR I INITS
10410 return false;
10411 }
10412 }
10413 } else {
10414 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"
, 10414); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsPrivateInstanceAccessor(accessorSetterNode)"
")"); do { *((volatile int*)__null) = 10414; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10415
10416 if (!emitLexicalInitialization(accessorSetterKeyAtom)) {
10417 // [stack] ADDINIT HOME HERIT? ARR I INITS GET SET
10418 // or:
10419 // [stack] ADDINIT CTOR HOME ARR I INITS GET SET
10420 return false;
10421 }
10422
10423 if (!emitPopN(1)) {
10424 // [stack] ADDINIT HOME HERIT? ARR I INITS GET
10425 // or:
10426 // [stack] ADDINIT CTOR HOME ARR I INITS GET
10427 return false;
10428 }
10429
10430 if (!emitLexicalInitialization(accessorGetterKeyAtom)) {
10431 // [stack] ADDINIT HOME HERIT? ARR I INITS GET
10432 // or:
10433 // [stack] ADDINIT CTOR HOME ARR I INITS GET
10434 return false;
10435 }
10436
10437 if (!emitPopN(1)) {
10438 // [stack] ADDINIT HOME HERIT? ARR I INITS
10439 // or:
10440 // [stack] ADDINIT CTOR HOME ARR I INITS
10441 return false;
10442 }
10443 }
10444 }
10445 if (!emit1(JSOp::InitElemInc)) {
10446 // [stack] ADDINIT HOME HERIT? ARR I
10447 // or:
10448 // [stack] ADDINIT CTOR HOME ARR I
10449 return false;
10450 }
10451 }
10452 }
10453
10454 // Pop I
10455 if (!emitPopN(1)) {
10456 // [stack] ADDINIT HOME HERIT? ARR
10457 // or:
10458 // [stack] ADDINIT CTOR HOME ARR
10459 return false;
10460 }
10461#endif
10462
10463 if (!ce.emitMemberInitializersEnd()) {
10464 // [stack] ADDINIT HOME HERIT?
10465 // or:
10466 // [stack] ADDINIT CTOR HOME
10467 return false;
10468 }
10469
10470 return true;
10471}
10472
10473bool BytecodeEmitter::emitPrivateMethodInitializers(ClassEmitter& ce,
10474 ListNode* obj) {
10475 for (ParseNode* propdef : obj->contents()) {
10476 if (!propdef->is<ClassMethod>()) {
10477 continue;
10478 }
10479 auto* classMethod = &propdef->as<ClassMethod>();
10480
10481 // Skip over anything which isn't a private instance accessor.
10482 if (!IsPrivateInstanceAccessor(classMethod)) {
10483 continue;
10484 }
10485
10486 if (!ce.prepareForMemberInitializer()) {
10487 // [stack] HOMEOBJ HERITAGE? ARRAY
10488 // or:
10489 // [stack] CTOR HOMEOBJ ARRAY
10490 return false;
10491 }
10492
10493 // Synthesize a name for the lexical variable that will store the
10494 // private method body.
10495 TaggedParserAtomIndex name = classMethod->name().as<NameNode>().atom();
10496 AccessorType accessorType = classMethod->accessorType();
10497 StringBuffer storedMethodName(fc);
10498 if (!storedMethodName.append(parserAtoms(), name)) {
10499 return false;
10500 }
10501 if (!storedMethodName.append(
10502 accessorType == AccessorType::Getter ? ".getter" : ".setter")) {
10503 return false;
10504 }
10505 auto storedMethodAtom =
10506 storedMethodName.finishParserAtom(parserAtoms(), fc);
10507
10508 // Emit the private method body and store it as a lexical var.
10509 if (!emitFunction(&classMethod->method())) {
10510 // [stack] HOMEOBJ HERITAGE? ARRAY METHOD
10511 // or:
10512 // [stack] CTOR HOMEOBJ ARRAY METHOD
10513 return false;
10514 }
10515 // The private method body needs to access the home object,
10516 // and the CE knows where that is on the stack.
10517 if (classMethod->method().funbox()->needsHomeObject()) {
10518 if (!ce.emitMemberInitializerHomeObject(false)) {
10519 // [stack] HOMEOBJ HERITAGE? ARRAY METHOD
10520 // or:
10521 // [stack] CTOR HOMEOBJ ARRAY METHOD
10522 return false;
10523 }
10524 }
10525 if (!emitLexicalInitialization(storedMethodAtom)) {
10526 // [stack] HOMEOBJ HERITAGE? ARRAY METHOD
10527 // or:
10528 // [stack] CTOR HOMEOBJ ARRAY METHOD
10529 return false;
10530 }
10531 if (!emit1(JSOp::Pop)) {
10532 // [stack] HOMEOBJ HERITAGE? ARRAY
10533 // or:
10534 // [stack] CTOR HOMEOBJ ARRAY
10535 return false;
10536 }
10537
10538 if (!emitPrivateMethodInitializer(classMethod, storedMethodAtom)) {
10539 // [stack] HOMEOBJ HERITAGE? ARRAY
10540 // or:
10541 // [stack] CTOR HOMEOBJ ARRAY
10542 return false;
10543 }
10544
10545 // Store the emitted initializer function into the .initializers array.
10546 if (!ce.emitStoreMemberInitializer()) {
10547 // [stack] HOMEOBJ HERITAGE? ARRAY
10548 // or:
10549 // [stack] CTOR HOMEOBJ ARRAY
10550 return false;
10551 }
10552 }
10553
10554 return true;
10555}
10556
10557bool BytecodeEmitter::emitPrivateMethodInitializer(
10558 ClassMethod* classMethod, TaggedParserAtomIndex storedMethodAtom) {
10559 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"
, 10559); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsPrivateInstanceAccessor(classMethod)"
")"); do { *((volatile int*)__null) = 10559; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10560
10561 auto* name = &classMethod->name().as<NameNode>();
10562
10563 // Emit the synthesized initializer function.
10564 FunctionNode* funNode = classMethod->initializerIfPrivate();
10565 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"
, 10565); AnnotateMozCrashReason("MOZ_ASSERT" "(" "funNode" ")"
); do { *((volatile int*)__null) = 10565; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10566 FunctionBox* funbox = funNode->funbox();
10567 FunctionEmitter fe(this, funbox, funNode->syntaxKind(),
10568 FunctionEmitter::IsHoisted::No);
10569 if (!fe.prepareForNonLazy()) {
10570 // [stack]
10571 return false;
10572 }
10573
10574 BytecodeEmitter bce2(this, funbox);
10575 if (!bce2.init(funNode->pn_pos)) {
10576 return false;
10577 }
10578 ParamsBodyNode* paramsBody = funNode->body();
10579 FunctionScriptEmitter fse(&bce2, funbox, Nothing(), Nothing());
10580 if (!fse.prepareForParameters()) {
10581 // [stack]
10582 return false;
10583 }
10584 if (!bce2.emitFunctionFormalParameters(paramsBody)) {
10585 // [stack]
10586 return false;
10587 }
10588 if (!fse.prepareForBody()) {
10589 // [stack]
10590 return false;
10591 }
10592
10593 if (!bce2.emit1(JSOp::FunctionThis)) {
10594 // [stack] THIS
10595 return false;
10596 }
10597 if (!bce2.emitGetPrivateName(name)) {
10598 // [stack] THIS NAME
10599 return false;
10600 }
10601 if (!bce2.emitGetName(storedMethodAtom)) {
10602 // [stack] THIS NAME METHOD
10603 return false;
10604 }
10605
10606 switch (name->privateNameKind()) {
10607 case PrivateNameKind::Setter:
10608 if (!bce2.emit1(JSOp::InitHiddenElemSetter)) {
10609 // [stack] THIS
10610 return false;
10611 }
10612 if (!bce2.emitGetPrivateName(name)) {
10613 // [stack] THIS NAME
10614 return false;
10615 }
10616 if (!bce2.emitAtomOp(
10617 JSOp::GetIntrinsic,
10618 TaggedParserAtomIndex::WellKnown::NoPrivateGetter())) {
10619 // [stack] THIS NAME FUN
10620 return false;
10621 }
10622 if (!bce2.emit1(JSOp::InitHiddenElemGetter)) {
10623 // [stack] THIS
10624 return false;
10625 }
10626 break;
10627 case PrivateNameKind::Getter:
10628 case PrivateNameKind::GetterSetter:
10629 if (classMethod->accessorType() == AccessorType::Getter) {
10630 if (!bce2.emit1(JSOp::InitHiddenElemGetter)) {
10631 // [stack] THIS
10632 return false;
10633 }
10634 } else {
10635 if (!bce2.emit1(JSOp::InitHiddenElemSetter)) {
10636 // [stack] THIS
10637 return false;
10638 }
10639 }
10640 break;
10641 default:
10642 MOZ_CRASH("Invalid op")do { do { } while (false); MOZ_ReportCrash("" "Invalid op", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp"
, 10642); AnnotateMozCrashReason("MOZ_CRASH(" "Invalid op" ")"
); do { *((volatile int*)__null) = 10642; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
10643 }
10644
10645 // Pop remaining THIS.
10646 if (!bce2.emit1(JSOp::Pop)) {
10647 // [stack]
10648 return false;
10649 }
10650
10651 if (!fse.emitEndBody()) {
10652 // [stack]
10653 return false;
10654 }
10655 if (!fse.intoStencil()) {
10656 return false;
10657 }
10658
10659 if (!fe.emitNonLazyEnd()) {
10660 // [stack] HOMEOBJ HERITAGE? ARRAY FUN
10661 // or:
10662 // [stack] CTOR HOMEOBJ ARRAY FUN
10663 return false;
10664 }
10665
10666 return true;
10667}
10668
10669const MemberInitializers& BytecodeEmitter::findMemberInitializersForCall() {
10670 for (BytecodeEmitter* current = this; current; current = current->parent) {
10671 if (current->sc->isFunctionBox()) {
10672 FunctionBox* funbox = current->sc->asFunctionBox();
10673
10674 if (funbox->isArrow()) {
10675 continue;
10676 }
10677
10678 // If we found a non-arrow / non-constructor we were never allowed to
10679 // expect fields in the first place.
10680 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"
, 10680); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "funbox->isClassConstructor()"
")"); do { *((volatile int*)__null) = 10680; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10681
10682 return funbox->useMemberInitializers() ? funbox->memberInitializers()
10683 : MemberInitializers::Empty();
10684 }
10685 }
10686
10687 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"
, 10687); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "compilationState.scopeContext.memberInitializers"
")"); do { *((volatile int*)__null) = 10687; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10688 return *compilationState.scopeContext.memberInitializers;
10689}
10690
10691bool BytecodeEmitter::emitInitializeInstanceMembers(
10692 bool isDerivedClassConstructor) {
10693 const MemberInitializers& memberInitializers =
10694 findMemberInitializersForCall();
10695 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"
, 10695); AnnotateMozCrashReason("MOZ_ASSERT" "(" "memberInitializers.valid"
")"); do { *((volatile int*)__null) = 10695; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10696
10697 if (memberInitializers.hasPrivateBrand) {
10698 // This is guaranteed to run after super(), so we don't need TDZ checks.
10699 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_this_())) {
10700 // [stack] THIS
10701 return false;
10702 }
10703 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_privateBrand_())) {
10704 // [stack] THIS BRAND
10705 return false;
10706 }
10707 if (isDerivedClassConstructor) {
10708 if (!emitCheckPrivateField(ThrowCondition::ThrowHas,
10709 ThrowMsgKind::PrivateBrandDoubleInit)) {
10710 // [stack] THIS BRAND BOOL
10711 return false;
10712 }
10713 if (!emit1(JSOp::Pop)) {
10714 // [stack] THIS BRAND
10715 return false;
10716 }
10717 }
10718 if (!emit1(JSOp::Null)) {
10719 // [stack] THIS BRAND NULL
10720 return false;
10721 }
10722 if (!emit1(JSOp::InitHiddenElem)) {
10723 // [stack] THIS
10724 return false;
10725 }
10726 if (!emit1(JSOp::Pop)) {
10727 // [stack]
10728 return false;
10729 }
10730 }
10731
10732 size_t numInitializers = memberInitializers.numMemberInitializers;
10733 if (numInitializers > 0) {
10734 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_initializers_())) {
10735 // [stack] ARRAY
10736 return false;
10737 }
10738
10739 for (size_t index = 0; index < numInitializers; index++) {
10740 if (index < numInitializers - 1) {
10741 // We Dup to keep the array around (it is consumed in the bytecode
10742 // below) for next iterations of this loop, except for the last
10743 // iteration, which avoids an extra Pop at the end of the loop.
10744 if (!emit1(JSOp::Dup)) {
10745 // [stack] ARRAY ARRAY
10746 return false;
10747 }
10748 }
10749
10750 if (!emitNumberOp(index)) {
10751 // [stack] ARRAY? ARRAY INDEX
10752 return false;
10753 }
10754
10755 if (!emit1(JSOp::GetElem)) {
10756 // [stack] ARRAY? FUNC
10757 return false;
10758 }
10759
10760 // This is guaranteed to run after super(), so we don't need TDZ checks.
10761 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_this_())) {
10762 // [stack] ARRAY? FUNC THIS
10763 return false;
10764 }
10765
10766 // Callee is always internal function.
10767 if (!emitCall(JSOp::CallIgnoresRv, 0)) {
10768 // [stack] ARRAY? RVAL
10769 return false;
10770 }
10771
10772 if (!emit1(JSOp::Pop)) {
10773 // [stack] ARRAY?
10774 return false;
10775 }
10776 }
10777#ifdef ENABLE_DECORATORS
10778 if (memberInitializers.hasDecorators) {
10779 // Decorators Proposal
10780 // https://arai-a.github.io/ecma262-compare/?pr=2417&id=sec-initializeinstanceelements
10781 // 4. For each element e of elements, do
10782 // 4.a. If elementRecord.[[Kind]] is field or accessor, then
10783 // 4.a.i. Perform ? InitializeFieldOrAccessor(O, elementRecord).
10784 //
10785
10786 // TODO: (See Bug 1817993) At the moment, we're applying the
10787 // initialization logic in two steps. The pre-decorator initialization
10788 // code runs, stores the initial value, and then we retrieve it here and
10789 // apply the initializers added by decorators. We should unify these two
10790 // steps.
10791 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_initializers_())) {
10792 // [stack] ARRAY
10793 return false;
10794 }
10795
10796 if (!emit1(JSOp::Dup)) {
10797 // [stack] ARRAY ARRAY
10798 return false;
10799 }
10800
10801 if (!emitAtomOp(JSOp::GetProp,
10802 TaggedParserAtomIndex::WellKnown::length())) {
10803 // [stack] ARRAY LENGTH
10804 return false;
10805 }
10806
10807 if (!emitNumberOp(static_cast<double>(numInitializers))) {
10808 // [stack] ARRAY LENGTH INDEX
10809 return false;
10810 }
10811
10812 InternalWhileEmitter wh(this);
10813 // At this point, we have no context to determine offsets in the
10814 // code for this while statement. Ideally, it would correspond to
10815 // the field we're initializing.
10816 if (!wh.emitCond()) {
10817 // [stack] ARRAY LENGTH INDEX
10818 return false;
10819 }
10820
10821 if (!emit1(JSOp::Dup)) {
10822 // [stack] ARRAY LENGTH INDEX INDEX
10823 return false;
10824 }
10825
10826 if (!emitDupAt(2)) {
10827 // [stack] ARRAY LENGTH INDEX INDEX LENGTH
10828 return false;
10829 }
10830
10831 if (!emit1(JSOp::Lt)) {
10832 // [stack] ARRAY LENGTH INDEX BOOL
10833 return false;
10834 }
10835
10836 if (!wh.emitBody()) {
10837 // [stack] ARRAY LENGTH INDEX
10838 return false;
10839 }
10840
10841 if (!emitDupAt(2)) {
10842 // [stack] ARRAY LENGTH INDEX ARRAY
10843 return false;
10844 }
10845
10846 if (!emitDupAt(1)) {
10847 // [stack] ARRAY LENGTH INDEX ARRAY INDEX
10848 return false;
10849 }
10850
10851 // Retrieve initializers for this field
10852 if (!emit1(JSOp::GetElem)) {
10853 // [stack] ARRAY LENGTH INDEX INITIALIZERS
10854 return false;
10855 }
10856
10857 // This is guaranteed to run after super(), so we don't need TDZ checks.
10858 if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_this_())) {
10859 // [stack] ARRAY LENGTH INDEX INITIALIZERS THIS
10860 return false;
10861 }
10862
10863 if (!emit1(JSOp::Swap)) {
10864 // [stack] ARRAY LENGTH INDEX THIS INITIALIZERS
10865 return false;
10866 }
10867
10868 DecoratorEmitter de(this);
10869 if (!de.emitInitializeFieldOrAccessor()) {
10870 // [stack] ARRAY LENGTH INDEX
10871 return false;
10872 }
10873
10874 if (!emit1(JSOp::Inc)) {
10875 // [stack] ARRAY LENGTH INDEX
10876 return false;
10877 }
10878
10879 if (!wh.emitEnd()) {
10880 // [stack] ARRAY LENGTH INDEX
10881 return false;
10882 }
10883
10884 if (!emitPopN(3)) {
10885 // [stack]
10886 return false;
10887 }
10888 // 5. Return unused.
10889
10890 if (!de.emitCallExtraInitializers(TaggedParserAtomIndex::WellKnown::
10891 dot_instanceExtraInitializers_())) {
10892 return false;
10893 }
10894 }
10895#endif
10896 }
10897 return true;
10898}
10899
10900bool BytecodeEmitter::emitInitializeStaticFields(ListNode* classMembers) {
10901 auto isStaticField = [](ParseNode* propdef) {
10902 return HasInitializer(propdef, true);
10903 };
10904 size_t numFields =
10905 std::count_if(classMembers->contents().begin(),
10906 classMembers->contents().end(), isStaticField);
10907
10908 if (numFields == 0) {
10909 return true;
10910 }
10911
10912 if (!emitGetName(
10913 TaggedParserAtomIndex::WellKnown::dot_staticInitializers_())) {
10914 // [stack] CTOR ARRAY
10915 return false;
10916 }
10917
10918 for (size_t fieldIndex = 0; fieldIndex < numFields; fieldIndex++) {
10919 bool hasNext = fieldIndex < numFields - 1;
10920 if (hasNext) {
10921 // We Dup to keep the array around (it is consumed in the bytecode below)
10922 // for next iterations of this loop, except for the last iteration, which
10923 // avoids an extra Pop at the end of the loop.
10924 if (!emit1(JSOp::Dup)) {
10925 // [stack] CTOR ARRAY ARRAY
10926 return false;
10927 }
10928 }
10929
10930 if (!emitNumberOp(fieldIndex)) {
10931 // [stack] CTOR ARRAY? ARRAY INDEX
10932 return false;
10933 }
10934
10935 if (!emit1(JSOp::GetElem)) {
10936 // [stack] CTOR ARRAY? FUNC
10937 return false;
10938 }
10939
10940 if (!emitDupAt(1 + hasNext)) {
10941 // [stack] CTOR ARRAY? FUNC CTOR
10942 return false;
10943 }
10944
10945 // Callee is always internal function.
10946 if (!emitCall(JSOp::CallIgnoresRv, 0)) {
10947 // [stack] CTOR ARRAY? RVAL
10948 return false;
10949 }
10950
10951 if (!emit1(JSOp::Pop)) {
10952 // [stack] CTOR ARRAY?
10953 return false;
10954 }
10955 }
10956
10957#ifdef ENABLE_DECORATORS
10958 // Decorators Proposal
10959 // https://arai-a.github.io/ecma262-compare/?pr=2417&id=sec-initializeinstanceelements
10960 // 4. For each element e of elements, do
10961 // 4.a. If elementRecord.[[Kind]] is field or accessor, then
10962 // 4.a.i. Perform ? InitializeFieldOrAccessor(O, elementRecord).
10963 //
10964
10965 // TODO: (See Bug 1817993) At the moment, we're applying the initialization
10966 // logic in two steps. The pre-decorator initialization code runs, stores
10967 // the initial value, and then we retrieve it here and apply the
10968 // initializers added by decorators. We should unify these two steps.
10969 if (!emitGetName(
10970 TaggedParserAtomIndex::WellKnown::dot_staticInitializers_())) {
10971 // [stack] CTOR ARRAY
10972 return false;
10973 }
10974
10975 if (!emit1(JSOp::Dup)) {
10976 // [stack] CTOR ARRAY ARRAY
10977 return false;
10978 }
10979
10980 if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::length())) {
10981 // [stack] CTOR ARRAY LENGTH
10982 return false;
10983 }
10984
10985 if (!emitNumberOp(static_cast<double>(numFields))) {
10986 // [stack] CTOR ARRAY LENGTH INDEX
10987 return false;
10988 }
10989
10990 InternalWhileEmitter wh(this);
10991 // At this point, we have no context to determine offsets in the
10992 // code for this while statement. Ideally, it would correspond to
10993 // the field we're initializing.
10994 if (!wh.emitCond()) {
10995 // [stack] CTOR ARRAY LENGTH INDEX
10996 return false;
10997 }
10998
10999 if (!emit1(JSOp::Dup)) {
11000 // [stack] CTOR ARRAY LENGTH INDEX INDEX
11001 return false;
11002 }
11003
11004 if (!emitDupAt(2)) {
11005 // [stack] CTOR ARRAY LENGTH INDEX INDEX LENGTH
11006 return false;
11007 }
11008
11009 if (!emit1(JSOp::Lt)) {
11010 // [stack] CTOR ARRAY LENGTH INDEX BOOL
11011 return false;
11012 }
11013
11014 if (!wh.emitBody()) {
11015 // [stack] CTOR ARRAY LENGTH INDEX
11016 return false;
11017 }
11018
11019 if (!emitDupAt(2)) {
11020 // [stack] CTOR ARRAY LENGTH INDEX ARRAY
11021 return false;
11022 }
11023
11024 if (!emitDupAt(1)) {
11025 // [stack] CTOR ARRAY LENGTH INDEX ARRAY INDEX
11026 return false;
11027 }
11028
11029 // Retrieve initializers for this field
11030 if (!emit1(JSOp::GetElem)) {
11031 // [stack] CTOR ARRAY LENGTH INDEX INITIALIZERS
11032 return false;
11033 }
11034
11035 if (!emitDupAt(4)) {
11036 // [stack] CTOR ARRAY LENGTH INDEX INITIALIZERS CTOR
11037 return false;
11038 }
11039
11040 if (!emit1(JSOp::Swap)) {
11041 // [stack] CTOR ARRAY LENGTH INDEX CTOR INITIALIZERS
11042 return false;
11043 }
11044
11045 DecoratorEmitter de(this);
11046 if (!de.emitInitializeFieldOrAccessor()) {
11047 // [stack] CTOR ARRAY LENGTH INDEX
11048 return false;
11049 }
11050
11051 if (!emit1(JSOp::Inc)) {
11052 // [stack] CTOR ARRAY LENGTH INDEX
11053 return false;
11054 }
11055
11056 if (!wh.emitEnd()) {
11057 // [stack] CTOR ARRAY LENGTH INDEX
11058 return false;
11059 }
11060
11061 if (!emitPopN(3)) {
11062 // [stack] CTOR
11063 return false;
11064 }
11065 // 5. Return unused.
11066#endif
11067
11068 // Overwrite |.staticInitializers| and |.staticFieldKeys| with undefined to
11069 // avoid keeping the arrays alive indefinitely.
11070 auto clearStaticFieldSlot = [&](TaggedParserAtomIndex name) {
11071 NameOpEmitter noe(this, name, NameOpEmitter::Kind::SimpleAssignment);
11072 if (!noe.prepareForRhs()) {
11073 // [stack] ENV? VAL?
11074 return false;
11075 }
11076
11077 if (!emit1(JSOp::Undefined)) {
11078 // [stack] ENV? VAL? UNDEFINED
11079 return false;
11080 }
11081
11082 if (!noe.emitAssignment()) {
11083 // [stack] VAL
11084 return false;
11085 }
11086
11087 if (!emit1(JSOp::Pop)) {
11088 // [stack]
11089 return false;
11090 }
11091
11092 return true;
11093 };
11094
11095 if (!clearStaticFieldSlot(
11096 TaggedParserAtomIndex::WellKnown::dot_staticInitializers_())) {
11097 return false;
11098 }
11099
11100 auto isStaticFieldWithComputedName = [](ParseNode* propdef) {
11101 return propdef->is<ClassField>() && propdef->as<ClassField>().isStatic() &&
11102 propdef->as<ClassField>().name().getKind() ==
11103 ParseNodeKind::ComputedName;
11104 };
11105
11106 if (std::any_of(classMembers->contents().begin(),
11107 classMembers->contents().end(),
11108 isStaticFieldWithComputedName)) {
11109 if (!clearStaticFieldSlot(
11110 TaggedParserAtomIndex::WellKnown::dot_staticFieldKeys_())) {
11111 return false;
11112 }
11113 }
11114
11115 return true;
11116}
11117
11118// Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See
11119// the comment on emitSwitch.
11120MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitObject(ListNode* objNode) {
11121 // Note: this method uses the ObjLiteralWriter and emits ObjLiteralStencil
11122 // objects into the GCThingList, which will evaluate them into real GC objects
11123 // or shapes during JSScript::fullyInitFromEmitter. Eventually we want
11124 // JSOp::Object to be a real opcode, but for now, performance constraints
11125 // limit us to evaluating object literals at the end of parse, when we're
11126 // allowed to allocate GC things.
11127 //
11128 // There are four cases here, in descending order of preference:
11129 //
11130 // 1. The list of property names is "normal" and constant (no computed
11131 // values, no integer indices), the values are all simple constants
11132 // (numbers, booleans, strings), *and* this occurs in a run-once
11133 // (singleton) context. In this case, we can emit ObjLiteral
11134 // instructions to build an object with values, and the object will be
11135 // attached to a JSOp::Object opcode, whose semantics are for the backend
11136 // to simply steal the object from the script.
11137 //
11138 // 2. The list of property names is "normal" and constant as above, *and* this
11139 // occurs in a run-once (singleton) context, but some values are complex
11140 // (computed expressions, sub-objects, functions, etc.). In this case, we
11141 // can still use JSOp::Object (because singleton context), but the object
11142 // has |undefined| property values and InitProp ops are emitted to set the
11143 // values.
11144 //
11145 // 3. The list of property names is "normal" and constant as above, but this
11146 // occurs in a non-run-once (non-singleton) context. In this case, we can
11147 // use the ObjLiteral functionality to describe an *empty* object (all
11148 // values left undefined) with the right fields, which will become a
11149 // JSOp::NewObject opcode using the object's shape to speed up the creation
11150 // of the object each time it executes. The emitted bytecode still needs
11151 // InitProp ops to set the values in this case.
11152 //
11153 // 4. Any other case. As a fallback, we use NewInit to create a new, empty
11154 // object (i.e., `{}`) and then emit bytecode to initialize its properties
11155 // one-by-one.
11156
11157 bool useObjLiteral = false;
11158 bool useObjLiteralValues = false;
11159 isPropertyListObjLiteralCompatible(objNode, &useObjLiteralValues,
11160 &useObjLiteral);
11161
11162 // [stack]
11163 //
11164 ObjectEmitter oe(this);
11165 if (useObjLiteral) {
11166 bool singleton = checkSingletonContext() &&
11167 !objNode->hasNonConstInitializer() && objNode->head();
11168 JSOp op;
11169 if (singleton) {
11170 // Case 1 or 2.
11171 op = JSOp::Object;
11172 } else {
11173 // Case 3.
11174 useObjLiteralValues = false;
11175 op = JSOp::NewObject;
11176 }
11177
11178 // Use an ObjLiteral op. This will record ObjLiteral insns in the
11179 // objLiteralWriter's buffer and add a fixup to the list of ObjLiteral
11180 // fixups so that at GC-publish time at the end of parse, the full object
11181 // (case 1 or 2) or shape (case 3) can be allocated and the bytecode can be
11182 // patched to refer to it.
11183 if (!emitPropertyListObjLiteral(objNode, op, useObjLiteralValues)) {
11184 // [stack] OBJ
11185 return false;
11186 }
11187 // Put the ObjectEmitter in the right state. This tells it that there will
11188 // already be an object on the stack as a result of the (eventual)
11189 // NewObject or Object op, and prepares it to emit values if needed.
11190 if (!oe.emitObjectWithTemplateOnStack()) {
11191 // [stack] OBJ
11192 return false;
11193 }
11194 if (!useObjLiteralValues) {
11195 // Case 2 or 3 above: we still need to emit bytecode to fill in the
11196 // object's property values.
11197 if (!emitPropertyList(objNode, oe, ObjectLiteral)) {
11198 // [stack] OBJ
11199 return false;
11200 }
11201 }
11202 } else {
11203 // Case 4 above: no ObjLiteral use, just bytecode to build the object from
11204 // scratch.
11205 if (!oe.emitObject(objNode->count())) {
11206 // [stack] OBJ
11207 return false;
11208 }
11209 if (!emitPropertyList(objNode, oe, ObjectLiteral)) {
11210 // [stack] OBJ
11211 return false;
11212 }
11213 }
11214
11215 if (!oe.emitEnd()) {
11216 // [stack] OBJ
11217 return false;
11218 }
11219
11220 return true;
11221}
11222
11223bool BytecodeEmitter::emitArrayLiteral(ListNode* array) {
11224 // Emit JSOp::Object if the array consists entirely of primitive values and we
11225 // are in a singleton context.
11226 if (checkSingletonContext() && !array->hasNonConstInitializer() &&
11227 !array->empty() && isArrayObjLiteralCompatible(array)) {
11228 return emitObjLiteralArray(array);
11229 }
11230
11231 return emitArray(array);
11232}
11233
11234bool BytecodeEmitter::emitArray(ListNode* array) {
11235 /*
11236 * Emit code for [a, b, c] that is equivalent to constructing a new
11237 * array and in source order evaluating each element value and adding
11238 * it to the array, without invoking latent setters. We use the
11239 * JSOp::NewInit and JSOp::InitElemArray bytecodes to ignore setters and
11240 * to avoid dup'ing and popping the array as each element is added, as
11241 * JSOp::SetElem/JSOp::SetProp would do.
11242 */
11243
11244 uint32_t nspread = 0;
11245 for (ParseNode* elem : array->contents()) {
11246 if (elem->isKind(ParseNodeKind::Spread)) {
11247 nspread++;
11248 }
11249 }
11250
11251 // Array literal's length is limited to NELEMENTS_LIMIT in parser.
11252 static_assert(NativeObject::MAX_DENSE_ELEMENTS_COUNT <= INT32_MAX(2147483647),
11253 "array literals' maximum length must not exceed limits "
11254 "required by BaselineCompiler::emit_NewArray, "
11255 "BaselineCompiler::emit_InitElemArray, "
11256 "and DoSetElemFallback's handling of JSOp::InitElemArray");
11257
11258 uint32_t count = array->count();
11259 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"
, 11259); AnnotateMozCrashReason("MOZ_ASSERT" "(" "count >= nspread"
")"); do { *((volatile int*)__null) = 11259; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11260 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"
, 11262); 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) = 11262; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
11261 "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"
, 11262); 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) = 11262; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
11262 "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"
, 11262); 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) = 11262; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
11263
11264 // For arrays with spread, this is a very pessimistic allocation, the
11265 // minimum possible final size.
11266 if (!emitUint32Operand(JSOp::NewArray, count - nspread)) {
11267 // [stack] ARRAY
11268 return false;
11269 }
11270
11271 uint32_t index = 0;
11272 bool afterSpread = false;
11273 for (ParseNode* elem : array->contents()) {
11274 if (elem->isKind(ParseNodeKind::Spread)) {
11275 if (!afterSpread) {
11276 afterSpread = true;
11277 if (!emitNumberOp(index)) {
11278 // [stack] ARRAY INDEX
11279 return false;
11280 }
11281 }
11282
11283 ParseNode* expr = elem->as<UnaryNode>().kid();
11284 SelfHostedIter selfHostedIter = getSelfHostedIterFor(expr);
11285
11286 if (!updateSourceCoordNotes(elem->pn_pos.begin)) {
11287 return false;
11288 }
11289 if (!emitIterable(expr, selfHostedIter)) {
11290 // [stack] ARRAY INDEX ITERABLE
11291 return false;
11292 }
11293 if (!emitIterator(selfHostedIter)) {
11294 // [stack] ARRAY INDEX NEXT ITER
11295 return false;
11296 }
11297 if (!emit2(JSOp::Pick, 3)) {
11298 // [stack] INDEX NEXT ITER ARRAY
11299 return false;
11300 }
11301 if (!emit2(JSOp::Pick, 3)) {
11302 // [stack] NEXT ITER ARRAY INDEX
11303 return false;
11304 }
11305 if (!emitSpread(selfHostedIter)) {
11306 // [stack] ARRAY INDEX
11307 return false;
11308 }
11309 } else {
11310 if (!updateSourceCoordNotesIfNonLiteral(elem)) {
11311 return false;
11312 }
11313 if (elem->isKind(ParseNodeKind::Elision)) {
11314 if (!emit1(JSOp::Hole)) {
11315 return false;
11316 }
11317 } else {
11318 if (!emitTree(elem, ValueUsage::WantValue)) {
11319 // [stack] ARRAY INDEX? VALUE
11320 return false;
11321 }
11322 }
11323
11324 if (afterSpread) {
11325 if (!emit1(JSOp::InitElemInc)) {
11326 // [stack] ARRAY (INDEX+1)
11327 return false;
11328 }
11329 } else {
11330 if (!emitUint32Operand(JSOp::InitElemArray, index)) {
11331 // [stack] ARRAY
11332 return false;
11333 }
11334 }
11335 }
11336
11337 index++;
11338 }
11339 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"
, 11339); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index == count"
")"); do { *((volatile int*)__null) = 11339; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11340 if (afterSpread) {
11341 if (!emit1(JSOp::Pop)) {
11342 // [stack] ARRAY
11343 return false;
11344 }
11345 }
11346 return true;
11347}
11348
11349bool BytecodeEmitter::emitSpreadIntoArray(UnaryNode* elem) {
11350 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"
, 11350); AnnotateMozCrashReason("MOZ_ASSERT" "(" "elem->isKind(ParseNodeKind::Spread)"
")"); do { *((volatile int*)__null) = 11350; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11351
11352 if (!updateSourceCoordNotes(elem->pn_pos.begin)) {
11353 // [stack] VALUE
11354 return false;
11355 }
11356
11357 SelfHostedIter selfHostedIter = getSelfHostedIterFor(elem->kid());
11358 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"
, 11359); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter == SelfHostedIter::Deny || selfHostedIter == SelfHostedIter::AllowContent"
")"); do { *((volatile int*)__null) = 11359; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11359 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"
, 11359); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter == SelfHostedIter::Deny || selfHostedIter == SelfHostedIter::AllowContent"
")"); do { *((volatile int*)__null) = 11359; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11360
11361 if (!emitIterator(selfHostedIter)) {
11362 // [stack] NEXT ITER
11363 return false;
11364 }
11365
11366 if (!emitUint32Operand(JSOp::NewArray, 0)) {
11367 // [stack] NEXT ITER ARRAY
11368 return false;
11369 }
11370
11371 if (!emitNumberOp(0)) {
11372 // [stack] NEXT ITER ARRAY INDEX
11373 return false;
11374 }
11375
11376 if (!emitSpread(selfHostedIter)) {
11377 // [stack] ARRAY INDEX
11378 return false;
11379 }
11380
11381 if (!emit1(JSOp::Pop)) {
11382 // [stack] ARRAY
11383 return false;
11384 }
11385 return true;
11386}
11387
11388#ifdef ENABLE_RECORD_TUPLE
11389bool BytecodeEmitter::emitRecordLiteral(ListNode* record) {
11390 if (!emitUint32Operand(JSOp::InitRecord, record->count())) {
11391 // [stack] RECORD
11392 return false;
11393 }
11394
11395 for (ParseNode* propdef : record->contents()) {
11396 if (propdef->isKind(ParseNodeKind::Spread)) {
11397 if (!emitTree(propdef->as<UnaryNode>().kid())) {
11398 // [stack] RECORD SPREADEE
11399 return false;
11400 }
11401 if (!emit1(JSOp::AddRecordSpread)) {
11402 // [stack] RECORD
11403 return false;
11404 }
11405 } else {
11406 BinaryNode* prop = &propdef->as<BinaryNode>();
11407
11408 ParseNode* key = prop->left();
11409 ParseNode* value = prop->right();
11410
11411 switch (key->getKind()) {
11412 case ParseNodeKind::ObjectPropertyName:
11413 if (!emitStringOp(JSOp::String, key->as<NameNode>().atom())) {
11414 return false;
11415 }
11416 break;
11417 case ParseNodeKind::ComputedName:
11418 if (!emitTree(key->as<UnaryNode>().kid())) {
11419 return false;
11420 }
11421 break;
11422 default:
11423 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"
, 11425); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr)"
")"); do { *((volatile int*)__null) = 11425; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11424 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"
, 11425); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr)"
")"); do { *((volatile int*)__null) = 11425; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11425 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"
, 11425); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr)"
")"); do { *((volatile int*)__null) = 11425; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11426 if (!emitTree(key)) {
11427 return false;
11428 }
11429 break;
11430 }
11431 // [stack] RECORD KEY
11432
11433 if (!emitTree(value)) {
11434 // [stack] RECORD KEY VALUE
11435 return false;
11436 }
11437
11438 if (!emit1(JSOp::AddRecordProperty)) {
11439 // [stack] RECORD
11440 return false;
11441 }
11442 }
11443 }
11444
11445 if (!emit1(JSOp::FinishRecord)) {
11446 // [stack] RECORD
11447 return false;
11448 }
11449
11450 return true;
11451}
11452
11453bool BytecodeEmitter::emitTupleLiteral(ListNode* tuple) {
11454 if (!emitUint32Operand(JSOp::InitTuple, tuple->count())) {
11455 // [stack] TUPLE
11456 return false;
11457 }
11458
11459 for (ParseNode* elt : tuple->contents()) {
11460 if (elt->isKind(ParseNodeKind::Spread)) {
11461 ParseNode* expr = elt->as<UnaryNode>().kid();
11462 auto selfHostedIter = getSelfHostedIterFor(expr);
11463
11464 if (!emitIterable(expr, selfHostedIter)) {
11465 // [stack] TUPLE ITERABLE
11466 return false;
11467 }
11468 if (!emitIterator(selfHostedIter)) {
11469 // [stack] TUPLE NEXT ITER
11470 return false;
11471 }
11472 if (!emit2(JSOp::Pick, 2)) {
11473 // [stack] NEXT ITER TUPLE
11474 return false;
11475 }
11476 if (!emitSpread(selfHostedIter, /* spreadeeStackItems = */ 1,
11477 JSOp::AddTupleElement)) {
11478 // [stack] TUPLE
11479 return false;
11480 }
11481 } else {
11482 // Update location to throw errors about non-primitive elements
11483 // in the correct position.
11484 if (!updateSourceCoordNotesIfNonLiteral(elt)) {
11485 return false;
11486 }
11487
11488 if (!emitTree(elt)) {
11489 // [stack] TUPLE VALUE
11490 return false;
11491 }
11492
11493 if (!emit1(JSOp::AddTupleElement)) {
11494 // [stack] TUPLE
11495 return false;
11496 }
11497 }
11498 }
11499
11500 if (!emit1(JSOp::FinishTuple)) {
11501 // [stack] TUPLE
11502 return false;
11503 }
11504
11505 return true;
11506}
11507#endif
11508
11509static inline JSOp UnaryOpParseNodeKindToJSOp(ParseNodeKind pnk) {
11510 switch (pnk) {
11511 case ParseNodeKind::ThrowStmt:
11512 return JSOp::Throw;
11513 case ParseNodeKind::VoidExpr:
11514 return JSOp::Void;
11515 case ParseNodeKind::NotExpr:
11516 return JSOp::Not;
11517 case ParseNodeKind::BitNotExpr:
11518 return JSOp::BitNot;
11519 case ParseNodeKind::PosExpr:
11520 return JSOp::Pos;
11521 case ParseNodeKind::NegExpr:
11522 return JSOp::Neg;
11523 default:
11524 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"
, 11524); AnnotateMozCrashReason("MOZ_CRASH(" "unexpected unary op"
")"); do { *((volatile int*)__null) = 11524; __attribute__((
nomerge)) ::abort(); } while (false); } while (false)
;
11525 }
11526}
11527
11528bool BytecodeEmitter::emitUnary(UnaryNode* unaryNode) {
11529 if (!updateSourceCoordNotes(unaryNode->pn_pos.begin)) {
11530 return false;
11531 }
11532
11533 JSOp op = UnaryOpParseNodeKindToJSOp(unaryNode->getKind());
11534 ValueUsage valueUsage =
11535 op == JSOp::Void ? ValueUsage::IgnoreValue : ValueUsage::WantValue;
11536 if (!emitTree(unaryNode->kid(), valueUsage)) {
11537 return false;
11538 }
11539 return emit1(op);
11540}
11541
11542bool BytecodeEmitter::emitTypeof(UnaryNode* typeofNode, JSOp op) {
11543 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"
, 11543); AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::Typeof || op == JSOp::TypeofExpr"
")"); do { *((volatile int*)__null) = 11543; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11544
11545 if (!updateSourceCoordNotes(typeofNode->pn_pos.begin)) {
11546 return false;
11547 }
11548
11549 if (!emitTree(typeofNode->kid())) {
11550 return false;
11551 }
11552
11553 return emit1(op);
11554}
11555
11556bool BytecodeEmitter::tryEmitTypeofEq(ListNode* node, bool* emitted) {
11557 // Emit specialized opcode for `typeof val == "type` or `typeof val != "type`
11558 // if possible.
11559 //
11560 // NOTE: Given the comparison is done for string, `==` and `===` have
11561 // no difference. Same for `!=` and `!==`.
11562 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"
, 11565); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::StrictEqExpr) || node->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)"
")"); do { *((volatile int*)__null) = 11565; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11563 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"
, 11565); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::StrictEqExpr) || node->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)"
")"); do { *((volatile int*)__null) = 11565; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11564 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"
, 11565); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::StrictEqExpr) || node->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)"
")"); do { *((volatile int*)__null) = 11565; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11565 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"
, 11565); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::StrictEqExpr) || node->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)"
")"); do { *((volatile int*)__null) = 11565; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11566
11567 if (node->count() != 2) {
11568 *emitted = false;
11569 return true;
11570 }
11571
11572 ParseNode* left = node->head();
11573 ParseNode* right = left->pn_next;
11574 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"
, 11574); AnnotateMozCrashReason("MOZ_ASSERT" "(" "right" ")"
); do { *((volatile int*)__null) = 11574; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
11575
11576 UnaryNode* typeofNode;
11577 NameNode* typenameNode;
11578 JSOp op;
11579
11580 if (node->isKind(ParseNodeKind::StrictEqExpr) ||
11581 node->isKind(ParseNodeKind::EqExpr)) {
11582 op = JSOp::Eq;
11583 } else {
11584 op = JSOp::Ne;
11585 }
11586
11587 // NOTE: ParseNodeKind::TypeOfExpr cannot use JSOp::TypeofEq.
11588 // See JSOp::GetName document.
11589 if (left->isKind(ParseNodeKind::TypeOfNameExpr) &&
11590 right->isKind(ParseNodeKind::StringExpr)) {
11591 typeofNode = &left->as<UnaryNode>();
11592 typenameNode = &right->as<NameNode>();
11593 } else if (right->isKind(ParseNodeKind::TypeOfNameExpr) &&
11594 left->isKind(ParseNodeKind::StringExpr)) {
11595 typeofNode = &right->as<UnaryNode>();
11596 typenameNode = &left->as<NameNode>();
11597 } else {
11598 *emitted = false;
11599 return true;
11600 }
11601
11602 JSType type;
11603 TaggedParserAtomIndex typeName = typenameNode->atom();
11604 if (typeName == TaggedParserAtomIndex::WellKnown::undefined()) {
11605 type = JSTYPE_UNDEFINED;
11606 } else if (typeName == TaggedParserAtomIndex::WellKnown::object()) {
11607 type = JSTYPE_OBJECT;
11608 } else if (typeName == TaggedParserAtomIndex::WellKnown::function()) {
11609 type = JSTYPE_FUNCTION;
11610 } else if (typeName == TaggedParserAtomIndex::WellKnown::string()) {
11611 type = JSTYPE_STRING;
11612 } else if (typeName == TaggedParserAtomIndex::WellKnown::number()) {
11613 type = JSTYPE_NUMBER;
11614 } else if (typeName == TaggedParserAtomIndex::WellKnown::boolean()) {
11615 type = JSTYPE_BOOLEAN;
11616 } else if (typeName == TaggedParserAtomIndex::WellKnown::symbol()) {
11617 type = JSTYPE_SYMBOL;
11618 } else if (typeName == TaggedParserAtomIndex::WellKnown::bigint()) {
11619 type = JSTYPE_BIGINT;
11620 }
11621#ifdef ENABLE_RECORD_TUPLE
11622 else if (typeName == TaggedParserAtomIndex::WellKnown::record()) {
11623 type = JSTYPE_RECORD;
11624 } else if (typeName == TaggedParserAtomIndex::WellKnown::tuple()) {
11625 type = JSTYPE_TUPLE;
11626 }
11627#endif
11628 else {
11629 *emitted = false;
11630 return true;
11631 }
11632
11633 if (!updateSourceCoordNotes(typeofNode->pn_pos.begin)) {
11634 return false;
11635 }
11636
11637 if (!emitTree(typeofNode->kid())) {
11638 // [stack] VAL
11639 return false;
11640 }
11641
11642 if (!emit2(JSOp::TypeofEq, TypeofEqOperand(type, op).rawValue())) {
11643 // [stack] CMP
11644 return false;
11645 }
11646
11647 *emitted = true;
11648 return true;
11649}
11650
11651bool BytecodeEmitter::emitFunctionFormalParameters(ParamsBodyNode* paramsBody) {
11652 FunctionBox* funbox = sc->asFunctionBox();
11653
11654 bool hasRest = funbox->hasRest();
11655
11656 FunctionParamsEmitter fpe(this, funbox);
11657 for (ParseNode* arg : paramsBody->parameters()) {
11658 ParseNode* bindingElement = arg;
11659 ParseNode* initializer = nullptr;
11660 if (arg->isKind(ParseNodeKind::AssignExpr)) {
11661 bindingElement = arg->as<BinaryNode>().left();
11662 initializer = arg->as<BinaryNode>().right();
11663 }
11664 bool hasInitializer = !!initializer;
11665 bool isRest =
11666 hasRest && arg->pn_next == *std::end(paramsBody->parameters());
11667 bool isDestructuring = !bindingElement->isKind(ParseNodeKind::Name);
11668
11669 // Left-hand sides are either simple names or destructuring patterns.
11670 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"
, 11672); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bindingElement->isKind(ParseNodeKind::Name) || bindingElement->isKind(ParseNodeKind::ArrayExpr) || bindingElement->isKind(ParseNodeKind::ObjectExpr)"
")"); do { *((volatile int*)__null) = 11672; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11671 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"
, 11672); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bindingElement->isKind(ParseNodeKind::Name) || bindingElement->isKind(ParseNodeKind::ArrayExpr) || bindingElement->isKind(ParseNodeKind::ObjectExpr)"
")"); do { *((volatile int*)__null) = 11672; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11672 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"
, 11672); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bindingElement->isKind(ParseNodeKind::Name) || bindingElement->isKind(ParseNodeKind::ArrayExpr) || bindingElement->isKind(ParseNodeKind::ObjectExpr)"
")"); do { *((volatile int*)__null) = 11672; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11673
11674 auto emitDefaultInitializer = [this, &initializer, &bindingElement]() {
11675 // [stack]
11676
11677 if (!this->emitInitializer(initializer, bindingElement)) {
11678 // [stack] DEFAULT
11679 return false;
11680 }
11681 return true;
11682 };
11683
11684 auto emitDestructuring = [this, &bindingElement]() {
11685 // [stack] ARG
11686
11687 if (!this->emitDestructuringOps(&bindingElement->as<ListNode>(),
11688 DestructuringFlavor::Declaration)) {
11689 // [stack] ARG
11690 return false;
11691 }
11692
11693 return true;
11694 };
11695
11696 if (isRest) {
11697 if (isDestructuring) {
11698 if (!fpe.prepareForDestructuringRest()) {
11699 // [stack]
11700 return false;
11701 }
11702 if (!emitDestructuring()) {
11703 // [stack]
11704 return false;
11705 }
11706 if (!fpe.emitDestructuringRestEnd()) {
11707 // [stack]
11708 return false;
11709 }
11710 } else {
11711 auto paramName = bindingElement->as<NameNode>().name();
11712 if (!fpe.emitRest(paramName)) {
11713 // [stack]
11714 return false;
11715 }
11716 }
11717
11718 continue;
11719 }
11720
11721 if (isDestructuring) {
11722 if (hasInitializer) {
11723 if (!fpe.prepareForDestructuringDefaultInitializer()) {
11724 // [stack]
11725 return false;
11726 }
11727 if (!emitDefaultInitializer()) {
11728 // [stack]
11729 return false;
11730 }
11731 if (!fpe.prepareForDestructuringDefault()) {
11732 // [stack]
11733 return false;
11734 }
11735 if (!emitDestructuring()) {
11736 // [stack]
11737 return false;
11738 }
11739 if (!fpe.emitDestructuringDefaultEnd()) {
11740 // [stack]
11741 return false;
11742 }
11743 } else {
11744 if (!fpe.prepareForDestructuring()) {
11745 // [stack]
11746 return false;
11747 }
11748 if (!emitDestructuring()) {
11749 // [stack]
11750 return false;
11751 }
11752 if (!fpe.emitDestructuringEnd()) {
11753 // [stack]
11754 return false;
11755 }
11756 }
11757
11758 continue;
11759 }
11760
11761 if (hasInitializer) {
11762 if (!fpe.prepareForDefault()) {
11763 // [stack]
11764 return false;
11765 }
11766 if (!emitDefaultInitializer()) {
11767 // [stack]
11768 return false;
11769 }
11770 auto paramName = bindingElement->as<NameNode>().name();
11771 if (!fpe.emitDefaultEnd(paramName)) {
11772 // [stack]
11773 return false;
11774 }
11775
11776 continue;
11777 }
11778
11779 auto paramName = bindingElement->as<NameNode>().name();
11780 if (!fpe.emitSimple(paramName)) {
11781 // [stack]
11782 return false;
11783 }
11784 }
11785
11786 return true;
11787}
11788
11789bool BytecodeEmitter::emitInitializeFunctionSpecialNames() {
11790 FunctionBox* funbox = sc->asFunctionBox();
11791
11792 // [stack]
11793
11794 auto emitInitializeFunctionSpecialName =
11795 [](BytecodeEmitter* bce, TaggedParserAtomIndex name, JSOp op) {
11796 // A special name must be slotful, either on the frame or on the
11797 // call environment.
11798 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"
, 11798); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bce->lookupName(name).hasKnownSlot()"
")"); do { *((volatile int*)__null) = 11798; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11799
11800 NameOpEmitter noe(bce, name, NameOpEmitter::Kind::Initialize);
11801 if (!noe.prepareForRhs()) {
11802 // [stack]
11803 return false;
11804 }
11805 if (!bce->emit1(op)) {
11806 // [stack] THIS/ARGUMENTS/NEW.TARGET
11807 return false;
11808 }
11809 if (!noe.emitAssignment()) {
11810 // [stack] THIS/ARGUMENTS/NEW.TARGET
11811 return false;
11812 }
11813 if (!bce->emit1(JSOp::Pop)) {
11814 // [stack]
11815 return false;
11816 }
11817
11818 return true;
11819 };
11820
11821 // Do nothing if the function doesn't have an arguments binding.
11822 if (funbox->needsArgsObj()) {
11823 // Self-hosted code should use the more efficient ArgumentsLength and
11824 // GetArgument intrinsics instead of `arguments`.
11825 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"
, 11825); AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode != BytecodeEmitter::SelfHosting"
")"); do { *((volatile int*)__null) = 11825; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11826 if (!emitInitializeFunctionSpecialName(
11827 this, TaggedParserAtomIndex::WellKnown::arguments(),
11828 JSOp::Arguments)) {
11829 // [stack]
11830 return false;
11831 }
11832 }
11833
11834 // Do nothing if the function doesn't have a this-binding (this
11835 // happens for instance if it doesn't use this/eval or if it's an
11836 // arrow function).
11837 if (funbox->functionHasThisBinding()) {
11838 if (!emitInitializeFunctionSpecialName(
11839 this, TaggedParserAtomIndex::WellKnown::dot_this_(),
11840 JSOp::FunctionThis)) {
11841 return false;
11842 }
11843 }
11844
11845 // Do nothing if the function doesn't have a new.target-binding (this happens
11846 // for instance if it doesn't use new.target/eval or if it's an arrow
11847 // function).
11848 if (funbox->functionHasNewTargetBinding()) {
11849 if (!emitInitializeFunctionSpecialName(
11850 this, TaggedParserAtomIndex::WellKnown::dot_newTarget_(),
11851 JSOp::NewTarget)) {
11852 return false;
11853 }
11854 }
11855
11856 // Do nothing if the function doesn't implicitly return a promise result.
11857 if (funbox->needsPromiseResult()) {
11858 if (!emitInitializeFunctionSpecialName(
11859 this, TaggedParserAtomIndex::WellKnown::dot_generator_(),
11860 JSOp::Generator)) {
11861 // [stack]
11862 return false;
11863 }
11864 }
11865 return true;
11866}
11867
11868bool BytecodeEmitter::emitLexicalInitialization(NameNode* name) {
11869 return emitLexicalInitialization(name->name());
11870}
11871
11872bool BytecodeEmitter::emitLexicalInitialization(TaggedParserAtomIndex name) {
11873 NameOpEmitter noe(this, name, NameOpEmitter::Kind::Initialize);
11874 if (!noe.prepareForRhs()) {
11875 return false;
11876 }
11877
11878 // The caller has pushed the RHS to the top of the stack. Assert that the
11879 // binding can be initialized without a binding object on the stack, and that
11880 // no JSOp::BindName or JSOp::BindGName ops were emitted.
11881 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"
, 11882); AnnotateMozCrashReason("MOZ_ASSERT" "(" "noe.loc().isLexical() || noe.loc().isSynthetic() || noe.loc().isPrivateMethod()"
")"); do { *((volatile int*)__null) = 11882; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11882 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"
, 11882); AnnotateMozCrashReason("MOZ_ASSERT" "(" "noe.loc().isLexical() || noe.loc().isSynthetic() || noe.loc().isPrivateMethod()"
")"); do { *((volatile int*)__null) = 11882; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11883 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"
, 11883); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!noe.emittedBindOp()"
")"); do { *((volatile int*)__null) = 11883; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11884
11885 if (!noe.emitAssignment()) {
11886 return false;
11887 }
11888
11889 return true;
11890}
11891
11892static MOZ_ALWAYS_INLINEinline ParseNode* FindConstructor(ListNode* classMethods) {
11893 for (ParseNode* classElement : classMethods->contents()) {
11894 ParseNode* unwrappedElement = classElement;
11895 if (unwrappedElement->is<LexicalScopeNode>()) {
11896 unwrappedElement = unwrappedElement->as<LexicalScopeNode>().scopeBody();
11897 }
11898 if (unwrappedElement->is<ClassMethod>()) {
11899 ClassMethod& method = unwrappedElement->as<ClassMethod>();
11900 ParseNode& methodName = method.name();
11901 if (!method.isStatic() &&
11902 (methodName.isKind(ParseNodeKind::ObjectPropertyName) ||
11903 methodName.isKind(ParseNodeKind::StringExpr)) &&
11904 methodName.as<NameNode>().atom() ==
11905 TaggedParserAtomIndex::WellKnown::constructor()) {
11906 return classElement;
11907 }
11908 }
11909 }
11910 return nullptr;
11911}
11912
11913bool BytecodeEmitter::emitNewPrivateName(TaggedParserAtomIndex bindingName,
11914 TaggedParserAtomIndex symbolName) {
11915 if (!emitAtomOp(JSOp::NewPrivateName, symbolName)) {
11916 // [stack] HERITAGE PRIVATENAME
11917 return false;
11918 }
11919
11920 // Add a binding for #name => privatename
11921 if (!emitLexicalInitialization(bindingName)) {
11922 // [stack] HERITAGE PRIVATENAME
11923 return false;
11924 }
11925
11926 // Pop Private name off the stack.
11927 if (!emit1(JSOp::Pop)) {
11928 // [stack] HERITAGE
11929 return false;
11930 }
11931
11932 return true;
11933}
11934
11935bool BytecodeEmitter::emitNewPrivateNames(
11936 TaggedParserAtomIndex privateBrandName, ListNode* classMembers) {
11937 bool hasPrivateBrand = false;
11938
11939 for (ParseNode* classElement : classMembers->contents()) {
11940 ParseNode* elementName;
11941 if (classElement->is<ClassMethod>()) {
11942 elementName = &classElement->as<ClassMethod>().name();
11943 } else if (classElement->is<ClassField>()) {
11944 elementName = &classElement->as<ClassField>().name();
11945 } else {
11946 continue;
11947 }
11948
11949 if (!elementName->isKind(ParseNodeKind::PrivateName)) {
11950 continue;
11951 }
11952
11953 // Non-static private methods' private names are optimized away.
11954 bool isOptimized = false;
11955 if (classElement->is<ClassMethod>() &&
11956 !classElement->as<ClassMethod>().isStatic()) {
11957 hasPrivateBrand = true;
11958 if (classElement->as<ClassMethod>().accessorType() ==
11959 AccessorType::None) {
11960 isOptimized = true;
11961 }
11962 }
11963
11964 if (!isOptimized) {
11965 auto privateName = elementName->as<NameNode>().name();
11966 if (!emitNewPrivateName(privateName, privateName)) {
11967 return false;
11968 }
11969 }
11970 }
11971
11972 if (hasPrivateBrand) {
11973 // We don't make a private name for every optimized method, but we need one
11974 // private name per class, the `.privateBrand`.
11975 if (!emitNewPrivateName(
11976 TaggedParserAtomIndex::WellKnown::dot_privateBrand_(),
11977 privateBrandName)) {
11978 return false;
11979 }
11980 }
11981 return true;
11982}
11983
11984// This follows ES6 14.5.14 (ClassDefinitionEvaluation) and ES6 14.5.15
11985// (BindingClassDeclarationEvaluation).
11986bool BytecodeEmitter::emitClass(
11987 ClassNode* classNode,
11988 ClassNameKind nameKind /* = ClassNameKind::BindingName */,
11989 TaggedParserAtomIndex
11990 nameForAnonymousClass /* = TaggedParserAtomIndex::null() */) {
11991 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"
, 11992); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(nameKind == ClassNameKind::InferredName) == bool(nameForAnonymousClass)"
")"); do { *((volatile int*)__null) = 11992; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11992 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"
, 11992); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(nameKind == ClassNameKind::InferredName) == bool(nameForAnonymousClass)"
")"); do { *((volatile int*)__null) = 11992; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11993
11994 ParseNode* heritageExpression = classNode->heritage();
11995 ListNode* classMembers = classNode->memberList();
11996 ParseNode* constructor = FindConstructor(classMembers);
11997
11998 // If |nameKind != ClassNameKind::ComputedName|
11999 // [stack]
12000 // Else
12001 // [stack] NAME
12002
12003 ClassEmitter ce(this);
12004 TaggedParserAtomIndex innerName;
12005 ClassEmitter::Kind kind = ClassEmitter::Kind::Expression;
12006 if (ClassNames* names = classNode->names()) {
12007 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"
, 12007); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nameKind == ClassNameKind::BindingName"
")"); do { *((volatile int*)__null) = 12007; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12008 innerName = names->innerBinding()->name();
12009 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"
, 12009); AnnotateMozCrashReason("MOZ_ASSERT" "(" "innerName"
")"); do { *((volatile int*)__null) = 12009; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12010
12011 if (names->outerBinding()) {
12012 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"
, 12012); AnnotateMozCrashReason("MOZ_ASSERT" "(" "names->outerBinding()->name()"
")"); do { *((volatile int*)__null) = 12012; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12013 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"
, 12013); AnnotateMozCrashReason("MOZ_ASSERT" "(" "names->outerBinding()->name() == innerName"
")"); do { *((volatile int*)__null) = 12013; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12014 kind = ClassEmitter::Kind::Declaration;
12015 }
12016 }
12017
12018 if (LexicalScopeNode* scopeBindings = classNode->scopeBindings()) {
12019 if (!ce.emitScope(scopeBindings->scopeBindings())) {
12020 // [stack]
12021 return false;
12022 }
12023 }
12024
12025 bool isDerived = !!heritageExpression;
12026 if (isDerived) {
12027 if (!updateSourceCoordNotes(classNode->pn_pos.begin)) {
12028 return false;
12029 }
12030 if (!markStepBreakpoint()) {
12031 return false;
12032 }
12033 if (!emitTree(heritageExpression)) {
12034 // [stack] HERITAGE
12035 return false;
12036 }
12037 }
12038
12039 // The class body scope holds any private names. Those mustn't be visible in
12040 // the heritage expression and hence the scope must be emitted after the
12041 // heritage expression.
12042 if (ClassBodyScopeNode* bodyScopeBindings = classNode->bodyScopeBindings()) {
12043 if (!ce.emitBodyScope(bodyScopeBindings->scopeBindings())) {
12044 // [stack] HERITAGE
12045 return false;
12046 }
12047
12048 // The spec does not say anything about private brands being symbols. It's
12049 // an implementation detail. So we can give the special private brand
12050 // symbol any description we want and users won't normally see it. For
12051 // debugging, use the class name.
12052 auto privateBrandName = innerName;
12053 if (!innerName) {
12054 privateBrandName = nameForAnonymousClass
12055 ? nameForAnonymousClass
12056 : TaggedParserAtomIndex::WellKnown::anonymous();
12057 }
12058 if (!emitNewPrivateNames(privateBrandName, classMembers)) {
12059 return false;
12060 }
12061 }
12062
12063 bool hasNameOnStack = nameKind == ClassNameKind::ComputedName;
12064 if (isDerived) {
12065 if (!ce.emitDerivedClass(innerName, nameForAnonymousClass,
12066 hasNameOnStack)) {
12067 // [stack] HOMEOBJ HERITAGE
12068 return false;
12069 }
12070 } else {
12071 if (!ce.emitClass(innerName, nameForAnonymousClass, hasNameOnStack)) {
12072 // [stack] HOMEOBJ
12073 return false;
12074 }
12075 }
12076
12077 // Stack currently has HOMEOBJ followed by optional HERITAGE. When HERITAGE
12078 // is not used, an implicit value of %FunctionPrototype% is implied.
12079
12080 // See |Parser::classMember(...)| for the reason why |.initializers| is
12081 // created within its own scope.
12082 Maybe<LexicalScopeEmitter> lse;
12083 FunctionNode* ctor;
12084#ifdef ENABLE_DECORATORS
12085 bool extraInitializersPresent = false;
12086#endif
12087 if (constructor->is<LexicalScopeNode>()) {
12088 LexicalScopeNode* constructorScope = &constructor->as<LexicalScopeNode>();
12089
12090 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"
, 12090); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!constructorScope->isEmptyScope()"
")"); do { *((volatile int*)__null) = 12090; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12091#ifdef ENABLE_DECORATORS
12092 // With decorators enabled we expect to see |.initializers|,
12093 // and |.instanceExtraInitializers| in this scope.
12094 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"
, 12094); AnnotateMozCrashReason("MOZ_ASSERT" "(" "constructorScope->scopeBindings()->length == 2"
")"); do { *((volatile int*)__null) = 12094; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12095 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"
, 12097); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()"
")"); do { *((volatile int*)__null) = 12097; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12096 .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"
, 12097); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()"
")"); do { *((volatile int*)__null) = 12097; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12097 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"
, 12097); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()"
")"); do { *((volatile int*)__null) = 12097; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12098 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"
, 12101); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_()"
")"); do { *((volatile int*)__null) = 12101; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12099 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"
, 12101); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_()"
")"); do { *((volatile int*)__null) = 12101; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12100 .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"
, 12101); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_()"
")"); do { *((volatile int*)__null) = 12101; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12101 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"
, 12101); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_()"
")"); do { *((volatile int*)__null) = 12101; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12102
12103 // We should only call this code if we know decorators are present, see bug
12104 // 1871147.
12105 lse.emplace(this);
12106 if (!lse->emitScope(ScopeKind::Lexical,
12107 constructorScope->scopeBindings())) {
12108 return false;
12109 }
12110
12111 // TODO: See bug 1868220 for support for static extra initializers.
12112 if (!ce.prepareForExtraInitializers(TaggedParserAtomIndex::WellKnown::
12113 dot_instanceExtraInitializers_())) {
12114 return false;
12115 }
12116
12117 if (classNode->addInitializerFunction()) {
12118 DecoratorEmitter de(this);
12119 if (!de.emitCreateAddInitializerFunction(
12120 classNode->addInitializerFunction(),
12121 TaggedParserAtomIndex::WellKnown::
12122 dot_instanceExtraInitializers_())) {
12123 // [stack] HOMEOBJ HERITAGE? ADDINIT
12124 return false;
12125 }
12126
12127 if (!emitUnpickN(isDerived ? 2 : 1)) {
12128 // [stack] ADDINIT HOMEOBJ HERITAGE?
12129 return false;
12130 }
12131
12132 extraInitializersPresent = true;
12133 }
12134#else
12135 // The constructor scope should only contain the |.initializers| binding.
12136 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"
, 12136); AnnotateMozCrashReason("MOZ_ASSERT" "(" "constructorScope->scopeBindings()->length == 1"
")"); do { *((volatile int*)__null) = 12136; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12137 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"
, 12139); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()"
")"); do { *((volatile int*)__null) = 12139; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12138 .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"
, 12139); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()"
")"); do { *((volatile int*)__null) = 12139; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12139 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"
, 12139); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()"
")"); do { *((volatile int*)__null) = 12139; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12140#endif
12141
12142 auto needsInitializer = [](ParseNode* propdef) {
12143 return NeedsFieldInitializer(propdef, false) ||
12144 NeedsAccessorInitializer(propdef, false);
12145 };
12146
12147 // As an optimization omit the |.initializers| binding when no instance
12148 // fields or private methods are present.
12149 bool needsInitializers =
12150 std::any_of(classMembers->contents().begin(),
12151 classMembers->contents().end(), needsInitializer);
12152 if (needsInitializers) {
12153#ifndef ENABLE_DECORATORS
12154 lse.emplace(this);
12155 if (!lse->emitScope(ScopeKind::Lexical,
12156 constructorScope->scopeBindings())) {
12157 return false;
12158 }
12159#endif
12160 // Any class with field initializers will have a constructor
12161 if (!emitCreateMemberInitializers(ce, classMembers,
12162 FieldPlacement::Instance
12163#ifdef ENABLE_DECORATORS
12164 ,
12165 isDerived
12166#endif
12167 )) {
12168 return false;
12169 }
12170 }
12171
12172 ctor = &constructorScope->scopeBody()->as<ClassMethod>().method();
12173 } else {
12174 // The |.initializers| binding is never emitted when in self-hosting mode.
12175 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"
, 12175); AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode == BytecodeEmitter::SelfHosting"
")"); do { *((volatile int*)__null) = 12175; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12176 ctor = &constructor->as<ClassMethod>().method();
12177 }
12178
12179 bool needsHomeObject = ctor->funbox()->needsHomeObject();
12180 // HERITAGE is consumed inside emitFunction.
12181 if (nameKind == ClassNameKind::InferredName) {
12182 if (!setFunName(ctor->funbox(), nameForAnonymousClass)) {
12183 return false;
12184 }
12185 }
12186 if (!emitFunction(ctor, isDerived)) {
12187 // [stack] HOMEOBJ CTOR
12188 return false;
12189 }
12190 if (lse.isSome()) {
12191 if (!lse->emitEnd()) {
12192 return false;
12193 }
12194 lse.reset();
12195 }
12196 if (!ce.emitInitConstructor(needsHomeObject)) {
12197 // [stack] CTOR HOMEOBJ
12198 return false;
12199 }
12200
12201 if (!emitCreateFieldKeys(classMembers, FieldPlacement::Instance)) {
12202 return false;
12203 }
12204
12205#ifdef ENABLE_DECORATORS
12206 // TODO: See Bug 1868220 for support for static extra initializers.
12207 if (!emit1(JSOp::Undefined)) {
12208 // [stack] ADDINIT? CTOR HOMEOBJ UNDEFINED
12209 return false;
12210 }
12211 if (!emitUnpickN(2)) {
12212 // [stack] ADDINIT? UNDEFINED CTOR HOMEOBJ
12213 }
12214#endif
12215
12216 if (!emitCreateMemberInitializers(ce, classMembers, FieldPlacement::Static
12217#ifdef ENABLE_DECORATORS
12218 ,
12219 false
12220#endif
12221 )) {
12222 return false;
12223 }
12224
12225#ifdef ENABLE_DECORATORS
12226 if (!emitPickN(2)) {
12227 // [stack] ADDINIT? CTOR HOMEOBJ UNDEFINED
12228 return false;
12229 }
12230 if (!emitPopN(1)) {
12231 // [stack] ADDINIT? CTOR HOMEOBJ
12232 return false;
12233 }
12234#endif
12235
12236 if (!emitCreateFieldKeys(classMembers, FieldPlacement::Static)) {
12237 return false;
12238 }
12239
12240 if (!emitPropertyList(classMembers, ce, ClassBody)) {
12241 // [stack] CTOR HOMEOBJ
12242 return false;
12243 }
12244
12245#ifdef ENABLE_DECORATORS
12246 if (extraInitializersPresent) {
12247 if (!emitPickN(2)) {
12248 // [stack] CTOR HOMEOBJ ADDINIT
12249 return false;
12250 }
12251 if (!emitPopN(1)) {
12252 // [stack] CTOR HOMEOBJ
12253 return false;
12254 }
12255 }
12256#endif
12257
12258 if (!ce.emitBinding()) {
12259 // [stack] CTOR
12260 return false;
12261 }
12262
12263 if (!emitInitializeStaticFields(classMembers)) {
12264 // [stack] CTOR
12265 return false;
12266 }
12267
12268#if ENABLE_DECORATORS
12269 if (!ce.prepareForDecorators()) {
12270 // [stack] CTOR
12271 return false;
12272 }
12273 if (classNode->decorators() != nullptr) {
12274 DecoratorEmitter de(this);
12275 NameNode* className =
12276 classNode->names() ? classNode->names()->innerBinding() : nullptr;
12277 if (!de.emitApplyDecoratorsToClassDefinition(className,
12278 classNode->decorators())) {
12279 // [stack] CTOR
12280 return false;
12281 }
12282 }
12283#endif
12284
12285 if (!ce.emitEnd(kind)) {
12286 // [stack] # class declaration
12287 // [stack]
12288 // [stack] # class expression
12289 // [stack] CTOR
12290 return false;
12291 }
12292
12293 return true;
12294}
12295
12296bool BytecodeEmitter::emitExportDefault(BinaryNode* exportNode) {
12297 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"
, 12297); AnnotateMozCrashReason("MOZ_ASSERT" "(" "exportNode->isKind(ParseNodeKind::ExportDefaultStmt)"
")"); do { *((volatile int*)__null) = 12297; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12298
12299 ParseNode* valueNode = exportNode->left();
12300 if (valueNode->isDirectRHSAnonFunction()) {
12301 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"
, 12301); AnnotateMozCrashReason("MOZ_ASSERT" "(" "exportNode->right()"
")"); do { *((volatile int*)__null) = 12301; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12302
12303 if (!emitAnonymousFunctionWithName(
12304 valueNode, TaggedParserAtomIndex::WellKnown::default_())) {
12305 return false;
12306 }
12307 } else {
12308 if (!emitTree(valueNode)) {
12309 return false;
12310 }
12311 }
12312
12313 if (ParseNode* binding = exportNode->right()) {
12314 if (!emitLexicalInitialization(&binding->as<NameNode>())) {
12315 return false;
12316 }
12317
12318 if (!emit1(JSOp::Pop)) {
12319 return false;
12320 }
12321 }
12322
12323 return true;
12324}
12325
12326bool BytecodeEmitter::emitTree(
12327 ParseNode* pn, ValueUsage valueUsage /* = ValueUsage::WantValue */,
12328 EmitLineNumberNote emitLineNote /* = EMIT_LINENOTE */) {
12329 AutoCheckRecursionLimit recursion(fc);
12330 if (!recursion.check(fc)) {
12331 return false;
12332 }
12333
12334 /* Emit notes to tell the current bytecode's source line number.
12335 However, a couple trees require special treatment; see the
12336 relevant emitter functions for details. */
12337 if (emitLineNote == EMIT_LINENOTE &&
12338 !ParseNodeRequiresSpecialLineNumberNotes(pn)) {
12339 if (!updateLineNumberNotes(pn->pn_pos.begin)) {
12340 return false;
12341 }
12342 }
12343
12344 switch (pn->getKind()) {
12345 case ParseNodeKind::Function:
12346 if (!emitFunction(&pn->as<FunctionNode>())) {
12347 return false;
12348 }
12349 break;
12350
12351 case ParseNodeKind::ParamsBody:
12352 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"
, 12353); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "ParamsBody should be handled in emitFunctionScript."
")"); do { *((volatile int*)__null) = 12353; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12353 "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"
, 12353); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "ParamsBody should be handled in emitFunctionScript."
")"); do { *((volatile int*)__null) = 12353; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12354 break;
12355
12356 case ParseNodeKind::IfStmt:
12357 if (!emitIf(&pn->as<TernaryNode>())) {
12358 return false;
12359 }
12360 break;
12361
12362 case ParseNodeKind::SwitchStmt:
12363 if (!emitSwitch(&pn->as<SwitchStatement>())) {
12364 return false;
12365 }
12366 break;
12367
12368 case ParseNodeKind::WhileStmt:
12369 if (!emitWhile(&pn->as<BinaryNode>())) {
12370 return false;
12371 }
12372 break;
12373
12374 case ParseNodeKind::DoWhileStmt:
12375 if (!emitDo(&pn->as<BinaryNode>())) {
12376 return false;
12377 }
12378 break;
12379
12380 case ParseNodeKind::ForStmt:
12381 if (!emitFor(&pn->as<ForNode>())) {
12382 return false;
12383 }
12384 break;
12385
12386 case ParseNodeKind::BreakStmt:
12387 // Ensure that the column of the 'break' is set properly.
12388 if (!updateSourceCoordNotes(pn->pn_pos.begin)) {
12389 return false;
12390 }
12391 if (!markStepBreakpoint()) {
12392 return false;
12393 }
12394
12395 if (!emitBreak(pn->as<BreakStatement>().label())) {
12396 return false;
12397 }
12398 break;
12399
12400 case ParseNodeKind::ContinueStmt:
12401 // Ensure that the column of the 'continue' is set properly.
12402 if (!updateSourceCoordNotes(pn->pn_pos.begin)) {
12403 return false;
12404 }
12405 if (!markStepBreakpoint()) {
12406 return false;
12407 }
12408
12409 if (!emitContinue(pn->as<ContinueStatement>().label())) {
12410 return false;
12411 }
12412 break;
12413
12414 case ParseNodeKind::WithStmt:
12415 if (!emitWith(&pn->as<BinaryNode>())) {
12416 return false;
12417 }
12418 break;
12419
12420 case ParseNodeKind::TryStmt:
12421 if (!emitTry(&pn->as<TryNode>())) {
12422 return false;
12423 }
12424 break;
12425
12426 case ParseNodeKind::Catch:
12427 if (!emitCatch(&pn->as<BinaryNode>())) {
12428 return false;
12429 }
12430 break;
12431
12432 case ParseNodeKind::VarStmt:
12433 if (!emitDeclarationList(&pn->as<ListNode>())) {
12434 return false;
12435 }
12436 break;
12437
12438 case ParseNodeKind::ReturnStmt:
12439 if (!emitReturn(&pn->as<UnaryNode>())) {
12440 return false;
12441 }
12442 break;
12443
12444 case ParseNodeKind::YieldStarExpr:
12445 if (!emitYieldStar(pn->as<UnaryNode>().kid())) {
12446 return false;
12447 }
12448 break;
12449
12450 case ParseNodeKind::Generator:
12451 if (!emit1(JSOp::Generator)) {
12452 return false;
12453 }
12454 break;
12455
12456 case ParseNodeKind::InitialYield:
12457 if (!emitInitialYield(&pn->as<UnaryNode>())) {
12458 return false;
12459 }
12460 break;
12461
12462 case ParseNodeKind::YieldExpr:
12463 if (!emitYield(&pn->as<UnaryNode>())) {
12464 return false;
12465 }
12466 break;
12467
12468 case ParseNodeKind::AwaitExpr:
12469 if (!emitAwaitInInnermostScope(&pn->as<UnaryNode>())) {
12470 return false;
12471 }
12472 break;
12473
12474 case ParseNodeKind::StatementList:
12475 if (!emitStatementList(&pn->as<ListNode>())) {
12476 return false;
12477 }
12478 break;
12479
12480 case ParseNodeKind::EmptyStmt:
12481 break;
12482
12483 case ParseNodeKind::ExpressionStmt:
12484 if (!emitExpressionStatement(&pn->as<UnaryNode>())) {
12485 return false;
12486 }
12487 break;
12488
12489 case ParseNodeKind::LabelStmt:
12490 if (!emitLabeledStatement(&pn->as<LabeledStatement>())) {
12491 return false;
12492 }
12493 break;
12494
12495 case ParseNodeKind::CommaExpr:
12496 if (!emitSequenceExpr(&pn->as<ListNode>(), valueUsage)) {
12497 return false;
12498 }
12499 break;
12500
12501 case ParseNodeKind::InitExpr:
12502 case ParseNodeKind::AssignExpr:
12503 case ParseNodeKind::AddAssignExpr:
12504 case ParseNodeKind::SubAssignExpr:
12505 case ParseNodeKind::BitOrAssignExpr:
12506 case ParseNodeKind::BitXorAssignExpr:
12507 case ParseNodeKind::BitAndAssignExpr:
12508 case ParseNodeKind::LshAssignExpr:
12509 case ParseNodeKind::RshAssignExpr:
12510 case ParseNodeKind::UrshAssignExpr:
12511 case ParseNodeKind::MulAssignExpr:
12512 case ParseNodeKind::DivAssignExpr:
12513 case ParseNodeKind::ModAssignExpr:
12514 case ParseNodeKind::PowAssignExpr: {
12515 BinaryNode* assignNode = &pn->as<BinaryNode>();
12516 if (!emitAssignmentOrInit(assignNode->getKind(), assignNode->left(),
12517 assignNode->right())) {
12518 return false;
12519 }
12520 break;
12521 }
12522
12523 case ParseNodeKind::CoalesceAssignExpr:
12524 case ParseNodeKind::OrAssignExpr:
12525 case ParseNodeKind::AndAssignExpr:
12526 if (!emitShortCircuitAssignment(&pn->as<AssignmentNode>())) {
12527 return false;
12528 }
12529 break;
12530
12531 case ParseNodeKind::ConditionalExpr:
12532 if (!emitConditionalExpression(pn->as<ConditionalExpression>(),
12533 valueUsage)) {
12534 return false;
12535 }
12536 break;
12537
12538 case ParseNodeKind::OrExpr:
12539 case ParseNodeKind::CoalesceExpr:
12540 case ParseNodeKind::AndExpr:
12541 if (!emitShortCircuit(&pn->as<ListNode>(), valueUsage)) {
12542 return false;
12543 }
12544 break;
12545
12546 case ParseNodeKind::StrictEqExpr:
12547 case ParseNodeKind::EqExpr:
12548 case ParseNodeKind::StrictNeExpr:
12549 case ParseNodeKind::NeExpr: {
12550 bool emitted;
12551 if (!tryEmitTypeofEq(&pn->as<ListNode>(), &emitted)) {
12552 return false;
12553 }
12554 if (emitted) {
12555 return true;
12556 }
12557 }
12558 [[fallthrough]];
12559
12560 case ParseNodeKind::AddExpr:
12561 case ParseNodeKind::SubExpr:
12562 case ParseNodeKind::BitOrExpr:
12563 case ParseNodeKind::BitXorExpr:
12564 case ParseNodeKind::BitAndExpr:
12565 case ParseNodeKind::LtExpr:
12566 case ParseNodeKind::LeExpr:
12567 case ParseNodeKind::GtExpr:
12568 case ParseNodeKind::GeExpr:
12569 case ParseNodeKind::InExpr:
12570 case ParseNodeKind::InstanceOfExpr:
12571 case ParseNodeKind::LshExpr:
12572 case ParseNodeKind::RshExpr:
12573 case ParseNodeKind::UrshExpr:
12574 case ParseNodeKind::MulExpr:
12575 case ParseNodeKind::DivExpr:
12576 case ParseNodeKind::ModExpr:
12577 if (!emitLeftAssociative(&pn->as<ListNode>())) {
12578 return false;
12579 }
12580 break;
12581
12582 case ParseNodeKind::PrivateInExpr:
12583 if (!emitPrivateInExpr(&pn->as<ListNode>())) {
12584 return false;
12585 }
12586 break;
12587
12588 case ParseNodeKind::PowExpr:
12589 if (!emitRightAssociative(&pn->as<ListNode>())) {
12590 return false;
12591 }
12592 break;
12593
12594 case ParseNodeKind::TypeOfNameExpr:
12595 if (!emitTypeof(&pn->as<UnaryNode>(), JSOp::Typeof)) {
12596 return false;
12597 }
12598 break;
12599
12600 case ParseNodeKind::TypeOfExpr:
12601 if (!emitTypeof(&pn->as<UnaryNode>(), JSOp::TypeofExpr)) {
12602 return false;
12603 }
12604 break;
12605
12606 case ParseNodeKind::ThrowStmt:
12607 if (!updateSourceCoordNotes(pn->pn_pos.begin)) {
12608 return false;
12609 }
12610 if (!markStepBreakpoint()) {
12611 return false;
12612 }
12613 [[fallthrough]];
12614 case ParseNodeKind::VoidExpr:
12615 case ParseNodeKind::NotExpr:
12616 case ParseNodeKind::BitNotExpr:
12617 case ParseNodeKind::PosExpr:
12618 case ParseNodeKind::NegExpr:
12619 if (!emitUnary(&pn->as<UnaryNode>())) {
12620 return false;
12621 }
12622 break;
12623
12624 case ParseNodeKind::PreIncrementExpr:
12625 case ParseNodeKind::PreDecrementExpr:
12626 case ParseNodeKind::PostIncrementExpr:
12627 case ParseNodeKind::PostDecrementExpr:
12628 if (!emitIncOrDec(&pn->as<UnaryNode>(), valueUsage)) {
12629 return false;
12630 }
12631 break;
12632
12633 case ParseNodeKind::DeleteNameExpr:
12634 if (!emitDeleteName(&pn->as<UnaryNode>())) {
12635 return false;
12636 }
12637 break;
12638
12639 case ParseNodeKind::DeletePropExpr:
12640 if (!emitDeleteProperty(&pn->as<UnaryNode>())) {
12641 return false;
12642 }
12643 break;
12644
12645 case ParseNodeKind::DeleteElemExpr:
12646 if (!emitDeleteElement(&pn->as<UnaryNode>())) {
12647 return false;
12648 }
12649 break;
12650
12651 case ParseNodeKind::DeleteExpr:
12652 if (!emitDeleteExpression(&pn->as<UnaryNode>())) {
12653 return false;
12654 }
12655 break;
12656
12657 case ParseNodeKind::DeleteOptionalChainExpr:
12658 if (!emitDeleteOptionalChain(&pn->as<UnaryNode>())) {
12659 return false;
12660 }
12661 break;
12662
12663 case ParseNodeKind::OptionalChain:
12664 if (!emitOptionalChain(&pn->as<UnaryNode>(), valueUsage)) {
12665 return false;
12666 }
12667 break;
12668
12669 case ParseNodeKind::DotExpr: {
12670 PropertyAccess* prop = &pn->as<PropertyAccess>();
12671 bool isSuper = prop->isSuper();
12672 PropOpEmitter poe(this, PropOpEmitter::Kind::Get,
12673 isSuper ? PropOpEmitter::ObjKind::Super
12674 : PropOpEmitter::ObjKind::Other);
12675 if (!poe.prepareForObj()) {
12676 return false;
12677 }
12678 if (isSuper) {
12679 UnaryNode* base = &prop->expression().as<UnaryNode>();
12680 if (!emitGetThisForSuperBase(base)) {
12681 // [stack] THIS
12682 return false;
12683 }
12684 } else {
12685 if (!emitPropLHS(prop)) {
12686 // [stack] OBJ
12687 return false;
12688 }
12689 }
12690 if (!poe.emitGet(prop->key().atom())) {
12691 // [stack] PROP
12692 return false;
12693 }
12694 break;
12695 }
12696
12697 case ParseNodeKind::ArgumentsLength: {
12698 if (sc->isFunctionBox() &&
12699 sc->asFunctionBox()->isEligibleForArgumentsLength() &&
12700 !sc->asFunctionBox()->needsArgsObj()) {
12701 if (!emit1(JSOp::ArgumentsLength)) {
12702 return false;
12703 }
12704 } else {
12705 PropOpEmitter poe(this, PropOpEmitter::Kind::Get,
12706 PropOpEmitter::ObjKind::Other);
12707 if (!poe.prepareForObj()) {
12708 return false;
12709 }
12710
12711 NameOpEmitter noe(this, TaggedParserAtomIndex::WellKnown::arguments(),
12712 NameOpEmitter::Kind::Get);
12713 if (!noe.emitGet()) {
12714 return false;
12715 }
12716 if (!poe.emitGet(TaggedParserAtomIndex::WellKnown::length())) {
12717 return false;
12718 }
12719 }
12720 break;
12721 }
12722
12723 case ParseNodeKind::ElemExpr: {
12724 PropertyByValue* elem = &pn->as<PropertyByValue>();
12725 bool isSuper = elem->isSuper();
12726 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"
, 12726); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)"
")"); do { *((volatile int*)__null) = 12726; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12727 ElemOpEmitter eoe(this, ElemOpEmitter::Kind::Get,
12728 isSuper ? ElemOpEmitter::ObjKind::Super
12729 : ElemOpEmitter::ObjKind::Other);
12730 if (!emitElemObjAndKey(elem, isSuper, eoe)) {
12731 // [stack] # if Super
12732 // [stack] THIS KEY
12733 // [stack] # otherwise
12734 // [stack] OBJ KEY
12735 return false;
12736 }
12737 if (!eoe.emitGet()) {
12738 // [stack] ELEM
12739 return false;
12740 }
12741
12742 break;
12743 }
12744
12745 case ParseNodeKind::PrivateMemberExpr: {
12746 PrivateMemberAccess* privateExpr = &pn->as<PrivateMemberAccess>();
12747 PrivateOpEmitter xoe(this, PrivateOpEmitter::Kind::Get,
12748 privateExpr->privateName().name());
12749 if (!emitTree(&privateExpr->expression())) {
12750 // [stack] OBJ
12751 return false;
12752 }
12753 if (!xoe.emitReference()) {
12754 // [stack] OBJ NAME
12755 return false;
12756 }
12757 if (!xoe.emitGet()) {
12758 // [stack] VALUE
12759 return false;
12760 }
12761
12762 break;
12763 }
12764
12765 case ParseNodeKind::NewExpr:
12766 case ParseNodeKind::TaggedTemplateExpr:
12767 case ParseNodeKind::CallExpr:
12768 case ParseNodeKind::SuperCallExpr:
12769 if (!emitCallOrNew(&pn->as<CallNode>(), valueUsage)) {
12770 return false;
12771 }
12772 break;
12773
12774 case ParseNodeKind::LexicalScope:
12775 if (!emitLexicalScope(&pn->as<LexicalScopeNode>())) {
12776 return false;
12777 }
12778 break;
12779
12780 case ParseNodeKind::ConstDecl:
12781 case ParseNodeKind::LetDecl:
12782 if (!emitDeclarationList(&pn->as<ListNode>())) {
12783 return false;
12784 }
12785 break;
12786#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
12787 case ParseNodeKind::UsingDecl:
12788 if (!emitDeclarationList(&pn->as<ListNode>())) {
12789 return false;
12790 }
12791 break;
12792#endif
12793
12794 case ParseNodeKind::ImportDecl:
12795 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"
, 12795); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isModuleContext()"
")"); do { *((volatile int*)__null) = 12795; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12796 break;
12797
12798 case ParseNodeKind::ExportStmt: {
12799 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"
, 12799); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isModuleContext()"
")"); do { *((volatile int*)__null) = 12799; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12800 UnaryNode* node = &pn->as<UnaryNode>();
12801 ParseNode* decl = node->kid();
12802 if (decl->getKind() != ParseNodeKind::ExportSpecList) {
12803 if (!emitTree(decl)) {
12804 return false;
12805 }
12806 }
12807 break;
12808 }
12809
12810 case ParseNodeKind::ExportDefaultStmt:
12811 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"
, 12811); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isModuleContext()"
")"); do { *((volatile int*)__null) = 12811; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12812 if (!emitExportDefault(&pn->as<BinaryNode>())) {
12813 return false;
12814 }
12815 break;
12816
12817 case ParseNodeKind::ExportFromStmt:
12818 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"
, 12818); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isModuleContext()"
")"); do { *((volatile int*)__null) = 12818; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12819 break;
12820
12821 case ParseNodeKind::CallSiteObj:
12822 if (!emitCallSiteObject(&pn->as<CallSiteNode>())) {
12823 return false;
12824 }
12825 break;
12826
12827 case ParseNodeKind::ArrayExpr:
12828 if (!emitArrayLiteral(&pn->as<ListNode>())) {
12829 return false;
12830 }
12831 break;
12832
12833 case ParseNodeKind::ObjectExpr:
12834 if (!emitObject(&pn->as<ListNode>())) {
12835 return false;
12836 }
12837 break;
12838
12839 case ParseNodeKind::Name:
12840 if (!emitGetName(&pn->as<NameNode>())) {
12841 return false;
12842 }
12843 break;
12844
12845 case ParseNodeKind::PrivateName:
12846 if (!emitGetPrivateName(&pn->as<NameNode>())) {
12847 return false;
12848 }
12849 break;
12850
12851 case ParseNodeKind::TemplateStringListExpr:
12852 if (!emitTemplateString(&pn->as<ListNode>())) {
12853 return false;
12854 }
12855 break;
12856
12857 case ParseNodeKind::TemplateStringExpr:
12858 case ParseNodeKind::StringExpr:
12859 if (!emitStringOp(JSOp::String, pn->as<NameNode>().atom())) {
12860 return false;
12861 }
12862 break;
12863
12864 case ParseNodeKind::NumberExpr:
12865 if (!emitNumberOp(pn->as<NumericLiteral>().value())) {
12866 return false;
12867 }
12868 break;
12869
12870 case ParseNodeKind::BigIntExpr:
12871 if (!emitBigIntOp(&pn->as<BigIntLiteral>())) {
12872 return false;
12873 }
12874 break;
12875
12876 case ParseNodeKind::RegExpExpr: {
12877 GCThingIndex index;
12878 if (!perScriptData().gcThingList().append(&pn->as<RegExpLiteral>(),
12879 &index)) {
12880 return false;
12881 }
12882 if (!emitRegExp(index)) {
12883 return false;
12884 }
12885 break;
12886 }
12887
12888 case ParseNodeKind::TrueExpr:
12889 if (!emit1(JSOp::True)) {
12890 return false;
12891 }
12892 break;
12893 case ParseNodeKind::FalseExpr:
12894 if (!emit1(JSOp::False)) {
12895 return false;
12896 }
12897 break;
12898 case ParseNodeKind::NullExpr:
12899 if (!emit1(JSOp::Null)) {
12900 return false;
12901 }
12902 break;
12903 case ParseNodeKind::RawUndefinedExpr:
12904 if (!emit1(JSOp::Undefined)) {
12905 return false;
12906 }
12907 break;
12908
12909 case ParseNodeKind::ThisExpr:
12910 if (!emitThisLiteral(&pn->as<ThisLiteral>())) {
12911 return false;
12912 }
12913 break;
12914
12915 case ParseNodeKind::DebuggerStmt:
12916 if (!updateSourceCoordNotes(pn->pn_pos.begin)) {
12917 return false;
12918 }
12919 if (!markStepBreakpoint()) {
12920 return false;
12921 }
12922 if (!emit1(JSOp::Debugger)) {
12923 return false;
12924 }
12925 break;
12926
12927 case ParseNodeKind::ClassDecl:
12928 if (!emitClass(&pn->as<ClassNode>())) {
12929 return false;
12930 }
12931 break;
12932
12933 case ParseNodeKind::NewTargetExpr:
12934 if (!emitNewTarget(&pn->as<NewTargetNode>())) {
12935 return false;
12936 }
12937 break;
12938
12939 case ParseNodeKind::ImportMetaExpr:
12940 if (!emit1(JSOp::ImportMeta)) {
12941 return false;
12942 }
12943 break;
12944
12945 case ParseNodeKind::CallImportExpr: {
12946 BinaryNode* spec = &pn->as<BinaryNode>().right()->as<BinaryNode>();
12947
12948 if (!emitTree(spec->left())) {
12949 // [stack] specifier
12950 return false;
12951 }
12952
12953 if (!spec->right()->isKind(ParseNodeKind::PosHolder)) {
12954 // [stack] specifier options
12955 if (!emitTree(spec->right())) {
12956 return false;
12957 }
12958 } else {
12959 // [stack] specifier undefined
12960 if (!emit1(JSOp::Undefined)) {
12961 return false;
12962 }
12963 }
12964
12965 if (!emit1(JSOp::DynamicImport)) {
12966 return false;
12967 }
12968
12969 break;
12970 }
12971
12972 case ParseNodeKind::SetThis:
12973 if (!emitSetThis(&pn->as<BinaryNode>())) {
12974 return false;
12975 }
12976 break;
12977
12978#ifdef ENABLE_RECORD_TUPLE
12979 case ParseNodeKind::RecordExpr:
12980 if (!emitRecordLiteral(&pn->as<ListNode>())) {
12981 return false;
12982 }
12983 break;
12984
12985 case ParseNodeKind::TupleExpr:
12986 if (!emitTupleLiteral(&pn->as<ListNode>())) {
12987 return false;
12988 }
12989 break;
12990#endif
12991
12992 case ParseNodeKind::PropertyNameExpr:
12993 case ParseNodeKind::PosHolder:
12994 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"
, 12995); AnnotateMozCrashReason("MOZ_CRASH(" "MOZ_FALLTHROUGH_ASSERT: "
"Should never try to emit ParseNodeKind::PosHolder or ::Property"
")"); do { *((volatile int*)__null) = 12995; __attribute__((
nomerge)) ::abort(); } while (false); } while (false)
12995 "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"
, 12995); AnnotateMozCrashReason("MOZ_CRASH(" "MOZ_FALLTHROUGH_ASSERT: "
"Should never try to emit ParseNodeKind::PosHolder or ::Property"
")"); do { *((volatile int*)__null) = 12995; __attribute__((
nomerge)) ::abort(); } while (false); } while (false)
;
12996
12997 default:
12998 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"
, 12998); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0" ")"); do
{ *((volatile int*)__null) = 12998; __attribute__((nomerge))
::abort(); } while (false); } } while (false)
;
12999 }
13000
13001 return true;
13002}
13003
13004static bool AllocSrcNote(FrontendContext* fc, SrcNotesVector& notes,
13005 unsigned size, unsigned* index) {
13006 size_t oldLength = notes.length();
13007
13008 if (MOZ_UNLIKELY(oldLength + size > MaxSrcNotesLength)(__builtin_expect(!!(oldLength + size > MaxSrcNotesLength)
, 0))
) {
13009 ReportAllocationOverflow(fc);
13010 return false;
13011 }
13012
13013 if (!notes.growByUninitialized(size)) {
13014 return false;
13015 }
13016
13017 *index = oldLength;
13018 return true;
13019}
13020
13021bool BytecodeEmitter::addTryNote(TryNoteKind kind, uint32_t stackDepth,
13022 BytecodeOffset start, BytecodeOffset end) {
13023 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"
, 13023); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inPrologue()"
")"); do { *((volatile int*)__null) = 13023; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13024 return bytecodeSection().tryNoteList().append(kind, stackDepth, start, end);
13025}
13026
13027bool BytecodeEmitter::newSrcNote(SrcNoteType type, unsigned* indexp) {
13028 SrcNotesVector& notes = bytecodeSection().notes();
13029 unsigned index;
13030
13031 /*
13032 * Compute delta from the last annotated bytecode's offset. If it's too
13033 * big to fit in sn, allocate one or more xdelta notes and reset sn.
13034 */
13035 BytecodeOffset offset = bytecodeSection().offset();
13036 ptrdiff_t delta = (offset - bytecodeSection().lastNoteOffset()).value();
13037 bytecodeSection().setLastNoteOffset(offset);
13038
13039 auto allocator = [&](unsigned size) -> SrcNote* {
13040 if (!AllocSrcNote(fc, notes, size, &index)) {
13041 return nullptr;
13042 }
13043 return &notes[index];
13044 };
13045
13046 if (!SrcNoteWriter::writeNote(type, delta, allocator)) {
13047 return false;
13048 }
13049
13050 if (indexp) {
13051 *indexp = index;
13052 }
13053
13054 if (type == SrcNoteType::NewLine || type == SrcNoteType::SetLine) {
13055 lastLineOnlySrcNoteIndex = index;
13056 } else {
13057 lastLineOnlySrcNoteIndex = LastSrcNoteIsNotLineOnly;
13058 }
13059
13060 return true;
13061}
13062
13063bool BytecodeEmitter::newSrcNote2(SrcNoteType type, ptrdiff_t offset,
13064 unsigned* indexp) {
13065 unsigned index;
13066 if (!newSrcNote(type, &index)) {
13067 return false;
13068 }
13069 if (!newSrcNoteOperand(offset)) {
13070 return false;
13071 }
13072 if (indexp) {
13073 *indexp = index;
13074 }
13075 return true;
13076}
13077
13078bool BytecodeEmitter::convertLastNewLineToNewLineColumn(
13079 JS::LimitedColumnNumberOneOrigin column) {
13080 SrcNotesVector& notes = bytecodeSection().notes();
13081 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"
, 13081); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lastLineOnlySrcNoteIndex == notes.length() - 1"
")"); do { *((volatile int*)__null) = 13081; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13082 SrcNote* sn = &notes[lastLineOnlySrcNoteIndex];
13083 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"
, 13083); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sn->type() == SrcNoteType::NewLine"
")"); do { *((volatile int*)__null) = 13083; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13084
13085 SrcNoteWriter::convertNote(sn, SrcNoteType::NewLineColumn);
13086 if (!newSrcNoteOperand(SrcNote::NewLineColumn::toOperand(column))) {
13087 return false;
13088 }
13089
13090 lastLineOnlySrcNoteIndex = LastSrcNoteIsNotLineOnly;
13091 return true;
13092}
13093
13094bool BytecodeEmitter::convertLastSetLineToSetLineColumn(
13095 JS::LimitedColumnNumberOneOrigin column) {
13096 SrcNotesVector& notes = bytecodeSection().notes();
13097 // The Line operand is either 1 byte or 4 bytes.
13098 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"
, 13099); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lastLineOnlySrcNoteIndex == notes.length() - 1 - 1 || lastLineOnlySrcNoteIndex == notes.length() - 1 - 4"
")"); do { *((volatile int*)__null) = 13099; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
13099 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"
, 13099); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lastLineOnlySrcNoteIndex == notes.length() - 1 - 1 || lastLineOnlySrcNoteIndex == notes.length() - 1 - 4"
")"); do { *((volatile int*)__null) = 13099; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13100 SrcNote* sn = &notes[lastLineOnlySrcNoteIndex];
13101 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"
, 13101); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sn->type() == SrcNoteType::SetLine"
")"); do { *((volatile int*)__null) = 13101; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13102
13103 SrcNoteWriter::convertNote(sn, SrcNoteType::SetLineColumn);
13104 if (!newSrcNoteOperand(SrcNote::SetLineColumn::columnToOperand(column))) {
13105 return false;
13106 }
13107
13108 lastLineOnlySrcNoteIndex = LastSrcNoteIsNotLineOnly;
13109 return true;
13110}
13111
13112bool BytecodeEmitter::newSrcNoteOperand(ptrdiff_t operand) {
13113 if (!SrcNote::isRepresentableOperand(operand)) {
13114 reportError(nullptr, JSMSG_NEED_DIET, "script");
13115 return false;
13116 }
13117
13118 SrcNotesVector& notes = bytecodeSection().notes();
13119
13120 auto allocator = [&](unsigned size) -> SrcNote* {
13121 unsigned index;
13122 if (!AllocSrcNote(fc, notes, size, &index)) {
13123 return nullptr;
13124 }
13125 return &notes[index];
13126 };
13127
13128 return SrcNoteWriter::writeOperand(operand, allocator);
13129}
13130
13131bool BytecodeEmitter::intoScriptStencil(ScriptIndex scriptIndex) {
13132 js::UniquePtr<ImmutableScriptData> immutableScriptData =
13133 createImmutableScriptData();
13134 if (!immutableScriptData) {
13135 return false;
13136 }
13137
13138 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"
, 13139); AnnotateMozCrashReason("MOZ_ASSERT" "(" "outermostScope().hasNonSyntacticScopeOnChain() == sc->hasNonSyntacticScope()"
")"); do { *((volatile int*)__null) = 13139; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
13139 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"
, 13139); AnnotateMozCrashReason("MOZ_ASSERT" "(" "outermostScope().hasNonSyntacticScopeOnChain() == sc->hasNonSyntacticScope()"
")"); do { *((volatile int*)__null) = 13139; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13140
13141 auto& things = perScriptData().gcThingList().objects();
13142 if (!compilationState.appendGCThings(fc, scriptIndex, things)) {
13143 return false;
13144 }
13145
13146 // Hand over the ImmutableScriptData instance generated by BCE.
13147 auto* sharedData =
13148 SharedImmutableScriptData::createWith(fc, std::move(immutableScriptData));
13149 if (!sharedData) {
13150 return false;
13151 }
13152
13153 // De-duplicate the bytecode within the runtime.
13154 if (!compilationState.sharedData.addAndShare(fc, scriptIndex, sharedData)) {
13155 return false;
13156 }
13157
13158 ScriptStencil& script = compilationState.scriptData[scriptIndex];
13159 script.setHasSharedData();
13160
13161 // Update flags specific to functions.
13162 if (sc->isFunctionBox()) {
13163 FunctionBox* funbox = sc->asFunctionBox();
13164 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"
, 13164); AnnotateMozCrashReason("MOZ_ASSERT" "(" "&script == &funbox->functionStencil()"
")"); do { *((volatile int*)__null) = 13164; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13165 funbox->copyUpdatedImmutableFlags();
13166 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"
, 13166); AnnotateMozCrashReason("MOZ_ASSERT" "(" "script.isFunction()"
")"); do { *((volatile int*)__null) = 13166; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13167 } else {
13168 ScriptStencilExtra& scriptExtra = compilationState.scriptExtra[scriptIndex];
13169 sc->copyScriptExtraFields(scriptExtra);
13170 }
13171
13172 return true;
13173}
13174
13175SelfHostedIter BytecodeEmitter::getSelfHostedIterFor(ParseNode* parseNode) {
13176 if (emitterMode == BytecodeEmitter::SelfHosting &&
13177 parseNode->isKind(ParseNodeKind::CallExpr)) {
13178 auto* callee = parseNode->as<CallNode>().callee();
13179 if (callee->isName(TaggedParserAtomIndex::WellKnown::allowContentIter())) {
13180 return SelfHostedIter::AllowContent;
13181 }
13182 if (callee->isName(
13183 TaggedParserAtomIndex::WellKnown::allowContentIterWith())) {
13184 return SelfHostedIter::AllowContentWith;
13185 }
13186 if (callee->isName(
13187 TaggedParserAtomIndex::WellKnown::allowContentIterWithNext())) {
13188 return SelfHostedIter::AllowContentWithNext;
13189 }
13190 }
13191
13192 return SelfHostedIter::Deny;
13193}
13194
13195#if defined(DEBUG1) || defined(JS_JITSPEW1)
13196void BytecodeEmitter::dumpAtom(TaggedParserAtomIndex index) const {
13197 parserAtoms().dump(index);
13198}
13199#endif