File: | var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp |
Warning: | line 821, column 3 Value stored to 'pc' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- |
2 | * vim: set ts=8 sts=2 et sw=2 tw=80: |
3 | * This Source Code Form is subject to the terms of the Mozilla Public |
4 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
6 | |
7 | /* |
8 | * JS bytecode generation. |
9 | */ |
10 | |
11 | #include "frontend/BytecodeEmitter.h" |
12 | |
13 | #include "mozilla/Casting.h" // mozilla::AssertedCast |
14 | #include "mozilla/DebugOnly.h" // mozilla::DebugOnly |
15 | #include "mozilla/FloatingPoint.h" // mozilla::NumberEqualsInt32, mozilla::NumberIsInt32 |
16 | #include "mozilla/HashTable.h" // mozilla::HashSet |
17 | #include "mozilla/Maybe.h" // mozilla::{Maybe,Nothing,Some} |
18 | #include "mozilla/Saturate.h" |
19 | #include "mozilla/Variant.h" // mozilla::AsVariant |
20 | |
21 | #include <algorithm> |
22 | #include <iterator> |
23 | #include <string.h> |
24 | |
25 | #include "jstypes.h" // JS_BIT |
26 | |
27 | #include "frontend/AbstractScopePtr.h" // ScopeIndex |
28 | #include "frontend/BytecodeControlStructures.h" // NestableControl, BreakableControl, LabelControl, LoopControl, TryFinallyControl |
29 | #include "frontend/CallOrNewEmitter.h" // CallOrNewEmitter |
30 | #include "frontend/CForEmitter.h" // CForEmitter |
31 | #include "frontend/DecoratorEmitter.h" // DecoratorEmitter |
32 | #include "frontend/DefaultEmitter.h" // DefaultEmitter |
33 | #include "frontend/DoWhileEmitter.h" // DoWhileEmitter |
34 | #include "frontend/ElemOpEmitter.h" // ElemOpEmitter |
35 | #include "frontend/EmitterScope.h" // EmitterScope |
36 | #include "frontend/ExpressionStatementEmitter.h" // ExpressionStatementEmitter |
37 | #include "frontend/ForInEmitter.h" // ForInEmitter |
38 | #include "frontend/ForOfEmitter.h" // ForOfEmitter |
39 | #include "frontend/FunctionEmitter.h" // FunctionEmitter, FunctionScriptEmitter, FunctionParamsEmitter |
40 | #include "frontend/IfEmitter.h" // IfEmitter, InternalIfEmitter, CondEmitter |
41 | #include "frontend/LabelEmitter.h" // LabelEmitter |
42 | #include "frontend/LexicalScopeEmitter.h" // LexicalScopeEmitter |
43 | #include "frontend/ModuleSharedContext.h" // ModuleSharedContext |
44 | #include "frontend/NameAnalysisTypes.h" // PrivateNameKind |
45 | #include "frontend/NameFunctions.h" // NameFunctions |
46 | #include "frontend/NameOpEmitter.h" // NameOpEmitter |
47 | #include "frontend/ObjectEmitter.h" // PropertyEmitter, ObjectEmitter, ClassEmitter |
48 | #include "frontend/OptionalEmitter.h" // OptionalEmitter |
49 | #include "frontend/ParseContext.h" // ParseContext::Scope |
50 | #include "frontend/ParseNode.h" // ParseNodeKind, ParseNode and subclasses |
51 | #include "frontend/Parser.h" // Parser |
52 | #include "frontend/ParserAtom.h" // ParserAtomsTable, ParserAtom |
53 | #include "frontend/PrivateOpEmitter.h" // PrivateOpEmitter |
54 | #include "frontend/PropOpEmitter.h" // PropOpEmitter |
55 | #include "frontend/SourceNotes.h" // SrcNote, SrcNoteType, SrcNoteWriter |
56 | #include "frontend/SwitchEmitter.h" // SwitchEmitter |
57 | #include "frontend/TaggedParserAtomIndexHasher.h" // TaggedParserAtomIndexHasher |
58 | #include "frontend/TDZCheckCache.h" // TDZCheckCache |
59 | #include "frontend/TryEmitter.h" // TryEmitter |
60 | #include "frontend/UsingEmitter.h" // UsingEmitter |
61 | #include "frontend/WhileEmitter.h" // WhileEmitter |
62 | #include "js/ColumnNumber.h" // JS::LimitedColumnNumberOneOrigin, JS::ColumnNumberOffset |
63 | #include "js/friend/ErrorMessages.h" // JSMSG_* |
64 | #include "js/friend/StackLimits.h" // AutoCheckRecursionLimit |
65 | #include "util/StringBuilder.h" // StringBuilder |
66 | #include "vm/BytecodeUtil.h" // JOF_*, IsArgOp, IsLocalOp, SET_UINT24, SET_ICINDEX, BytecodeFallsThrough, BytecodeIsJumpTarget |
67 | #include "vm/CompletionKind.h" // CompletionKind |
68 | #include "vm/FunctionPrefixKind.h" // FunctionPrefixKind |
69 | #include "vm/GeneratorObject.h" // AbstractGeneratorObject |
70 | #include "vm/Opcodes.h" // JSOp, JSOpLength_* |
71 | #include "vm/PropMap.h" // SharedPropMap::MaxPropsForNonDictionary |
72 | #include "vm/Scope.h" // GetScopeDataTrailingNames |
73 | #include "vm/SharedStencil.h" // ScopeNote |
74 | #include "vm/ThrowMsgKind.h" // ThrowMsgKind |
75 | #include "vm/TypeofEqOperand.h" // TypeofEqOperand |
76 | |
77 | using namespace js; |
78 | using namespace js::frontend; |
79 | |
80 | using mozilla::AssertedCast; |
81 | using mozilla::AsVariant; |
82 | using mozilla::DebugOnly; |
83 | using mozilla::Maybe; |
84 | using mozilla::Nothing; |
85 | using mozilla::NumberEqualsInt32; |
86 | using mozilla::NumberIsInt32; |
87 | using mozilla::Some; |
88 | |
89 | static bool ParseNodeRequiresSpecialLineNumberNotes(ParseNode* pn) { |
90 | // The few node types listed below are exceptions to the usual |
91 | // location-source-note-emitting code in BytecodeEmitter::emitTree(). |
92 | // Single-line `while` loops and C-style `for` loops require careful |
93 | // handling to avoid strange stepping behavior. |
94 | // Functions usually shouldn't have location information (bug 1431202). |
95 | |
96 | ParseNodeKind kind = pn->getKind(); |
97 | return kind == ParseNodeKind::WhileStmt || kind == ParseNodeKind::ForStmt || |
98 | kind == ParseNodeKind::Function; |
99 | } |
100 | |
101 | static bool NeedsFieldInitializer(ParseNode* member, bool inStaticContext) { |
102 | // For the purposes of bytecode emission, StaticClassBlocks are treated as if |
103 | // they were static initializers. |
104 | return (member->is<StaticClassBlock>() && inStaticContext) || |
105 | (member->is<ClassField>() && |
106 | member->as<ClassField>().isStatic() == inStaticContext); |
107 | } |
108 | |
109 | static bool NeedsAccessorInitializer(ParseNode* member, bool isStatic) { |
110 | if (isStatic) { |
111 | return false; |
112 | } |
113 | return member->is<ClassMethod>() && |
114 | member->as<ClassMethod>().name().isKind(ParseNodeKind::PrivateName) && |
115 | !member->as<ClassMethod>().isStatic() && |
116 | member->as<ClassMethod>().accessorType() != AccessorType::None; |
117 | } |
118 | |
119 | static bool ShouldSuppressBreakpointsAndSourceNotes( |
120 | SharedContext* sc, BytecodeEmitter::EmitterMode emitterMode) { |
121 | // Suppress for all self-hosting code. |
122 | if (emitterMode == BytecodeEmitter::EmitterMode::SelfHosting) { |
123 | return true; |
124 | } |
125 | |
126 | // Suppress for synthesized class constructors. |
127 | if (sc->isFunctionBox()) { |
128 | FunctionBox* funbox = sc->asFunctionBox(); |
129 | return funbox->isSyntheticFunction() && funbox->isClassConstructor(); |
130 | } |
131 | |
132 | return false; |
133 | } |
134 | |
135 | BytecodeEmitter::BytecodeEmitter(BytecodeEmitter* parent, FrontendContext* fc, |
136 | SharedContext* sc, |
137 | const ErrorReporter& errorReporter, |
138 | CompilationState& compilationState, |
139 | EmitterMode emitterMode) |
140 | : sc(sc), |
141 | fc(fc), |
142 | parent(parent), |
143 | bytecodeSection_(fc, sc->extent().lineno, |
144 | JS::LimitedColumnNumberOneOrigin(sc->extent().column)), |
145 | perScriptData_(fc, compilationState), |
146 | errorReporter_(errorReporter), |
147 | compilationState(compilationState), |
148 | suppressBreakpointsAndSourceNotes( |
149 | ShouldSuppressBreakpointsAndSourceNotes(sc, emitterMode)), |
150 | emitterMode(emitterMode) { |
151 | MOZ_ASSERT_IF(parent, fc == parent->fc)do { if (parent) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(fc == parent->fc)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(fc == parent->fc))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("fc == parent->fc" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 151); AnnotateMozCrashReason("MOZ_ASSERT" "(" "fc == parent->fc" ")"); do { *((volatile int*)__null) = 151; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
152 | } |
153 | |
154 | BytecodeEmitter::BytecodeEmitter(BytecodeEmitter* parent, SharedContext* sc) |
155 | : BytecodeEmitter(parent, parent->fc, sc, parent->errorReporter_, |
156 | parent->compilationState, parent->emitterMode) {} |
157 | |
158 | BytecodeEmitter::BytecodeEmitter(FrontendContext* fc, |
159 | const EitherParser& parser, SharedContext* sc, |
160 | CompilationState& compilationState, |
161 | EmitterMode emitterMode) |
162 | : BytecodeEmitter(nullptr, fc, sc, parser.errorReporter(), compilationState, |
163 | emitterMode) { |
164 | ep_.emplace(parser); |
165 | } |
166 | |
167 | void BytecodeEmitter::initFromBodyPosition(TokenPos bodyPosition) { |
168 | setScriptStartOffsetIfUnset(bodyPosition.begin); |
169 | setFunctionBodyEndPos(bodyPosition.end); |
170 | } |
171 | |
172 | bool BytecodeEmitter::init() { |
173 | if (!parent) { |
174 | if (!compilationState.prepareSharedDataStorage(fc)) { |
175 | return false; |
176 | } |
177 | } |
178 | return perScriptData_.init(fc); |
179 | } |
180 | |
181 | bool BytecodeEmitter::init(TokenPos bodyPosition) { |
182 | initFromBodyPosition(bodyPosition); |
183 | return init(); |
184 | } |
185 | |
186 | template <typename T> |
187 | T* BytecodeEmitter::findInnermostNestableControl() const { |
188 | return NestableControl::findNearest<T>(innermostNestableControl); |
189 | } |
190 | |
191 | template <typename T, typename Predicate /* (T*) -> bool */> |
192 | T* BytecodeEmitter::findInnermostNestableControl(Predicate predicate) const { |
193 | return NestableControl::findNearest<T>(innermostNestableControl, predicate); |
194 | } |
195 | |
196 | NameLocation BytecodeEmitter::lookupName(TaggedParserAtomIndex name) { |
197 | return innermostEmitterScope()->lookup(this, name); |
198 | } |
199 | |
200 | void BytecodeEmitter::lookupPrivate(TaggedParserAtomIndex name, |
201 | NameLocation& loc, |
202 | Maybe<NameLocation>& brandLoc) { |
203 | innermostEmitterScope()->lookupPrivate(this, name, loc, brandLoc); |
204 | } |
205 | |
206 | Maybe<NameLocation> BytecodeEmitter::locationOfNameBoundInScope( |
207 | TaggedParserAtomIndex name, EmitterScope* target) { |
208 | return innermostEmitterScope()->locationBoundInScope(name, target); |
209 | } |
210 | |
211 | template <typename T> |
212 | Maybe<NameLocation> BytecodeEmitter::locationOfNameBoundInScopeType( |
213 | TaggedParserAtomIndex name, EmitterScope* source) { |
214 | EmitterScope* aScope = source; |
215 | while (!aScope->scope(this).is<T>()) { |
216 | aScope = aScope->enclosingInFrame(); |
217 | } |
218 | return source->locationBoundInScope(name, aScope); |
219 | } |
220 | |
221 | bool BytecodeEmitter::markStepBreakpoint() { |
222 | if (skipBreakpointSrcNotes()) { |
223 | return true; |
224 | } |
225 | |
226 | if (!newSrcNote(SrcNoteType::BreakpointStepSep)) { |
227 | return false; |
228 | } |
229 | |
230 | // We track the location of the most recent separator for use in |
231 | // markSimpleBreakpoint. Note that this means that the position must already |
232 | // be set before markStepBreakpoint is called. |
233 | bytecodeSection().updateSeparatorPosition(); |
234 | |
235 | return true; |
236 | } |
237 | |
238 | bool BytecodeEmitter::markSimpleBreakpoint() { |
239 | if (skipBreakpointSrcNotes()) { |
240 | return true; |
241 | } |
242 | |
243 | // If a breakable call ends up being the same location as the most recent |
244 | // expression start, we need to skip marking it breakable in order to avoid |
245 | // having two breakpoints with the same line/column position. |
246 | // Note: This assumes that the position for the call has already been set. |
247 | if (!bytecodeSection().isDuplicateLocation()) { |
248 | if (!newSrcNote(SrcNoteType::Breakpoint)) { |
249 | return false; |
250 | } |
251 | } |
252 | |
253 | return true; |
254 | } |
255 | |
256 | bool BytecodeEmitter::emitCheck(JSOp op, ptrdiff_t delta, |
257 | BytecodeOffset* offset) { |
258 | size_t oldLength = bytecodeSection().code().length(); |
259 | *offset = BytecodeOffset(oldLength); |
260 | |
261 | size_t newLength = oldLength + size_t(delta); |
262 | if (MOZ_UNLIKELY(newLength > MaxBytecodeLength)(__builtin_expect(!!(newLength > MaxBytecodeLength), 0))) { |
263 | ReportAllocationOverflow(fc); |
264 | return false; |
265 | } |
266 | |
267 | if (!bytecodeSection().code().growByUninitialized(delta)) { |
268 | return false; |
269 | } |
270 | |
271 | if (BytecodeOpHasIC(op)) { |
272 | // Even if every bytecode op is a JOF_IC op and the function has ARGC_LIMIT |
273 | // arguments, numICEntries cannot overflow. |
274 | static_assert(MaxBytecodeLength + 1 /* this */ + ARGC_LIMIT <= UINT32_MAX(4294967295U), |
275 | "numICEntries must not overflow"); |
276 | bytecodeSection().incrementNumICEntries(); |
277 | } |
278 | |
279 | return true; |
280 | } |
281 | |
282 | #ifdef DEBUG1 |
283 | bool BytecodeEmitter::checkStrictOrSloppy(JSOp op) const { |
284 | if (IsCheckStrictOp(op) && !sc->strict()) { |
285 | return false; |
286 | } |
287 | if (IsCheckSloppyOp(op) && sc->strict()) { |
288 | return false; |
289 | } |
290 | return true; |
291 | } |
292 | #endif |
293 | |
294 | bool BytecodeEmitter::emit1(JSOp op) { |
295 | MOZ_ASSERT(checkStrictOrSloppy(op))do { static_assert( mozilla::detail::AssertionConditionType< decltype(checkStrictOrSloppy(op))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(checkStrictOrSloppy(op)))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("checkStrictOrSloppy(op)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 295); AnnotateMozCrashReason("MOZ_ASSERT" "(" "checkStrictOrSloppy(op)" ")"); do { *((volatile int*)__null) = 295; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
296 | |
297 | BytecodeOffset offset; |
298 | if (!emitCheck(op, 1, &offset)) { |
299 | return false; |
300 | } |
301 | |
302 | jsbytecode* code = bytecodeSection().code(offset); |
303 | code[0] = jsbytecode(op); |
304 | bytecodeSection().updateDepth(op, offset); |
305 | return true; |
306 | } |
307 | |
308 | bool BytecodeEmitter::emit2(JSOp op, uint8_t op1) { |
309 | MOZ_ASSERT(checkStrictOrSloppy(op))do { static_assert( mozilla::detail::AssertionConditionType< decltype(checkStrictOrSloppy(op))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(checkStrictOrSloppy(op)))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("checkStrictOrSloppy(op)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 309); AnnotateMozCrashReason("MOZ_ASSERT" "(" "checkStrictOrSloppy(op)" ")"); do { *((volatile int*)__null) = 309; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
310 | |
311 | BytecodeOffset offset; |
312 | if (!emitCheck(op, 2, &offset)) { |
313 | return false; |
314 | } |
315 | |
316 | jsbytecode* code = bytecodeSection().code(offset); |
317 | code[0] = jsbytecode(op); |
318 | code[1] = jsbytecode(op1); |
319 | bytecodeSection().updateDepth(op, offset); |
320 | return true; |
321 | } |
322 | |
323 | bool BytecodeEmitter::emit3(JSOp op, jsbytecode op1, jsbytecode op2) { |
324 | MOZ_ASSERT(checkStrictOrSloppy(op))do { static_assert( mozilla::detail::AssertionConditionType< decltype(checkStrictOrSloppy(op))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(checkStrictOrSloppy(op)))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("checkStrictOrSloppy(op)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 324); AnnotateMozCrashReason("MOZ_ASSERT" "(" "checkStrictOrSloppy(op)" ")"); do { *((volatile int*)__null) = 324; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
325 | |
326 | /* These should filter through emitVarOp. */ |
327 | MOZ_ASSERT(!IsArgOp(op))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!IsArgOp(op))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!IsArgOp(op)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!IsArgOp(op)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 327); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsArgOp(op)" ")"); do { *((volatile int*)__null) = 327; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
328 | MOZ_ASSERT(!IsLocalOp(op))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!IsLocalOp(op))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!IsLocalOp(op)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!IsLocalOp(op)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 328); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsLocalOp(op)" ")"); do { *((volatile int*)__null) = 328; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
329 | |
330 | BytecodeOffset offset; |
331 | if (!emitCheck(op, 3, &offset)) { |
332 | return false; |
333 | } |
334 | |
335 | jsbytecode* code = bytecodeSection().code(offset); |
336 | code[0] = jsbytecode(op); |
337 | code[1] = op1; |
338 | code[2] = op2; |
339 | bytecodeSection().updateDepth(op, offset); |
340 | return true; |
341 | } |
342 | |
343 | bool BytecodeEmitter::emitN(JSOp op, size_t extra, BytecodeOffset* offset) { |
344 | MOZ_ASSERT(checkStrictOrSloppy(op))do { static_assert( mozilla::detail::AssertionConditionType< decltype(checkStrictOrSloppy(op))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(checkStrictOrSloppy(op)))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("checkStrictOrSloppy(op)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 344); AnnotateMozCrashReason("MOZ_ASSERT" "(" "checkStrictOrSloppy(op)" ")"); do { *((volatile int*)__null) = 344; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
345 | ptrdiff_t length = 1 + ptrdiff_t(extra); |
346 | |
347 | BytecodeOffset off; |
348 | if (!emitCheck(op, length, &off)) { |
349 | return false; |
350 | } |
351 | |
352 | jsbytecode* code = bytecodeSection().code(off); |
353 | code[0] = jsbytecode(op); |
354 | /* The remaining |extra| bytes are set by the caller */ |
355 | |
356 | /* |
357 | * Don't updateDepth if op's use-count comes from the immediate |
358 | * operand yet to be stored in the extra bytes after op. |
359 | */ |
360 | if (CodeSpec(op).nuses >= 0) { |
361 | bytecodeSection().updateDepth(op, off); |
362 | } |
363 | |
364 | if (offset) { |
365 | *offset = off; |
366 | } |
367 | return true; |
368 | } |
369 | |
370 | bool BytecodeEmitter::emitJumpTargetOp(JSOp op, BytecodeOffset* off) { |
371 | MOZ_ASSERT(BytecodeIsJumpTarget(op))do { static_assert( mozilla::detail::AssertionConditionType< decltype(BytecodeIsJumpTarget(op))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(BytecodeIsJumpTarget(op)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("BytecodeIsJumpTarget(op)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 371); AnnotateMozCrashReason("MOZ_ASSERT" "(" "BytecodeIsJumpTarget(op)" ")"); do { *((volatile int*)__null) = 371; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
372 | |
373 | // Record the current IC-entry index at start of this op. |
374 | uint32_t numEntries = bytecodeSection().numICEntries(); |
375 | |
376 | size_t n = GetOpLength(op) - 1; |
377 | MOZ_ASSERT(GetOpLength(op) >= 1 + ICINDEX_LEN)do { static_assert( mozilla::detail::AssertionConditionType< decltype(GetOpLength(op) >= 1 + ICINDEX_LEN)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(! !(GetOpLength(op) >= 1 + ICINDEX_LEN))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("GetOpLength(op) >= 1 + ICINDEX_LEN" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 377); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetOpLength(op) >= 1 + ICINDEX_LEN" ")"); do { *((volatile int*)__null) = 377; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
378 | |
379 | if (!emitN(op, n, off)) { |
380 | return false; |
381 | } |
382 | |
383 | SET_ICINDEX(bytecodeSection().code(*off), numEntries); |
384 | return true; |
385 | } |
386 | |
387 | bool BytecodeEmitter::emitJumpTarget(JumpTarget* target) { |
388 | BytecodeOffset off = bytecodeSection().offset(); |
389 | |
390 | // Alias consecutive jump targets. |
391 | if (bytecodeSection().lastTargetOffset().valid() && |
392 | off == bytecodeSection().lastTargetOffset() + |
393 | BytecodeOffsetDiff(JSOpLength_JumpTarget)) { |
394 | target->offset = bytecodeSection().lastTargetOffset(); |
395 | return true; |
396 | } |
397 | |
398 | target->offset = off; |
399 | bytecodeSection().setLastTargetOffset(off); |
400 | |
401 | BytecodeOffset opOff; |
402 | return emitJumpTargetOp(JSOp::JumpTarget, &opOff); |
403 | } |
404 | |
405 | bool BytecodeEmitter::emitJumpNoFallthrough(JSOp op, JumpList* jump) { |
406 | BytecodeOffset offset; |
407 | if (!emitCheck(op, 5, &offset)) { |
408 | return false; |
409 | } |
410 | |
411 | jsbytecode* code = bytecodeSection().code(offset); |
412 | code[0] = jsbytecode(op); |
413 | MOZ_ASSERT(!jump->offset.valid() ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(!jump->offset.valid() || (0 <= jump->offset .value() && jump->offset < offset))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(!jump->offset.valid() || (0 <= jump->offset.value () && jump->offset < offset)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!jump->offset.valid() || (0 <= jump->offset.value() && jump->offset < offset)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 414); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!jump->offset.valid() || (0 <= jump->offset.value() && jump->offset < offset)" ")"); do { *((volatile int*)__null) = 414; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
414 | (0 <= jump->offset.value() && jump->offset < offset))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!jump->offset.valid() || (0 <= jump->offset .value() && jump->offset < offset))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(!jump->offset.valid() || (0 <= jump->offset.value () && jump->offset < offset)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!jump->offset.valid() || (0 <= jump->offset.value() && jump->offset < offset)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 414); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!jump->offset.valid() || (0 <= jump->offset.value() && jump->offset < offset)" ")"); do { *((volatile int*)__null) = 414; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
415 | jump->push(bytecodeSection().code(BytecodeOffset(0)), offset); |
416 | bytecodeSection().updateDepth(op, offset); |
417 | return true; |
418 | } |
419 | |
420 | bool BytecodeEmitter::emitJump(JSOp op, JumpList* jump) { |
421 | if (!emitJumpNoFallthrough(op, jump)) { |
422 | return false; |
423 | } |
424 | if (BytecodeFallsThrough(op)) { |
425 | JumpTarget fallthrough; |
426 | if (!emitJumpTarget(&fallthrough)) { |
427 | return false; |
428 | } |
429 | } |
430 | return true; |
431 | } |
432 | |
433 | void BytecodeEmitter::patchJumpsToTarget(JumpList jump, JumpTarget target) { |
434 | MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType< decltype(!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset()))> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset())))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset())" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 436); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset())" ")"); do { *((volatile int*)__null) = 436; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
435 | !jump.offset.valid() ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset()))> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset())))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset())" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 436); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset())" ")"); do { *((volatile int*)__null) = 436; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
436 | (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset()))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset()))> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset())))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset())" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 436); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset())" ")"); do { *((volatile int*)__null) = 436; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
437 | MOZ_ASSERT(0 <= target.offset.value() &&do { static_assert( mozilla::detail::AssertionConditionType< decltype(0 <= target.offset.value() && target.offset <= bytecodeSection().offset())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(0 <= target.offset.value( ) && target.offset <= bytecodeSection().offset())) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("0 <= target.offset.value() && target.offset <= bytecodeSection().offset()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 438); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0 <= target.offset.value() && target.offset <= bytecodeSection().offset()" ")"); do { *((volatile int*)__null) = 438; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
438 | target.offset <= bytecodeSection().offset())do { static_assert( mozilla::detail::AssertionConditionType< decltype(0 <= target.offset.value() && target.offset <= bytecodeSection().offset())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(0 <= target.offset.value( ) && target.offset <= bytecodeSection().offset())) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("0 <= target.offset.value() && target.offset <= bytecodeSection().offset()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 438); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0 <= target.offset.value() && target.offset <= bytecodeSection().offset()" ")"); do { *((volatile int*)__null) = 438; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
439 | MOZ_ASSERT_IF(do { if (jump.offset.valid() && target.offset + BytecodeOffsetDiff (4) <= bytecodeSection().offset()) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(BytecodeIsJumpTarget (JSOp(*bytecodeSection().code(target.offset))))>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(! !(BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset )))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 442); AnnotateMozCrashReason("MOZ_ASSERT" "(" "BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))" ")"); do { *((volatile int*)__null) = 442; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
440 | jump.offset.valid() &&do { if (jump.offset.valid() && target.offset + BytecodeOffsetDiff (4) <= bytecodeSection().offset()) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(BytecodeIsJumpTarget (JSOp(*bytecodeSection().code(target.offset))))>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(! !(BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset )))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 442); AnnotateMozCrashReason("MOZ_ASSERT" "(" "BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))" ")"); do { *((volatile int*)__null) = 442; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
441 | target.offset + BytecodeOffsetDiff(4) <= bytecodeSection().offset(),do { if (jump.offset.valid() && target.offset + BytecodeOffsetDiff (4) <= bytecodeSection().offset()) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(BytecodeIsJumpTarget (JSOp(*bytecodeSection().code(target.offset))))>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(! !(BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset )))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 442); AnnotateMozCrashReason("MOZ_ASSERT" "(" "BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))" ")"); do { *((volatile int*)__null) = 442; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
442 | BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset))))do { if (jump.offset.valid() && target.offset + BytecodeOffsetDiff (4) <= bytecodeSection().offset()) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(BytecodeIsJumpTarget (JSOp(*bytecodeSection().code(target.offset))))>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(! !(BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset )))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 442); AnnotateMozCrashReason("MOZ_ASSERT" "(" "BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))" ")"); do { *((volatile int*)__null) = 442; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
443 | jump.patchAll(bytecodeSection().code(BytecodeOffset(0)), target); |
444 | } |
445 | |
446 | bool BytecodeEmitter::emitJumpTargetAndPatch(JumpList jump) { |
447 | if (!jump.offset.valid()) { |
448 | return true; |
449 | } |
450 | JumpTarget target; |
451 | if (!emitJumpTarget(&target)) { |
452 | return false; |
453 | } |
454 | patchJumpsToTarget(jump, target); |
455 | return true; |
456 | } |
457 | |
458 | bool BytecodeEmitter::emitCall(JSOp op, uint16_t argc, |
459 | const Maybe<uint32_t>& sourceCoordOffset) { |
460 | if (sourceCoordOffset.isSome()) { |
461 | if (!updateSourceCoordNotes(*sourceCoordOffset)) { |
462 | return false; |
463 | } |
464 | } |
465 | return emit3(op, ARGC_LO(argc), ARGC_HI(argc)); |
466 | } |
467 | |
468 | bool BytecodeEmitter::emitCall(JSOp op, uint16_t argc, ParseNode* pn) { |
469 | return emitCall(op, argc, pn ? Some(pn->pn_pos.begin) : Nothing()); |
470 | } |
471 | |
472 | bool BytecodeEmitter::emitDupAt(unsigned slotFromTop, unsigned count) { |
473 | MOZ_ASSERT(slotFromTop < unsigned(bytecodeSection().stackDepth()))do { static_assert( mozilla::detail::AssertionConditionType< decltype(slotFromTop < unsigned(bytecodeSection().stackDepth ()))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(slotFromTop < unsigned(bytecodeSection().stackDepth ())))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("slotFromTop < unsigned(bytecodeSection().stackDepth())", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 473); AnnotateMozCrashReason("MOZ_ASSERT" "(" "slotFromTop < unsigned(bytecodeSection().stackDepth())" ")"); do { *((volatile int*)__null) = 473; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
474 | MOZ_ASSERT(slotFromTop + 1 >= count)do { static_assert( mozilla::detail::AssertionConditionType< decltype(slotFromTop + 1 >= count)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(slotFromTop + 1 >= count) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("slotFromTop + 1 >= count" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 474); AnnotateMozCrashReason("MOZ_ASSERT" "(" "slotFromTop + 1 >= count" ")"); do { *((volatile int*)__null) = 474; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
475 | |
476 | if (slotFromTop == 0 && count == 1) { |
477 | return emit1(JSOp::Dup); |
478 | } |
479 | |
480 | if (slotFromTop == 1 && count == 2) { |
481 | return emit1(JSOp::Dup2); |
482 | } |
483 | |
484 | if (slotFromTop >= Bit(24)) { |
485 | reportError(nullptr, JSMSG_TOO_MANY_LOCALS); |
486 | return false; |
487 | } |
488 | |
489 | for (unsigned i = 0; i < count; i++) { |
490 | BytecodeOffset off; |
491 | if (!emitN(JSOp::DupAt, 3, &off)) { |
492 | return false; |
493 | } |
494 | |
495 | jsbytecode* pc = bytecodeSection().code(off); |
496 | SET_UINT24(pc, slotFromTop); |
497 | } |
498 | |
499 | return true; |
500 | } |
501 | |
502 | bool BytecodeEmitter::emitPopN(unsigned n) { |
503 | MOZ_ASSERT(n != 0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(n != 0)>::isValid, "invalid assertion condition") ; if ((__builtin_expect(!!(!(!!(n != 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("n != 0", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 503); AnnotateMozCrashReason("MOZ_ASSERT" "(" "n != 0" ")") ; do { *((volatile int*)__null) = 503; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
504 | |
505 | if (n == 1) { |
506 | return emit1(JSOp::Pop); |
507 | } |
508 | |
509 | // 2 JSOp::Pop instructions (2 bytes) are shorter than JSOp::PopN (3 bytes). |
510 | if (n == 2) { |
511 | return emit1(JSOp::Pop) && emit1(JSOp::Pop); |
512 | } |
513 | |
514 | return emitUint16Operand(JSOp::PopN, n); |
515 | } |
516 | |
517 | bool BytecodeEmitter::emitPickN(uint8_t n) { |
518 | MOZ_ASSERT(n != 0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(n != 0)>::isValid, "invalid assertion condition") ; if ((__builtin_expect(!!(!(!!(n != 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("n != 0", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 518); AnnotateMozCrashReason("MOZ_ASSERT" "(" "n != 0" ")") ; do { *((volatile int*)__null) = 518; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
519 | |
520 | if (n == 1) { |
521 | return emit1(JSOp::Swap); |
522 | } |
523 | |
524 | return emit2(JSOp::Pick, n); |
525 | } |
526 | |
527 | bool BytecodeEmitter::emitUnpickN(uint8_t n) { |
528 | MOZ_ASSERT(n != 0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(n != 0)>::isValid, "invalid assertion condition") ; if ((__builtin_expect(!!(!(!!(n != 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("n != 0", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 528); AnnotateMozCrashReason("MOZ_ASSERT" "(" "n != 0" ")") ; do { *((volatile int*)__null) = 528; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
529 | |
530 | if (n == 1) { |
531 | return emit1(JSOp::Swap); |
532 | } |
533 | |
534 | return emit2(JSOp::Unpick, n); |
535 | } |
536 | |
537 | bool BytecodeEmitter::emitCheckIsObj(CheckIsObjectKind kind) { |
538 | return emit2(JSOp::CheckIsObj, uint8_t(kind)); |
539 | } |
540 | |
541 | bool BytecodeEmitter::emitBuiltinObject(BuiltinObjectKind kind) { |
542 | return emit2(JSOp::BuiltinObject, uint8_t(kind)); |
543 | } |
544 | |
545 | /* Updates line number notes, not column notes. */ |
546 | bool BytecodeEmitter::updateLineNumberNotes(uint32_t offset) { |
547 | if (skipLocationSrcNotes()) { |
548 | return true; |
549 | } |
550 | |
551 | const ErrorReporter& er = errorReporter(); |
552 | std::optional<bool> onThisLineStatus = |
553 | er.isOnThisLine(offset, bytecodeSection().currentLine()); |
554 | if (!onThisLineStatus.has_value()) { |
555 | er.errorNoOffset(JSMSG_OUT_OF_MEMORY); |
556 | return false; |
557 | } |
558 | |
559 | bool onThisLine = *onThisLineStatus; |
560 | |
561 | if (!onThisLine) { |
562 | unsigned line = er.lineAt(offset); |
563 | unsigned delta = line - bytecodeSection().currentLine(); |
564 | |
565 | // If we use a `SetLine` note below, we want it to be relative to the |
566 | // scripts initial line number for better chance of sharing. |
567 | unsigned initialLine = sc->extent().lineno; |
568 | MOZ_ASSERT(line >= initialLine)do { static_assert( mozilla::detail::AssertionConditionType< decltype(line >= initialLine)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(line >= initialLine))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("line >= initialLine" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 568); AnnotateMozCrashReason("MOZ_ASSERT" "(" "line >= initialLine" ")"); do { *((volatile int*)__null) = 568; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
569 | |
570 | /* |
571 | * Encode any change in the current source line number by using |
572 | * either several SrcNoteType::NewLine notes or just one |
573 | * SrcNoteType::SetLine note, whichever consumes less space. |
574 | * |
575 | * NB: We handle backward line number deltas (possible with for |
576 | * loops where the update part is emitted after the body, but its |
577 | * line number is <= any line number in the body) here by letting |
578 | * unsigned delta_ wrap to a very large number, which triggers a |
579 | * SrcNoteType::SetLine. |
580 | */ |
581 | bytecodeSection().setCurrentLine(line, offset); |
582 | if (delta >= SrcNote::SetLine::lengthFor(line, initialLine)) { |
583 | if (!newSrcNote2(SrcNoteType::SetLine, |
584 | SrcNote::SetLine::toOperand(line, initialLine))) { |
585 | return false; |
586 | } |
587 | } else { |
588 | do { |
589 | if (!newSrcNote(SrcNoteType::NewLine)) { |
590 | return false; |
591 | } |
592 | } while (--delta != 0); |
593 | } |
594 | |
595 | bytecodeSection().updateSeparatorPositionIfPresent(); |
596 | } |
597 | return true; |
598 | } |
599 | |
600 | /* Updates the line number and column number information in the source notes. */ |
601 | bool BytecodeEmitter::updateSourceCoordNotes(uint32_t offset) { |
602 | if (skipLocationSrcNotes()) { |
603 | return true; |
604 | } |
605 | |
606 | if (!updateLineNumberNotes(offset)) { |
607 | return false; |
608 | } |
609 | |
610 | JS::LimitedColumnNumberOneOrigin columnIndex = |
611 | errorReporter().columnAt(offset); |
612 | |
613 | // Assert colspan is always representable. |
614 | static_assert((0 - ptrdiff_t(JS::LimitedColumnNumberOneOrigin::Limit)) >= |
615 | SrcNote::ColSpan::MinColSpan); |
616 | static_assert((ptrdiff_t(JS::LimitedColumnNumberOneOrigin::Limit) - 0) <= |
617 | SrcNote::ColSpan::MaxColSpan); |
618 | |
619 | JS::ColumnNumberOffset colspan = columnIndex - bytecodeSection().lastColumn(); |
620 | |
621 | if (colspan != JS::ColumnNumberOffset::zero()) { |
622 | if (lastLineOnlySrcNoteIndex != LastSrcNoteIsNotLineOnly) { |
623 | MOZ_ASSERT(bytecodeSection().lastColumn() ==do { static_assert( mozilla::detail::AssertionConditionType< decltype(bytecodeSection().lastColumn() == JS::LimitedColumnNumberOneOrigin ())>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(bytecodeSection().lastColumn() == JS::LimitedColumnNumberOneOrigin ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("bytecodeSection().lastColumn() == JS::LimitedColumnNumberOneOrigin()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 624); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().lastColumn() == JS::LimitedColumnNumberOneOrigin()" ")"); do { *((volatile int*)__null) = 624; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
624 | JS::LimitedColumnNumberOneOrigin())do { static_assert( mozilla::detail::AssertionConditionType< decltype(bytecodeSection().lastColumn() == JS::LimitedColumnNumberOneOrigin ())>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(bytecodeSection().lastColumn() == JS::LimitedColumnNumberOneOrigin ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("bytecodeSection().lastColumn() == JS::LimitedColumnNumberOneOrigin()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 624); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().lastColumn() == JS::LimitedColumnNumberOneOrigin()" ")"); do { *((volatile int*)__null) = 624; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
625 | |
626 | const SrcNotesVector& notes = bytecodeSection().notes(); |
627 | SrcNoteType type = notes[lastLineOnlySrcNoteIndex].type(); |
628 | if (type == SrcNoteType::NewLine) { |
629 | if (!convertLastNewLineToNewLineColumn(columnIndex)) { |
630 | return false; |
631 | } |
632 | } else { |
633 | MOZ_ASSERT(type == SrcNoteType::SetLine)do { static_assert( mozilla::detail::AssertionConditionType< decltype(type == SrcNoteType::SetLine)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(type == SrcNoteType::SetLine ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "type == SrcNoteType::SetLine", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 633); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == SrcNoteType::SetLine" ")"); do { *((volatile int*)__null) = 633; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
634 | if (!convertLastSetLineToSetLineColumn(columnIndex)) { |
635 | return false; |
636 | } |
637 | } |
638 | } else { |
639 | if (!newSrcNote2(SrcNoteType::ColSpan, |
640 | SrcNote::ColSpan::toOperand(colspan))) { |
641 | return false; |
642 | } |
643 | } |
644 | bytecodeSection().setLastColumn(columnIndex, offset); |
645 | bytecodeSection().updateSeparatorPositionIfPresent(); |
646 | } |
647 | return true; |
648 | } |
649 | |
650 | bool BytecodeEmitter::updateSourceCoordNotesIfNonLiteral(ParseNode* node) { |
651 | if (node->isLiteral()) { |
652 | return true; |
653 | } |
654 | return updateSourceCoordNotes(node->pn_pos.begin); |
655 | } |
656 | |
657 | uint32_t BytecodeEmitter::getOffsetForLoop(ParseNode* nextpn) const { |
658 | // Try to give the JSOp::LoopHead the same line number as the next |
659 | // instruction. nextpn is often a block, in which case the next instruction |
660 | // typically comes from the first statement inside. |
661 | if (nextpn->is<LexicalScopeNode>()) { |
662 | nextpn = nextpn->as<LexicalScopeNode>().scopeBody(); |
663 | } |
664 | if (nextpn->isKind(ParseNodeKind::StatementList)) { |
665 | if (ParseNode* firstStatement = nextpn->as<ListNode>().head()) { |
666 | nextpn = firstStatement; |
667 | } |
668 | } |
669 | |
670 | return nextpn->pn_pos.begin; |
671 | } |
672 | |
673 | bool BytecodeEmitter::emitUint16Operand(JSOp op, uint32_t operand) { |
674 | MOZ_ASSERT(operand <= UINT16_MAX)do { static_assert( mozilla::detail::AssertionConditionType< decltype(operand <= (65535))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(operand <= (65535)))), 0) )) { do { } while (false); MOZ_ReportAssertionFailure("operand <= (65535)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 674); AnnotateMozCrashReason("MOZ_ASSERT" "(" "operand <= (65535)" ")"); do { *((volatile int*)__null) = 674; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
675 | if (!emit3(op, UINT16_LO(operand), UINT16_HI(operand))) { |
676 | return false; |
677 | } |
678 | return true; |
679 | } |
680 | |
681 | bool BytecodeEmitter::emitUint32Operand(JSOp op, uint32_t operand) { |
682 | BytecodeOffset off; |
683 | if (!emitN(op, 4, &off)) { |
684 | return false; |
685 | } |
686 | SET_UINT32(bytecodeSection().code(off), operand); |
687 | return true; |
688 | } |
689 | |
690 | bool BytecodeEmitter::emitGoto(NestableControl* target, GotoKind kind) { |
691 | NonLocalExitControl nle(this, kind == GotoKind::Continue |
692 | ? NonLocalExitKind::Continue |
693 | : NonLocalExitKind::Break); |
694 | return nle.emitNonLocalJump(target); |
695 | } |
696 | |
697 | AbstractScopePtr BytecodeEmitter::innermostScope() const { |
698 | return innermostEmitterScope()->scope(this); |
699 | } |
700 | |
701 | ScopeIndex BytecodeEmitter::innermostScopeIndex() const { |
702 | return *innermostEmitterScope()->scopeIndex(this); |
703 | } |
704 | |
705 | bool BytecodeEmitter::emitGCIndexOp(JSOp op, GCThingIndex index) { |
706 | MOZ_ASSERT(checkStrictOrSloppy(op))do { static_assert( mozilla::detail::AssertionConditionType< decltype(checkStrictOrSloppy(op))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(checkStrictOrSloppy(op)))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("checkStrictOrSloppy(op)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 706); AnnotateMozCrashReason("MOZ_ASSERT" "(" "checkStrictOrSloppy(op)" ")"); do { *((volatile int*)__null) = 706; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
707 | |
708 | constexpr size_t OpLength = 1 + GCTHING_INDEX_LEN; |
709 | MOZ_ASSERT(GetOpLength(op) == OpLength)do { static_assert( mozilla::detail::AssertionConditionType< decltype(GetOpLength(op) == OpLength)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(GetOpLength(op) == OpLength) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("GetOpLength(op) == OpLength" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 709); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetOpLength(op) == OpLength" ")"); do { *((volatile int*)__null) = 709; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
710 | |
711 | BytecodeOffset offset; |
712 | if (!emitCheck(op, OpLength, &offset)) { |
713 | return false; |
714 | } |
715 | |
716 | jsbytecode* code = bytecodeSection().code(offset); |
717 | code[0] = jsbytecode(op); |
718 | SET_GCTHING_INDEX(code, index); |
719 | bytecodeSection().updateDepth(op, offset); |
720 | return true; |
721 | } |
722 | |
723 | bool BytecodeEmitter::emitAtomOp(JSOp op, TaggedParserAtomIndex atom) { |
724 | MOZ_ASSERT(atom)do { static_assert( mozilla::detail::AssertionConditionType< decltype(atom)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(atom))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("atom", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 724); AnnotateMozCrashReason("MOZ_ASSERT" "(" "atom" ")"); do { *((volatile int*)__null) = 724; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); |
725 | |
726 | // .generator lookups should be emitted as JSOp::GetAliasedVar instead of |
727 | // JSOp::GetName etc, to bypass |with| objects on the scope chain. |
728 | // It's safe to emit .this lookups though because |with| objects skip |
729 | // those. |
730 | MOZ_ASSERT_IF(op == JSOp::GetName || op == JSOp::GetGName,do { if (op == JSOp::GetName || op == JSOp::GetGName) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(atom != TaggedParserAtomIndex::WellKnown::dot_generator_())>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(atom != TaggedParserAtomIndex::WellKnown::dot_generator_() ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "atom != TaggedParserAtomIndex::WellKnown::dot_generator_()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 731); AnnotateMozCrashReason("MOZ_ASSERT" "(" "atom != TaggedParserAtomIndex::WellKnown::dot_generator_()" ")"); do { *((volatile int*)__null) = 731; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
731 | atom != TaggedParserAtomIndex::WellKnown::dot_generator_())do { if (op == JSOp::GetName || op == JSOp::GetGName) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(atom != TaggedParserAtomIndex::WellKnown::dot_generator_())>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(atom != TaggedParserAtomIndex::WellKnown::dot_generator_() ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "atom != TaggedParserAtomIndex::WellKnown::dot_generator_()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 731); AnnotateMozCrashReason("MOZ_ASSERT" "(" "atom != TaggedParserAtomIndex::WellKnown::dot_generator_()" ")"); do { *((volatile int*)__null) = 731; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
732 | |
733 | GCThingIndex index; |
734 | if (!makeAtomIndex(atom, ParserAtom::Atomize::Yes, &index)) { |
735 | return false; |
736 | } |
737 | |
738 | return emitAtomOp(op, index); |
739 | } |
740 | |
741 | bool BytecodeEmitter::emitAtomOp(JSOp op, GCThingIndex atomIndex) { |
742 | MOZ_ASSERT(JOF_OPTYPE(op) == JOF_ATOM)do { static_assert( mozilla::detail::AssertionConditionType< decltype(JOF_OPTYPE(op) == JOF_ATOM)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(JOF_OPTYPE(op) == JOF_ATOM)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("JOF_OPTYPE(op) == JOF_ATOM" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 742); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JOF_OPTYPE(op) == JOF_ATOM" ")"); do { *((volatile int*)__null) = 742; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
743 | #ifdef DEBUG1 |
744 | auto atom = perScriptData().gcThingList().getAtom(atomIndex); |
745 | MOZ_ASSERT(compilationState.parserAtoms.isInstantiatedAsJSAtom(atom))do { static_assert( mozilla::detail::AssertionConditionType< decltype(compilationState.parserAtoms.isInstantiatedAsJSAtom( atom))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(compilationState.parserAtoms.isInstantiatedAsJSAtom( atom)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("compilationState.parserAtoms.isInstantiatedAsJSAtom(atom)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 745); AnnotateMozCrashReason("MOZ_ASSERT" "(" "compilationState.parserAtoms.isInstantiatedAsJSAtom(atom)" ")"); do { *((volatile int*)__null) = 745; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
746 | #endif |
747 | return emitGCIndexOp(op, atomIndex); |
748 | } |
749 | |
750 | bool BytecodeEmitter::emitStringOp(JSOp op, TaggedParserAtomIndex atom) { |
751 | MOZ_ASSERT(atom)do { static_assert( mozilla::detail::AssertionConditionType< decltype(atom)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(atom))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("atom", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 751); AnnotateMozCrashReason("MOZ_ASSERT" "(" "atom" ")"); do { *((volatile int*)__null) = 751; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); |
752 | GCThingIndex index; |
753 | if (!makeAtomIndex(atom, ParserAtom::Atomize::No, &index)) { |
754 | return false; |
755 | } |
756 | |
757 | return emitStringOp(op, index); |
758 | } |
759 | |
760 | bool BytecodeEmitter::emitStringOp(JSOp op, GCThingIndex atomIndex) { |
761 | MOZ_ASSERT(JOF_OPTYPE(op) == JOF_STRING)do { static_assert( mozilla::detail::AssertionConditionType< decltype(JOF_OPTYPE(op) == JOF_STRING)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(JOF_OPTYPE(op) == JOF_STRING ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "JOF_OPTYPE(op) == JOF_STRING", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 761); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JOF_OPTYPE(op) == JOF_STRING" ")"); do { *((volatile int*)__null) = 761; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
762 | return emitGCIndexOp(op, atomIndex); |
763 | } |
764 | |
765 | bool BytecodeEmitter::emitInternedScopeOp(GCThingIndex index, JSOp op) { |
766 | MOZ_ASSERT(JOF_OPTYPE(op) == JOF_SCOPE)do { static_assert( mozilla::detail::AssertionConditionType< decltype(JOF_OPTYPE(op) == JOF_SCOPE)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(JOF_OPTYPE(op) == JOF_SCOPE) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("JOF_OPTYPE(op) == JOF_SCOPE" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 766); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JOF_OPTYPE(op) == JOF_SCOPE" ")"); do { *((volatile int*)__null) = 766; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
767 | MOZ_ASSERT(index < perScriptData().gcThingList().length())do { static_assert( mozilla::detail::AssertionConditionType< decltype(index < perScriptData().gcThingList().length())> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(index < perScriptData().gcThingList().length()))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("index < perScriptData().gcThingList().length()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 767); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index < perScriptData().gcThingList().length()" ")"); do { *((volatile int*)__null) = 767; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
768 | return emitGCIndexOp(op, index); |
769 | } |
770 | |
771 | bool BytecodeEmitter::emitInternedObjectOp(GCThingIndex index, JSOp op) { |
772 | MOZ_ASSERT(JOF_OPTYPE(op) == JOF_OBJECT)do { static_assert( mozilla::detail::AssertionConditionType< decltype(JOF_OPTYPE(op) == JOF_OBJECT)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(JOF_OPTYPE(op) == JOF_OBJECT ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "JOF_OPTYPE(op) == JOF_OBJECT", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 772); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JOF_OPTYPE(op) == JOF_OBJECT" ")"); do { *((volatile int*)__null) = 772; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
773 | MOZ_ASSERT(index < perScriptData().gcThingList().length())do { static_assert( mozilla::detail::AssertionConditionType< decltype(index < perScriptData().gcThingList().length())> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(index < perScriptData().gcThingList().length()))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("index < perScriptData().gcThingList().length()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 773); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index < perScriptData().gcThingList().length()" ")"); do { *((volatile int*)__null) = 773; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
774 | return emitGCIndexOp(op, index); |
775 | } |
776 | |
777 | bool BytecodeEmitter::emitRegExp(GCThingIndex index) { |
778 | return emitGCIndexOp(JSOp::RegExp, index); |
779 | } |
780 | |
781 | bool BytecodeEmitter::emitLocalOp(JSOp op, uint32_t slot) { |
782 | MOZ_ASSERT(JOF_OPTYPE(op) != JOF_ENVCOORD)do { static_assert( mozilla::detail::AssertionConditionType< decltype(JOF_OPTYPE(op) != JOF_ENVCOORD)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(JOF_OPTYPE(op) != JOF_ENVCOORD ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "JOF_OPTYPE(op) != JOF_ENVCOORD", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 782); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JOF_OPTYPE(op) != JOF_ENVCOORD" ")"); do { *((volatile int*)__null) = 782; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
783 | MOZ_ASSERT(IsLocalOp(op))do { static_assert( mozilla::detail::AssertionConditionType< decltype(IsLocalOp(op))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsLocalOp(op)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsLocalOp(op)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 783); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsLocalOp(op)" ")"); do { *((volatile int*)__null) = 783; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
784 | |
785 | BytecodeOffset off; |
786 | if (!emitN(op, LOCALNO_LEN, &off)) { |
787 | return false; |
788 | } |
789 | |
790 | SET_LOCALNO(bytecodeSection().code(off), slot); |
791 | return true; |
792 | } |
793 | |
794 | bool BytecodeEmitter::emitArgOp(JSOp op, uint16_t slot) { |
795 | MOZ_ASSERT(IsArgOp(op))do { static_assert( mozilla::detail::AssertionConditionType< decltype(IsArgOp(op))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsArgOp(op)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsArgOp(op)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 795); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsArgOp(op)" ")"); do { *((volatile int*)__null) = 795; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
796 | BytecodeOffset off; |
797 | if (!emitN(op, ARGNO_LEN, &off)) { |
798 | return false; |
799 | } |
800 | |
801 | SET_ARGNO(bytecodeSection().code(off), slot); |
802 | return true; |
803 | } |
804 | |
805 | bool BytecodeEmitter::emitEnvCoordOp(JSOp op, EnvironmentCoordinate ec) { |
806 | MOZ_ASSERT(JOF_OPTYPE(op) == JOF_ENVCOORD ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(JOF_OPTYPE(op) == JOF_ENVCOORD || JOF_OPTYPE(op) == JOF_DEBUGCOORD )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(JOF_OPTYPE(op) == JOF_ENVCOORD || JOF_OPTYPE(op) == JOF_DEBUGCOORD ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "JOF_OPTYPE(op) == JOF_ENVCOORD || JOF_OPTYPE(op) == JOF_DEBUGCOORD" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 807); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JOF_OPTYPE(op) == JOF_ENVCOORD || JOF_OPTYPE(op) == JOF_DEBUGCOORD" ")"); do { *((volatile int*)__null) = 807; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
807 | JOF_OPTYPE(op) == JOF_DEBUGCOORD)do { static_assert( mozilla::detail::AssertionConditionType< decltype(JOF_OPTYPE(op) == JOF_ENVCOORD || JOF_OPTYPE(op) == JOF_DEBUGCOORD )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(JOF_OPTYPE(op) == JOF_ENVCOORD || JOF_OPTYPE(op) == JOF_DEBUGCOORD ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "JOF_OPTYPE(op) == JOF_ENVCOORD || JOF_OPTYPE(op) == JOF_DEBUGCOORD" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 807); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JOF_OPTYPE(op) == JOF_ENVCOORD || JOF_OPTYPE(op) == JOF_DEBUGCOORD" ")"); do { *((volatile int*)__null) = 807; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
808 | |
809 | constexpr size_t N = ENVCOORD_HOPS_LEN + ENVCOORD_SLOT_LEN; |
810 | MOZ_ASSERT(GetOpLength(op) == 1 + N)do { static_assert( mozilla::detail::AssertionConditionType< decltype(GetOpLength(op) == 1 + N)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(GetOpLength(op) == 1 + N))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("GetOpLength(op) == 1 + N" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 810); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetOpLength(op) == 1 + N" ")"); do { *((volatile int*)__null) = 810; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
811 | |
812 | BytecodeOffset off; |
813 | if (!emitN(op, N, &off)) { |
814 | return false; |
815 | } |
816 | |
817 | jsbytecode* pc = bytecodeSection().code(off); |
818 | SET_ENVCOORD_HOPS(pc, ec.hops()); |
819 | pc += ENVCOORD_HOPS_LEN; |
820 | SET_ENVCOORD_SLOT(pc, ec.slot()); |
821 | pc += ENVCOORD_SLOT_LEN; |
Value stored to 'pc' is never read | |
822 | return true; |
823 | } |
824 | |
825 | bool BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer) const { |
826 | AutoCheckRecursionLimit recursion(fc); |
827 | if (!recursion.check(fc)) { |
828 | return false; |
829 | } |
830 | |
831 | restart: |
832 | |
833 | switch (pn->getKind()) { |
834 | // Trivial cases with no side effects. |
835 | case ParseNodeKind::EmptyStmt: |
836 | case ParseNodeKind::TrueExpr: |
837 | case ParseNodeKind::FalseExpr: |
838 | case ParseNodeKind::NullExpr: |
839 | case ParseNodeKind::RawUndefinedExpr: |
840 | case ParseNodeKind::Elision: |
841 | case ParseNodeKind::Generator: |
842 | MOZ_ASSERT(pn->is<NullaryNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<NullaryNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<NullaryNode> ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("pn->is<NullaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 842); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<NullaryNode>()" ")"); do { *((volatile int*)__null) = 842; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
843 | *answer = false; |
844 | return true; |
845 | |
846 | case ParseNodeKind::ObjectPropertyName: |
847 | case ParseNodeKind::PrivateName: // no side effects, unlike |
848 | // ParseNodeKind::Name |
849 | case ParseNodeKind::StringExpr: |
850 | case ParseNodeKind::TemplateStringExpr: |
851 | MOZ_ASSERT(pn->is<NameNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<NameNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<NameNode>()) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("pn->is<NameNode>()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 851); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<NameNode>()" ")"); do { *((volatile int*)__null) = 851; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
852 | *answer = false; |
853 | return true; |
854 | |
855 | case ParseNodeKind::RegExpExpr: |
856 | MOZ_ASSERT(pn->is<RegExpLiteral>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<RegExpLiteral>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<RegExpLiteral> ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("pn->is<RegExpLiteral>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 856); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<RegExpLiteral>()" ")"); do { *((volatile int*)__null) = 856; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
857 | *answer = false; |
858 | return true; |
859 | |
860 | case ParseNodeKind::NumberExpr: |
861 | MOZ_ASSERT(pn->is<NumericLiteral>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<NumericLiteral>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<NumericLiteral> ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("pn->is<NumericLiteral>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 861); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<NumericLiteral>()" ")"); do { *((volatile int*)__null) = 861; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
862 | *answer = false; |
863 | return true; |
864 | |
865 | case ParseNodeKind::BigIntExpr: |
866 | MOZ_ASSERT(pn->is<BigIntLiteral>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<BigIntLiteral>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<BigIntLiteral> ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("pn->is<BigIntLiteral>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 866); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BigIntLiteral>()" ")"); do { *((volatile int*)__null) = 866; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
867 | *answer = false; |
868 | return true; |
869 | |
870 | // |this| can throw in derived class constructors, including nested arrow |
871 | // functions or eval. |
872 | case ParseNodeKind::ThisExpr: |
873 | MOZ_ASSERT(pn->is<UnaryNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<UnaryNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<UnaryNode>() ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "pn->is<UnaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 873); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()" ")"); do { *((volatile int*)__null) = 873; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
874 | *answer = sc->needsThisTDZChecks(); |
875 | return true; |
876 | |
877 | // |new.target| doesn't have any side-effects. |
878 | case ParseNodeKind::NewTargetExpr: { |
879 | MOZ_ASSERT(pn->is<NewTargetNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<NewTargetNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<NewTargetNode> ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("pn->is<NewTargetNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 879); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<NewTargetNode>()" ")"); do { *((volatile int*)__null) = 879; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
880 | *answer = false; |
881 | return true; |
882 | } |
883 | |
884 | // Trivial binary nodes with more token pos holders. |
885 | case ParseNodeKind::ImportMetaExpr: { |
886 | MOZ_ASSERT(pn->as<BinaryNode>().left()->isKind(ParseNodeKind::PosHolder))do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->as<BinaryNode>().left()->isKind(ParseNodeKind ::PosHolder))>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(pn->as<BinaryNode>().left ()->isKind(ParseNodeKind::PosHolder)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("pn->as<BinaryNode>().left()->isKind(ParseNodeKind::PosHolder)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 886); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->as<BinaryNode>().left()->isKind(ParseNodeKind::PosHolder)" ")"); do { *((volatile int*)__null) = 886; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
887 | MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->as<BinaryNode>().right()->isKind(ParseNodeKind ::PosHolder))>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(pn->as<BinaryNode>().right ()->isKind(ParseNodeKind::PosHolder)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("pn->as<BinaryNode>().right()->isKind(ParseNodeKind::PosHolder)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 888); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->as<BinaryNode>().right()->isKind(ParseNodeKind::PosHolder)" ")"); do { *((volatile int*)__null) = 888; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
888 | pn->as<BinaryNode>().right()->isKind(ParseNodeKind::PosHolder))do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->as<BinaryNode>().right()->isKind(ParseNodeKind ::PosHolder))>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(pn->as<BinaryNode>().right ()->isKind(ParseNodeKind::PosHolder)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("pn->as<BinaryNode>().right()->isKind(ParseNodeKind::PosHolder)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 888); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->as<BinaryNode>().right()->isKind(ParseNodeKind::PosHolder)" ")"); do { *((volatile int*)__null) = 888; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
889 | *answer = false; |
890 | return true; |
891 | } |
892 | |
893 | case ParseNodeKind::BreakStmt: |
894 | MOZ_ASSERT(pn->is<BreakStatement>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<BreakStatement>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<BreakStatement> ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("pn->is<BreakStatement>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 894); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BreakStatement>()" ")"); do { *((volatile int*)__null) = 894; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
895 | *answer = true; |
896 | return true; |
897 | |
898 | case ParseNodeKind::ContinueStmt: |
899 | MOZ_ASSERT(pn->is<ContinueStatement>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<ContinueStatement>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<ContinueStatement >()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("pn->is<ContinueStatement>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 899); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<ContinueStatement>()" ")"); do { *((volatile int*)__null) = 899; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
900 | *answer = true; |
901 | return true; |
902 | |
903 | case ParseNodeKind::DebuggerStmt: |
904 | MOZ_ASSERT(pn->is<DebuggerStatement>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<DebuggerStatement>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<DebuggerStatement >()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("pn->is<DebuggerStatement>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 904); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<DebuggerStatement>()" ")"); do { *((volatile int*)__null) = 904; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
905 | *answer = true; |
906 | return true; |
907 | |
908 | // Watch out for getters! |
909 | case ParseNodeKind::OptionalDotExpr: |
910 | case ParseNodeKind::DotExpr: |
911 | case ParseNodeKind::ArgumentsLength: |
912 | MOZ_ASSERT(pn->is<BinaryNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<BinaryNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<BinaryNode>( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("pn->is<BinaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 912); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()" ")"); do { *((volatile int*)__null) = 912; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
913 | *answer = true; |
914 | return true; |
915 | |
916 | // Unary cases with side effects only if the child has them. |
917 | case ParseNodeKind::TypeOfExpr: |
918 | case ParseNodeKind::VoidExpr: |
919 | case ParseNodeKind::NotExpr: |
920 | return checkSideEffects(pn->as<UnaryNode>().kid(), answer); |
921 | |
922 | // Even if the name expression is effect-free, performing ToPropertyKey on |
923 | // it might not be effect-free: |
924 | // |
925 | // RegExp.prototype.toString = () => { throw 42; }; |
926 | // ({ [/regex/]: 0 }); // ToPropertyKey(/regex/) throws 42 |
927 | // |
928 | // function Q() { |
929 | // ({ [new.target]: 0 }); |
930 | // } |
931 | // Q.toString = () => { throw 17; }; |
932 | // new Q; // new.target will be Q, ToPropertyKey(Q) throws 17 |
933 | case ParseNodeKind::ComputedName: |
934 | MOZ_ASSERT(pn->is<UnaryNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<UnaryNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<UnaryNode>() ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "pn->is<UnaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 934); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()" ")"); do { *((volatile int*)__null) = 934; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
935 | *answer = true; |
936 | return true; |
937 | |
938 | // Looking up or evaluating the associated name could throw. |
939 | case ParseNodeKind::TypeOfNameExpr: |
940 | MOZ_ASSERT(pn->is<UnaryNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<UnaryNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<UnaryNode>() ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "pn->is<UnaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 940); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()" ")"); do { *((volatile int*)__null) = 940; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
941 | *answer = true; |
942 | return true; |
943 | |
944 | // This unary case has side effects on the enclosing object, sure. But |
945 | // that's not the question this function answers: it's whether the |
946 | // operation may have a side effect on something *other* than the result |
947 | // of the overall operation in which it's embedded. The answer to that |
948 | // is no, because an object literal having a mutated prototype only |
949 | // produces a value, without affecting anything else. |
950 | case ParseNodeKind::MutateProto: |
951 | return checkSideEffects(pn->as<UnaryNode>().kid(), answer); |
952 | |
953 | // Unary cases with obvious side effects. |
954 | case ParseNodeKind::PreIncrementExpr: |
955 | case ParseNodeKind::PostIncrementExpr: |
956 | case ParseNodeKind::PreDecrementExpr: |
957 | case ParseNodeKind::PostDecrementExpr: |
958 | case ParseNodeKind::ThrowStmt: |
959 | MOZ_ASSERT(pn->is<UnaryNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<UnaryNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<UnaryNode>() ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "pn->is<UnaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 959); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()" ")"); do { *((volatile int*)__null) = 959; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
960 | *answer = true; |
961 | return true; |
962 | |
963 | // These might invoke valueOf/toString, even with a subexpression without |
964 | // side effects! Consider |+{ valueOf: null, toString: null }|. |
965 | case ParseNodeKind::BitNotExpr: |
966 | case ParseNodeKind::PosExpr: |
967 | case ParseNodeKind::NegExpr: |
968 | MOZ_ASSERT(pn->is<UnaryNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<UnaryNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<UnaryNode>() ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "pn->is<UnaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 968); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()" ")"); do { *((volatile int*)__null) = 968; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
969 | *answer = true; |
970 | return true; |
971 | |
972 | // This invokes the (user-controllable) iterator protocol. |
973 | case ParseNodeKind::Spread: |
974 | MOZ_ASSERT(pn->is<UnaryNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<UnaryNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<UnaryNode>() ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "pn->is<UnaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 974); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()" ")"); do { *((volatile int*)__null) = 974; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
975 | *answer = true; |
976 | return true; |
977 | |
978 | case ParseNodeKind::InitialYield: |
979 | case ParseNodeKind::YieldStarExpr: |
980 | case ParseNodeKind::YieldExpr: |
981 | case ParseNodeKind::AwaitExpr: |
982 | MOZ_ASSERT(pn->is<UnaryNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<UnaryNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<UnaryNode>() ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "pn->is<UnaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 982); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()" ")"); do { *((volatile int*)__null) = 982; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
983 | *answer = true; |
984 | return true; |
985 | |
986 | // Deletion generally has side effects, even if isolated cases have none. |
987 | case ParseNodeKind::DeleteNameExpr: |
988 | case ParseNodeKind::DeletePropExpr: |
989 | case ParseNodeKind::DeleteElemExpr: |
990 | case ParseNodeKind::DeleteOptionalChainExpr: |
991 | MOZ_ASSERT(pn->is<UnaryNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<UnaryNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<UnaryNode>() ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "pn->is<UnaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 991); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()" ")"); do { *((volatile int*)__null) = 991; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
992 | *answer = true; |
993 | return true; |
994 | |
995 | // Deletion of a non-Reference expression has side effects only through |
996 | // evaluating the expression. |
997 | case ParseNodeKind::DeleteExpr: { |
998 | ParseNode* expr = pn->as<UnaryNode>().kid(); |
999 | return checkSideEffects(expr, answer); |
1000 | } |
1001 | |
1002 | case ParseNodeKind::ExpressionStmt: |
1003 | return checkSideEffects(pn->as<UnaryNode>().kid(), answer); |
1004 | |
1005 | // Binary cases with obvious side effects. |
1006 | case ParseNodeKind::InitExpr: |
1007 | *answer = true; |
1008 | return true; |
1009 | |
1010 | case ParseNodeKind::AssignExpr: |
1011 | case ParseNodeKind::AddAssignExpr: |
1012 | case ParseNodeKind::SubAssignExpr: |
1013 | case ParseNodeKind::CoalesceAssignExpr: |
1014 | case ParseNodeKind::OrAssignExpr: |
1015 | case ParseNodeKind::AndAssignExpr: |
1016 | case ParseNodeKind::BitOrAssignExpr: |
1017 | case ParseNodeKind::BitXorAssignExpr: |
1018 | case ParseNodeKind::BitAndAssignExpr: |
1019 | case ParseNodeKind::LshAssignExpr: |
1020 | case ParseNodeKind::RshAssignExpr: |
1021 | case ParseNodeKind::UrshAssignExpr: |
1022 | case ParseNodeKind::MulAssignExpr: |
1023 | case ParseNodeKind::DivAssignExpr: |
1024 | case ParseNodeKind::ModAssignExpr: |
1025 | case ParseNodeKind::PowAssignExpr: |
1026 | MOZ_ASSERT(pn->is<AssignmentNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<AssignmentNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<AssignmentNode> ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("pn->is<AssignmentNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1026); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<AssignmentNode>()" ")"); do { *((volatile int*)__null) = 1026; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1027 | *answer = true; |
1028 | return true; |
1029 | |
1030 | case ParseNodeKind::SetThis: |
1031 | MOZ_ASSERT(pn->is<BinaryNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<BinaryNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<BinaryNode>( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("pn->is<BinaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1031); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()" ")"); do { *((volatile int*)__null) = 1031; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1032 | *answer = true; |
1033 | return true; |
1034 | |
1035 | case ParseNodeKind::StatementList: |
1036 | // Strict equality operations and short circuit operators are well-behaved |
1037 | // and perform no conversions. |
1038 | case ParseNodeKind::CoalesceExpr: |
1039 | case ParseNodeKind::OrExpr: |
1040 | case ParseNodeKind::AndExpr: |
1041 | case ParseNodeKind::StrictEqExpr: |
1042 | case ParseNodeKind::StrictNeExpr: |
1043 | // Any subexpression of a comma expression could be effectful. |
1044 | case ParseNodeKind::CommaExpr: |
1045 | MOZ_ASSERT(!pn->as<ListNode>().empty())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!pn->as<ListNode>().empty())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!pn->as<ListNode>() .empty()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!pn->as<ListNode>().empty()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1045); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!pn->as<ListNode>().empty()" ")"); do { *((volatile int*)__null) = 1045; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1046 | [[fallthrough]]; |
1047 | // Subcomponents of a literal may be effectful. |
1048 | case ParseNodeKind::ArrayExpr: |
1049 | case ParseNodeKind::ObjectExpr: |
1050 | for (ParseNode* item : pn->as<ListNode>().contents()) { |
1051 | if (!checkSideEffects(item, answer)) { |
1052 | return false; |
1053 | } |
1054 | if (*answer) { |
1055 | return true; |
1056 | } |
1057 | } |
1058 | return true; |
1059 | |
1060 | #ifdef ENABLE_RECORD_TUPLE |
1061 | case ParseNodeKind::RecordExpr: |
1062 | case ParseNodeKind::TupleExpr: |
1063 | MOZ_CRASH("Record and Tuple are not supported yet")do { do { } while (false); MOZ_ReportCrash("" "Record and Tuple are not supported yet" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1063); AnnotateMozCrashReason("MOZ_CRASH(" "Record and Tuple are not supported yet" ")"); do { *((volatile int*)__null) = 1063; __attribute__((nomerge )) ::abort(); } while (false); } while (false); |
1064 | #endif |
1065 | |
1066 | #ifdef ENABLE_DECORATORS |
1067 | case ParseNodeKind::DecoratorList: |
1068 | MOZ_CRASH("Decorators are not supported yet")do { do { } while (false); MOZ_ReportCrash("" "Decorators are not supported yet" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1068); AnnotateMozCrashReason("MOZ_CRASH(" "Decorators are not supported yet" ")"); do { *((volatile int*)__null) = 1068; __attribute__((nomerge )) ::abort(); } while (false); } while (false); |
1069 | #endif |
1070 | |
1071 | #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT |
1072 | case ParseNodeKind::UsingDecl: |
1073 | case ParseNodeKind::AwaitUsingDecl: |
1074 | MOZ_CRASH("Using declarations are not supported yet")do { do { } while (false); MOZ_ReportCrash("" "Using declarations are not supported yet" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1074); AnnotateMozCrashReason("MOZ_CRASH(" "Using declarations are not supported yet" ")"); do { *((volatile int*)__null) = 1074; __attribute__((nomerge )) ::abort(); } while (false); } while (false); |
1075 | #endif |
1076 | |
1077 | // Most other binary operations (parsed as lists in SpiderMonkey) may |
1078 | // perform conversions triggering side effects. Math operations perform |
1079 | // ToNumber and may fail invoking invalid user-defined toString/valueOf: |
1080 | // |5 < { toString: null }|. |instanceof| throws if provided a |
1081 | // non-object constructor: |null instanceof null|. |in| throws if given |
1082 | // a non-object RHS: |5 in null|. |
1083 | case ParseNodeKind::BitOrExpr: |
1084 | case ParseNodeKind::BitXorExpr: |
1085 | case ParseNodeKind::BitAndExpr: |
1086 | case ParseNodeKind::EqExpr: |
1087 | case ParseNodeKind::NeExpr: |
1088 | case ParseNodeKind::LtExpr: |
1089 | case ParseNodeKind::LeExpr: |
1090 | case ParseNodeKind::GtExpr: |
1091 | case ParseNodeKind::GeExpr: |
1092 | case ParseNodeKind::InstanceOfExpr: |
1093 | case ParseNodeKind::InExpr: |
1094 | case ParseNodeKind::PrivateInExpr: |
1095 | case ParseNodeKind::LshExpr: |
1096 | case ParseNodeKind::RshExpr: |
1097 | case ParseNodeKind::UrshExpr: |
1098 | case ParseNodeKind::AddExpr: |
1099 | case ParseNodeKind::SubExpr: |
1100 | case ParseNodeKind::MulExpr: |
1101 | case ParseNodeKind::DivExpr: |
1102 | case ParseNodeKind::ModExpr: |
1103 | case ParseNodeKind::PowExpr: |
1104 | MOZ_ASSERT(pn->as<ListNode>().count() >= 2)do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->as<ListNode>().count() >= 2)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(pn->as<ListNode>().count() >= 2))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("pn->as<ListNode>().count() >= 2" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1104); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->as<ListNode>().count() >= 2" ")"); do { *((volatile int*)__null) = 1104; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1105 | *answer = true; |
1106 | return true; |
1107 | |
1108 | case ParseNodeKind::PropertyDefinition: |
1109 | case ParseNodeKind::Case: { |
1110 | BinaryNode* node = &pn->as<BinaryNode>(); |
1111 | if (!checkSideEffects(node->left(), answer)) { |
1112 | return false; |
1113 | } |
1114 | if (*answer) { |
1115 | return true; |
1116 | } |
1117 | return checkSideEffects(node->right(), answer); |
1118 | } |
1119 | |
1120 | // More getters. |
1121 | case ParseNodeKind::ElemExpr: |
1122 | case ParseNodeKind::OptionalElemExpr: |
1123 | MOZ_ASSERT(pn->is<BinaryNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<BinaryNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<BinaryNode>( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("pn->is<BinaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1123); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()" ")"); do { *((volatile int*)__null) = 1123; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1124 | *answer = true; |
1125 | return true; |
1126 | |
1127 | // Throws if the operand is not of the right class. Can also call a private |
1128 | // getter. |
1129 | case ParseNodeKind::PrivateMemberExpr: |
1130 | case ParseNodeKind::OptionalPrivateMemberExpr: |
1131 | *answer = true; |
1132 | return true; |
1133 | |
1134 | // These affect visible names in this code, or in other code. |
1135 | case ParseNodeKind::ImportDecl: |
1136 | case ParseNodeKind::ExportFromStmt: |
1137 | case ParseNodeKind::ExportDefaultStmt: |
1138 | MOZ_ASSERT(pn->is<BinaryNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<BinaryNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<BinaryNode>( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("pn->is<BinaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1138); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()" ")"); do { *((volatile int*)__null) = 1138; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1139 | *answer = true; |
1140 | return true; |
1141 | |
1142 | // Likewise. |
1143 | case ParseNodeKind::ExportStmt: |
1144 | MOZ_ASSERT(pn->is<UnaryNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<UnaryNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<UnaryNode>() ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "pn->is<UnaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1144); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()" ")"); do { *((volatile int*)__null) = 1144; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1145 | *answer = true; |
1146 | return true; |
1147 | |
1148 | case ParseNodeKind::CallImportExpr: |
1149 | case ParseNodeKind::CallImportSpec: |
1150 | MOZ_ASSERT(pn->is<BinaryNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<BinaryNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<BinaryNode>( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("pn->is<BinaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1150); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()" ")"); do { *((volatile int*)__null) = 1150; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1151 | *answer = true; |
1152 | return true; |
1153 | |
1154 | // Every part of a loop might be effect-free, but looping infinitely *is* |
1155 | // an effect. (Language lawyer trivia: C++ says threads can be assumed |
1156 | // to exit or have side effects, C++14 [intro.multithread]p27, so a C++ |
1157 | // implementation's equivalent of the below could set |*answer = false;| |
1158 | // if all loop sub-nodes set |*answer = false|!) |
1159 | case ParseNodeKind::DoWhileStmt: |
1160 | case ParseNodeKind::WhileStmt: |
1161 | case ParseNodeKind::ForStmt: |
1162 | MOZ_ASSERT(pn->is<BinaryNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<BinaryNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<BinaryNode>( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("pn->is<BinaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1162); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()" ")"); do { *((volatile int*)__null) = 1162; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1163 | *answer = true; |
1164 | return true; |
1165 | |
1166 | // Declarations affect the name set of the relevant scope. |
1167 | case ParseNodeKind::VarStmt: |
1168 | case ParseNodeKind::ConstDecl: |
1169 | case ParseNodeKind::LetDecl: |
1170 | MOZ_ASSERT(pn->is<ListNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<ListNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<ListNode>()) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("pn->is<ListNode>()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1170); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<ListNode>()" ")"); do { *((volatile int*)__null) = 1170; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1171 | *answer = true; |
1172 | return true; |
1173 | |
1174 | case ParseNodeKind::IfStmt: |
1175 | case ParseNodeKind::ConditionalExpr: { |
1176 | TernaryNode* node = &pn->as<TernaryNode>(); |
1177 | if (!checkSideEffects(node->kid1(), answer)) { |
1178 | return false; |
1179 | } |
1180 | if (*answer) { |
1181 | return true; |
1182 | } |
1183 | if (!checkSideEffects(node->kid2(), answer)) { |
1184 | return false; |
1185 | } |
1186 | if (*answer) { |
1187 | return true; |
1188 | } |
1189 | if ((pn = node->kid3())) { |
1190 | goto restart; |
1191 | } |
1192 | return true; |
1193 | } |
1194 | |
1195 | // Function calls can invoke non-local code. |
1196 | case ParseNodeKind::NewExpr: |
1197 | case ParseNodeKind::CallExpr: |
1198 | case ParseNodeKind::OptionalCallExpr: |
1199 | case ParseNodeKind::TaggedTemplateExpr: |
1200 | case ParseNodeKind::SuperCallExpr: |
1201 | MOZ_ASSERT(pn->is<BinaryNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<BinaryNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<BinaryNode>( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("pn->is<BinaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1201); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()" ")"); do { *((volatile int*)__null) = 1201; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1202 | *answer = true; |
1203 | return true; |
1204 | |
1205 | // Function arg lists can contain arbitrary expressions. Technically |
1206 | // this only causes side-effects if one of the arguments does, but since |
1207 | // the call being made will always trigger side-effects, it isn't needed. |
1208 | case ParseNodeKind::Arguments: |
1209 | MOZ_ASSERT(pn->is<ListNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<ListNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<ListNode>()) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("pn->is<ListNode>()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1209); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<ListNode>()" ")"); do { *((volatile int*)__null) = 1209; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1210 | *answer = true; |
1211 | return true; |
1212 | |
1213 | case ParseNodeKind::OptionalChain: |
1214 | MOZ_ASSERT(pn->is<UnaryNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<UnaryNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<UnaryNode>() ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "pn->is<UnaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1214); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()" ")"); do { *((volatile int*)__null) = 1214; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1215 | *answer = true; |
1216 | return true; |
1217 | |
1218 | // Classes typically introduce names. Even if no name is introduced, |
1219 | // the heritage and/or class body (through computed property names) |
1220 | // usually have effects. |
1221 | case ParseNodeKind::ClassDecl: |
1222 | MOZ_ASSERT(pn->is<ClassNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<ClassNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<ClassNode>() ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "pn->is<ClassNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1222); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<ClassNode>()" ")"); do { *((volatile int*)__null) = 1222; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1223 | *answer = true; |
1224 | return true; |
1225 | |
1226 | // |with| calls |ToObject| on its expression and so throws if that value |
1227 | // is null/undefined. |
1228 | case ParseNodeKind::WithStmt: |
1229 | MOZ_ASSERT(pn->is<BinaryNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<BinaryNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<BinaryNode>( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("pn->is<BinaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1229); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()" ")"); do { *((volatile int*)__null) = 1229; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1230 | *answer = true; |
1231 | return true; |
1232 | |
1233 | case ParseNodeKind::ReturnStmt: |
1234 | MOZ_ASSERT(pn->is<BinaryNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<BinaryNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<BinaryNode>( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("pn->is<BinaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1234); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()" ")"); do { *((volatile int*)__null) = 1234; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1235 | *answer = true; |
1236 | return true; |
1237 | |
1238 | case ParseNodeKind::Name: |
1239 | MOZ_ASSERT(pn->is<NameNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<NameNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<NameNode>()) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("pn->is<NameNode>()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1239); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<NameNode>()" ")"); do { *((volatile int*)__null) = 1239; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1240 | *answer = true; |
1241 | return true; |
1242 | |
1243 | // Shorthands could trigger getters: the |x| in the object literal in |
1244 | // |with ({ get x() { throw 42; } }) ({ x });|, for example, triggers |
1245 | // one. (Of course, it isn't necessary to use |with| for a shorthand to |
1246 | // trigger a getter.) |
1247 | case ParseNodeKind::Shorthand: |
1248 | MOZ_ASSERT(pn->is<BinaryNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<BinaryNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<BinaryNode>( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("pn->is<BinaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1248); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()" ")"); do { *((volatile int*)__null) = 1248; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1249 | *answer = true; |
1250 | return true; |
1251 | |
1252 | case ParseNodeKind::Function: |
1253 | MOZ_ASSERT(pn->is<FunctionNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<FunctionNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<FunctionNode> ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("pn->is<FunctionNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1253); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<FunctionNode>()" ")"); do { *((volatile int*)__null) = 1253; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1254 | /* |
1255 | * A named function, contrary to ES3, is no longer effectful, because |
1256 | * we bind its name lexically (using JSOp::Callee) instead of creating |
1257 | * an Object instance and binding a readonly, permanent property in it |
1258 | * (the object and binding can be detected and hijacked or captured). |
1259 | * This is a bug fix to ES3; it is fixed in ES3.1 drafts. |
1260 | */ |
1261 | *answer = false; |
1262 | return true; |
1263 | |
1264 | case ParseNodeKind::Module: |
1265 | *answer = false; |
1266 | return true; |
1267 | |
1268 | case ParseNodeKind::TryStmt: { |
1269 | TryNode* tryNode = &pn->as<TryNode>(); |
1270 | if (!checkSideEffects(tryNode->body(), answer)) { |
1271 | return false; |
1272 | } |
1273 | if (*answer) { |
1274 | return true; |
1275 | } |
1276 | if (LexicalScopeNode* catchScope = tryNode->catchScope()) { |
1277 | if (!checkSideEffects(catchScope, answer)) { |
1278 | return false; |
1279 | } |
1280 | if (*answer) { |
1281 | return true; |
1282 | } |
1283 | } |
1284 | if (ParseNode* finallyBlock = tryNode->finallyBlock()) { |
1285 | if (!checkSideEffects(finallyBlock, answer)) { |
1286 | return false; |
1287 | } |
1288 | } |
1289 | return true; |
1290 | } |
1291 | |
1292 | case ParseNodeKind::Catch: { |
1293 | BinaryNode* catchClause = &pn->as<BinaryNode>(); |
1294 | if (ParseNode* name = catchClause->left()) { |
1295 | if (!checkSideEffects(name, answer)) { |
1296 | return false; |
1297 | } |
1298 | if (*answer) { |
1299 | return true; |
1300 | } |
1301 | } |
1302 | return checkSideEffects(catchClause->right(), answer); |
1303 | } |
1304 | |
1305 | case ParseNodeKind::SwitchStmt: { |
1306 | SwitchStatement* switchStmt = &pn->as<SwitchStatement>(); |
1307 | if (!checkSideEffects(&switchStmt->discriminant(), answer)) { |
1308 | return false; |
1309 | } |
1310 | return *answer || |
1311 | checkSideEffects(&switchStmt->lexicalForCaseList(), answer); |
1312 | } |
1313 | |
1314 | case ParseNodeKind::LabelStmt: |
1315 | return checkSideEffects(pn->as<LabeledStatement>().statement(), answer); |
1316 | |
1317 | case ParseNodeKind::LexicalScope: |
1318 | return checkSideEffects(pn->as<LexicalScopeNode>().scopeBody(), answer); |
1319 | |
1320 | // We could methodically check every interpolated expression, but it's |
1321 | // probably not worth the trouble. Treat template strings as effect-free |
1322 | // only if they don't contain any substitutions. |
1323 | case ParseNodeKind::TemplateStringListExpr: { |
1324 | ListNode* list = &pn->as<ListNode>(); |
1325 | MOZ_ASSERT(!list->empty())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!list->empty())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!list->empty()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!list->empty()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1325); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!list->empty()" ")"); do { *((volatile int*)__null) = 1325; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1326 | MOZ_ASSERT((list->count() % 2) == 1,do { static_assert( mozilla::detail::AssertionConditionType< decltype((list->count() % 2) == 1)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!((list->count() % 2) == 1) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("(list->count() % 2) == 1" " (" "template strings must alternate template and substitution " "parts" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1328); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(list->count() % 2) == 1" ") (" "template strings must alternate template and substitution " "parts" ")"); do { *((volatile int*)__null) = 1328; __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false) |
1327 | "template strings must alternate template and substitution "do { static_assert( mozilla::detail::AssertionConditionType< decltype((list->count() % 2) == 1)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!((list->count() % 2) == 1) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("(list->count() % 2) == 1" " (" "template strings must alternate template and substitution " "parts" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1328); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(list->count() % 2) == 1" ") (" "template strings must alternate template and substitution " "parts" ")"); do { *((volatile int*)__null) = 1328; __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false) |
1328 | "parts")do { static_assert( mozilla::detail::AssertionConditionType< decltype((list->count() % 2) == 1)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!((list->count() % 2) == 1) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("(list->count() % 2) == 1" " (" "template strings must alternate template and substitution " "parts" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1328); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(list->count() % 2) == 1" ") (" "template strings must alternate template and substitution " "parts" ")"); do { *((volatile int*)__null) = 1328; __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false); |
1329 | *answer = list->count() > 1; |
1330 | return true; |
1331 | } |
1332 | |
1333 | // This should be unreachable but is left as-is for now. |
1334 | case ParseNodeKind::ParamsBody: |
1335 | *answer = true; |
1336 | return true; |
1337 | |
1338 | case ParseNodeKind::ForIn: // by ParseNodeKind::For |
1339 | case ParseNodeKind::ForOf: // by ParseNodeKind::For |
1340 | case ParseNodeKind::ForHead: // by ParseNodeKind::For |
1341 | case ParseNodeKind::DefaultConstructor: // by ParseNodeKind::ClassDecl |
1342 | case ParseNodeKind::ClassBodyScope: // by ParseNodeKind::ClassDecl |
1343 | case ParseNodeKind::ClassMethod: // by ParseNodeKind::ClassDecl |
1344 | case ParseNodeKind::ClassField: // by ParseNodeKind::ClassDecl |
1345 | case ParseNodeKind::ClassNames: // by ParseNodeKind::ClassDecl |
1346 | case ParseNodeKind::StaticClassBlock: // by ParseNodeKind::ClassDecl |
1347 | case ParseNodeKind::ClassMemberList: // by ParseNodeKind::ClassDecl |
1348 | case ParseNodeKind::ImportSpecList: // by ParseNodeKind::Import |
1349 | case ParseNodeKind::ImportSpec: // by ParseNodeKind::Import |
1350 | case ParseNodeKind::ImportNamespaceSpec: // by ParseNodeKind::Import |
1351 | case ParseNodeKind::ImportAttribute: // by ParseNodeKind::Import |
1352 | case ParseNodeKind::ImportAttributeList: // by ParseNodeKind::Import |
1353 | case ParseNodeKind::ImportModuleRequest: // by ParseNodeKind::Import |
1354 | case ParseNodeKind::ExportBatchSpecStmt: // by ParseNodeKind::Export |
1355 | case ParseNodeKind::ExportSpecList: // by ParseNodeKind::Export |
1356 | case ParseNodeKind::ExportSpec: // by ParseNodeKind::Export |
1357 | case ParseNodeKind::ExportNamespaceSpec: // by ParseNodeKind::Export |
1358 | case ParseNodeKind::CallSiteObj: // by ParseNodeKind::TaggedTemplate |
1359 | case ParseNodeKind::PosHolder: // by ParseNodeKind::NewTarget |
1360 | case ParseNodeKind::SuperBase: // by ParseNodeKind::Elem and others |
1361 | case ParseNodeKind::PropertyNameExpr: // by ParseNodeKind::Dot |
1362 | MOZ_CRASH("handled by parent nodes")do { do { } while (false); MOZ_ReportCrash("" "handled by parent nodes" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1362); AnnotateMozCrashReason("MOZ_CRASH(" "handled by parent nodes" ")"); do { *((volatile int*)__null) = 1362; __attribute__((nomerge )) ::abort(); } while (false); } while (false); |
1363 | |
1364 | case ParseNodeKind::LastUnused: |
1365 | case ParseNodeKind::Limit: |
1366 | MOZ_CRASH("invalid node kind")do { do { } while (false); MOZ_ReportCrash("" "invalid node kind" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1366); AnnotateMozCrashReason("MOZ_CRASH(" "invalid node kind" ")"); do { *((volatile int*)__null) = 1366; __attribute__((nomerge )) ::abort(); } while (false); } while (false); |
1367 | } |
1368 | |
1369 | MOZ_CRASH(do { do { } while (false); MOZ_ReportCrash("" "invalid, unenumerated ParseNodeKind value encountered in " "BytecodeEmitter::checkSideEffects", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1371); AnnotateMozCrashReason("MOZ_CRASH(" "invalid, unenumerated ParseNodeKind value encountered in " "BytecodeEmitter::checkSideEffects" ")"); do { *((volatile int *)__null) = 1371; __attribute__((nomerge)) ::abort(); } while (false); } while (false) |
1370 | "invalid, unenumerated ParseNodeKind value encountered in "do { do { } while (false); MOZ_ReportCrash("" "invalid, unenumerated ParseNodeKind value encountered in " "BytecodeEmitter::checkSideEffects", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1371); AnnotateMozCrashReason("MOZ_CRASH(" "invalid, unenumerated ParseNodeKind value encountered in " "BytecodeEmitter::checkSideEffects" ")"); do { *((volatile int *)__null) = 1371; __attribute__((nomerge)) ::abort(); } while (false); } while (false) |
1371 | "BytecodeEmitter::checkSideEffects")do { do { } while (false); MOZ_ReportCrash("" "invalid, unenumerated ParseNodeKind value encountered in " "BytecodeEmitter::checkSideEffects", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1371); AnnotateMozCrashReason("MOZ_CRASH(" "invalid, unenumerated ParseNodeKind value encountered in " "BytecodeEmitter::checkSideEffects" ")"); do { *((volatile int *)__null) = 1371; __attribute__((nomerge)) ::abort(); } while (false); } while (false); |
1372 | } |
1373 | |
1374 | bool BytecodeEmitter::isInLoop() const { |
1375 | return findInnermostNestableControl<LoopControl>(); |
1376 | } |
1377 | |
1378 | bool BytecodeEmitter::checkSingletonContext() const { |
1379 | MOZ_ASSERT_IF(sc->treatAsRunOnce(), sc->isTopLevelContext())do { if (sc->treatAsRunOnce()) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(sc->isTopLevelContext ())>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(sc->isTopLevelContext()))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("sc->isTopLevelContext()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1379); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isTopLevelContext()" ")"); do { *((volatile int*)__null) = 1379; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
1380 | return sc->treatAsRunOnce() && !isInLoop(); |
1381 | } |
1382 | |
1383 | bool BytecodeEmitter::needsImplicitThis() const { |
1384 | // Short-circuit if there is an enclosing 'with' scope. |
1385 | if (sc->inWith()) { |
1386 | return true; |
1387 | } |
1388 | |
1389 | // Otherwise see if the current point is under a 'with'. |
1390 | for (EmitterScope* es = innermostEmitterScope(); es; |
1391 | es = es->enclosingInFrame()) { |
1392 | if (es->scope(this).kind() == ScopeKind::With) { |
1393 | return true; |
1394 | } |
1395 | } |
1396 | |
1397 | return false; |
1398 | } |
1399 | |
1400 | size_t BytecodeEmitter::countThisEnvironmentHops() const { |
1401 | unsigned numHops = 0; |
1402 | |
1403 | for (const auto* current = this; current; current = current->parent) { |
1404 | for (EmitterScope* es = current->innermostEmitterScope(); es; |
1405 | es = es->enclosingInFrame()) { |
1406 | if (es->scope(current).is<FunctionScope>()) { |
1407 | if (!es->scope(current).isArrow()) { |
1408 | // The Parser is responsible for marking the environment as either |
1409 | // closed-over or used-by-eval which ensure that is must exist. |
1410 | MOZ_ASSERT(es->scope(current).hasEnvironment())do { static_assert( mozilla::detail::AssertionConditionType< decltype(es->scope(current).hasEnvironment())>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(es->scope(current).hasEnvironment()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("es->scope(current).hasEnvironment()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1410); AnnotateMozCrashReason("MOZ_ASSERT" "(" "es->scope(current).hasEnvironment()" ")"); do { *((volatile int*)__null) = 1410; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1411 | return numHops; |
1412 | } |
1413 | } |
1414 | if (es->scope(current).hasEnvironment()) { |
1415 | numHops++; |
1416 | } |
1417 | } |
1418 | } |
1419 | |
1420 | // The "this" environment exists outside of the compilation, but the |
1421 | // `ScopeContext` recorded the number of additional hops needed, so add |
1422 | // those in now. |
1423 | MOZ_ASSERT(sc->allowSuperProperty())do { static_assert( mozilla::detail::AssertionConditionType< decltype(sc->allowSuperProperty())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(sc->allowSuperProperty()) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("sc->allowSuperProperty()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1423); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->allowSuperProperty()" ")"); do { *((volatile int*)__null) = 1423; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1424 | numHops += compilationState.scopeContext.enclosingThisEnvironmentHops; |
1425 | return numHops; |
1426 | } |
1427 | |
1428 | bool BytecodeEmitter::emitThisEnvironmentCallee() { |
1429 | // Get the innermost enclosing function that has a |this| binding. |
1430 | |
1431 | // Directly load callee from the frame if possible. |
1432 | if (sc->isFunctionBox() && !sc->asFunctionBox()->isArrow()) { |
1433 | return emit1(JSOp::Callee); |
1434 | } |
1435 | |
1436 | // We have to load the callee from the environment chain. |
1437 | size_t numHops = countThisEnvironmentHops(); |
1438 | |
1439 | static_assert( |
1440 | ENVCOORD_HOPS_LIMIT - 1 <= UINT8_MAX(255), |
1441 | "JSOp::EnvCallee operand size should match ENVCOORD_HOPS_LIMIT"); |
1442 | |
1443 | MOZ_ASSERT(numHops < ENVCOORD_HOPS_LIMIT - 1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(numHops < ENVCOORD_HOPS_LIMIT - 1)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(numHops < ENVCOORD_HOPS_LIMIT - 1))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("numHops < ENVCOORD_HOPS_LIMIT - 1", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1443); AnnotateMozCrashReason("MOZ_ASSERT" "(" "numHops < ENVCOORD_HOPS_LIMIT - 1" ")"); do { *((volatile int*)__null) = 1443; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1444 | |
1445 | return emit2(JSOp::EnvCallee, numHops); |
1446 | } |
1447 | |
1448 | bool BytecodeEmitter::emitSuperBase() { |
1449 | if (!emitThisEnvironmentCallee()) { |
1450 | return false; |
1451 | } |
1452 | |
1453 | return emit1(JSOp::SuperBase); |
1454 | } |
1455 | |
1456 | void BytecodeEmitter::reportError(ParseNode* pn, unsigned errorNumber, |
1457 | ...) const { |
1458 | uint32_t offset = pn ? pn->pn_pos.begin : *scriptStartOffset; |
1459 | |
1460 | va_list args; |
1461 | va_start(args, errorNumber)__builtin_va_start(args, errorNumber); |
1462 | |
1463 | errorReporter().errorWithNotesAtVA(nullptr, AsVariant(offset), errorNumber, |
1464 | &args); |
1465 | |
1466 | va_end(args)__builtin_va_end(args); |
1467 | } |
1468 | |
1469 | void BytecodeEmitter::reportError(uint32_t offset, unsigned errorNumber, |
1470 | ...) const { |
1471 | va_list args; |
1472 | va_start(args, errorNumber)__builtin_va_start(args, errorNumber); |
1473 | |
1474 | errorReporter().errorWithNotesAtVA(nullptr, AsVariant(offset), errorNumber, |
1475 | &args); |
1476 | |
1477 | va_end(args)__builtin_va_end(args); |
1478 | } |
1479 | |
1480 | bool BytecodeEmitter::addObjLiteralData(ObjLiteralWriter& writer, |
1481 | GCThingIndex* outIndex) { |
1482 | if (!writer.checkForDuplicatedNames(fc)) { |
1483 | return false; |
1484 | } |
1485 | |
1486 | size_t len = writer.getCode().size(); |
1487 | auto* code = compilationState.alloc.newArrayUninitialized<uint8_t>(len); |
1488 | if (!code) { |
1489 | js::ReportOutOfMemory(fc); |
1490 | return false; |
1491 | } |
1492 | memcpy(code, writer.getCode().data(), len); |
1493 | |
1494 | ObjLiteralIndex objIndex(compilationState.objLiteralData.length()); |
1495 | if (uint32_t(objIndex) >= TaggedScriptThingIndex::IndexLimit) { |
1496 | ReportAllocationOverflow(fc); |
1497 | return false; |
1498 | } |
1499 | if (!compilationState.objLiteralData.emplaceBack(code, len, writer.getKind(), |
1500 | writer.getFlags(), |
1501 | writer.getPropertyCount())) { |
1502 | js::ReportOutOfMemory(fc); |
1503 | return false; |
1504 | } |
1505 | |
1506 | return perScriptData().gcThingList().append(objIndex, outIndex); |
1507 | } |
1508 | |
1509 | bool BytecodeEmitter::emitPrepareIteratorResult() { |
1510 | constexpr JSOp op = JSOp::NewObject; |
1511 | |
1512 | ObjLiteralWriter writer; |
1513 | writer.beginShape(op); |
1514 | |
1515 | writer.setPropNameNoDuplicateCheck(parserAtoms(), |
1516 | TaggedParserAtomIndex::WellKnown::value()); |
1517 | if (!writer.propWithUndefinedValue(fc)) { |
1518 | return false; |
1519 | } |
1520 | writer.setPropNameNoDuplicateCheck(parserAtoms(), |
1521 | TaggedParserAtomIndex::WellKnown::done()); |
1522 | if (!writer.propWithUndefinedValue(fc)) { |
1523 | return false; |
1524 | } |
1525 | |
1526 | GCThingIndex shape; |
1527 | if (!addObjLiteralData(writer, &shape)) { |
1528 | return false; |
1529 | } |
1530 | |
1531 | return emitGCIndexOp(op, shape); |
1532 | } |
1533 | |
1534 | bool BytecodeEmitter::emitFinishIteratorResult(bool done) { |
1535 | if (!emitAtomOp(JSOp::InitProp, TaggedParserAtomIndex::WellKnown::value())) { |
1536 | return false; |
1537 | } |
1538 | if (!emit1(done ? JSOp::True : JSOp::False)) { |
1539 | return false; |
1540 | } |
1541 | if (!emitAtomOp(JSOp::InitProp, TaggedParserAtomIndex::WellKnown::done())) { |
1542 | return false; |
1543 | } |
1544 | return true; |
1545 | } |
1546 | |
1547 | bool BytecodeEmitter::emitGetNameAtLocation(TaggedParserAtomIndex name, |
1548 | const NameLocation& loc) { |
1549 | NameOpEmitter noe(this, name, loc, NameOpEmitter::Kind::Get); |
1550 | if (!noe.emitGet()) { |
1551 | return false; |
1552 | } |
1553 | |
1554 | return true; |
1555 | } |
1556 | |
1557 | bool BytecodeEmitter::emitGetName(NameNode* name) { |
1558 | MOZ_ASSERT(name->isKind(ParseNodeKind::Name))do { static_assert( mozilla::detail::AssertionConditionType< decltype(name->isKind(ParseNodeKind::Name))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(name->isKind(ParseNodeKind ::Name)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("name->isKind(ParseNodeKind::Name)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1558); AnnotateMozCrashReason("MOZ_ASSERT" "(" "name->isKind(ParseNodeKind::Name)" ")"); do { *((volatile int*)__null) = 1558; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1559 | |
1560 | return emitGetName(name->name()); |
1561 | } |
1562 | |
1563 | bool BytecodeEmitter::emitGetPrivateName(NameNode* name) { |
1564 | MOZ_ASSERT(name->isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType< decltype(name->isKind(ParseNodeKind::PrivateName))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(name->isKind(ParseNodeKind::PrivateName)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("name->isKind(ParseNodeKind::PrivateName)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1564); AnnotateMozCrashReason("MOZ_ASSERT" "(" "name->isKind(ParseNodeKind::PrivateName)" ")"); do { *((volatile int*)__null) = 1564; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1565 | return emitGetPrivateName(name->name()); |
1566 | } |
1567 | |
1568 | bool BytecodeEmitter::emitGetPrivateName(TaggedParserAtomIndex nameAtom) { |
1569 | // The parser ensures the private name is present on the environment chain, |
1570 | // but its location can be Dynamic or Global when emitting debugger |
1571 | // eval-in-frame code. |
1572 | NameLocation location = lookupName(nameAtom); |
1573 | MOZ_ASSERT(location.kind() == NameLocation::Kind::FrameSlot ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(location.kind() == NameLocation::Kind::FrameSlot || location .kind() == NameLocation::Kind::EnvironmentCoordinate || location .kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation ::Kind::Global)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(location.kind() == NameLocation ::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate || location.kind() == NameLocation::Kind::Dynamic || location .kind() == NameLocation::Kind::Global))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("location.kind() == NameLocation::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate || location.kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation::Kind::Global" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1576); AnnotateMozCrashReason("MOZ_ASSERT" "(" "location.kind() == NameLocation::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate || location.kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation::Kind::Global" ")"); do { *((volatile int*)__null) = 1576; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
1574 | location.kind() == NameLocation::Kind::EnvironmentCoordinate ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(location.kind() == NameLocation::Kind::FrameSlot || location .kind() == NameLocation::Kind::EnvironmentCoordinate || location .kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation ::Kind::Global)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(location.kind() == NameLocation ::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate || location.kind() == NameLocation::Kind::Dynamic || location .kind() == NameLocation::Kind::Global))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("location.kind() == NameLocation::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate || location.kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation::Kind::Global" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1576); AnnotateMozCrashReason("MOZ_ASSERT" "(" "location.kind() == NameLocation::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate || location.kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation::Kind::Global" ")"); do { *((volatile int*)__null) = 1576; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
1575 | location.kind() == NameLocation::Kind::Dynamic ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(location.kind() == NameLocation::Kind::FrameSlot || location .kind() == NameLocation::Kind::EnvironmentCoordinate || location .kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation ::Kind::Global)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(location.kind() == NameLocation ::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate || location.kind() == NameLocation::Kind::Dynamic || location .kind() == NameLocation::Kind::Global))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("location.kind() == NameLocation::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate || location.kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation::Kind::Global" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1576); AnnotateMozCrashReason("MOZ_ASSERT" "(" "location.kind() == NameLocation::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate || location.kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation::Kind::Global" ")"); do { *((volatile int*)__null) = 1576; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
1576 | location.kind() == NameLocation::Kind::Global)do { static_assert( mozilla::detail::AssertionConditionType< decltype(location.kind() == NameLocation::Kind::FrameSlot || location .kind() == NameLocation::Kind::EnvironmentCoordinate || location .kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation ::Kind::Global)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(location.kind() == NameLocation ::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate || location.kind() == NameLocation::Kind::Dynamic || location .kind() == NameLocation::Kind::Global))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("location.kind() == NameLocation::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate || location.kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation::Kind::Global" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1576); AnnotateMozCrashReason("MOZ_ASSERT" "(" "location.kind() == NameLocation::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate || location.kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation::Kind::Global" ")"); do { *((volatile int*)__null) = 1576; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1577 | |
1578 | return emitGetNameAtLocation(nameAtom, location); |
1579 | } |
1580 | |
1581 | bool BytecodeEmitter::emitTDZCheckIfNeeded(TaggedParserAtomIndex name, |
1582 | const NameLocation& loc, |
1583 | ValueIsOnStack isOnStack) { |
1584 | // Dynamic accesses have TDZ checks built into their VM code and should |
1585 | // never emit explicit TDZ checks. |
1586 | MOZ_ASSERT(loc.hasKnownSlot())do { static_assert( mozilla::detail::AssertionConditionType< decltype(loc.hasKnownSlot())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(loc.hasKnownSlot()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("loc.hasKnownSlot()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1586); AnnotateMozCrashReason("MOZ_ASSERT" "(" "loc.hasKnownSlot()" ")"); do { *((volatile int*)__null) = 1586; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1587 | MOZ_ASSERT(loc.isLexical() || loc.isPrivateMethod() || loc.isSynthetic())do { static_assert( mozilla::detail::AssertionConditionType< decltype(loc.isLexical() || loc.isPrivateMethod() || loc.isSynthetic ())>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(loc.isLexical() || loc.isPrivateMethod() || loc.isSynthetic ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("loc.isLexical() || loc.isPrivateMethod() || loc.isSynthetic()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1587); AnnotateMozCrashReason("MOZ_ASSERT" "(" "loc.isLexical() || loc.isPrivateMethod() || loc.isSynthetic()" ")"); do { *((volatile int*)__null) = 1587; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1588 | |
1589 | // Private names are implemented as lexical bindings, but it's just an |
1590 | // implementation detail. Per spec there's no TDZ check when using them. |
1591 | if (parserAtoms().isPrivateName(name)) { |
1592 | return true; |
1593 | } |
1594 | |
1595 | Maybe<MaybeCheckTDZ> check = |
1596 | innermostTDZCheckCache->needsTDZCheck(this, name); |
1597 | if (!check) { |
1598 | return false; |
1599 | } |
1600 | |
1601 | // We've already emitted a check in this basic block. |
1602 | if (*check == DontCheckTDZ) { |
1603 | return true; |
1604 | } |
1605 | |
1606 | // If the value is not on the stack, we have to load it first. |
1607 | if (isOnStack == ValueIsOnStack::No) { |
1608 | if (loc.kind() == NameLocation::Kind::FrameSlot) { |
1609 | if (!emitLocalOp(JSOp::GetLocal, loc.frameSlot())) { |
1610 | return false; |
1611 | } |
1612 | } else { |
1613 | if (!emitEnvCoordOp(JSOp::GetAliasedVar, loc.environmentCoordinate())) { |
1614 | return false; |
1615 | } |
1616 | } |
1617 | } |
1618 | |
1619 | // Emit the lexical check. |
1620 | if (loc.kind() == NameLocation::Kind::FrameSlot) { |
1621 | if (!emitLocalOp(JSOp::CheckLexical, loc.frameSlot())) { |
1622 | return false; |
1623 | } |
1624 | } else { |
1625 | if (!emitEnvCoordOp(JSOp::CheckAliasedLexical, |
1626 | loc.environmentCoordinate())) { |
1627 | return false; |
1628 | } |
1629 | } |
1630 | |
1631 | // Pop the value if needed. |
1632 | if (isOnStack == ValueIsOnStack::No) { |
1633 | if (!emit1(JSOp::Pop)) { |
1634 | return false; |
1635 | } |
1636 | } |
1637 | |
1638 | return innermostTDZCheckCache->noteTDZCheck(this, name, DontCheckTDZ); |
1639 | } |
1640 | |
1641 | bool BytecodeEmitter::emitPropLHS(PropertyAccess* prop) { |
1642 | MOZ_ASSERT(!prop->isSuper())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!prop->isSuper())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!prop->isSuper()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!prop->isSuper()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1642); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!prop->isSuper()" ")"); do { *((volatile int*)__null) = 1642; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1643 | |
1644 | ParseNode* expr = &prop->expression(); |
1645 | |
1646 | if (!expr->is<PropertyAccess>() || expr->as<PropertyAccess>().isSuper()) { |
1647 | // The non-optimized case. |
1648 | return emitTree(expr); |
1649 | } |
1650 | |
1651 | // If the object operand is also a dotted property reference, reverse the |
1652 | // list linked via expression() temporarily so we can iterate over it from |
1653 | // the bottom up (reversing again as we go), to avoid excessive recursion. |
1654 | PropertyAccess* pndot = &expr->as<PropertyAccess>(); |
1655 | ParseNode* pnup = nullptr; |
1656 | ParseNode* pndown; |
1657 | for (;;) { |
1658 | // Reverse pndot->expression() to point up, not down. |
1659 | pndown = &pndot->expression(); |
1660 | pndot->setExpression(pnup); |
1661 | if (!pndown->is<PropertyAccess>() || |
1662 | pndown->as<PropertyAccess>().isSuper()) { |
1663 | break; |
1664 | } |
1665 | pnup = pndot; |
1666 | pndot = &pndown->as<PropertyAccess>(); |
1667 | } |
1668 | |
1669 | // pndown is a primary expression, not a dotted property reference. |
1670 | if (!emitTree(pndown)) { |
1671 | return false; |
1672 | } |
1673 | |
1674 | while (true) { |
1675 | // Walk back up the list, emitting annotated name ops. |
1676 | if (!emitAtomOp(JSOp::GetProp, pndot->key().atom())) { |
1677 | return false; |
1678 | } |
1679 | |
1680 | // Reverse the pndot->expression() link again. |
1681 | pnup = pndot->maybeExpression(); |
1682 | pndot->setExpression(pndown); |
1683 | pndown = pndot; |
1684 | if (!pnup) { |
1685 | break; |
1686 | } |
1687 | pndot = &pnup->as<PropertyAccess>(); |
1688 | } |
1689 | return true; |
1690 | } |
1691 | |
1692 | bool BytecodeEmitter::emitPropIncDec(UnaryNode* incDec, ValueUsage valueUsage) { |
1693 | PropertyAccess* prop = &incDec->kid()->as<PropertyAccess>(); |
1694 | bool isSuper = prop->isSuper(); |
1695 | ParseNodeKind kind = incDec->getKind(); |
1696 | PropOpEmitter poe( |
1697 | this, |
1698 | kind == ParseNodeKind::PostIncrementExpr |
1699 | ? PropOpEmitter::Kind::PostIncrement |
1700 | : kind == ParseNodeKind::PreIncrementExpr |
1701 | ? PropOpEmitter::Kind::PreIncrement |
1702 | : kind == ParseNodeKind::PostDecrementExpr |
1703 | ? PropOpEmitter::Kind::PostDecrement |
1704 | : PropOpEmitter::Kind::PreDecrement, |
1705 | isSuper ? PropOpEmitter::ObjKind::Super : PropOpEmitter::ObjKind::Other); |
1706 | if (!poe.prepareForObj()) { |
1707 | return false; |
1708 | } |
1709 | if (isSuper) { |
1710 | UnaryNode* base = &prop->expression().as<UnaryNode>(); |
1711 | if (!emitGetThisForSuperBase(base)) { |
1712 | // [stack] THIS |
1713 | return false; |
1714 | } |
1715 | } else { |
1716 | if (!emitPropLHS(prop)) { |
1717 | // [stack] OBJ |
1718 | return false; |
1719 | } |
1720 | } |
1721 | if (!poe.emitIncDec(prop->key().atom(), valueUsage)) { |
1722 | // [stack] RESULT |
1723 | return false; |
1724 | } |
1725 | |
1726 | return true; |
1727 | } |
1728 | |
1729 | bool BytecodeEmitter::emitNameIncDec(UnaryNode* incDec, ValueUsage valueUsage) { |
1730 | MOZ_ASSERT(incDec->kid()->isKind(ParseNodeKind::Name))do { static_assert( mozilla::detail::AssertionConditionType< decltype(incDec->kid()->isKind(ParseNodeKind::Name))> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(incDec->kid()->isKind(ParseNodeKind::Name)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("incDec->kid()->isKind(ParseNodeKind::Name)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1730); AnnotateMozCrashReason("MOZ_ASSERT" "(" "incDec->kid()->isKind(ParseNodeKind::Name)" ")"); do { *((volatile int*)__null) = 1730; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1731 | |
1732 | ParseNodeKind kind = incDec->getKind(); |
1733 | NameNode* name = &incDec->kid()->as<NameNode>(); |
1734 | NameOpEmitter noe(this, name->atom(), |
1735 | kind == ParseNodeKind::PostIncrementExpr |
1736 | ? NameOpEmitter::Kind::PostIncrement |
1737 | : kind == ParseNodeKind::PreIncrementExpr |
1738 | ? NameOpEmitter::Kind::PreIncrement |
1739 | : kind == ParseNodeKind::PostDecrementExpr |
1740 | ? NameOpEmitter::Kind::PostDecrement |
1741 | : NameOpEmitter::Kind::PreDecrement); |
1742 | if (!noe.emitIncDec(valueUsage)) { |
1743 | return false; |
1744 | } |
1745 | |
1746 | return true; |
1747 | } |
1748 | |
1749 | bool BytecodeEmitter::emitElemObjAndKey(PropertyByValue* elem, |
1750 | ElemOpEmitter& eoe) { |
1751 | ParseNode* exprOrSuper = &elem->expression(); |
1752 | ParseNode* key = &elem->key(); |
1753 | |
1754 | if (!eoe.prepareForObj()) { |
1755 | // [stack] |
1756 | return false; |
1757 | } |
1758 | |
1759 | if (elem->isSuper()) { |
1760 | auto* base = &exprOrSuper->as<UnaryNode>(); |
1761 | if (!emitGetThisForSuperBase(base)) { |
1762 | // [stack] THIS |
1763 | return false; |
1764 | } |
1765 | } else { |
1766 | if (!emitTree(exprOrSuper)) { |
1767 | // [stack] OBJ |
1768 | return false; |
1769 | } |
1770 | } |
1771 | |
1772 | if (!eoe.prepareForKey()) { |
1773 | // [stack] # if Super |
1774 | // [stack] THIS? THIS |
1775 | // [stack] # otherwise |
1776 | // [stack] OBJ? OBJ |
1777 | return false; |
1778 | } |
1779 | |
1780 | if (!emitTree(key)) { |
1781 | // [stack] # if Super |
1782 | // [stack] THIS? THIS KEY |
1783 | // [stack] # otherwise |
1784 | // [stack] OBJ? OBJ KEY |
1785 | return false; |
1786 | } |
1787 | |
1788 | return true; |
1789 | } |
1790 | |
1791 | bool BytecodeEmitter::emitElemOpBase(JSOp op) { |
1792 | if (!emit1(op)) { |
1793 | return false; |
1794 | } |
1795 | |
1796 | return true; |
1797 | } |
1798 | |
1799 | static ElemOpEmitter::Kind ConvertIncDecKind(ParseNodeKind kind) { |
1800 | switch (kind) { |
1801 | case ParseNodeKind::PostIncrementExpr: |
1802 | return ElemOpEmitter::Kind::PostIncrement; |
1803 | case ParseNodeKind::PreIncrementExpr: |
1804 | return ElemOpEmitter::Kind::PreIncrement; |
1805 | case ParseNodeKind::PostDecrementExpr: |
1806 | return ElemOpEmitter::Kind::PostDecrement; |
1807 | case ParseNodeKind::PreDecrementExpr: |
1808 | return ElemOpEmitter::Kind::PreDecrement; |
1809 | default: |
1810 | MOZ_CRASH("unexpected inc/dec node kind")do { do { } while (false); MOZ_ReportCrash("" "unexpected inc/dec node kind" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1810); AnnotateMozCrashReason("MOZ_CRASH(" "unexpected inc/dec node kind" ")"); do { *((volatile int*)__null) = 1810; __attribute__((nomerge )) ::abort(); } while (false); } while (false); |
1811 | } |
1812 | } |
1813 | |
1814 | static PrivateOpEmitter::Kind PrivateConvertIncDecKind(ParseNodeKind kind) { |
1815 | switch (kind) { |
1816 | case ParseNodeKind::PostIncrementExpr: |
1817 | return PrivateOpEmitter::Kind::PostIncrement; |
1818 | case ParseNodeKind::PreIncrementExpr: |
1819 | return PrivateOpEmitter::Kind::PreIncrement; |
1820 | case ParseNodeKind::PostDecrementExpr: |
1821 | return PrivateOpEmitter::Kind::PostDecrement; |
1822 | case ParseNodeKind::PreDecrementExpr: |
1823 | return PrivateOpEmitter::Kind::PreDecrement; |
1824 | default: |
1825 | MOZ_CRASH("unexpected inc/dec node kind")do { do { } while (false); MOZ_ReportCrash("" "unexpected inc/dec node kind" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1825); AnnotateMozCrashReason("MOZ_CRASH(" "unexpected inc/dec node kind" ")"); do { *((volatile int*)__null) = 1825; __attribute__((nomerge )) ::abort(); } while (false); } while (false); |
1826 | } |
1827 | } |
1828 | |
1829 | bool BytecodeEmitter::emitElemIncDec(UnaryNode* incDec, ValueUsage valueUsage) { |
1830 | PropertyByValue* elemExpr = &incDec->kid()->as<PropertyByValue>(); |
1831 | bool isSuper = elemExpr->isSuper(); |
1832 | MOZ_ASSERT(!elemExpr->key().isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!elemExpr->key().isKind(ParseNodeKind::PrivateName ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!elemExpr->key().isKind(ParseNodeKind::PrivateName )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!elemExpr->key().isKind(ParseNodeKind::PrivateName)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1832); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elemExpr->key().isKind(ParseNodeKind::PrivateName)" ")"); do { *((volatile int*)__null) = 1832; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1833 | ParseNodeKind kind = incDec->getKind(); |
1834 | ElemOpEmitter eoe( |
1835 | this, ConvertIncDecKind(kind), |
1836 | isSuper ? ElemOpEmitter::ObjKind::Super : ElemOpEmitter::ObjKind::Other); |
1837 | if (!emitElemObjAndKey(elemExpr, eoe)) { |
1838 | // [stack] # if Super |
1839 | // [stack] THIS KEY |
1840 | // [stack] # otherwise |
1841 | // [stack] OBJ KEY |
1842 | return false; |
1843 | } |
1844 | if (!eoe.emitIncDec(valueUsage)) { |
1845 | // [stack] RESULT |
1846 | return false; |
1847 | } |
1848 | |
1849 | return true; |
1850 | } |
1851 | |
1852 | bool BytecodeEmitter::emitCallIncDec(UnaryNode* incDec) { |
1853 | MOZ_ASSERT(incDec->isKind(ParseNodeKind::PreIncrementExpr) ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec ->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind (ParseNodeKind::PostDecrementExpr))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(incDec->isKind(ParseNodeKind ::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr ) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec ->isKind(ParseNodeKind::PostDecrementExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind(ParseNodeKind::PostDecrementExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1856); AnnotateMozCrashReason("MOZ_ASSERT" "(" "incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind(ParseNodeKind::PostDecrementExpr)" ")"); do { *((volatile int*)__null) = 1856; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
1854 | incDec->isKind(ParseNodeKind::PostIncrementExpr) ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec ->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind (ParseNodeKind::PostDecrementExpr))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(incDec->isKind(ParseNodeKind ::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr ) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec ->isKind(ParseNodeKind::PostDecrementExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind(ParseNodeKind::PostDecrementExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1856); AnnotateMozCrashReason("MOZ_ASSERT" "(" "incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind(ParseNodeKind::PostDecrementExpr)" ")"); do { *((volatile int*)__null) = 1856; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
1855 | incDec->isKind(ParseNodeKind::PreDecrementExpr) ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec ->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind (ParseNodeKind::PostDecrementExpr))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(incDec->isKind(ParseNodeKind ::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr ) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec ->isKind(ParseNodeKind::PostDecrementExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind(ParseNodeKind::PostDecrementExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1856); AnnotateMozCrashReason("MOZ_ASSERT" "(" "incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind(ParseNodeKind::PostDecrementExpr)" ")"); do { *((volatile int*)__null) = 1856; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
1856 | incDec->isKind(ParseNodeKind::PostDecrementExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec ->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind (ParseNodeKind::PostDecrementExpr))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(incDec->isKind(ParseNodeKind ::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr ) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec ->isKind(ParseNodeKind::PostDecrementExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind(ParseNodeKind::PostDecrementExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1856); AnnotateMozCrashReason("MOZ_ASSERT" "(" "incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind(ParseNodeKind::PostDecrementExpr)" ")"); do { *((volatile int*)__null) = 1856; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1857 | |
1858 | ParseNode* call = incDec->kid(); |
1859 | MOZ_ASSERT(call->isKind(ParseNodeKind::CallExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(call->isKind(ParseNodeKind::CallExpr))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(call->isKind(ParseNodeKind::CallExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("call->isKind(ParseNodeKind::CallExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1859); AnnotateMozCrashReason("MOZ_ASSERT" "(" "call->isKind(ParseNodeKind::CallExpr)" ")"); do { *((volatile int*)__null) = 1859; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1860 | if (!emitTree(call)) { |
1861 | // [stack] CALLRESULT |
1862 | return false; |
1863 | } |
1864 | if (!emit1(JSOp::ToNumeric)) { |
1865 | // [stack] N |
1866 | return false; |
1867 | } |
1868 | |
1869 | // The increment/decrement has no side effects, so proceed to throw for |
1870 | // invalid assignment target. |
1871 | return emit2(JSOp::ThrowMsg, uint8_t(ThrowMsgKind::AssignToCall)); |
1872 | } |
1873 | |
1874 | bool BytecodeEmitter::emitPrivateIncDec(UnaryNode* incDec, |
1875 | ValueUsage valueUsage) { |
1876 | PrivateMemberAccess* privateExpr = &incDec->kid()->as<PrivateMemberAccess>(); |
1877 | ParseNodeKind kind = incDec->getKind(); |
1878 | PrivateOpEmitter xoe(this, PrivateConvertIncDecKind(kind), |
1879 | privateExpr->privateName().name()); |
1880 | if (!emitTree(&privateExpr->expression())) { |
1881 | // [stack] OBJ |
1882 | return false; |
1883 | } |
1884 | if (!xoe.emitReference()) { |
1885 | // [stack] OBJ NAME |
1886 | return false; |
1887 | } |
1888 | if (!xoe.emitIncDec(valueUsage)) { |
1889 | // [stack] RESULT |
1890 | return false; |
1891 | } |
1892 | |
1893 | return true; |
1894 | } |
1895 | |
1896 | bool BytecodeEmitter::emitDouble(double d) { |
1897 | BytecodeOffset offset; |
1898 | if (!emitCheck(JSOp::Double, 9, &offset)) { |
1899 | return false; |
1900 | } |
1901 | |
1902 | jsbytecode* code = bytecodeSection().code(offset); |
1903 | code[0] = jsbytecode(JSOp::Double); |
1904 | SET_INLINE_VALUE(code, DoubleValue(d)); |
1905 | bytecodeSection().updateDepth(JSOp::Double, offset); |
1906 | return true; |
1907 | } |
1908 | |
1909 | bool BytecodeEmitter::emitNumberOp(double dval) { |
1910 | int32_t ival; |
1911 | if (NumberIsInt32(dval, &ival)) { |
1912 | if (ival == 0) { |
1913 | return emit1(JSOp::Zero); |
1914 | } |
1915 | if (ival == 1) { |
1916 | return emit1(JSOp::One); |
1917 | } |
1918 | if ((int)(int8_t)ival == ival) { |
1919 | return emit2(JSOp::Int8, uint8_t(int8_t(ival))); |
1920 | } |
1921 | |
1922 | uint32_t u = uint32_t(ival); |
1923 | if (u < Bit(16)) { |
1924 | if (!emitUint16Operand(JSOp::Uint16, u)) { |
1925 | return false; |
1926 | } |
1927 | } else if (u < Bit(24)) { |
1928 | BytecodeOffset off; |
1929 | if (!emitN(JSOp::Uint24, 3, &off)) { |
1930 | return false; |
1931 | } |
1932 | SET_UINT24(bytecodeSection().code(off), u); |
1933 | } else { |
1934 | BytecodeOffset off; |
1935 | if (!emitN(JSOp::Int32, 4, &off)) { |
1936 | return false; |
1937 | } |
1938 | SET_INT32(bytecodeSection().code(off), ival); |
1939 | } |
1940 | return true; |
1941 | } |
1942 | |
1943 | return emitDouble(dval); |
1944 | } |
1945 | |
1946 | /* |
1947 | * Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. |
1948 | * LLVM is deciding to inline this function which uses a lot of stack space |
1949 | * into emitTree which is recursive and uses relatively little stack space. |
1950 | */ |
1951 | MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitSwitch(SwitchStatement* switchStmt) { |
1952 | LexicalScopeNode& lexical = switchStmt->lexicalForCaseList(); |
1953 | MOZ_ASSERT(lexical.isKind(ParseNodeKind::LexicalScope))do { static_assert( mozilla::detail::AssertionConditionType< decltype(lexical.isKind(ParseNodeKind::LexicalScope))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(lexical.isKind(ParseNodeKind::LexicalScope)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("lexical.isKind(ParseNodeKind::LexicalScope)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1953); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lexical.isKind(ParseNodeKind::LexicalScope)" ")"); do { *((volatile int*)__null) = 1953; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1954 | ListNode* cases = &lexical.scopeBody()->as<ListNode>(); |
1955 | MOZ_ASSERT(cases->isKind(ParseNodeKind::StatementList))do { static_assert( mozilla::detail::AssertionConditionType< decltype(cases->isKind(ParseNodeKind::StatementList))>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(cases->isKind(ParseNodeKind::StatementList)))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("cases->isKind(ParseNodeKind::StatementList)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1955); AnnotateMozCrashReason("MOZ_ASSERT" "(" "cases->isKind(ParseNodeKind::StatementList)" ")"); do { *((volatile int*)__null) = 1955; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1956 | |
1957 | SwitchEmitter se(this); |
1958 | if (!se.emitDiscriminant(switchStmt->discriminant().pn_pos.begin)) { |
1959 | return false; |
1960 | } |
1961 | |
1962 | if (!markStepBreakpoint()) { |
1963 | return false; |
1964 | } |
1965 | if (!emitTree(&switchStmt->discriminant())) { |
1966 | return false; |
1967 | } |
1968 | |
1969 | // Enter the scope before pushing the switch BreakableControl since all |
1970 | // breaks are under this scope. |
1971 | |
1972 | if (!lexical.isEmptyScope()) { |
1973 | if (!se.emitLexical(lexical.scopeBindings())) { |
1974 | return false; |
1975 | } |
1976 | |
1977 | // A switch statement may contain hoisted functions inside its |
1978 | // cases. The hasTopLevelFunctionDeclarations flag is propagated from the |
1979 | // StatementList bodies of the cases to the case list. |
1980 | if (cases->hasTopLevelFunctionDeclarations()) { |
1981 | for (ParseNode* item : cases->contents()) { |
1982 | CaseClause* caseClause = &item->as<CaseClause>(); |
1983 | ListNode* statements = caseClause->statementList(); |
1984 | if (statements->hasTopLevelFunctionDeclarations()) { |
1985 | if (!emitHoistedFunctionsInList(statements)) { |
1986 | return false; |
1987 | } |
1988 | } |
1989 | } |
1990 | } |
1991 | } else { |
1992 | MOZ_ASSERT(!cases->hasTopLevelFunctionDeclarations())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!cases->hasTopLevelFunctionDeclarations())>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(!cases->hasTopLevelFunctionDeclarations()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!cases->hasTopLevelFunctionDeclarations()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1992); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!cases->hasTopLevelFunctionDeclarations()" ")"); do { *((volatile int*)__null) = 1992; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1993 | } |
1994 | |
1995 | SwitchEmitter::TableGenerator tableGen(this); |
1996 | uint32_t caseCount = cases->count() - (switchStmt->hasDefault() ? 1 : 0); |
1997 | if (caseCount == 0) { |
1998 | tableGen.finish(0); |
1999 | } else { |
2000 | for (ParseNode* item : cases->contents()) { |
2001 | CaseClause* caseClause = &item->as<CaseClause>(); |
2002 | if (caseClause->isDefault()) { |
2003 | continue; |
2004 | } |
2005 | |
2006 | ParseNode* caseValue = caseClause->caseExpression(); |
2007 | |
2008 | if (caseValue->getKind() != ParseNodeKind::NumberExpr) { |
2009 | tableGen.setInvalid(); |
2010 | break; |
2011 | } |
2012 | |
2013 | int32_t i; |
2014 | if (!NumberEqualsInt32(caseValue->as<NumericLiteral>().value(), &i)) { |
2015 | tableGen.setInvalid(); |
2016 | break; |
2017 | } |
2018 | |
2019 | if (!tableGen.addNumber(i)) { |
2020 | return false; |
2021 | } |
2022 | } |
2023 | |
2024 | tableGen.finish(caseCount); |
2025 | } |
2026 | |
2027 | if (!se.validateCaseCount(caseCount)) { |
2028 | return false; |
2029 | } |
2030 | |
2031 | bool isTableSwitch = tableGen.isValid(); |
2032 | if (isTableSwitch) { |
2033 | if (!se.emitTable(tableGen)) { |
2034 | return false; |
2035 | } |
2036 | } else { |
2037 | if (!se.emitCond()) { |
2038 | return false; |
2039 | } |
2040 | |
2041 | // Emit code for evaluating cases and jumping to case statements. |
2042 | for (ParseNode* item : cases->contents()) { |
2043 | CaseClause* caseClause = &item->as<CaseClause>(); |
2044 | if (caseClause->isDefault()) { |
2045 | continue; |
2046 | } |
2047 | |
2048 | if (!se.prepareForCaseValue()) { |
2049 | return false; |
2050 | } |
2051 | |
2052 | ParseNode* caseValue = caseClause->caseExpression(); |
2053 | // If the expression is a literal, suppress line number emission so |
2054 | // that debugging works more naturally. |
2055 | if (!emitTree( |
2056 | caseValue, ValueUsage::WantValue, |
2057 | caseValue->isLiteral() ? SUPPRESS_LINENOTE : EMIT_LINENOTE)) { |
2058 | return false; |
2059 | } |
2060 | |
2061 | if (!se.emitCaseJump()) { |
2062 | return false; |
2063 | } |
2064 | } |
2065 | } |
2066 | |
2067 | // Emit code for each case's statements. |
2068 | for (ParseNode* item : cases->contents()) { |
2069 | CaseClause* caseClause = &item->as<CaseClause>(); |
2070 | if (caseClause->isDefault()) { |
2071 | if (!se.emitDefaultBody()) { |
2072 | return false; |
2073 | } |
2074 | } else { |
2075 | if (isTableSwitch) { |
2076 | ParseNode* caseValue = caseClause->caseExpression(); |
2077 | MOZ_ASSERT(caseValue->isKind(ParseNodeKind::NumberExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(caseValue->isKind(ParseNodeKind::NumberExpr))> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(caseValue->isKind(ParseNodeKind::NumberExpr)))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("caseValue->isKind(ParseNodeKind::NumberExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2077); AnnotateMozCrashReason("MOZ_ASSERT" "(" "caseValue->isKind(ParseNodeKind::NumberExpr)" ")"); do { *((volatile int*)__null) = 2077; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2078 | |
2079 | NumericLiteral* literal = &caseValue->as<NumericLiteral>(); |
2080 | #ifdef DEBUG1 |
2081 | // Use NumberEqualsInt32 here because switches compare using |
2082 | // strict equality, which will equate -0 and +0. In contrast |
2083 | // NumberIsInt32 would return false for -0. |
2084 | int32_t v; |
2085 | MOZ_ASSERT(mozilla::NumberEqualsInt32(literal->value(), &v))do { static_assert( mozilla::detail::AssertionConditionType< decltype(mozilla::NumberEqualsInt32(literal->value(), & v))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(mozilla::NumberEqualsInt32(literal->value(), & v)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mozilla::NumberEqualsInt32(literal->value(), &v)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2085); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mozilla::NumberEqualsInt32(literal->value(), &v)" ")"); do { *((volatile int*)__null) = 2085; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2086 | #endif |
2087 | int32_t i = int32_t(literal->value()); |
2088 | |
2089 | if (!se.emitCaseBody(i, tableGen)) { |
2090 | return false; |
2091 | } |
2092 | } else { |
2093 | if (!se.emitCaseBody()) { |
2094 | return false; |
2095 | } |
2096 | } |
2097 | } |
2098 | |
2099 | if (!emitTree(caseClause->statementList())) { |
2100 | return false; |
2101 | } |
2102 | } |
2103 | |
2104 | if (!se.emitEnd()) { |
2105 | return false; |
2106 | } |
2107 | |
2108 | return true; |
2109 | } |
2110 | |
2111 | bool BytecodeEmitter::allocateResumeIndex(BytecodeOffset offset, |
2112 | uint32_t* resumeIndex) { |
2113 | static constexpr uint32_t MaxResumeIndex = BitMask(24); |
2114 | |
2115 | static_assert( |
2116 | MaxResumeIndex < uint32_t(AbstractGeneratorObject::RESUME_INDEX_RUNNING), |
2117 | "resumeIndex should not include magic AbstractGeneratorObject " |
2118 | "resumeIndex values"); |
2119 | static_assert( |
2120 | MaxResumeIndex <= INT32_MAX(2147483647) / sizeof(uintptr_t), |
2121 | "resumeIndex * sizeof(uintptr_t) must fit in an int32. JIT code relies " |
2122 | "on this when loading resume entries from BaselineScript"); |
2123 | |
2124 | *resumeIndex = bytecodeSection().resumeOffsetList().length(); |
2125 | if (*resumeIndex > MaxResumeIndex) { |
2126 | reportError(nullptr, JSMSG_TOO_MANY_RESUME_INDEXES); |
2127 | return false; |
2128 | } |
2129 | |
2130 | return bytecodeSection().resumeOffsetList().append(offset.value()); |
2131 | } |
2132 | |
2133 | bool BytecodeEmitter::allocateResumeIndexRange( |
2134 | mozilla::Span<BytecodeOffset> offsets, uint32_t* firstResumeIndex) { |
2135 | *firstResumeIndex = 0; |
2136 | |
2137 | for (size_t i = 0, len = offsets.size(); i < len; i++) { |
2138 | uint32_t resumeIndex; |
2139 | if (!allocateResumeIndex(offsets[i], &resumeIndex)) { |
2140 | return false; |
2141 | } |
2142 | if (i == 0) { |
2143 | *firstResumeIndex = resumeIndex; |
2144 | } |
2145 | } |
2146 | |
2147 | return true; |
2148 | } |
2149 | |
2150 | bool BytecodeEmitter::emitYieldOp(JSOp op) { |
2151 | // ParseContext::Scope::setOwnStackSlotCount should check the fixed slot |
2152 | // for the following, and it should prevent using fixed slot if there are |
2153 | // too many bindings: |
2154 | // * generator or asyn function |
2155 | // * module code after top-level await |
2156 | MOZ_ASSERT(innermostEmitterScopeNoCheck()->frameSlotEnd() <=do { static_assert( mozilla::detail::AssertionConditionType< decltype(innermostEmitterScopeNoCheck()->frameSlotEnd() <= ParseContext::Scope::FixedSlotLimit)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(innermostEmitterScopeNoCheck ()->frameSlotEnd() <= ParseContext::Scope::FixedSlotLimit ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "innermostEmitterScopeNoCheck()->frameSlotEnd() <= ParseContext::Scope::FixedSlotLimit" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2157); AnnotateMozCrashReason("MOZ_ASSERT" "(" "innermostEmitterScopeNoCheck()->frameSlotEnd() <= ParseContext::Scope::FixedSlotLimit" ")"); do { *((volatile int*)__null) = 2157; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2157 | ParseContext::Scope::FixedSlotLimit)do { static_assert( mozilla::detail::AssertionConditionType< decltype(innermostEmitterScopeNoCheck()->frameSlotEnd() <= ParseContext::Scope::FixedSlotLimit)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(innermostEmitterScopeNoCheck ()->frameSlotEnd() <= ParseContext::Scope::FixedSlotLimit ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "innermostEmitterScopeNoCheck()->frameSlotEnd() <= ParseContext::Scope::FixedSlotLimit" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2157); AnnotateMozCrashReason("MOZ_ASSERT" "(" "innermostEmitterScopeNoCheck()->frameSlotEnd() <= ParseContext::Scope::FixedSlotLimit" ")"); do { *((volatile int*)__null) = 2157; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2158 | |
2159 | if (op == JSOp::FinalYieldRval) { |
2160 | return emit1(JSOp::FinalYieldRval); |
2161 | } |
2162 | |
2163 | MOZ_ASSERT(op == JSOp::InitialYield || op == JSOp::Yield ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(op == JSOp::InitialYield || op == JSOp::Yield || op == JSOp::Await)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(op == JSOp::InitialYield || op == JSOp::Yield || op == JSOp::Await))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("op == JSOp::InitialYield || op == JSOp::Yield || op == JSOp::Await" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2164); AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::InitialYield || op == JSOp::Yield || op == JSOp::Await" ")"); do { *((volatile int*)__null) = 2164; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2164 | op == JSOp::Await)do { static_assert( mozilla::detail::AssertionConditionType< decltype(op == JSOp::InitialYield || op == JSOp::Yield || op == JSOp::Await)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(op == JSOp::InitialYield || op == JSOp::Yield || op == JSOp::Await))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("op == JSOp::InitialYield || op == JSOp::Yield || op == JSOp::Await" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2164); AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::InitialYield || op == JSOp::Yield || op == JSOp::Await" ")"); do { *((volatile int*)__null) = 2164; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2165 | |
2166 | BytecodeOffset off; |
2167 | if (!emitN(op, 3, &off)) { |
2168 | return false; |
2169 | } |
2170 | |
2171 | if (op == JSOp::InitialYield || op == JSOp::Yield) { |
2172 | bytecodeSection().addNumYields(); |
2173 | } |
2174 | |
2175 | uint32_t resumeIndex; |
2176 | if (!allocateResumeIndex(bytecodeSection().offset(), &resumeIndex)) { |
2177 | return false; |
2178 | } |
2179 | |
2180 | SET_RESUMEINDEX(bytecodeSection().code(off), resumeIndex); |
2181 | |
2182 | BytecodeOffset unusedOffset; |
2183 | return emitJumpTargetOp(JSOp::AfterYield, &unusedOffset); |
2184 | } |
2185 | |
2186 | bool BytecodeEmitter::emitPushResumeKind(GeneratorResumeKind kind) { |
2187 | return emit2(JSOp::ResumeKind, uint8_t(kind)); |
2188 | } |
2189 | |
2190 | bool BytecodeEmitter::emitSetThis(BinaryNode* setThisNode) { |
2191 | // ParseNodeKind::SetThis is used to update |this| after a super() call |
2192 | // in a derived class constructor. |
2193 | |
2194 | MOZ_ASSERT(setThisNode->isKind(ParseNodeKind::SetThis))do { static_assert( mozilla::detail::AssertionConditionType< decltype(setThisNode->isKind(ParseNodeKind::SetThis))>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(setThisNode->isKind(ParseNodeKind::SetThis)))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("setThisNode->isKind(ParseNodeKind::SetThis)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2194); AnnotateMozCrashReason("MOZ_ASSERT" "(" "setThisNode->isKind(ParseNodeKind::SetThis)" ")"); do { *((volatile int*)__null) = 2194; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2195 | MOZ_ASSERT(setThisNode->left()->isKind(ParseNodeKind::Name))do { static_assert( mozilla::detail::AssertionConditionType< decltype(setThisNode->left()->isKind(ParseNodeKind::Name ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(setThisNode->left()->isKind(ParseNodeKind::Name )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("setThisNode->left()->isKind(ParseNodeKind::Name)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2195); AnnotateMozCrashReason("MOZ_ASSERT" "(" "setThisNode->left()->isKind(ParseNodeKind::Name)" ")"); do { *((volatile int*)__null) = 2195; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2196 | |
2197 | auto name = setThisNode->left()->as<NameNode>().name(); |
2198 | |
2199 | // The 'this' binding is not lexical, but due to super() semantics this |
2200 | // initialization needs to be treated as a lexical one. |
2201 | NameLocation loc = lookupName(name); |
2202 | NameLocation lexicalLoc; |
2203 | if (loc.kind() == NameLocation::Kind::FrameSlot) { |
2204 | lexicalLoc = NameLocation::FrameSlot(BindingKind::Let, loc.frameSlot()); |
2205 | } else if (loc.kind() == NameLocation::Kind::EnvironmentCoordinate) { |
2206 | EnvironmentCoordinate coord = loc.environmentCoordinate(); |
2207 | uint8_t hops = AssertedCast<uint8_t>(coord.hops()); |
2208 | lexicalLoc = NameLocation::EnvironmentCoordinate(BindingKind::Let, hops, |
2209 | coord.slot()); |
2210 | } else { |
2211 | MOZ_ASSERT(loc.kind() == NameLocation::Kind::Dynamic)do { static_assert( mozilla::detail::AssertionConditionType< decltype(loc.kind() == NameLocation::Kind::Dynamic)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(loc.kind() == NameLocation::Kind::Dynamic))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("loc.kind() == NameLocation::Kind::Dynamic" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2211); AnnotateMozCrashReason("MOZ_ASSERT" "(" "loc.kind() == NameLocation::Kind::Dynamic" ")"); do { *((volatile int*)__null) = 2211; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2212 | lexicalLoc = loc; |
2213 | } |
2214 | |
2215 | NameOpEmitter noe(this, name, lexicalLoc, NameOpEmitter::Kind::Initialize); |
2216 | if (!noe.prepareForRhs()) { |
2217 | // [stack] |
2218 | return false; |
2219 | } |
2220 | |
2221 | // Emit the new |this| value. |
2222 | if (!emitTree(setThisNode->right())) { |
2223 | // [stack] NEWTHIS |
2224 | return false; |
2225 | } |
2226 | |
2227 | // Get the original |this| and throw if we already initialized |
2228 | // it. Do *not* use the NameLocation argument, as that's the special |
2229 | // lexical location below to deal with super() semantics. |
2230 | if (!emitGetName(name)) { |
2231 | // [stack] NEWTHIS THIS |
2232 | return false; |
2233 | } |
2234 | if (!emit1(JSOp::CheckThisReinit)) { |
2235 | // [stack] NEWTHIS THIS |
2236 | return false; |
2237 | } |
2238 | if (!emit1(JSOp::Pop)) { |
2239 | // [stack] NEWTHIS |
2240 | return false; |
2241 | } |
2242 | if (!noe.emitAssignment()) { |
2243 | // [stack] NEWTHIS |
2244 | return false; |
2245 | } |
2246 | |
2247 | if (!emitInitializeInstanceMembers(true)) { |
2248 | return false; |
2249 | } |
2250 | |
2251 | return true; |
2252 | } |
2253 | |
2254 | bool BytecodeEmitter::defineHoistedTopLevelFunctions(ParseNode* body) { |
2255 | MOZ_ASSERT(inPrologue())do { static_assert( mozilla::detail::AssertionConditionType< decltype(inPrologue())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(inPrologue()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("inPrologue()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2255); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inPrologue()" ")"); do { *((volatile int*)__null) = 2255; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2256 | MOZ_ASSERT(sc->isGlobalContext() || (sc->isEvalContext() && !sc->strict()))do { static_assert( mozilla::detail::AssertionConditionType< decltype(sc->isGlobalContext() || (sc->isEvalContext() && !sc->strict()))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(sc->isGlobalContext() || ( sc->isEvalContext() && !sc->strict())))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("sc->isGlobalContext() || (sc->isEvalContext() && !sc->strict())" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2256); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isGlobalContext() || (sc->isEvalContext() && !sc->strict())" ")"); do { *((volatile int*)__null) = 2256; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2257 | MOZ_ASSERT(body->is<LexicalScopeNode>() || body->is<ListNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(body->is<LexicalScopeNode>() || body->is <ListNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(body->is<LexicalScopeNode >() || body->is<ListNode>()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("body->is<LexicalScopeNode>() || body->is<ListNode>()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2257); AnnotateMozCrashReason("MOZ_ASSERT" "(" "body->is<LexicalScopeNode>() || body->is<ListNode>()" ")"); do { *((volatile int*)__null) = 2257; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2258 | |
2259 | if (body->is<LexicalScopeNode>()) { |
2260 | body = body->as<LexicalScopeNode>().scopeBody(); |
2261 | MOZ_ASSERT(body->is<ListNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(body->is<ListNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(body->is<ListNode>( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("body->is<ListNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2261); AnnotateMozCrashReason("MOZ_ASSERT" "(" "body->is<ListNode>()" ")"); do { *((volatile int*)__null) = 2261; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2262 | } |
2263 | |
2264 | if (!body->as<ListNode>().hasTopLevelFunctionDeclarations()) { |
2265 | return true; |
2266 | } |
2267 | |
2268 | return emitHoistedFunctionsInList(&body->as<ListNode>()); |
2269 | } |
2270 | |
2271 | // For Global and sloppy-Eval scripts, this performs most of the steps of the |
2272 | // spec's [GlobalDeclarationInstantiation] and [EvalDeclarationInstantiation] |
2273 | // operations. |
2274 | // |
2275 | // Note that while strict-Eval is handled in the same part of the spec, it never |
2276 | // fails for global-redeclaration checks so those scripts initialize directly in |
2277 | // their bytecode. |
2278 | bool BytecodeEmitter::emitDeclarationInstantiation(ParseNode* body) { |
2279 | if (sc->isModuleContext()) { |
2280 | // ES Modules have dedicated variable and lexial environments and therefore |
2281 | // do not have to perform redeclaration checks. We initialize their bindings |
2282 | // elsewhere in bytecode. |
2283 | return true; |
2284 | } |
2285 | |
2286 | if (sc->isEvalContext() && sc->strict()) { |
2287 | // Strict Eval has a dedicated variables (and lexical) environment and |
2288 | // therefore does not have to perform redeclaration checks. We initialize |
2289 | // their bindings elsewhere in the bytecode. |
2290 | return true; |
2291 | } |
2292 | |
2293 | // If we have no variables bindings, then we are done! |
2294 | if (sc->isGlobalContext()) { |
2295 | if (!sc->asGlobalContext()->bindings) { |
2296 | return true; |
2297 | } |
2298 | } else { |
2299 | MOZ_ASSERT(sc->isEvalContext())do { static_assert( mozilla::detail::AssertionConditionType< decltype(sc->isEvalContext())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(sc->isEvalContext()))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("sc->isEvalContext()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2299); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isEvalContext()" ")"); do { *((volatile int*)__null) = 2299; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2300 | |
2301 | if (!sc->asEvalContext()->bindings) { |
2302 | return true; |
2303 | } |
2304 | } |
2305 | |
2306 | #if DEBUG1 |
2307 | // There should be no emitted functions yet. |
2308 | for (const auto& thing : perScriptData().gcThingList().objects()) { |
2309 | MOZ_ASSERT(thing.isEmptyGlobalScope() || thing.isScope())do { static_assert( mozilla::detail::AssertionConditionType< decltype(thing.isEmptyGlobalScope() || thing.isScope())>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(thing.isEmptyGlobalScope() || thing.isScope()))), 0) )) { do { } while (false); MOZ_ReportAssertionFailure("thing.isEmptyGlobalScope() || thing.isScope()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2309); AnnotateMozCrashReason("MOZ_ASSERT" "(" "thing.isEmptyGlobalScope() || thing.isScope()" ")"); do { *((volatile int*)__null) = 2309; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2310 | } |
2311 | #endif |
2312 | |
2313 | // Emit the hoisted functions to gc-things list. There is no bytecode |
2314 | // generated yet to bind them. |
2315 | if (!defineHoistedTopLevelFunctions(body)) { |
2316 | return false; |
2317 | } |
2318 | |
2319 | // Save the last GCThingIndex emitted. The hoisted functions are contained in |
2320 | // the gc-things list up until this point. This set of gc-things also contain |
2321 | // initial scopes (of which there must be at least one). |
2322 | MOZ_ASSERT(perScriptData().gcThingList().length() > 0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(perScriptData().gcThingList().length() > 0)>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(perScriptData().gcThingList().length() > 0))), 0) )) { do { } while (false); MOZ_ReportAssertionFailure("perScriptData().gcThingList().length() > 0" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2322); AnnotateMozCrashReason("MOZ_ASSERT" "(" "perScriptData().gcThingList().length() > 0" ")"); do { *((volatile int*)__null) = 2322; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2323 | GCThingIndex lastFun = |
2324 | GCThingIndex(perScriptData().gcThingList().length() - 1); |
2325 | |
2326 | #if DEBUG1 |
2327 | for (const auto& thing : perScriptData().gcThingList().objects()) { |
2328 | MOZ_ASSERT(thing.isEmptyGlobalScope() || thing.isScope() ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(thing.isEmptyGlobalScope() || thing.isScope() || thing .isFunction())>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(thing.isEmptyGlobalScope() || thing .isScope() || thing.isFunction()))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("thing.isEmptyGlobalScope() || thing.isScope() || thing.isFunction()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2329); AnnotateMozCrashReason("MOZ_ASSERT" "(" "thing.isEmptyGlobalScope() || thing.isScope() || thing.isFunction()" ")"); do { *((volatile int*)__null) = 2329; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2329 | thing.isFunction())do { static_assert( mozilla::detail::AssertionConditionType< decltype(thing.isEmptyGlobalScope() || thing.isScope() || thing .isFunction())>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(thing.isEmptyGlobalScope() || thing .isScope() || thing.isFunction()))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("thing.isEmptyGlobalScope() || thing.isScope() || thing.isFunction()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2329); AnnotateMozCrashReason("MOZ_ASSERT" "(" "thing.isEmptyGlobalScope() || thing.isScope() || thing.isFunction()" ")"); do { *((volatile int*)__null) = 2329; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2330 | } |
2331 | #endif |
2332 | |
2333 | // Check for declaration conflicts and initialize the bindings. |
2334 | // NOTE: The self-hosting top-level script should not populate the builtins |
2335 | // directly on the GlobalObject (and instead uses JSOp::GetIntrinsic for |
2336 | // lookups). |
2337 | if (emitterMode == BytecodeEmitter::EmitterMode::Normal) { |
2338 | if (!emitGCIndexOp(JSOp::GlobalOrEvalDeclInstantiation, lastFun)) { |
2339 | return false; |
2340 | } |
2341 | } |
2342 | |
2343 | return true; |
2344 | } |
2345 | |
2346 | bool BytecodeEmitter::emitScript(ParseNode* body) { |
2347 | setScriptStartOffsetIfUnset(body->pn_pos.begin); |
2348 | |
2349 | MOZ_ASSERT(inPrologue())do { static_assert( mozilla::detail::AssertionConditionType< decltype(inPrologue())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(inPrologue()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("inPrologue()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2349); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inPrologue()" ")"); do { *((volatile int*)__null) = 2349; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2350 | |
2351 | TDZCheckCache tdzCache(this); |
2352 | EmitterScope emitterScope(this); |
2353 | Maybe<AsyncEmitter> topLevelAwait; |
2354 | if (sc->isGlobalContext()) { |
2355 | if (!emitterScope.enterGlobal(this, sc->asGlobalContext())) { |
2356 | return false; |
2357 | } |
2358 | } else if (sc->isEvalContext()) { |
2359 | if (!emitterScope.enterEval(this, sc->asEvalContext())) { |
2360 | return false; |
2361 | } |
2362 | } else { |
2363 | MOZ_ASSERT(sc->isModuleContext())do { static_assert( mozilla::detail::AssertionConditionType< decltype(sc->isModuleContext())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(sc->isModuleContext()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("sc->isModuleContext()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2363); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isModuleContext()" ")"); do { *((volatile int*)__null) = 2363; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2364 | if (!emitterScope.enterModule(this, sc->asModuleContext())) { |
2365 | return false; |
2366 | } |
2367 | if (sc->asModuleContext()->isAsync()) { |
2368 | topLevelAwait.emplace(this); |
2369 | } |
2370 | } |
2371 | |
2372 | setFunctionBodyEndPos(body->pn_pos.end); |
2373 | |
2374 | bool isSloppyEval = sc->isEvalContext() && !sc->strict(); |
2375 | if (isSloppyEval && body->is<LexicalScopeNode>() && |
2376 | !body->as<LexicalScopeNode>().isEmptyScope()) { |
2377 | // Sloppy eval scripts may emit hoisted functions bindings with a |
2378 | // `JSOp::GlobalOrEvalDeclInstantiation` opcode below. If this eval needs a |
2379 | // top-level lexical environment, we must ensure that environment is created |
2380 | // before those functions are created and bound. |
2381 | // |
2382 | // This differs from the global-script case below because the global-lexical |
2383 | // environment exists outside the script itself. In the case of strict eval |
2384 | // scripts, the `emitterScope` above is already sufficient. |
2385 | EmitterScope lexicalEmitterScope(this); |
2386 | LexicalScopeNode* scope = &body->as<LexicalScopeNode>(); |
2387 | |
2388 | if (!lexicalEmitterScope.enterLexical(this, ScopeKind::Lexical, |
2389 | scope->scopeBindings())) { |
2390 | return false; |
2391 | } |
2392 | |
2393 | if (!emitDeclarationInstantiation(scope->scopeBody())) { |
2394 | return false; |
2395 | } |
2396 | |
2397 | switchToMain(); |
2398 | |
2399 | ParseNode* scopeBody = scope->scopeBody(); |
2400 | if (!emitLexicalScopeBody(scopeBody)) { |
2401 | return false; |
2402 | } |
2403 | |
2404 | if (!updateSourceCoordNotes(scopeBody->pn_pos.end)) { |
2405 | return false; |
2406 | } |
2407 | |
2408 | if (!lexicalEmitterScope.leave(this)) { |
2409 | return false; |
2410 | } |
2411 | } else { |
2412 | if (!emitDeclarationInstantiation(body)) { |
2413 | return false; |
2414 | } |
2415 | if (topLevelAwait) { |
2416 | if (!topLevelAwait->prepareForModule()) { |
2417 | return false; |
2418 | } |
2419 | } |
2420 | |
2421 | switchToMain(); |
2422 | |
2423 | #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT |
2424 | if (!emitterScope.prepareForModuleDisposableScopeBody(this)) { |
2425 | return false; |
2426 | } |
2427 | #endif |
2428 | |
2429 | if (topLevelAwait) { |
2430 | if (!topLevelAwait->prepareForBody()) { |
2431 | return false; |
2432 | } |
2433 | } |
2434 | |
2435 | if (!emitTree(body)) { |
2436 | // [stack] |
2437 | return false; |
2438 | } |
2439 | |
2440 | if (!updateSourceCoordNotes(body->pn_pos.end)) { |
2441 | return false; |
2442 | } |
2443 | } |
2444 | |
2445 | #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT |
2446 | if (!emitterScope.emitModuleDisposableScopeBodyEnd(this)) { |
2447 | return false; |
2448 | } |
2449 | #endif |
2450 | |
2451 | if (topLevelAwait) { |
2452 | if (!topLevelAwait->emitEndModule()) { |
2453 | return false; |
2454 | } |
2455 | } |
2456 | |
2457 | if (!markSimpleBreakpoint()) { |
2458 | return false; |
2459 | } |
2460 | |
2461 | if (!emitReturnRval()) { |
2462 | return false; |
2463 | } |
2464 | |
2465 | if (!emitterScope.leave(this)) { |
2466 | return false; |
2467 | } |
2468 | |
2469 | if (!NameFunctions(fc, parserAtoms(), body)) { |
2470 | return false; |
2471 | } |
2472 | |
2473 | // Create a Stencil and convert it into a JSScript. |
2474 | return intoScriptStencil(CompilationStencil::TopLevelIndex); |
2475 | } |
2476 | |
2477 | js::UniquePtr<ImmutableScriptData> |
2478 | BytecodeEmitter::createImmutableScriptData() { |
2479 | uint32_t nslots; |
2480 | if (!getNslots(&nslots)) { |
2481 | return nullptr; |
2482 | } |
2483 | |
2484 | bool isFunction = sc->isFunctionBox(); |
2485 | uint16_t funLength = isFunction ? sc->asFunctionBox()->length() : 0; |
2486 | |
2487 | mozilla::SaturateUint8 propertyCountEstimate = propertyAdditionEstimate; |
2488 | |
2489 | // Add fields to the property count estimate. |
2490 | if (isFunction && sc->asFunctionBox()->useMemberInitializers()) { |
2491 | propertyCountEstimate += |
2492 | sc->asFunctionBox()->memberInitializers().numMemberInitializers; |
2493 | } |
2494 | |
2495 | return ImmutableScriptData::new_( |
2496 | fc, mainOffset(), maxFixedSlots, nslots, bodyScopeIndex, |
2497 | bytecodeSection().numICEntries(), isFunction, funLength, |
2498 | propertyCountEstimate.value(), bytecodeSection().code(), |
2499 | bytecodeSection().notes(), bytecodeSection().resumeOffsetList().span(), |
2500 | bytecodeSection().scopeNoteList().span(), |
2501 | bytecodeSection().tryNoteList().span()); |
2502 | } |
2503 | |
2504 | #if defined(ENABLE_DECORATORS) || defined(ENABLE_EXPLICIT_RESOURCE_MANAGEMENT) |
2505 | bool BytecodeEmitter::emitCheckIsCallable() { |
2506 | // This emits code to check if the value at the top of the stack is |
2507 | // callable. The value is left on the stack. |
2508 | // [stack] VAL |
2509 | if (!emitAtomOp(JSOp::GetIntrinsic, |
2510 | TaggedParserAtomIndex::WellKnown::IsCallable())) { |
2511 | // [stack] VAL ISCALLABLE |
2512 | return false; |
2513 | } |
2514 | if (!emit1(JSOp::Undefined)) { |
2515 | // [stack] VAL ISCALLABLE UNDEFINED |
2516 | return false; |
2517 | } |
2518 | if (!emitDupAt(2)) { |
2519 | // [stack] VAL ISCALLABLE UNDEFINED VAL |
2520 | return false; |
2521 | } |
2522 | return emitCall(JSOp::Call, 1); |
2523 | // [stack] VAL ISCALLABLE_RESULT |
2524 | } |
2525 | #endif |
2526 | |
2527 | bool BytecodeEmitter::getNslots(uint32_t* nslots) const { |
2528 | uint64_t nslots64 = |
2529 | maxFixedSlots + static_cast<uint64_t>(bytecodeSection().maxStackDepth()); |
2530 | if (nslots64 > UINT32_MAX(4294967295U)) { |
2531 | reportError(nullptr, JSMSG_NEED_DIET, "script"); |
2532 | return false; |
2533 | } |
2534 | *nslots = nslots64; |
2535 | return true; |
2536 | } |
2537 | |
2538 | bool BytecodeEmitter::emitFunctionScript(FunctionNode* funNode) { |
2539 | MOZ_ASSERT(inPrologue())do { static_assert( mozilla::detail::AssertionConditionType< decltype(inPrologue())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(inPrologue()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("inPrologue()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2539); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inPrologue()" ")"); do { *((volatile int*)__null) = 2539; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2540 | ParamsBodyNode* paramsBody = funNode->body(); |
2541 | FunctionBox* funbox = sc->asFunctionBox(); |
2542 | |
2543 | setScriptStartOffsetIfUnset(paramsBody->pn_pos.begin); |
2544 | |
2545 | // [stack] |
2546 | |
2547 | FunctionScriptEmitter fse(this, funbox, Some(paramsBody->pn_pos.begin), |
2548 | Some(paramsBody->pn_pos.end)); |
2549 | if (!fse.prepareForParameters()) { |
2550 | // [stack] |
2551 | return false; |
2552 | } |
2553 | |
2554 | if (!emitFunctionFormalParameters(paramsBody)) { |
2555 | // [stack] |
2556 | return false; |
2557 | } |
2558 | |
2559 | if (!fse.prepareForBody()) { |
2560 | // [stack] |
2561 | return false; |
2562 | } |
2563 | |
2564 | if (!emitTree(paramsBody->body())) { |
2565 | // [stack] |
2566 | return false; |
2567 | } |
2568 | |
2569 | if (!fse.emitEndBody()) { |
2570 | // [stack] |
2571 | return false; |
2572 | } |
2573 | |
2574 | if (funbox->index() == CompilationStencil::TopLevelIndex) { |
2575 | if (!NameFunctions(fc, parserAtoms(), funNode)) { |
2576 | return false; |
2577 | } |
2578 | } |
2579 | |
2580 | return fse.intoStencil(); |
2581 | } |
2582 | |
2583 | class js::frontend::DestructuringLHSRef { |
2584 | struct None { |
2585 | size_t numReferenceSlots() const { return 0; } |
2586 | }; |
2587 | |
2588 | mozilla::Variant<None, NameOpEmitter, PropOpEmitter, ElemOpEmitter, |
2589 | PrivateOpEmitter> |
2590 | emitter_ = AsVariant(None{}); |
2591 | |
2592 | public: |
2593 | template <typename T> |
2594 | void from(T&& emitter) { |
2595 | emitter_.emplace<T>(std::forward<T>(emitter)); |
2596 | } |
2597 | |
2598 | template <typename T> |
2599 | T& emitter() { |
2600 | return emitter_.as<T>(); |
2601 | } |
2602 | |
2603 | /** |
2604 | * Return the number of values pushed onto the stack. |
2605 | */ |
2606 | size_t numReferenceSlots() const { |
2607 | return emitter_.match([](auto& e) { return e.numReferenceSlots(); }); |
2608 | } |
2609 | }; |
2610 | |
2611 | bool BytecodeEmitter::emitDestructuringLHSRef(ParseNode* target, |
2612 | DestructuringFlavor flav, |
2613 | DestructuringLHSRef& lref) { |
2614 | #ifdef DEBUG1 |
2615 | int depth = bytecodeSection().stackDepth(); |
2616 | #endif |
2617 | |
2618 | switch (target->getKind()) { |
2619 | case ParseNodeKind::ArrayExpr: |
2620 | case ParseNodeKind::ObjectExpr: |
2621 | // No need to recurse into ParseNodeKind::Array and ParseNodeKind::Object |
2622 | // subpatterns here, since emitSetOrInitializeDestructuring does the |
2623 | // recursion when setting or initializing the value. |
2624 | break; |
2625 | |
2626 | case ParseNodeKind::Name: { |
2627 | auto* name = &target->as<NameNode>(); |
2628 | NameOpEmitter noe(this, name->atom(), |
2629 | flav == DestructuringFlavor::Assignment |
2630 | ? NameOpEmitter::Kind::SimpleAssignment |
2631 | : NameOpEmitter::Kind::Initialize); |
2632 | if (!noe.prepareForRhs()) { |
2633 | return false; |
2634 | } |
2635 | |
2636 | lref.from(std::move(noe)); |
2637 | return true; |
2638 | } |
2639 | |
2640 | case ParseNodeKind::ArgumentsLength: |
2641 | case ParseNodeKind::DotExpr: { |
2642 | PropertyAccess* prop = &target->as<PropertyAccess>(); |
2643 | bool isSuper = prop->isSuper(); |
2644 | PropOpEmitter poe(this, PropOpEmitter::Kind::SimpleAssignment, |
2645 | isSuper ? PropOpEmitter::ObjKind::Super |
2646 | : PropOpEmitter::ObjKind::Other); |
2647 | if (!poe.prepareForObj()) { |
2648 | return false; |
2649 | } |
2650 | if (isSuper) { |
2651 | UnaryNode* base = &prop->expression().as<UnaryNode>(); |
2652 | if (!emitGetThisForSuperBase(base)) { |
2653 | // [stack] THIS SUPERBASE |
2654 | return false; |
2655 | } |
2656 | } else { |
2657 | if (!emitTree(&prop->expression())) { |
2658 | // [stack] OBJ |
2659 | return false; |
2660 | } |
2661 | } |
2662 | if (!poe.prepareForRhs()) { |
2663 | // [stack] # if Super |
2664 | // [stack] THIS SUPERBASE |
2665 | // [stack] # otherwise |
2666 | // [stack] OBJ |
2667 | return false; |
2668 | } |
2669 | |
2670 | lref.from(std::move(poe)); |
2671 | break; |
2672 | } |
2673 | |
2674 | case ParseNodeKind::ElemExpr: { |
2675 | PropertyByValue* elem = &target->as<PropertyByValue>(); |
2676 | bool isSuper = elem->isSuper(); |
2677 | MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!elem->key().isKind(ParseNodeKind::PrivateName))> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!elem->key().isKind(ParseNodeKind::PrivateName))) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!elem->key().isKind(ParseNodeKind::PrivateName)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2677); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)" ")"); do { *((volatile int*)__null) = 2677; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2678 | ElemOpEmitter eoe(this, ElemOpEmitter::Kind::SimpleAssignment, |
2679 | isSuper ? ElemOpEmitter::ObjKind::Super |
2680 | : ElemOpEmitter::ObjKind::Other); |
2681 | if (!emitElemObjAndKey(elem, eoe)) { |
2682 | // [stack] # if Super |
2683 | // [stack] THIS KEY |
2684 | // [stack] # otherwise |
2685 | // [stack] OBJ KEY |
2686 | return false; |
2687 | } |
2688 | if (!eoe.prepareForRhs()) { |
2689 | // [stack] # if Super |
2690 | // [stack] THIS KEY SUPERBASE |
2691 | // [stack] # otherwise |
2692 | // [stack] OBJ KEY |
2693 | return false; |
2694 | } |
2695 | |
2696 | lref.from(std::move(eoe)); |
2697 | break; |
2698 | } |
2699 | |
2700 | case ParseNodeKind::PrivateMemberExpr: { |
2701 | PrivateMemberAccess* privateExpr = &target->as<PrivateMemberAccess>(); |
2702 | PrivateOpEmitter xoe(this, PrivateOpEmitter::Kind::SimpleAssignment, |
2703 | privateExpr->privateName().name()); |
2704 | if (!emitTree(&privateExpr->expression())) { |
2705 | // [stack] OBJ |
2706 | return false; |
2707 | } |
2708 | if (!xoe.emitReference()) { |
2709 | // [stack] OBJ NAME |
2710 | return false; |
2711 | } |
2712 | |
2713 | lref.from(std::move(xoe)); |
2714 | break; |
2715 | } |
2716 | |
2717 | case ParseNodeKind::CallExpr: |
2718 | MOZ_ASSERT_UNREACHABLE(do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget " "rejects function calls as assignment " "targets in destructuring assignments" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2721); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget " "rejects function calls as assignment " "targets in destructuring assignments" ")"); do { *((volatile int*)__null) = 2721; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2719 | "Parser::reportIfNotValidSimpleAssignmentTarget "do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget " "rejects function calls as assignment " "targets in destructuring assignments" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2721); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget " "rejects function calls as assignment " "targets in destructuring assignments" ")"); do { *((volatile int*)__null) = 2721; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2720 | "rejects function calls as assignment "do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget " "rejects function calls as assignment " "targets in destructuring assignments" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2721); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget " "rejects function calls as assignment " "targets in destructuring assignments" ")"); do { *((volatile int*)__null) = 2721; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2721 | "targets in destructuring assignments")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget " "rejects function calls as assignment " "targets in destructuring assignments" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2721); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget " "rejects function calls as assignment " "targets in destructuring assignments" ")"); do { *((volatile int*)__null) = 2721; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2722 | break; |
2723 | |
2724 | default: |
2725 | MOZ_CRASH("emitDestructuringLHSRef: bad lhs kind")do { do { } while (false); MOZ_ReportCrash("" "emitDestructuringLHSRef: bad lhs kind" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2725); AnnotateMozCrashReason("MOZ_CRASH(" "emitDestructuringLHSRef: bad lhs kind" ")"); do { *((volatile int*)__null) = 2725; __attribute__((nomerge )) ::abort(); } while (false); } while (false); |
2726 | } |
2727 | |
2728 | MOZ_ASSERT(bytecodeSection().stackDepth() ==do { static_assert( mozilla::detail::AssertionConditionType< decltype(bytecodeSection().stackDepth() == depth + int(lref.numReferenceSlots ()))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(bytecodeSection().stackDepth() == depth + int(lref.numReferenceSlots ())))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("bytecodeSection().stackDepth() == depth + int(lref.numReferenceSlots())" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2729); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == depth + int(lref.numReferenceSlots())" ")"); do { *((volatile int*)__null) = 2729; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2729 | depth + int(lref.numReferenceSlots()))do { static_assert( mozilla::detail::AssertionConditionType< decltype(bytecodeSection().stackDepth() == depth + int(lref.numReferenceSlots ()))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(bytecodeSection().stackDepth() == depth + int(lref.numReferenceSlots ())))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("bytecodeSection().stackDepth() == depth + int(lref.numReferenceSlots())" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2729); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == depth + int(lref.numReferenceSlots())" ")"); do { *((volatile int*)__null) = 2729; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2730 | |
2731 | return true; |
2732 | } |
2733 | |
2734 | bool BytecodeEmitter::emitSetOrInitializeDestructuring( |
2735 | ParseNode* target, DestructuringFlavor flav, DestructuringLHSRef& lref) { |
2736 | // Now emit the lvalue opcode sequence. If the lvalue is a nested |
2737 | // destructuring initialiser-form, call ourselves to handle it, then pop |
2738 | // the matched value. Otherwise emit an lvalue bytecode sequence followed |
2739 | // by an assignment op. |
2740 | |
2741 | switch (target->getKind()) { |
2742 | case ParseNodeKind::ArrayExpr: |
2743 | case ParseNodeKind::ObjectExpr: |
2744 | if (!emitDestructuringOps(&target->as<ListNode>(), flav)) { |
2745 | return false; |
2746 | } |
2747 | // emitDestructuringOps leaves the assigned (to-be-destructured) value on |
2748 | // top of the stack. |
2749 | break; |
2750 | |
2751 | case ParseNodeKind::Name: { |
2752 | // The environment is already pushed by emitDestructuringLHSRef. |
2753 | // [stack] ENV? VAL |
2754 | auto& noe = lref.emitter<NameOpEmitter>(); |
2755 | |
2756 | if (!noe.emitAssignment()) { |
2757 | // [stack] VAL |
2758 | return false; |
2759 | } |
2760 | break; |
2761 | } |
2762 | |
2763 | case ParseNodeKind::ArgumentsLength: |
2764 | case ParseNodeKind::DotExpr: { |
2765 | // The reference is already pushed by emitDestructuringLHSRef. |
2766 | // [stack] # if Super |
2767 | // [stack] THIS SUPERBASE VAL |
2768 | // [stack] # otherwise |
2769 | // [stack] OBJ VAL |
2770 | auto& poe = lref.emitter<PropOpEmitter>(); |
2771 | auto* prop = &target->as<PropertyAccess>(); |
2772 | |
2773 | if (!poe.emitAssignment(prop->key().atom())) { |
2774 | // [stack] # VAL |
2775 | return false; |
2776 | } |
2777 | break; |
2778 | } |
2779 | |
2780 | case ParseNodeKind::ElemExpr: { |
2781 | // The reference is already pushed by emitDestructuringLHSRef. |
2782 | // [stack] # if Super |
2783 | // [stack] THIS KEY SUPERBASE VAL |
2784 | // [stack] # otherwise |
2785 | // [stack] OBJ KEY VAL |
2786 | auto& eoe = lref.emitter<ElemOpEmitter>(); |
2787 | |
2788 | if (!eoe.emitAssignment()) { |
2789 | // [stack] VAL |
2790 | return false; |
2791 | } |
2792 | break; |
2793 | } |
2794 | |
2795 | case ParseNodeKind::PrivateMemberExpr: { |
2796 | // The reference is already pushed by emitDestructuringLHSRef. |
2797 | // [stack] OBJ NAME VAL |
2798 | auto& xoe = lref.emitter<PrivateOpEmitter>(); |
2799 | |
2800 | if (!xoe.emitAssignment()) { |
2801 | // [stack] VAL |
2802 | return false; |
2803 | } |
2804 | break; |
2805 | } |
2806 | |
2807 | case ParseNodeKind::CallExpr: |
2808 | MOZ_ASSERT_UNREACHABLE(do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget " "rejects function calls as assignment " "targets in destructuring assignments" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2811); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget " "rejects function calls as assignment " "targets in destructuring assignments" ")"); do { *((volatile int*)__null) = 2811; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2809 | "Parser::reportIfNotValidSimpleAssignmentTarget "do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget " "rejects function calls as assignment " "targets in destructuring assignments" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2811); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget " "rejects function calls as assignment " "targets in destructuring assignments" ")"); do { *((volatile int*)__null) = 2811; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2810 | "rejects function calls as assignment "do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget " "rejects function calls as assignment " "targets in destructuring assignments" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2811); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget " "rejects function calls as assignment " "targets in destructuring assignments" ")"); do { *((volatile int*)__null) = 2811; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2811 | "targets in destructuring assignments")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget " "rejects function calls as assignment " "targets in destructuring assignments" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2811); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget " "rejects function calls as assignment " "targets in destructuring assignments" ")"); do { *((volatile int*)__null) = 2811; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2812 | break; |
2813 | |
2814 | default: |
2815 | MOZ_CRASH("emitSetOrInitializeDestructuring: bad lhs kind")do { do { } while (false); MOZ_ReportCrash("" "emitSetOrInitializeDestructuring: bad lhs kind" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2815); AnnotateMozCrashReason("MOZ_CRASH(" "emitSetOrInitializeDestructuring: bad lhs kind" ")"); do { *((volatile int*)__null) = 2815; __attribute__((nomerge )) ::abort(); } while (false); } while (false); |
2816 | } |
2817 | |
2818 | // Pop the assigned value. |
2819 | if (!emit1(JSOp::Pop)) { |
2820 | // [stack] # empty |
2821 | return false; |
2822 | } |
2823 | |
2824 | return true; |
2825 | } |
2826 | |
2827 | JSOp BytecodeEmitter::getIterCallOp(JSOp callOp, |
2828 | SelfHostedIter selfHostedIter) const { |
2829 | if (emitterMode == BytecodeEmitter::SelfHosting) { |
2830 | MOZ_ASSERT(selfHostedIter != SelfHostedIter::Deny)do { static_assert( mozilla::detail::AssertionConditionType< decltype(selfHostedIter != SelfHostedIter::Deny)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(selfHostedIter != SelfHostedIter::Deny))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2830); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny" ")"); do { *((volatile int*)__null) = 2830; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2831 | |
2832 | switch (callOp) { |
2833 | case JSOp::Call: |
2834 | return JSOp::CallContent; |
2835 | case JSOp::CallIter: |
2836 | return JSOp::CallContentIter; |
2837 | default: |
2838 | MOZ_CRASH("Unknown iterator call op")do { do { } while (false); MOZ_ReportCrash("" "Unknown iterator call op" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2838); AnnotateMozCrashReason("MOZ_CRASH(" "Unknown iterator call op" ")"); do { *((volatile int*)__null) = 2838; __attribute__((nomerge )) ::abort(); } while (false); } while (false); |
2839 | } |
2840 | } |
2841 | |
2842 | return callOp; |
2843 | } |
2844 | |
2845 | bool BytecodeEmitter::emitIteratorNext( |
2846 | const Maybe<uint32_t>& callSourceCoordOffset, |
2847 | IteratorKind iterKind /* = IteratorKind::Sync */, |
2848 | SelfHostedIter selfHostedIter /* = SelfHostedIter::Deny */) { |
2849 | MOZ_ASSERT(selfHostedIter != SelfHostedIter::Deny ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter ::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" " (" ".next() iteration is prohibited in self-hosted code because it" "can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2852); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" ") (" ".next() iteration is prohibited in self-hosted code because it" "can run user-modifiable iteration code" ")"); do { *((volatile int*)__null) = 2852; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
2850 | emitterMode != BytecodeEmitter::SelfHosting,do { static_assert( mozilla::detail::AssertionConditionType< decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter ::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" " (" ".next() iteration is prohibited in self-hosted code because it" "can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2852); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" ") (" ".next() iteration is prohibited in self-hosted code because it" "can run user-modifiable iteration code" ")"); do { *((volatile int*)__null) = 2852; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
2851 | ".next() iteration is prohibited in self-hosted code because it"do { static_assert( mozilla::detail::AssertionConditionType< decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter ::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" " (" ".next() iteration is prohibited in self-hosted code because it" "can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2852); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" ") (" ".next() iteration is prohibited in self-hosted code because it" "can run user-modifiable iteration code" ")"); do { *((volatile int*)__null) = 2852; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
2852 | "can run user-modifiable iteration code")do { static_assert( mozilla::detail::AssertionConditionType< decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter ::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" " (" ".next() iteration is prohibited in self-hosted code because it" "can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2852); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" ") (" ".next() iteration is prohibited in self-hosted code because it" "can run user-modifiable iteration code" ")"); do { *((volatile int*)__null) = 2852; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
2853 | |
2854 | // [stack] ... NEXT ITER |
2855 | MOZ_ASSERT(bytecodeSection().stackDepth() >= 2)do { static_assert( mozilla::detail::AssertionConditionType< decltype(bytecodeSection().stackDepth() >= 2)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(bytecodeSection().stackDepth() >= 2))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("bytecodeSection().stackDepth() >= 2" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2855); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() >= 2" ")"); do { *((volatile int*)__null) = 2855; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2856 | |
2857 | if (!emitCall(getIterCallOp(JSOp::Call, selfHostedIter), 0, |
2858 | callSourceCoordOffset)) { |
2859 | // [stack] ... RESULT |
2860 | return false; |
2861 | } |
2862 | |
2863 | if (iterKind == IteratorKind::Async) { |
2864 | if (!emitAwaitInInnermostScope()) { |
2865 | // [stack] ... RESULT |
2866 | return false; |
2867 | } |
2868 | } |
2869 | |
2870 | if (!emitCheckIsObj(CheckIsObjectKind::IteratorNext)) { |
2871 | // [stack] ... RESULT |
2872 | return false; |
2873 | } |
2874 | return true; |
2875 | } |
2876 | |
2877 | bool BytecodeEmitter::emitIteratorCloseInScope( |
2878 | EmitterScope& currentScope, |
2879 | IteratorKind iterKind /* = IteratorKind::Sync */, |
2880 | CompletionKind completionKind /* = CompletionKind::Normal */, |
2881 | SelfHostedIter selfHostedIter /* = SelfHostedIter::Deny */) { |
2882 | MOZ_ASSERT(selfHostedIter != SelfHostedIter::Deny ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter ::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" " (" ".close() on iterators is prohibited in self-hosted code because " "it can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2885); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" ") (" ".close() on iterators is prohibited in self-hosted code because " "it can run user-modifiable iteration code" ")"); do { *((volatile int*)__null) = 2885; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
2883 | emitterMode != BytecodeEmitter::SelfHosting,do { static_assert( mozilla::detail::AssertionConditionType< decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter ::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" " (" ".close() on iterators is prohibited in self-hosted code because " "it can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2885); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" ") (" ".close() on iterators is prohibited in self-hosted code because " "it can run user-modifiable iteration code" ")"); do { *((volatile int*)__null) = 2885; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
2884 | ".close() on iterators is prohibited in self-hosted code because "do { static_assert( mozilla::detail::AssertionConditionType< decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter ::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" " (" ".close() on iterators is prohibited in self-hosted code because " "it can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2885); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" ") (" ".close() on iterators is prohibited in self-hosted code because " "it can run user-modifiable iteration code" ")"); do { *((volatile int*)__null) = 2885; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
2885 | "it can run user-modifiable iteration code")do { static_assert( mozilla::detail::AssertionConditionType< decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter ::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" " (" ".close() on iterators is prohibited in self-hosted code because " "it can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2885); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" ") (" ".close() on iterators is prohibited in self-hosted code because " "it can run user-modifiable iteration code" ")"); do { *((volatile int*)__null) = 2885; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
2886 | |
2887 | if (iterKind == IteratorKind::Sync) { |
2888 | return emit2(JSOp::CloseIter, uint8_t(completionKind)); |
2889 | } |
2890 | |
2891 | // Generate inline logic corresponding to IteratorClose (ES2021 7.4.6) and |
2892 | // AsyncIteratorClose (ES2021 7.4.7). Steps numbers apply to both operations. |
2893 | // |
2894 | // Callers need to ensure that the iterator object is at the top of the |
2895 | // stack. |
2896 | |
2897 | // For non-Throw completions, we emit the equivalent of: |
2898 | // |
2899 | // var returnMethod = GetMethod(iterator, "return"); |
2900 | // if (returnMethod !== undefined) { |
2901 | // var innerResult = [Await] Call(returnMethod, iterator); |
2902 | // CheckIsObj(innerResult); |
2903 | // } |
2904 | // |
2905 | // Whereas for Throw completions, we emit: |
2906 | // |
2907 | // try { |
2908 | // var returnMethod = GetMethod(iterator, "return"); |
2909 | // if (returnMethod !== undefined) { |
2910 | // [Await] Call(returnMethod, iterator); |
2911 | // } |
2912 | // } catch {} |
2913 | |
2914 | Maybe<TryEmitter> tryCatch; |
2915 | |
2916 | if (completionKind == CompletionKind::Throw) { |
2917 | tryCatch.emplace(this, TryEmitter::Kind::TryCatch, |
2918 | TryEmitter::ControlKind::NonSyntactic); |
2919 | |
2920 | if (!tryCatch->emitTry()) { |
2921 | // [stack] ... ITER |
2922 | return false; |
2923 | } |
2924 | } |
2925 | |
2926 | if (!emit1(JSOp::Dup)) { |
2927 | // [stack] ... ITER ITER |
2928 | return false; |
2929 | } |
2930 | |
2931 | // Steps 1-2 are assertions, step 3 is implicit. |
2932 | |
2933 | // Step 4. |
2934 | // |
2935 | // Get the "return" method. |
2936 | if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::return_())) { |
2937 | // [stack] ... ITER RET |
2938 | return false; |
2939 | } |
2940 | |
2941 | // Step 5. |
2942 | // |
2943 | // Do nothing if "return" is undefined or null. |
2944 | InternalIfEmitter ifReturnMethodIsDefined(this); |
2945 | if (!emit1(JSOp::IsNullOrUndefined)) { |
2946 | // [stack] ... ITER RET NULL-OR-UNDEF |
2947 | return false; |
2948 | } |
2949 | |
2950 | if (!ifReturnMethodIsDefined.emitThenElse( |
2951 | IfEmitter::ConditionKind::Negative)) { |
2952 | // [stack] ... ITER RET |
2953 | return false; |
2954 | } |
2955 | |
2956 | // Steps 5.c, 7. |
2957 | // |
2958 | // Call the "return" method. |
2959 | if (!emit1(JSOp::Swap)) { |
2960 | // [stack] ... RET ITER |
2961 | return false; |
2962 | } |
2963 | |
2964 | if (!emitCall(getIterCallOp(JSOp::Call, selfHostedIter), 0)) { |
2965 | // [stack] ... RESULT |
2966 | return false; |
2967 | } |
2968 | |
2969 | // 7.4.7 AsyncIteratorClose, step 5.d. |
2970 | if (iterKind == IteratorKind::Async) { |
2971 | if (completionKind != CompletionKind::Throw) { |
2972 | // Await clobbers rval, so save the current rval. |
2973 | if (!emit1(JSOp::GetRval)) { |
2974 | // [stack] ... RESULT RVAL |
2975 | return false; |
2976 | } |
2977 | if (!emit1(JSOp::Swap)) { |
2978 | // [stack] ... RVAL RESULT |
2979 | return false; |
2980 | } |
2981 | } |
2982 | |
2983 | if (!emitAwaitInScope(currentScope)) { |
2984 | // [stack] ... RVAL? RESULT |
2985 | return false; |
2986 | } |
2987 | |
2988 | if (completionKind != CompletionKind::Throw) { |
2989 | if (!emit1(JSOp::Swap)) { |
2990 | // [stack] ... RESULT RVAL |
2991 | return false; |
2992 | } |
2993 | if (!emit1(JSOp::SetRval)) { |
2994 | // [stack] ... RESULT |
2995 | return false; |
2996 | } |
2997 | } |
2998 | } |
2999 | |
3000 | // Step 6 (Handled in caller). |
3001 | |
3002 | // Step 8. |
3003 | if (completionKind != CompletionKind::Throw) { |
3004 | // Check that the "return" result is an object. |
3005 | if (!emitCheckIsObj(CheckIsObjectKind::IteratorReturn)) { |
3006 | // [stack] ... RESULT |
3007 | return false; |
3008 | } |
3009 | } |
3010 | |
3011 | if (!ifReturnMethodIsDefined.emitElse()) { |
3012 | // [stack] ... ITER RET |
3013 | return false; |
3014 | } |
3015 | |
3016 | if (!emit1(JSOp::Pop)) { |
3017 | // [stack] ... ITER |
3018 | return false; |
3019 | } |
3020 | |
3021 | if (!ifReturnMethodIsDefined.emitEnd()) { |
3022 | return false; |
3023 | } |
3024 | |
3025 | if (completionKind == CompletionKind::Throw) { |
3026 | if (!tryCatch->emitCatch()) { |
3027 | // [stack] ... ITER EXC |
3028 | return false; |
3029 | } |
3030 | |
3031 | // Just ignore the exception thrown by call and await. |
3032 | if (!emit1(JSOp::Pop)) { |
3033 | // [stack] ... ITER |
3034 | return false; |
3035 | } |
3036 | |
3037 | if (!tryCatch->emitEnd()) { |
3038 | // [stack] ... ITER |
3039 | return false; |
3040 | } |
3041 | } |
3042 | |
3043 | // Step 9 (Handled in caller). |
3044 | |
3045 | return emit1(JSOp::Pop); |
3046 | // [stack] ... |
3047 | } |
3048 | |
3049 | template <typename InnerEmitter> |
3050 | bool BytecodeEmitter::wrapWithDestructuringTryNote(int32_t iterDepth, |
3051 | InnerEmitter emitter) { |
3052 | MOZ_ASSERT(bytecodeSection().stackDepth() >= iterDepth)do { static_assert( mozilla::detail::AssertionConditionType< decltype(bytecodeSection().stackDepth() >= iterDepth)>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(bytecodeSection().stackDepth() >= iterDepth))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("bytecodeSection().stackDepth() >= iterDepth" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3052); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() >= iterDepth" ")"); do { *((volatile int*)__null) = 3052; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3053 | |
3054 | // Pad a nop at the beginning of the bytecode covered by the trynote so |
3055 | // that when unwinding environments, we may unwind to the scope |
3056 | // corresponding to the pc *before* the start, in case the first bytecode |
3057 | // emitted by |emitter| is the start of an inner scope. See comment above |
3058 | // UnwindEnvironmentToTryPc. |
3059 | if (!emit1(JSOp::TryDestructuring)) { |
3060 | return false; |
3061 | } |
3062 | |
3063 | BytecodeOffset start = bytecodeSection().offset(); |
3064 | if (!emitter(this)) { |
3065 | return false; |
3066 | } |
3067 | BytecodeOffset end = bytecodeSection().offset(); |
3068 | if (start != end) { |
3069 | return addTryNote(TryNoteKind::Destructuring, iterDepth, start, end); |
3070 | } |
3071 | return true; |
3072 | } |
3073 | |
3074 | bool BytecodeEmitter::emitDefault(ParseNode* defaultExpr, ParseNode* pattern) { |
3075 | // [stack] VALUE |
3076 | |
3077 | DefaultEmitter de(this); |
3078 | if (!de.prepareForDefault()) { |
3079 | // [stack] |
3080 | return false; |
3081 | } |
3082 | if (!emitInitializer(defaultExpr, pattern)) { |
3083 | // [stack] DEFAULTVALUE |
3084 | return false; |
3085 | } |
3086 | if (!de.emitEnd()) { |
3087 | // [stack] VALUE/DEFAULTVALUE |
3088 | return false; |
3089 | } |
3090 | return true; |
3091 | } |
3092 | |
3093 | bool BytecodeEmitter::emitAnonymousFunctionWithName( |
3094 | ParseNode* node, TaggedParserAtomIndex name) { |
3095 | MOZ_ASSERT(node->isDirectRHSAnonFunction())do { static_assert( mozilla::detail::AssertionConditionType< decltype(node->isDirectRHSAnonFunction())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(node->isDirectRHSAnonFunction ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("node->isDirectRHSAnonFunction()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3095); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isDirectRHSAnonFunction()" ")"); do { *((volatile int*)__null) = 3095; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3096 | |
3097 | if (node->is<FunctionNode>()) { |
3098 | // Function doesn't have 'name' property at this point. |
3099 | // Set function's name at compile time. |
3100 | setFunName(node->as<FunctionNode>().funbox(), name); |
3101 | |
3102 | return emitTree(node); |
3103 | } |
3104 | |
3105 | MOZ_ASSERT(node->is<ClassNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(node->is<ClassNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(node->is<ClassNode> ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("node->is<ClassNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3105); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->is<ClassNode>()" ")"); do { *((volatile int*)__null) = 3105; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3106 | |
3107 | return emitClass(&node->as<ClassNode>(), ClassNameKind::InferredName, name); |
3108 | } |
3109 | |
3110 | bool BytecodeEmitter::emitAnonymousFunctionWithComputedName( |
3111 | ParseNode* node, FunctionPrefixKind prefixKind) { |
3112 | MOZ_ASSERT(node->isDirectRHSAnonFunction())do { static_assert( mozilla::detail::AssertionConditionType< decltype(node->isDirectRHSAnonFunction())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(node->isDirectRHSAnonFunction ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("node->isDirectRHSAnonFunction()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3112); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isDirectRHSAnonFunction()" ")"); do { *((volatile int*)__null) = 3112; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3113 | |
3114 | if (node->is<FunctionNode>()) { |
3115 | if (!emitTree(node)) { |
3116 | // [stack] NAME FUN |
3117 | return false; |
3118 | } |
3119 | if (!emitDupAt(1)) { |
3120 | // [stack] NAME FUN NAME |
3121 | return false; |
3122 | } |
3123 | if (!emit2(JSOp::SetFunName, uint8_t(prefixKind))) { |
3124 | // [stack] NAME FUN |
3125 | return false; |
3126 | } |
3127 | return true; |
3128 | } |
3129 | |
3130 | MOZ_ASSERT(node->is<ClassNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(node->is<ClassNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(node->is<ClassNode> ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("node->is<ClassNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3130); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->is<ClassNode>()" ")"); do { *((volatile int*)__null) = 3130; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3131 | MOZ_ASSERT(prefixKind == FunctionPrefixKind::None)do { static_assert( mozilla::detail::AssertionConditionType< decltype(prefixKind == FunctionPrefixKind::None)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(prefixKind == FunctionPrefixKind::None))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("prefixKind == FunctionPrefixKind::None" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3131); AnnotateMozCrashReason("MOZ_ASSERT" "(" "prefixKind == FunctionPrefixKind::None" ")"); do { *((volatile int*)__null) = 3131; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3132 | |
3133 | return emitClass(&node->as<ClassNode>(), ClassNameKind::ComputedName); |
3134 | } |
3135 | |
3136 | void BytecodeEmitter::setFunName(FunctionBox* funbox, |
3137 | TaggedParserAtomIndex name) const { |
3138 | // The inferred name may already be set if this function is an interpreted |
3139 | // lazy function and we OOM'ed after we set the inferred name the first |
3140 | // time. |
3141 | if (funbox->hasInferredName()) { |
3142 | MOZ_ASSERT(!funbox->emitBytecode)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!funbox->emitBytecode)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!funbox->emitBytecode))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!funbox->emitBytecode" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3142); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!funbox->emitBytecode" ")"); do { *((volatile int*)__null) = 3142; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3143 | MOZ_ASSERT(funbox->displayAtom() == name)do { static_assert( mozilla::detail::AssertionConditionType< decltype(funbox->displayAtom() == name)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(funbox->displayAtom() == name ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "funbox->displayAtom() == name", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3143); AnnotateMozCrashReason("MOZ_ASSERT" "(" "funbox->displayAtom() == name" ")"); do { *((volatile int*)__null) = 3143; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3144 | } else { |
3145 | funbox->setInferredName(name); |
3146 | } |
3147 | } |
3148 | |
3149 | bool BytecodeEmitter::emitInitializer(ParseNode* initializer, |
3150 | ParseNode* pattern) { |
3151 | if (initializer->isDirectRHSAnonFunction()) { |
3152 | MOZ_ASSERT(!pattern->isInParens())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!pattern->isInParens())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!pattern->isInParens()))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("!pattern->isInParens()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3152); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!pattern->isInParens()" ")"); do { *((volatile int*)__null) = 3152; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3153 | auto name = pattern->as<NameNode>().name(); |
3154 | if (!emitAnonymousFunctionWithName(initializer, name)) { |
3155 | return false; |
3156 | } |
3157 | } else { |
3158 | if (!emitTree(initializer)) { |
3159 | return false; |
3160 | } |
3161 | } |
3162 | |
3163 | return true; |
3164 | } |
3165 | |
3166 | bool BytecodeEmitter::emitDestructuringOpsArray(ListNode* pattern, |
3167 | DestructuringFlavor flav) { |
3168 | MOZ_ASSERT(getSelfHostedIterFor(pattern) == SelfHostedIter::Deny,do { static_assert( mozilla::detail::AssertionConditionType< decltype(getSelfHostedIterFor(pattern) == SelfHostedIter::Deny )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(getSelfHostedIterFor(pattern) == SelfHostedIter::Deny ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "getSelfHostedIterFor(pattern) == SelfHostedIter::Deny" " (" "array destructuring is prohibited in self-hosted code because it" "can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3170); AnnotateMozCrashReason("MOZ_ASSERT" "(" "getSelfHostedIterFor(pattern) == SelfHostedIter::Deny" ") (" "array destructuring is prohibited in self-hosted code because it" "can run user-modifiable iteration code" ")"); do { *((volatile int*)__null) = 3170; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
3169 | "array destructuring is prohibited in self-hosted code because it"do { static_assert( mozilla::detail::AssertionConditionType< decltype(getSelfHostedIterFor(pattern) == SelfHostedIter::Deny )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(getSelfHostedIterFor(pattern) == SelfHostedIter::Deny ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "getSelfHostedIterFor(pattern) == SelfHostedIter::Deny" " (" "array destructuring is prohibited in self-hosted code because it" "can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3170); AnnotateMozCrashReason("MOZ_ASSERT" "(" "getSelfHostedIterFor(pattern) == SelfHostedIter::Deny" ") (" "array destructuring is prohibited in self-hosted code because it" "can run user-modifiable iteration code" ")"); do { *((volatile int*)__null) = 3170; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
3170 | "can run user-modifiable iteration code")do { static_assert( mozilla::detail::AssertionConditionType< decltype(getSelfHostedIterFor(pattern) == SelfHostedIter::Deny )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(getSelfHostedIterFor(pattern) == SelfHostedIter::Deny ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "getSelfHostedIterFor(pattern) == SelfHostedIter::Deny" " (" "array destructuring is prohibited in self-hosted code because it" "can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3170); AnnotateMozCrashReason("MOZ_ASSERT" "(" "getSelfHostedIterFor(pattern) == SelfHostedIter::Deny" ") (" "array destructuring is prohibited in self-hosted code because it" "can run user-modifiable iteration code" ")"); do { *((volatile int*)__null) = 3170; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3171 | MOZ_ASSERT(pattern->isKind(ParseNodeKind::ArrayExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(pattern->isKind(ParseNodeKind::ArrayExpr))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(pattern->isKind(ParseNodeKind::ArrayExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("pattern->isKind(ParseNodeKind::ArrayExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3171); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pattern->isKind(ParseNodeKind::ArrayExpr)" ")"); do { *((volatile int*)__null) = 3171; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3172 | MOZ_ASSERT(bytecodeSection().stackDepth() != 0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(bytecodeSection().stackDepth() != 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(bytecodeSection().stackDepth () != 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("bytecodeSection().stackDepth() != 0", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3172); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() != 0" ")"); do { *((volatile int*)__null) = 3172; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3173 | |
3174 | // Here's pseudo code for |let [a, b, , c=y, ...d] = x;| |
3175 | // |
3176 | // Lines that are annotated "covered by trynote" mean that upon throwing |
3177 | // an exception, IteratorClose is called on iter only if done is false. |
3178 | // |
3179 | // let x, y; |
3180 | // let a, b, c, d; |
3181 | // let iter, next, lref, result, done, value; // stack values |
3182 | // |
3183 | // // NOTE: the fast path for this example is not applicable, because of |
3184 | // // the spread and the assignment |c=y|, but it is documented here for a |
3185 | // // simpler example, |let [a,b] = x;| |
3186 | // // |
3187 | // // if (IsOptimizableArray(x)) { |
3188 | // // a = x[0]; |
3189 | // // b = x[1]; |
3190 | // // goto end: // (skip everything below) |
3191 | // // } |
3192 | // |
3193 | // iter = x[Symbol.iterator](); |
3194 | // next = iter.next; |
3195 | // |
3196 | // // ==== emitted by loop for a ==== |
3197 | // lref = GetReference(a); // covered by trynote |
3198 | // |
3199 | // result = Call(next, iter); |
3200 | // done = result.done; |
3201 | // |
3202 | // if (done) |
3203 | // value = undefined; |
3204 | // else |
3205 | // value = result.value; |
3206 | // |
3207 | // SetOrInitialize(lref, value); // covered by trynote |
3208 | // |
3209 | // // ==== emitted by loop for b ==== |
3210 | // lref = GetReference(b); // covered by trynote |
3211 | // |
3212 | // if (done) { |
3213 | // value = undefined; |
3214 | // } else { |
3215 | // result = Call(next, iter); |
3216 | // done = result.done; |
3217 | // if (done) |
3218 | // value = undefined; |
3219 | // else |
3220 | // value = result.value; |
3221 | // } |
3222 | // |
3223 | // SetOrInitialize(lref, value); // covered by trynote |
3224 | // |
3225 | // // ==== emitted by loop for elision ==== |
3226 | // if (done) { |
3227 | // value = undefined; |
3228 | // } else { |
3229 | // result = Call(next, iter); |
3230 | // done = result.done; |
3231 | // if (done) |
3232 | // value = undefined; |
3233 | // else |
3234 | // value = result.value; |
3235 | // } |
3236 | // |
3237 | // // ==== emitted by loop for c ==== |
3238 | // lref = GetReference(c); // covered by trynote |
3239 | // |
3240 | // if (done) { |
3241 | // value = undefined; |
3242 | // } else { |
3243 | // result = Call(next, iter); |
3244 | // done = result.done; |
3245 | // if (done) |
3246 | // value = undefined; |
3247 | // else |
3248 | // value = result.value; |
3249 | // } |
3250 | // |
3251 | // if (value === undefined) |
3252 | // value = y; // covered by trynote |
3253 | // |
3254 | // SetOrInitialize(lref, value); // covered by trynote |
3255 | // |
3256 | // // ==== emitted by loop for d ==== |
3257 | // lref = GetReference(d); // covered by trynote |
3258 | // |
3259 | // if (done) |
3260 | // value = []; |
3261 | // else |
3262 | // value = [...iter]; |
3263 | // |
3264 | // SetOrInitialize(lref, value); // covered by trynote |
3265 | // |
3266 | // // === emitted after loop === |
3267 | // if (!done) |
3268 | // IteratorClose(iter); |
3269 | // |
3270 | // end: |
3271 | |
3272 | bool isEligibleForArrayOptimizations = true; |
3273 | for (ParseNode* member : pattern->contents()) { |
3274 | switch (member->getKind()) { |
3275 | case ParseNodeKind::Elision: |
3276 | break; |
3277 | case ParseNodeKind::Name: { |
3278 | auto name = member->as<NameNode>().name(); |
3279 | NameLocation loc = lookupName(name); |
3280 | if (loc.kind() != NameLocation::Kind::ArgumentSlot && |
3281 | loc.kind() != NameLocation::Kind::FrameSlot && |
3282 | loc.kind() != NameLocation::Kind::EnvironmentCoordinate) { |
3283 | isEligibleForArrayOptimizations = false; |
3284 | } |
3285 | break; |
3286 | } |
3287 | default: |
3288 | // Unfortunately we can't handle any recursive destructuring, |
3289 | // because we can't guarantee that the recursed-into parts |
3290 | // won't run code which invalidates our constraints. We also |
3291 | // cannot handle ParseNodeKind::AssignExpr for similar reasons. |
3292 | isEligibleForArrayOptimizations = false; |
3293 | break; |
3294 | } |
3295 | if (!isEligibleForArrayOptimizations) { |
3296 | break; |
3297 | } |
3298 | } |
3299 | |
3300 | // Use an iterator to destructure the RHS, instead of index lookup. We |
3301 | // must leave the *original* value on the stack. |
3302 | if (!emit1(JSOp::Dup)) { |
3303 | // [stack] ... OBJ OBJ |
3304 | return false; |
3305 | } |
3306 | |
3307 | Maybe<InternalIfEmitter> ifArrayOptimizable; |
3308 | |
3309 | if (isEligibleForArrayOptimizations) { |
3310 | ifArrayOptimizable.emplace( |
3311 | this, BranchEmitterBase::LexicalKind::MayContainLexicalAccessInBranch); |
3312 | |
3313 | if (!emit1(JSOp::Dup)) { |
3314 | // [stack] OBJ OBJ |
3315 | return false; |
3316 | } |
3317 | |
3318 | if (!emit1(JSOp::OptimizeGetIterator)) { |
3319 | // [stack] OBJ OBJ IS_OPTIMIZABLE |
3320 | return false; |
3321 | } |
3322 | |
3323 | if (!ifArrayOptimizable->emitThenElse()) { |
3324 | // [stack] OBJ OBJ |
3325 | return false; |
3326 | } |
3327 | |
3328 | if (!emitAtomOp(JSOp::GetProp, |
3329 | TaggedParserAtomIndex::WellKnown::length())) { |
3330 | // [stack] OBJ LENGTH |
3331 | return false; |
3332 | } |
3333 | |
3334 | if (!emit1(JSOp::Swap)) { |
3335 | // [stack] LENGTH OBJ |
3336 | return false; |
3337 | } |
3338 | |
3339 | uint32_t idx = 0; |
3340 | for (ParseNode* member : pattern->contents()) { |
3341 | if (member->isKind(ParseNodeKind::Elision)) { |
3342 | idx += 1; |
3343 | continue; |
3344 | } |
3345 | MOZ_ASSERT(member->isKind(ParseNodeKind::Name))do { static_assert( mozilla::detail::AssertionConditionType< decltype(member->isKind(ParseNodeKind::Name))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(member->isKind(ParseNodeKind::Name)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("member->isKind(ParseNodeKind::Name)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3345); AnnotateMozCrashReason("MOZ_ASSERT" "(" "member->isKind(ParseNodeKind::Name)" ")"); do { *((volatile int*)__null) = 3345; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3346 | |
3347 | if (!emit1(JSOp::Dup)) { |
3348 | // [stack] LENGTH OBJ OBJ |
3349 | return false; |
3350 | } |
3351 | |
3352 | if (!emitNumberOp(idx)) { |
3353 | // [stack] LENGTH OBJ OBJ IDX |
3354 | return false; |
3355 | } |
3356 | |
3357 | if (!emit1(JSOp::Dup)) { |
3358 | // [stack] LENGTH OBJ OBJ IDX IDX |
3359 | return false; |
3360 | } |
3361 | |
3362 | if (!emitDupAt(4)) { |
3363 | // [stack] LENGTH OBJ OBJ IDX IDX LENGTH |
3364 | return false; |
3365 | } |
3366 | |
3367 | if (!emit1(JSOp::Lt)) { |
3368 | // [stack] LENGTH OBJ OBJ IDX IS_IN_DENSE_BOUNDS |
3369 | return false; |
3370 | } |
3371 | |
3372 | InternalIfEmitter isInDenseBounds(this); |
3373 | if (!isInDenseBounds.emitThenElse()) { |
3374 | // [stack] LENGTH OBJ OBJ IDX |
3375 | return false; |
3376 | } |
3377 | |
3378 | if (!emit1(JSOp::GetElem)) { |
3379 | // [stack] LENGTH OBJ VALUE |
3380 | return false; |
3381 | } |
3382 | |
3383 | if (!isInDenseBounds.emitElse()) { |
3384 | // [stack] LENGTH OBJ OBJ IDX |
3385 | return false; |
3386 | } |
3387 | |
3388 | if (!emitPopN(2)) { |
3389 | // [stack] LENGTH OBJ |
3390 | return false; |
3391 | } |
3392 | |
3393 | if (!emit1(JSOp::Undefined)) { |
3394 | // [stack] LENGTH OBJ UNDEFINED |
3395 | return false; |
3396 | } |
3397 | |
3398 | if (!isInDenseBounds.emitEnd()) { |
3399 | // [stack] LENGTH OBJ VALUE|UNDEFINED |
3400 | return false; |
3401 | } |
3402 | |
3403 | DestructuringLHSRef lref; |
3404 | if (!emitDestructuringLHSRef(member, flav, lref)) { |
3405 | // [stack] LENGTH OBJ |
3406 | return false; |
3407 | } |
3408 | |
3409 | if (!emitSetOrInitializeDestructuring(member, flav, lref)) { |
3410 | // [stack] LENGTH OBJ |
3411 | return false; |
3412 | } |
3413 | |
3414 | idx += 1; |
3415 | } |
3416 | |
3417 | if (!emit1(JSOp::Swap)) { |
3418 | // [stack] OBJ LENGTH |
3419 | return false; |
3420 | } |
3421 | |
3422 | if (!emit1(JSOp::Pop)) { |
3423 | // [stack] OBJ |
3424 | return false; |
3425 | } |
3426 | |
3427 | if (!ifArrayOptimizable->emitElse()) { |
3428 | // [stack] OBJ OBJ |
3429 | return false; |
3430 | } |
3431 | } |
3432 | |
3433 | if (!emitIterator(SelfHostedIter::Deny)) { |
3434 | // [stack] ... OBJ NEXT ITER |
3435 | return false; |
3436 | } |
3437 | |
3438 | // For an empty pattern [], call IteratorClose unconditionally. Nothing |
3439 | // else needs to be done. |
3440 | if (!pattern->head()) { |
3441 | if (!emit1(JSOp::Swap)) { |
3442 | // [stack] ... OBJ ITER NEXT |
3443 | return false; |
3444 | } |
3445 | if (!emit1(JSOp::Pop)) { |
3446 | // [stack] ... OBJ ITER |
3447 | return false; |
3448 | } |
3449 | |
3450 | if (!emitIteratorCloseInInnermostScope()) { |
3451 | // [stack] ... OBJ |
3452 | return false; |
3453 | } |
3454 | |
3455 | if (ifArrayOptimizable.isSome()) { |
3456 | if (!ifArrayOptimizable->emitEnd()) { |
3457 | // [stack] OBJ |
3458 | return false; |
3459 | } |
3460 | } |
3461 | |
3462 | return true; |
3463 | } |
3464 | |
3465 | // Push an initial FALSE value for DONE. |
3466 | if (!emit1(JSOp::False)) { |
3467 | // [stack] ... OBJ NEXT ITER FALSE |
3468 | return false; |
3469 | } |
3470 | |
3471 | // TryNoteKind::Destructuring expects the iterator and the done value |
3472 | // to be the second to top and the top of the stack, respectively. |
3473 | // IteratorClose is called upon exception only if done is false. |
3474 | int32_t tryNoteDepth = bytecodeSection().stackDepth(); |
3475 | |
3476 | for (ParseNode* member : pattern->contents()) { |
3477 | bool isFirst = member == pattern->head(); |
3478 | DebugOnly<bool> hasNext = !!member->pn_next; |
3479 | |
3480 | ParseNode* subpattern; |
3481 | if (member->isKind(ParseNodeKind::Spread)) { |
3482 | subpattern = member->as<UnaryNode>().kid(); |
3483 | |
3484 | MOZ_ASSERT(!subpattern->isKind(ParseNodeKind::AssignExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!subpattern->isKind(ParseNodeKind::AssignExpr))> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!subpattern->isKind(ParseNodeKind::AssignExpr)))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("!subpattern->isKind(ParseNodeKind::AssignExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3484); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!subpattern->isKind(ParseNodeKind::AssignExpr)" ")"); do { *((volatile int*)__null) = 3484; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3485 | } else { |
3486 | subpattern = member; |
3487 | } |
3488 | |
3489 | ParseNode* lhsPattern = subpattern; |
3490 | ParseNode* pndefault = nullptr; |
3491 | if (subpattern->isKind(ParseNodeKind::AssignExpr)) { |
3492 | lhsPattern = subpattern->as<AssignmentNode>().left(); |
3493 | pndefault = subpattern->as<AssignmentNode>().right(); |
3494 | } |
3495 | |
3496 | // Spec requires LHS reference to be evaluated first. |
3497 | DestructuringLHSRef lref; |
3498 | bool isElision = lhsPattern->isKind(ParseNodeKind::Elision); |
3499 | if (!isElision) { |
3500 | auto emitLHSRef = [lhsPattern, flav, &lref](BytecodeEmitter* bce) { |
3501 | return bce->emitDestructuringLHSRef(lhsPattern, flav, lref); |
3502 | // [stack] ... OBJ NEXT ITER DONE LREF* |
3503 | }; |
3504 | if (!wrapWithDestructuringTryNote(tryNoteDepth, emitLHSRef)) { |
3505 | return false; |
3506 | } |
3507 | } |
3508 | |
3509 | // Number of stack slots emitted for the LHS reference. |
3510 | size_t emitted = lref.numReferenceSlots(); |
3511 | |
3512 | // Pick the DONE value to the top of the stack. |
3513 | if (emitted) { |
3514 | if (!emitPickN(emitted)) { |
3515 | // [stack] ... OBJ NEXT ITER LREF* DONE |
3516 | return false; |
3517 | } |
3518 | } |
3519 | |
3520 | if (isFirst) { |
3521 | // If this element is the first, DONE is always FALSE, so pop it. |
3522 | // |
3523 | // Non-first elements should emit if-else depending on the |
3524 | // member pattern, below. |
3525 | if (!emit1(JSOp::Pop)) { |
3526 | // [stack] ... OBJ NEXT ITER LREF* |
3527 | return false; |
3528 | } |
3529 | } |
3530 | |
3531 | if (member->isKind(ParseNodeKind::Spread)) { |
3532 | InternalIfEmitter ifThenElse(this); |
3533 | if (!isFirst) { |
3534 | // If spread is not the first element of the pattern, |
3535 | // iterator can already be completed. |
3536 | // [stack] ... OBJ NEXT ITER LREF* DONE |
3537 | |
3538 | if (!ifThenElse.emitThenElse()) { |
3539 | // [stack] ... OBJ NEXT ITER LREF* |
3540 | return false; |
3541 | } |
3542 | |
3543 | if (!emitUint32Operand(JSOp::NewArray, 0)) { |
3544 | // [stack] ... OBJ NEXT ITER LREF* ARRAY |
3545 | return false; |
3546 | } |
3547 | if (!ifThenElse.emitElse()) { |
3548 | // [stack] ... OBJ NEXT ITER LREF* |
3549 | return false; |
3550 | } |
3551 | } |
3552 | |
3553 | // If iterator is not completed, create a new array with the rest |
3554 | // of the iterator. |
3555 | if (!emitDupAt(emitted + 1, 2)) { |
3556 | // [stack] ... OBJ NEXT ITER LREF* NEXT ITER |
3557 | return false; |
3558 | } |
3559 | if (!emitUint32Operand(JSOp::NewArray, 0)) { |
3560 | // [stack] ... OBJ NEXT ITER LREF* NEXT ITER ARRAY |
3561 | return false; |
3562 | } |
3563 | if (!emitNumberOp(0)) { |
3564 | // [stack] ... OBJ NEXT ITER LREF* NEXT ITER ARRAY INDEX |
3565 | return false; |
3566 | } |
3567 | if (!emitSpread(SelfHostedIter::Deny)) { |
3568 | // [stack] ... OBJ NEXT ITER LREF* ARRAY INDEX |
3569 | return false; |
3570 | } |
3571 | if (!emit1(JSOp::Pop)) { |
3572 | // [stack] ... OBJ NEXT ITER LREF* ARRAY |
3573 | return false; |
3574 | } |
3575 | |
3576 | if (!isFirst) { |
3577 | if (!ifThenElse.emitEnd()) { |
3578 | return false; |
3579 | } |
3580 | MOZ_ASSERT(ifThenElse.pushed() == 1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(ifThenElse.pushed() == 1)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(ifThenElse.pushed() == 1))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("ifThenElse.pushed() == 1" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3580); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ifThenElse.pushed() == 1" ")"); do { *((volatile int*)__null) = 3580; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3581 | } |
3582 | |
3583 | // At this point the iterator is done. Unpick a TRUE value for DONE above |
3584 | // ITER. |
3585 | if (!emit1(JSOp::True)) { |
3586 | // [stack] ... OBJ NEXT ITER LREF* ARRAY TRUE |
3587 | return false; |
3588 | } |
3589 | if (!emitUnpickN(emitted + 1)) { |
3590 | // [stack] ... OBJ NEXT ITER TRUE LREF* ARRAY |
3591 | return false; |
3592 | } |
3593 | |
3594 | auto emitAssignment = [lhsPattern, flav, &lref](BytecodeEmitter* bce) { |
3595 | return bce->emitSetOrInitializeDestructuring(lhsPattern, flav, lref); |
3596 | // [stack] ... OBJ NEXT ITER TRUE |
3597 | }; |
3598 | if (!wrapWithDestructuringTryNote(tryNoteDepth, emitAssignment)) { |
3599 | return false; |
3600 | } |
3601 | |
3602 | MOZ_ASSERT(!hasNext)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!hasNext)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!hasNext))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!hasNext", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3602); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!hasNext" ")" ); do { *((volatile int*)__null) = 3602; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3603 | break; |
3604 | } |
3605 | |
3606 | InternalIfEmitter ifAlreadyDone(this); |
3607 | if (!isFirst) { |
3608 | // [stack] ... OBJ NEXT ITER LREF* DONE |
3609 | |
3610 | if (!ifAlreadyDone.emitThenElse()) { |
3611 | // [stack] ... OBJ NEXT ITER LREF* |
3612 | return false; |
3613 | } |
3614 | |
3615 | if (!emit1(JSOp::Undefined)) { |
3616 | // [stack] ... OBJ NEXT ITER LREF* UNDEF |
3617 | return false; |
3618 | } |
3619 | if (!emit1(JSOp::NopDestructuring)) { |
3620 | // [stack] ... OBJ NEXT ITER LREF* UNDEF |
3621 | return false; |
3622 | } |
3623 | |
3624 | // The iterator is done. Unpick a TRUE value for DONE above ITER. |
3625 | if (!emit1(JSOp::True)) { |
3626 | // [stack] ... OBJ NEXT ITER LREF* UNDEF TRUE |
3627 | return false; |
3628 | } |
3629 | if (!emitUnpickN(emitted + 1)) { |
3630 | // [stack] ... OBJ NEXT ITER TRUE LREF* UNDEF |
3631 | return false; |
3632 | } |
3633 | |
3634 | if (!ifAlreadyDone.emitElse()) { |
3635 | // [stack] ... OBJ NEXT ITER LREF* |
3636 | return false; |
3637 | } |
3638 | } |
3639 | |
3640 | if (!emitDupAt(emitted + 1, 2)) { |
3641 | // [stack] ... OBJ NEXT ITER LREF* NEXT |
3642 | return false; |
3643 | } |
3644 | if (!emitIteratorNext(Some(pattern->pn_pos.begin))) { |
3645 | // [stack] ... OBJ NEXT ITER LREF* RESULT |
3646 | return false; |
3647 | } |
3648 | if (!emit1(JSOp::Dup)) { |
3649 | // [stack] ... OBJ NEXT ITER LREF* RESULT RESULT |
3650 | return false; |
3651 | } |
3652 | if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::done())) { |
3653 | // [stack] ... OBJ NEXT ITER LREF* RESULT DONE |
3654 | return false; |
3655 | } |
3656 | |
3657 | if (!emit1(JSOp::Dup)) { |
3658 | // [stack] ... OBJ NEXT ITER LREF* RESULT DONE DONE |
3659 | return false; |
3660 | } |
3661 | if (!emitUnpickN(emitted + 2)) { |
3662 | // [stack] ... OBJ NEXT ITER DONE LREF* RESULT DONE |
3663 | return false; |
3664 | } |
3665 | |
3666 | InternalIfEmitter ifDone(this); |
3667 | if (!ifDone.emitThenElse()) { |
3668 | // [stack] ... OBJ NEXT ITER DONE LREF* RESULT |
3669 | return false; |
3670 | } |
3671 | |
3672 | if (!emit1(JSOp::Pop)) { |
3673 | // [stack] ... OBJ NEXT ITER DONE LREF* |
3674 | return false; |
3675 | } |
3676 | if (!emit1(JSOp::Undefined)) { |
3677 | // [stack] ... OBJ NEXT ITER DONE LREF* UNDEF |
3678 | return false; |
3679 | } |
3680 | if (!emit1(JSOp::NopDestructuring)) { |
3681 | // [stack] ... OBJ NEXT ITER DONE LREF* UNDEF |
3682 | return false; |
3683 | } |
3684 | |
3685 | if (!ifDone.emitElse()) { |
3686 | // [stack] ... OBJ NEXT ITER DONE LREF* RESULT |
3687 | return false; |
3688 | } |
3689 | |
3690 | if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::value())) { |
3691 | // [stack] ... OBJ NEXT ITER DONE LREF* VALUE |
3692 | return false; |
3693 | } |
3694 | |
3695 | if (!ifDone.emitEnd()) { |
3696 | return false; |
3697 | } |
3698 | MOZ_ASSERT(ifDone.pushed() == 0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(ifDone.pushed() == 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(ifDone.pushed() == 0))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("ifDone.pushed() == 0" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3698); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ifDone.pushed() == 0" ")"); do { *((volatile int*)__null) = 3698; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3699 | |
3700 | if (!isFirst) { |
3701 | if (!ifAlreadyDone.emitEnd()) { |
3702 | return false; |
3703 | } |
3704 | MOZ_ASSERT(ifAlreadyDone.pushed() == 2)do { static_assert( mozilla::detail::AssertionConditionType< decltype(ifAlreadyDone.pushed() == 2)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(ifAlreadyDone.pushed() == 2) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("ifAlreadyDone.pushed() == 2" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3704); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ifAlreadyDone.pushed() == 2" ")"); do { *((volatile int*)__null) = 3704; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3705 | } |
3706 | |
3707 | if (pndefault) { |
3708 | auto emitDefault = [pndefault, lhsPattern](BytecodeEmitter* bce) { |
3709 | return bce->emitDefault(pndefault, lhsPattern); |
3710 | // [stack] ... OBJ NEXT ITER DONE LREF* VALUE |
3711 | }; |
3712 | |
3713 | if (!wrapWithDestructuringTryNote(tryNoteDepth, emitDefault)) { |
3714 | return false; |
3715 | } |
3716 | } |
3717 | |
3718 | if (!isElision) { |
3719 | auto emitAssignment = [lhsPattern, flav, &lref](BytecodeEmitter* bce) { |
3720 | return bce->emitSetOrInitializeDestructuring(lhsPattern, flav, lref); |
3721 | // [stack] ... OBJ NEXT ITER DONE |
3722 | }; |
3723 | |
3724 | if (!wrapWithDestructuringTryNote(tryNoteDepth, emitAssignment)) { |
3725 | return false; |
3726 | } |
3727 | } else { |
3728 | if (!emit1(JSOp::Pop)) { |
3729 | // [stack] ... OBJ NEXT ITER DONE |
3730 | return false; |
3731 | } |
3732 | } |
3733 | } |
3734 | |
3735 | // The last DONE value is on top of the stack. If not DONE, call |
3736 | // IteratorClose. |
3737 | // [stack] ... OBJ NEXT ITER DONE |
3738 | |
3739 | InternalIfEmitter ifDone(this); |
3740 | if (!ifDone.emitThenElse()) { |
3741 | // [stack] ... OBJ NEXT ITER |
3742 | return false; |
3743 | } |
3744 | if (!emitPopN(2)) { |
3745 | // [stack] ... OBJ |
3746 | return false; |
3747 | } |
3748 | if (!ifDone.emitElse()) { |
3749 | // [stack] ... OBJ NEXT ITER |
3750 | return false; |
3751 | } |
3752 | if (!emit1(JSOp::Swap)) { |
3753 | // [stack] ... OBJ ITER NEXT |
3754 | return false; |
3755 | } |
3756 | if (!emit1(JSOp::Pop)) { |
3757 | // [stack] ... OBJ ITER |
3758 | return false; |
3759 | } |
3760 | if (!emitIteratorCloseInInnermostScope()) { |
3761 | // [stack] ... OBJ |
3762 | return false; |
3763 | } |
3764 | if (!ifDone.emitEnd()) { |
3765 | return false; |
3766 | } |
3767 | |
3768 | if (ifArrayOptimizable.isSome()) { |
3769 | if (!ifArrayOptimizable->emitEnd()) { |
3770 | // [stack] OBJ |
3771 | return false; |
3772 | } |
3773 | } |
3774 | |
3775 | return true; |
3776 | } |
3777 | |
3778 | bool BytecodeEmitter::emitComputedPropertyName(UnaryNode* computedPropName) { |
3779 | MOZ_ASSERT(computedPropName->isKind(ParseNodeKind::ComputedName))do { static_assert( mozilla::detail::AssertionConditionType< decltype(computedPropName->isKind(ParseNodeKind::ComputedName ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(computedPropName->isKind(ParseNodeKind::ComputedName )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("computedPropName->isKind(ParseNodeKind::ComputedName)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3779); AnnotateMozCrashReason("MOZ_ASSERT" "(" "computedPropName->isKind(ParseNodeKind::ComputedName)" ")"); do { *((volatile int*)__null) = 3779; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3780 | return emitTree(computedPropName->kid()) && emit1(JSOp::ToPropertyKey); |
3781 | } |
3782 | |
3783 | bool BytecodeEmitter::emitDestructuringOpsObject(ListNode* pattern, |
3784 | DestructuringFlavor flav) { |
3785 | MOZ_ASSERT(pattern->isKind(ParseNodeKind::ObjectExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(pattern->isKind(ParseNodeKind::ObjectExpr))>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(pattern->isKind(ParseNodeKind::ObjectExpr)))), 0) )) { do { } while (false); MOZ_ReportAssertionFailure("pattern->isKind(ParseNodeKind::ObjectExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3785); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pattern->isKind(ParseNodeKind::ObjectExpr)" ")"); do { *((volatile int*)__null) = 3785; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3786 | |
3787 | // [stack] ... RHS |
3788 | MOZ_ASSERT(bytecodeSection().stackDepth() > 0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(bytecodeSection().stackDepth() > 0)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(! !(bytecodeSection().stackDepth() > 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("bytecodeSection().stackDepth() > 0" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3788); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() > 0" ")"); do { *((volatile int*)__null) = 3788; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3789 | |
3790 | if (!emit1(JSOp::CheckObjCoercible)) { |
3791 | // [stack] ... RHS |
3792 | return false; |
3793 | } |
3794 | |
3795 | bool needsRestPropertyExcludedSet = |
3796 | pattern->count() > 1 && pattern->last()->isKind(ParseNodeKind::Spread); |
3797 | if (needsRestPropertyExcludedSet) { |
3798 | if (!emitDestructuringObjRestExclusionSet(pattern)) { |
3799 | // [stack] ... RHS SET |
3800 | return false; |
3801 | } |
3802 | |
3803 | if (!emit1(JSOp::Swap)) { |
3804 | // [stack] ... SET RHS |
3805 | return false; |
3806 | } |
3807 | } |
3808 | |
3809 | for (ParseNode* member : pattern->contents()) { |
3810 | ParseNode* subpattern; |
3811 | bool hasKeyOnStack = false; |
3812 | if (member->isKind(ParseNodeKind::MutateProto) || |
3813 | member->isKind(ParseNodeKind::Spread)) { |
3814 | subpattern = member->as<UnaryNode>().kid(); |
3815 | |
3816 | MOZ_ASSERT_IF(member->isKind(ParseNodeKind::Spread),do { if (member->isKind(ParseNodeKind::Spread)) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(!subpattern ->isKind(ParseNodeKind::AssignExpr))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!subpattern->isKind(ParseNodeKind ::AssignExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!subpattern->isKind(ParseNodeKind::AssignExpr)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3817); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!subpattern->isKind(ParseNodeKind::AssignExpr)" ")"); do { *((volatile int*)__null) = 3817; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
3817 | !subpattern->isKind(ParseNodeKind::AssignExpr))do { if (member->isKind(ParseNodeKind::Spread)) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(!subpattern ->isKind(ParseNodeKind::AssignExpr))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!subpattern->isKind(ParseNodeKind ::AssignExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!subpattern->isKind(ParseNodeKind::AssignExpr)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3817); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!subpattern->isKind(ParseNodeKind::AssignExpr)" ")"); do { *((volatile int*)__null) = 3817; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
3818 | } else { |
3819 | MOZ_ASSERT(member->isKind(ParseNodeKind::PropertyDefinition) ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(member->isKind(ParseNodeKind::PropertyDefinition) || member ->isKind(ParseNodeKind::Shorthand)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3820); AnnotateMozCrashReason("MOZ_ASSERT" "(" "member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)" ")"); do { *((volatile int*)__null) = 3820; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
3820 | member->isKind(ParseNodeKind::Shorthand))do { static_assert( mozilla::detail::AssertionConditionType< decltype(member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(member->isKind(ParseNodeKind::PropertyDefinition) || member ->isKind(ParseNodeKind::Shorthand)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3820); AnnotateMozCrashReason("MOZ_ASSERT" "(" "member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)" ")"); do { *((volatile int*)__null) = 3820; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3821 | subpattern = member->as<BinaryNode>().right(); |
3822 | |
3823 | // Computed property names are evaluated before the subpattern. |
3824 | ParseNode* key = member->as<BinaryNode>().left(); |
3825 | if (key->isKind(ParseNodeKind::ComputedName)) { |
3826 | if (!emitComputedPropertyName(&key->as<UnaryNode>())) { |
3827 | // [stack] ... SET? RHS KEY |
3828 | return false; |
3829 | } |
3830 | hasKeyOnStack = true; |
3831 | } |
3832 | } |
3833 | |
3834 | ParseNode* lhs = subpattern; |
3835 | ParseNode* pndefault = nullptr; |
3836 | if (subpattern->isKind(ParseNodeKind::AssignExpr)) { |
3837 | lhs = subpattern->as<AssignmentNode>().left(); |
3838 | pndefault = subpattern->as<AssignmentNode>().right(); |
3839 | } |
3840 | |
3841 | // Spec requires LHS reference to be evaluated first. |
3842 | DestructuringLHSRef lref; |
3843 | if (!emitDestructuringLHSRef(lhs, flav, lref)) { |
3844 | // [stack] ... SET? RHS KEY? LREF* |
3845 | return false; |
3846 | } |
3847 | |
3848 | // Number of stack slots emitted for the LHS reference. |
3849 | size_t emitted = lref.numReferenceSlots(); |
3850 | |
3851 | // Duplicate the value being destructured to use as a reference base. |
3852 | if (!emitDupAt(emitted + hasKeyOnStack)) { |
3853 | // [stack] ... SET? RHS KEY? LREF* RHS |
3854 | return false; |
3855 | } |
3856 | |
3857 | if (member->isKind(ParseNodeKind::Spread)) { |
3858 | if (!updateSourceCoordNotes(member->pn_pos.begin)) { |
3859 | return false; |
3860 | } |
3861 | |
3862 | if (!emit1(JSOp::NewInit)) { |
3863 | // [stack] ... SET? RHS LREF* RHS TARGET |
3864 | return false; |
3865 | } |
3866 | if (!emit1(JSOp::Dup)) { |
3867 | // [stack] ... SET? RHS LREF* RHS TARGET TARGET |
3868 | return false; |
3869 | } |
3870 | if (!emit2(JSOp::Pick, 2)) { |
3871 | // [stack] ... SET? RHS LREF* TARGET TARGET RHS |
3872 | return false; |
3873 | } |
3874 | |
3875 | if (needsRestPropertyExcludedSet) { |
3876 | if (!emit2(JSOp::Pick, emitted + 4)) { |
3877 | // [stack] ... RHS LREF* TARGET TARGET RHS SET |
3878 | return false; |
3879 | } |
3880 | } |
3881 | |
3882 | CopyOption option = needsRestPropertyExcludedSet ? CopyOption::Filtered |
3883 | : CopyOption::Unfiltered; |
3884 | if (!emitCopyDataProperties(option)) { |
3885 | // [stack] ... RHS LREF* TARGET |
3886 | return false; |
3887 | } |
3888 | |
3889 | // Destructure TARGET per this member's lhs. |
3890 | if (!emitSetOrInitializeDestructuring(lhs, flav, lref)) { |
3891 | // [stack] ... RHS |
3892 | return false; |
3893 | } |
3894 | |
3895 | MOZ_ASSERT(member == pattern->last(), "Rest property is always last")do { static_assert( mozilla::detail::AssertionConditionType< decltype(member == pattern->last())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(member == pattern->last() ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "member == pattern->last()" " (" "Rest property is always last" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3895); AnnotateMozCrashReason("MOZ_ASSERT" "(" "member == pattern->last()" ") (" "Rest property is always last" ")"); do { *((volatile int *)__null) = 3895; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3896 | break; |
3897 | } |
3898 | |
3899 | // Now push the property value currently being matched, which is the value |
3900 | // of the current property name "label" on the left of a colon in the object |
3901 | // initialiser. |
3902 | if (member->isKind(ParseNodeKind::MutateProto)) { |
3903 | if (!emitAtomOp(JSOp::GetProp, |
3904 | TaggedParserAtomIndex::WellKnown::proto_())) { |
3905 | // [stack] ... SET? RHS LREF* PROP |
3906 | return false; |
3907 | } |
3908 | } else { |
3909 | MOZ_ASSERT(member->isKind(ParseNodeKind::PropertyDefinition) ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(member->isKind(ParseNodeKind::PropertyDefinition) || member ->isKind(ParseNodeKind::Shorthand)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3910); AnnotateMozCrashReason("MOZ_ASSERT" "(" "member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)" ")"); do { *((volatile int*)__null) = 3910; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
3910 | member->isKind(ParseNodeKind::Shorthand))do { static_assert( mozilla::detail::AssertionConditionType< decltype(member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(member->isKind(ParseNodeKind::PropertyDefinition) || member ->isKind(ParseNodeKind::Shorthand)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3910); AnnotateMozCrashReason("MOZ_ASSERT" "(" "member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)" ")"); do { *((volatile int*)__null) = 3910; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3911 | |
3912 | ParseNode* key = member->as<BinaryNode>().left(); |
3913 | if (key->isKind(ParseNodeKind::ObjectPropertyName) || |
3914 | key->isKind(ParseNodeKind::StringExpr)) { |
3915 | if (!emitAtomOp(JSOp::GetProp, key->as<NameNode>().atom())) { |
3916 | // [stack] ... SET? RHS LREF* PROP |
3917 | return false; |
3918 | } |
3919 | } else { |
3920 | if (key->isKind(ParseNodeKind::NumberExpr)) { |
3921 | if (!emitNumberOp(key->as<NumericLiteral>().value())) { |
3922 | // [stack]... SET? RHS LREF* RHS KEY |
3923 | return false; |
3924 | } |
3925 | } else { |
3926 | // Otherwise this is a computed property name. BigInt keys are parsed |
3927 | // as (synthetic) computed property names, too. |
3928 | MOZ_ASSERT(key->isKind(ParseNodeKind::ComputedName))do { static_assert( mozilla::detail::AssertionConditionType< decltype(key->isKind(ParseNodeKind::ComputedName))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(key->isKind(ParseNodeKind::ComputedName)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("key->isKind(ParseNodeKind::ComputedName)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3928); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::ComputedName)" ")"); do { *((volatile int*)__null) = 3928; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3929 | MOZ_ASSERT(hasKeyOnStack)do { static_assert( mozilla::detail::AssertionConditionType< decltype(hasKeyOnStack)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(hasKeyOnStack))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("hasKeyOnStack", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3929); AnnotateMozCrashReason("MOZ_ASSERT" "(" "hasKeyOnStack" ")"); do { *((volatile int*)__null) = 3929; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3930 | |
3931 | if (!emit2(JSOp::Pick, emitted + 1)) { |
3932 | // [stack] ... SET? RHS LREF* RHS KEY |
3933 | return false; |
3934 | } |
3935 | |
3936 | // Add the computed property key to the exclusion set. |
3937 | if (needsRestPropertyExcludedSet) { |
3938 | if (!emitDupAt(emitted + 3)) { |
3939 | // [stack] ... SET RHS LREF* RHS KEY SET |
3940 | return false; |
3941 | } |
3942 | if (!emitDupAt(1)) { |
3943 | // [stack] ... SET RHS LREF* RHS KEY SET KEY |
3944 | return false; |
3945 | } |
3946 | if (!emit1(JSOp::Undefined)) { |
3947 | // [stack] ... SET RHS LREF* RHS KEY SET KEY UNDEFINED |
3948 | return false; |
3949 | } |
3950 | if (!emit1(JSOp::InitElem)) { |
3951 | // [stack] ... SET RHS LREF* RHS KEY SET |
3952 | return false; |
3953 | } |
3954 | if (!emit1(JSOp::Pop)) { |
3955 | // [stack] ... SET RHS LREF* RHS KEY |
3956 | return false; |
3957 | } |
3958 | } |
3959 | } |
3960 | |
3961 | // Get the property value. |
3962 | if (!emitElemOpBase(JSOp::GetElem)) { |
3963 | // [stack] ... SET? RHS LREF* PROP |
3964 | return false; |
3965 | } |
3966 | } |
3967 | } |
3968 | |
3969 | if (pndefault) { |
3970 | if (!emitDefault(pndefault, lhs)) { |
3971 | // [stack] ... SET? RHS LREF* VALUE |
3972 | return false; |
3973 | } |
3974 | } |
3975 | |
3976 | // Destructure PROP per this member's lhs. |
3977 | if (!emitSetOrInitializeDestructuring(lhs, flav, lref)) { |
3978 | // [stack] ... SET? RHS |
3979 | return false; |
3980 | } |
3981 | } |
3982 | |
3983 | return true; |
3984 | } |
3985 | |
3986 | static bool IsDestructuringRestExclusionSetObjLiteralCompatible( |
3987 | ListNode* pattern) { |
3988 | uint32_t propCount = 0; |
3989 | for (ParseNode* member : pattern->contents()) { |
3990 | if (member->isKind(ParseNodeKind::Spread)) { |
3991 | MOZ_ASSERT(!member->pn_next, "unexpected trailing element after spread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!member->pn_next)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!member->pn_next))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!member->pn_next" " (" "unexpected trailing element after spread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3991); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!member->pn_next" ") (" "unexpected trailing element after spread" ")"); do { * ((volatile int*)__null) = 3991; __attribute__((nomerge)) ::abort (); } while (false); } } while (false); |
3992 | break; |
3993 | } |
3994 | |
3995 | propCount++; |
3996 | |
3997 | if (member->isKind(ParseNodeKind::MutateProto)) { |
3998 | continue; |
3999 | } |
4000 | |
4001 | ParseNode* key = member->as<BinaryNode>().left(); |
4002 | if (key->isKind(ParseNodeKind::ObjectPropertyName) || |
4003 | key->isKind(ParseNodeKind::StringExpr)) { |
4004 | continue; |
4005 | } |
4006 | |
4007 | // Number and BigInt keys aren't yet supported. Computed property names need |
4008 | // to be added dynamically. |
4009 | MOZ_ASSERT(key->isKind(ParseNodeKind::NumberExpr) ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(key->isKind(ParseNodeKind::NumberExpr) || key-> isKind(ParseNodeKind::BigIntExpr) || key->isKind(ParseNodeKind ::ComputedName))>::isValid, "invalid assertion condition") ; if ((__builtin_expect(!!(!(!!(key->isKind(ParseNodeKind:: NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr) || key ->isKind(ParseNodeKind::ComputedName)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr) || key->isKind(ParseNodeKind::ComputedName)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4011); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr) || key->isKind(ParseNodeKind::ComputedName)" ")"); do { *((volatile int*)__null) = 4011; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
4010 | key->isKind(ParseNodeKind::BigIntExpr) ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(key->isKind(ParseNodeKind::NumberExpr) || key-> isKind(ParseNodeKind::BigIntExpr) || key->isKind(ParseNodeKind ::ComputedName))>::isValid, "invalid assertion condition") ; if ((__builtin_expect(!!(!(!!(key->isKind(ParseNodeKind:: NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr) || key ->isKind(ParseNodeKind::ComputedName)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr) || key->isKind(ParseNodeKind::ComputedName)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4011); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr) || key->isKind(ParseNodeKind::ComputedName)" ")"); do { *((volatile int*)__null) = 4011; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
4011 | key->isKind(ParseNodeKind::ComputedName))do { static_assert( mozilla::detail::AssertionConditionType< decltype(key->isKind(ParseNodeKind::NumberExpr) || key-> isKind(ParseNodeKind::BigIntExpr) || key->isKind(ParseNodeKind ::ComputedName))>::isValid, "invalid assertion condition") ; if ((__builtin_expect(!!(!(!!(key->isKind(ParseNodeKind:: NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr) || key ->isKind(ParseNodeKind::ComputedName)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr) || key->isKind(ParseNodeKind::ComputedName)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4011); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr) || key->isKind(ParseNodeKind::ComputedName)" ")"); do { *((volatile int*)__null) = 4011; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4012 | return false; |
4013 | } |
4014 | |
4015 | if (propCount > SharedPropMap::MaxPropsForNonDictionary) { |
4016 | // JSOp::NewObject cannot accept dictionary-mode objects. |
4017 | return false; |
4018 | } |
4019 | |
4020 | return true; |
4021 | } |
4022 | |
4023 | bool BytecodeEmitter::emitDestructuringObjRestExclusionSet(ListNode* pattern) { |
4024 | MOZ_ASSERT(pattern->isKind(ParseNodeKind::ObjectExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(pattern->isKind(ParseNodeKind::ObjectExpr))>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(pattern->isKind(ParseNodeKind::ObjectExpr)))), 0) )) { do { } while (false); MOZ_ReportAssertionFailure("pattern->isKind(ParseNodeKind::ObjectExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4024); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pattern->isKind(ParseNodeKind::ObjectExpr)" ")"); do { *((volatile int*)__null) = 4024; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4025 | MOZ_ASSERT(pattern->last()->isKind(ParseNodeKind::Spread))do { static_assert( mozilla::detail::AssertionConditionType< decltype(pattern->last()->isKind(ParseNodeKind::Spread) )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(pattern->last()->isKind(ParseNodeKind::Spread) ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "pattern->last()->isKind(ParseNodeKind::Spread)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4025); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pattern->last()->isKind(ParseNodeKind::Spread)" ")"); do { *((volatile int*)__null) = 4025; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4026 | |
4027 | // See if we can use ObjLiteral to construct the exclusion set object. |
4028 | if (IsDestructuringRestExclusionSetObjLiteralCompatible(pattern)) { |
4029 | if (!emitDestructuringRestExclusionSetObjLiteral(pattern)) { |
4030 | // [stack] OBJ |
4031 | return false; |
4032 | } |
4033 | } else { |
4034 | // Take the slow but sure way and start off with a blank object. |
4035 | if (!emit1(JSOp::NewInit)) { |
4036 | // [stack] OBJ |
4037 | return false; |
4038 | } |
4039 | } |
4040 | |
4041 | for (ParseNode* member : pattern->contents()) { |
4042 | if (member->isKind(ParseNodeKind::Spread)) { |
4043 | MOZ_ASSERT(!member->pn_next, "unexpected trailing element after spread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!member->pn_next)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!member->pn_next))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!member->pn_next" " (" "unexpected trailing element after spread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4043); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!member->pn_next" ") (" "unexpected trailing element after spread" ")"); do { * ((volatile int*)__null) = 4043; __attribute__((nomerge)) ::abort (); } while (false); } } while (false); |
4044 | break; |
4045 | } |
4046 | |
4047 | TaggedParserAtomIndex pnatom; |
4048 | if (member->isKind(ParseNodeKind::MutateProto)) { |
4049 | pnatom = TaggedParserAtomIndex::WellKnown::proto_(); |
4050 | } else { |
4051 | ParseNode* key = member->as<BinaryNode>().left(); |
4052 | if (key->isKind(ParseNodeKind::ObjectPropertyName) || |
4053 | key->isKind(ParseNodeKind::StringExpr)) { |
4054 | pnatom = key->as<NameNode>().atom(); |
4055 | } else if (key->isKind(ParseNodeKind::NumberExpr)) { |
4056 | if (!emitNumberOp(key->as<NumericLiteral>().value())) { |
4057 | return false; |
4058 | } |
4059 | } else { |
4060 | // Otherwise this is a computed property name which needs to be added |
4061 | // dynamically. BigInt keys are parsed as (synthetic) computed property |
4062 | // names, too. |
4063 | MOZ_ASSERT(key->isKind(ParseNodeKind::ComputedName))do { static_assert( mozilla::detail::AssertionConditionType< decltype(key->isKind(ParseNodeKind::ComputedName))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(key->isKind(ParseNodeKind::ComputedName)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("key->isKind(ParseNodeKind::ComputedName)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4063); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::ComputedName)" ")"); do { *((volatile int*)__null) = 4063; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4064 | continue; |
4065 | } |
4066 | } |
4067 | |
4068 | // Initialize elements with |undefined|. |
4069 | if (!emit1(JSOp::Undefined)) { |
4070 | return false; |
4071 | } |
4072 | |
4073 | if (!pnatom) { |
4074 | if (!emit1(JSOp::InitElem)) { |
4075 | return false; |
4076 | } |
4077 | } else { |
4078 | if (!emitAtomOp(JSOp::InitProp, pnatom)) { |
4079 | return false; |
4080 | } |
4081 | } |
4082 | } |
4083 | |
4084 | return true; |
4085 | } |
4086 | |
4087 | bool BytecodeEmitter::emitDestructuringOps(ListNode* pattern, |
4088 | DestructuringFlavor flav) { |
4089 | if (pattern->isKind(ParseNodeKind::ArrayExpr)) { |
4090 | return emitDestructuringOpsArray(pattern, flav); |
4091 | } |
4092 | return emitDestructuringOpsObject(pattern, flav); |
4093 | } |
4094 | |
4095 | bool BytecodeEmitter::emitTemplateString(ListNode* templateString) { |
4096 | bool pushedString = false; |
4097 | |
4098 | for (ParseNode* item : templateString->contents()) { |
4099 | bool isString = (item->getKind() == ParseNodeKind::StringExpr || |
4100 | item->getKind() == ParseNodeKind::TemplateStringExpr); |
4101 | |
4102 | // Skip empty strings. These are very common: a template string like |
4103 | // `${a}${b}` has three empty strings and without this optimization |
4104 | // we'd emit four JSOp::Add operations instead of just one. |
4105 | if (isString && item->as<NameNode>().atom() == |
4106 | TaggedParserAtomIndex::WellKnown::empty()) { |
4107 | continue; |
4108 | } |
4109 | |
4110 | if (!isString) { |
4111 | // We update source notes before emitting the expression |
4112 | if (!updateSourceCoordNotes(item->pn_pos.begin)) { |
4113 | return false; |
4114 | } |
4115 | } |
4116 | |
4117 | if (!emitTree(item)) { |
4118 | return false; |
4119 | } |
4120 | |
4121 | if (!isString) { |
4122 | // We need to convert the expression to a string |
4123 | if (!emit1(JSOp::ToString)) { |
4124 | return false; |
4125 | } |
4126 | } |
4127 | |
4128 | if (pushedString) { |
4129 | // We've pushed two strings onto the stack. Add them together, leaving |
4130 | // just one. |
4131 | if (!emit1(JSOp::Add)) { |
4132 | return false; |
4133 | } |
4134 | } else { |
4135 | pushedString = true; |
4136 | } |
4137 | } |
4138 | |
4139 | if (!pushedString) { |
4140 | // All strings were empty, this can happen for something like `${""}`. |
4141 | // Just push an empty string. |
4142 | if (!emitStringOp(JSOp::String, |
4143 | TaggedParserAtomIndex::WellKnown::empty())) { |
4144 | return false; |
4145 | } |
4146 | } |
4147 | |
4148 | return true; |
4149 | } |
4150 | |
4151 | bool BytecodeEmitter::emitDeclarationList(ListNode* declList) { |
4152 | for (ParseNode* decl : declList->contents()) { |
4153 | ParseNode* pattern; |
4154 | ParseNode* initializer; |
4155 | if (decl->isKind(ParseNodeKind::Name)) { |
4156 | pattern = decl; |
4157 | initializer = nullptr; |
4158 | } else { |
4159 | AssignmentNode* assignNode = &decl->as<AssignmentNode>(); |
4160 | pattern = assignNode->left(); |
4161 | initializer = assignNode->right(); |
4162 | } |
4163 | |
4164 | if (pattern->isKind(ParseNodeKind::Name)) { |
4165 | // initializer can be null here. |
4166 | if (!emitSingleDeclaration(declList, &pattern->as<NameNode>(), |
4167 | initializer)) { |
4168 | return false; |
4169 | } |
4170 | } else { |
4171 | MOZ_ASSERT(pattern->isKind(ParseNodeKind::ArrayExpr) ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(pattern->isKind(ParseNodeKind::ArrayExpr) || pattern ->isKind(ParseNodeKind::ObjectExpr))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pattern->isKind(ParseNodeKind ::ArrayExpr) || pattern->isKind(ParseNodeKind::ObjectExpr) ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "pattern->isKind(ParseNodeKind::ArrayExpr) || pattern->isKind(ParseNodeKind::ObjectExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4172); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pattern->isKind(ParseNodeKind::ArrayExpr) || pattern->isKind(ParseNodeKind::ObjectExpr)" ")"); do { *((volatile int*)__null) = 4172; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
4172 | pattern->isKind(ParseNodeKind::ObjectExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(pattern->isKind(ParseNodeKind::ArrayExpr) || pattern ->isKind(ParseNodeKind::ObjectExpr))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pattern->isKind(ParseNodeKind ::ArrayExpr) || pattern->isKind(ParseNodeKind::ObjectExpr) ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "pattern->isKind(ParseNodeKind::ArrayExpr) || pattern->isKind(ParseNodeKind::ObjectExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4172); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pattern->isKind(ParseNodeKind::ArrayExpr) || pattern->isKind(ParseNodeKind::ObjectExpr)" ")"); do { *((volatile int*)__null) = 4172; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4173 | MOZ_ASSERT(initializer != nullptr)do { static_assert( mozilla::detail::AssertionConditionType< decltype(initializer != nullptr)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(initializer != nullptr))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("initializer != nullptr" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4173); AnnotateMozCrashReason("MOZ_ASSERT" "(" "initializer != nullptr" ")"); do { *((volatile int*)__null) = 4173; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4174 | |
4175 | if (!updateSourceCoordNotes(initializer->pn_pos.begin)) { |
4176 | return false; |
4177 | } |
4178 | if (!markStepBreakpoint()) { |
4179 | return false; |
4180 | } |
4181 | if (!emitTree(initializer)) { |
4182 | return false; |
4183 | } |
4184 | |
4185 | if (!emitDestructuringOps(&pattern->as<ListNode>(), |
4186 | DestructuringFlavor::Declaration)) { |
4187 | return false; |
4188 | } |
4189 | |
4190 | if (!emit1(JSOp::Pop)) { |
4191 | return false; |
4192 | } |
4193 | } |
4194 | } |
4195 | return true; |
4196 | } |
4197 | |
4198 | bool BytecodeEmitter::emitSingleDeclaration(ListNode* declList, NameNode* decl, |
4199 | ParseNode* initializer) { |
4200 | MOZ_ASSERT(decl->isKind(ParseNodeKind::Name))do { static_assert( mozilla::detail::AssertionConditionType< decltype(decl->isKind(ParseNodeKind::Name))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(decl->isKind(ParseNodeKind ::Name)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("decl->isKind(ParseNodeKind::Name)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4200); AnnotateMozCrashReason("MOZ_ASSERT" "(" "decl->isKind(ParseNodeKind::Name)" ")"); do { *((volatile int*)__null) = 4200; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4201 | |
4202 | // Nothing to do for initializer-less 'var' declarations, as there's no TDZ. |
4203 | if (!initializer && declList->isKind(ParseNodeKind::VarStmt)) { |
4204 | return true; |
4205 | } |
4206 | |
4207 | auto nameAtom = decl->name(); |
4208 | NameOpEmitter noe(this, nameAtom, NameOpEmitter::Kind::Initialize); |
4209 | if (!noe.prepareForRhs()) { |
4210 | // [stack] ENV? |
4211 | return false; |
4212 | } |
4213 | if (!initializer) { |
4214 | // Lexical declarations are initialized to undefined without an |
4215 | // initializer. |
4216 | MOZ_ASSERT(declList->isKind(ParseNodeKind::LetDecl),do { static_assert( mozilla::detail::AssertionConditionType< decltype(declList->isKind(ParseNodeKind::LetDecl))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(declList->isKind(ParseNodeKind::LetDecl)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("declList->isKind(ParseNodeKind::LetDecl)" " (" "var declarations without initializers handled above, " "and const declarations must have initializers" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4218); AnnotateMozCrashReason("MOZ_ASSERT" "(" "declList->isKind(ParseNodeKind::LetDecl)" ") (" "var declarations without initializers handled above, " "and const declarations must have initializers" ")"); do { * ((volatile int*)__null) = 4218; __attribute__((nomerge)) ::abort (); } while (false); } } while (false) |
4217 | "var declarations without initializers handled above, "do { static_assert( mozilla::detail::AssertionConditionType< decltype(declList->isKind(ParseNodeKind::LetDecl))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(declList->isKind(ParseNodeKind::LetDecl)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("declList->isKind(ParseNodeKind::LetDecl)" " (" "var declarations without initializers handled above, " "and const declarations must have initializers" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4218); AnnotateMozCrashReason("MOZ_ASSERT" "(" "declList->isKind(ParseNodeKind::LetDecl)" ") (" "var declarations without initializers handled above, " "and const declarations must have initializers" ")"); do { * ((volatile int*)__null) = 4218; __attribute__((nomerge)) ::abort (); } while (false); } } while (false) |
4218 | "and const declarations must have initializers")do { static_assert( mozilla::detail::AssertionConditionType< decltype(declList->isKind(ParseNodeKind::LetDecl))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(declList->isKind(ParseNodeKind::LetDecl)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("declList->isKind(ParseNodeKind::LetDecl)" " (" "var declarations without initializers handled above, " "and const declarations must have initializers" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4218); AnnotateMozCrashReason("MOZ_ASSERT" "(" "declList->isKind(ParseNodeKind::LetDecl)" ") (" "var declarations without initializers handled above, " "and const declarations must have initializers" ")"); do { * ((volatile int*)__null) = 4218; __attribute__((nomerge)) ::abort (); } while (false); } } while (false); |
4219 | if (!emit1(JSOp::Undefined)) { |
4220 | // [stack] ENV? UNDEF |
4221 | return false; |
4222 | } |
4223 | } else { |
4224 | MOZ_ASSERT(initializer)do { static_assert( mozilla::detail::AssertionConditionType< decltype(initializer)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(initializer))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("initializer", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4224); AnnotateMozCrashReason("MOZ_ASSERT" "(" "initializer" ")"); do { *((volatile int*)__null) = 4224; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4225 | |
4226 | if (!updateSourceCoordNotes(initializer->pn_pos.begin)) { |
4227 | return false; |
4228 | } |
4229 | if (!markStepBreakpoint()) { |
4230 | return false; |
4231 | } |
4232 | if (!emitInitializer(initializer, decl)) { |
4233 | // [stack] ENV? V |
4234 | return false; |
4235 | } |
4236 | } |
4237 | |
4238 | #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT |
4239 | if (declList->isKind(ParseNodeKind::UsingDecl)) { |
4240 | if (!innermostEmitterScope()->prepareForDisposableAssignment( |
4241 | UsingHint::Sync)) { |
4242 | // [stack] ENV? V |
4243 | return false; |
4244 | } |
4245 | } else if (declList->isKind(ParseNodeKind::AwaitUsingDecl)) { |
4246 | if (!innermostEmitterScope()->prepareForDisposableAssignment( |
4247 | UsingHint::Async)) { |
4248 | // [stack] ENV? V |
4249 | return false; |
4250 | } |
4251 | } |
4252 | #endif |
4253 | |
4254 | if (!noe.emitAssignment()) { |
4255 | // [stack] V |
4256 | return false; |
4257 | } |
4258 | |
4259 | if (!emit1(JSOp::Pop)) { |
4260 | // [stack] |
4261 | return false; |
4262 | } |
4263 | |
4264 | return true; |
4265 | } |
4266 | |
4267 | bool BytecodeEmitter::emitAssignmentRhs( |
4268 | ParseNode* rhs, TaggedParserAtomIndex anonFunctionName) { |
4269 | if (rhs->isDirectRHSAnonFunction()) { |
4270 | if (anonFunctionName) { |
4271 | return emitAnonymousFunctionWithName(rhs, anonFunctionName); |
4272 | } |
4273 | return emitAnonymousFunctionWithComputedName(rhs, FunctionPrefixKind::None); |
4274 | } |
4275 | return emitTree(rhs); |
4276 | } |
4277 | |
4278 | // The RHS value to assign is already on the stack, i.e., the next enumeration |
4279 | // value in a for-in or for-of loop. Offset is the location in the stack of the |
4280 | // already-emitted rhs. If we emitted a JSOp::BindUnqualifiedName or |
4281 | // JSOp::BindUnqualifiedGName, then the scope is on the top of the stack and we |
4282 | // need to dig one deeper to get the right RHS value. |
4283 | bool BytecodeEmitter::emitAssignmentRhs(uint8_t offset) { |
4284 | if (offset != 1) { |
4285 | return emitPickN(offset - 1); |
4286 | } |
4287 | |
4288 | return true; |
4289 | } |
4290 | |
4291 | static inline JSOp CompoundAssignmentParseNodeKindToJSOp(ParseNodeKind pnk) { |
4292 | switch (pnk) { |
4293 | case ParseNodeKind::InitExpr: |
4294 | return JSOp::Nop; |
4295 | case ParseNodeKind::AssignExpr: |
4296 | return JSOp::Nop; |
4297 | case ParseNodeKind::AddAssignExpr: |
4298 | return JSOp::Add; |
4299 | case ParseNodeKind::SubAssignExpr: |
4300 | return JSOp::Sub; |
4301 | case ParseNodeKind::BitOrAssignExpr: |
4302 | return JSOp::BitOr; |
4303 | case ParseNodeKind::BitXorAssignExpr: |
4304 | return JSOp::BitXor; |
4305 | case ParseNodeKind::BitAndAssignExpr: |
4306 | return JSOp::BitAnd; |
4307 | case ParseNodeKind::LshAssignExpr: |
4308 | return JSOp::Lsh; |
4309 | case ParseNodeKind::RshAssignExpr: |
4310 | return JSOp::Rsh; |
4311 | case ParseNodeKind::UrshAssignExpr: |
4312 | return JSOp::Ursh; |
4313 | case ParseNodeKind::MulAssignExpr: |
4314 | return JSOp::Mul; |
4315 | case ParseNodeKind::DivAssignExpr: |
4316 | return JSOp::Div; |
4317 | case ParseNodeKind::ModAssignExpr: |
4318 | return JSOp::Mod; |
4319 | case ParseNodeKind::PowAssignExpr: |
4320 | return JSOp::Pow; |
4321 | case ParseNodeKind::CoalesceAssignExpr: |
4322 | case ParseNodeKind::OrAssignExpr: |
4323 | case ParseNodeKind::AndAssignExpr: |
4324 | // Short-circuit assignment operators are handled elsewhere. |
4325 | [[fallthrough]]; |
4326 | default: |
4327 | MOZ_CRASH("unexpected compound assignment op")do { do { } while (false); MOZ_ReportCrash("" "unexpected compound assignment op" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4327); AnnotateMozCrashReason("MOZ_CRASH(" "unexpected compound assignment op" ")"); do { *((volatile int*)__null) = 4327; __attribute__((nomerge )) ::abort(); } while (false); } while (false); |
4328 | } |
4329 | } |
4330 | |
4331 | bool BytecodeEmitter::emitAssignmentOrInit(ParseNodeKind kind, ParseNode* lhs, |
4332 | ParseNode* rhs) { |
4333 | JSOp compoundOp = CompoundAssignmentParseNodeKindToJSOp(kind); |
4334 | bool isCompound = compoundOp != JSOp::Nop; |
4335 | bool isInit = kind == ParseNodeKind::InitExpr; |
4336 | |
4337 | // We estimate the number of properties this could create |
4338 | // if used as constructor merely by counting this.foo = assignment |
4339 | // or init expressions; |
4340 | // |
4341 | // This currently doesn't handle this[x] = foo; |
4342 | if (isInit || kind == ParseNodeKind::AssignExpr) { |
4343 | if (lhs->isKind(ParseNodeKind::DotExpr)) { |
4344 | if (lhs->as<PropertyAccess>().expression().isKind( |
4345 | ParseNodeKind::ThisExpr)) { |
4346 | propertyAdditionEstimate++; |
4347 | } |
4348 | } |
4349 | } |
4350 | |
4351 | MOZ_ASSERT_IF(isInit, lhs->isKind(ParseNodeKind::DotExpr) ||do { if (isInit) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(lhs->isKind(ParseNodeKind::DotExpr) || lhs-> isKind(ParseNodeKind::ElemExpr) || lhs->isKind(ParseNodeKind ::PrivateMemberExpr))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(lhs->isKind(ParseNodeKind ::DotExpr) || lhs->isKind(ParseNodeKind::ElemExpr) || lhs-> isKind(ParseNodeKind::PrivateMemberExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("lhs->isKind(ParseNodeKind::DotExpr) || lhs->isKind(ParseNodeKind::ElemExpr) || lhs->isKind(ParseNodeKind::PrivateMemberExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4353); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lhs->isKind(ParseNodeKind::DotExpr) || lhs->isKind(ParseNodeKind::ElemExpr) || lhs->isKind(ParseNodeKind::PrivateMemberExpr)" ")"); do { *((volatile int*)__null) = 4353; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
4352 | lhs->isKind(ParseNodeKind::ElemExpr) ||do { if (isInit) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(lhs->isKind(ParseNodeKind::DotExpr) || lhs-> isKind(ParseNodeKind::ElemExpr) || lhs->isKind(ParseNodeKind ::PrivateMemberExpr))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(lhs->isKind(ParseNodeKind ::DotExpr) || lhs->isKind(ParseNodeKind::ElemExpr) || lhs-> isKind(ParseNodeKind::PrivateMemberExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("lhs->isKind(ParseNodeKind::DotExpr) || lhs->isKind(ParseNodeKind::ElemExpr) || lhs->isKind(ParseNodeKind::PrivateMemberExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4353); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lhs->isKind(ParseNodeKind::DotExpr) || lhs->isKind(ParseNodeKind::ElemExpr) || lhs->isKind(ParseNodeKind::PrivateMemberExpr)" ")"); do { *((volatile int*)__null) = 4353; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
4353 | lhs->isKind(ParseNodeKind::PrivateMemberExpr))do { if (isInit) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(lhs->isKind(ParseNodeKind::DotExpr) || lhs-> isKind(ParseNodeKind::ElemExpr) || lhs->isKind(ParseNodeKind ::PrivateMemberExpr))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(lhs->isKind(ParseNodeKind ::DotExpr) || lhs->isKind(ParseNodeKind::ElemExpr) || lhs-> isKind(ParseNodeKind::PrivateMemberExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("lhs->isKind(ParseNodeKind::DotExpr) || lhs->isKind(ParseNodeKind::ElemExpr) || lhs->isKind(ParseNodeKind::PrivateMemberExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4353); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lhs->isKind(ParseNodeKind::DotExpr) || lhs->isKind(ParseNodeKind::ElemExpr) || lhs->isKind(ParseNodeKind::PrivateMemberExpr)" ")"); do { *((volatile int*)__null) = 4353; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
4354 | |
4355 | // |name| is used within NameOpEmitter, so its lifetime must surpass |noe|. |
4356 | TaggedParserAtomIndex name; |
4357 | |
4358 | Maybe<NameOpEmitter> noe; |
4359 | Maybe<PropOpEmitter> poe; |
4360 | Maybe<ElemOpEmitter> eoe; |
4361 | Maybe<PrivateOpEmitter> xoe; |
4362 | |
4363 | // Deal with non-name assignments. |
4364 | uint8_t offset = 1; |
4365 | |
4366 | // Purpose of anonFunctionName: |
4367 | // |
4368 | // In normal name assignments (`f = function(){}`), an anonymous function gets |
4369 | // an inferred name based on the left-hand side name node. |
4370 | // |
4371 | // In normal property assignments (`obj.x = function(){}`), the anonymous |
4372 | // function does not have a computed name, and rhs->isDirectRHSAnonFunction() |
4373 | // will be false (and anonFunctionName will not be used). However, in field |
4374 | // initializers (`class C { x = function(){} }`), field initialization is |
4375 | // implemented via a property or elem assignment (where we are now), and |
4376 | // rhs->isDirectRHSAnonFunction() is set - so we'll assign the name of the |
4377 | // function. |
4378 | TaggedParserAtomIndex anonFunctionName; |
4379 | |
4380 | switch (lhs->getKind()) { |
4381 | case ParseNodeKind::Name: { |
4382 | name = lhs->as<NameNode>().name(); |
4383 | anonFunctionName = name; |
4384 | noe.emplace(this, name, |
4385 | isCompound ? NameOpEmitter::Kind::CompoundAssignment |
4386 | : NameOpEmitter::Kind::SimpleAssignment); |
4387 | break; |
4388 | } |
4389 | case ParseNodeKind::ArgumentsLength: |
4390 | case ParseNodeKind::DotExpr: { |
4391 | PropertyAccess* prop = &lhs->as<PropertyAccess>(); |
4392 | bool isSuper = prop->isSuper(); |
4393 | poe.emplace(this, |
4394 | isCompound ? PropOpEmitter::Kind::CompoundAssignment |
4395 | : isInit ? PropOpEmitter::Kind::PropInit |
4396 | : PropOpEmitter::Kind::SimpleAssignment, |
4397 | isSuper ? PropOpEmitter::ObjKind::Super |
4398 | : PropOpEmitter::ObjKind::Other); |
4399 | if (!poe->prepareForObj()) { |
4400 | return false; |
4401 | } |
4402 | anonFunctionName = prop->name(); |
4403 | if (isSuper) { |
4404 | UnaryNode* base = &prop->expression().as<UnaryNode>(); |
4405 | if (!emitGetThisForSuperBase(base)) { |
4406 | // [stack] THIS SUPERBASE |
4407 | return false; |
4408 | } |
4409 | // SUPERBASE is pushed onto THIS later in poe->emitGet below. |
4410 | offset += 2; |
4411 | } else { |
4412 | if (!emitTree(&prop->expression())) { |
4413 | // [stack] OBJ |
4414 | return false; |
4415 | } |
4416 | offset += 1; |
4417 | } |
4418 | break; |
4419 | } |
4420 | case ParseNodeKind::ElemExpr: { |
4421 | PropertyByValue* elem = &lhs->as<PropertyByValue>(); |
4422 | bool isSuper = elem->isSuper(); |
4423 | MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!elem->key().isKind(ParseNodeKind::PrivateName))> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!elem->key().isKind(ParseNodeKind::PrivateName))) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!elem->key().isKind(ParseNodeKind::PrivateName)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4423); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)" ")"); do { *((volatile int*)__null) = 4423; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4424 | eoe.emplace(this, |
4425 | isCompound ? ElemOpEmitter::Kind::CompoundAssignment |
4426 | : isInit ? ElemOpEmitter::Kind::PropInit |
4427 | : ElemOpEmitter::Kind::SimpleAssignment, |
4428 | isSuper ? ElemOpEmitter::ObjKind::Super |
4429 | : ElemOpEmitter::ObjKind::Other); |
4430 | if (!emitElemObjAndKey(elem, *eoe)) { |
4431 | // [stack] # if Super |
4432 | // [stack] THIS KEY |
4433 | // [stack] # otherwise |
4434 | // [stack] OBJ KEY |
4435 | return false; |
4436 | } |
4437 | if (isSuper) { |
4438 | // SUPERBASE is pushed onto KEY in eoe->emitGet below. |
4439 | offset += 3; |
4440 | } else { |
4441 | offset += 2; |
4442 | } |
4443 | break; |
4444 | } |
4445 | case ParseNodeKind::PrivateMemberExpr: { |
4446 | PrivateMemberAccess* privateExpr = &lhs->as<PrivateMemberAccess>(); |
4447 | xoe.emplace(this, |
4448 | isCompound ? PrivateOpEmitter::Kind::CompoundAssignment |
4449 | : isInit ? PrivateOpEmitter::Kind::PropInit |
4450 | : PrivateOpEmitter::Kind::SimpleAssignment, |
4451 | privateExpr->privateName().name()); |
4452 | if (!emitTree(&privateExpr->expression())) { |
4453 | // [stack] OBJ |
4454 | return false; |
4455 | } |
4456 | if (!xoe->emitReference()) { |
4457 | // [stack] OBJ KEY |
4458 | return false; |
4459 | } |
4460 | offset += xoe->numReferenceSlots(); |
4461 | break; |
4462 | } |
4463 | case ParseNodeKind::ArrayExpr: |
4464 | case ParseNodeKind::ObjectExpr: |
4465 | break; |
4466 | case ParseNodeKind::CallExpr: |
4467 | if (!emitTree(lhs)) { |
4468 | return false; |
4469 | } |
4470 | |
4471 | // Assignment to function calls is forbidden, but we have to make the |
4472 | // call first. Now we can throw. |
4473 | if (!emit2(JSOp::ThrowMsg, uint8_t(ThrowMsgKind::AssignToCall))) { |
4474 | return false; |
4475 | } |
4476 | |
4477 | // Rebalance the stack to placate stack-depth assertions. |
4478 | if (!emit1(JSOp::Pop)) { |
4479 | return false; |
4480 | } |
4481 | break; |
4482 | default: |
4483 | MOZ_ASSERT(0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(0)>::isValid, "invalid assertion condition"); if ( (__builtin_expect(!!(!(!!(0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("0", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4483); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0" ")"); do { *((volatile int*)__null) = 4483; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); |
4484 | } |
4485 | |
4486 | if (isCompound) { |
4487 | MOZ_ASSERT(rhs)do { static_assert( mozilla::detail::AssertionConditionType< decltype(rhs)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(rhs))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("rhs", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4487); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rhs" ")"); do { *((volatile int*)__null) = 4487; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); |
4488 | switch (lhs->getKind()) { |
4489 | case ParseNodeKind::ArgumentsLength: |
4490 | case ParseNodeKind::DotExpr: { |
4491 | PropertyAccess* prop = &lhs->as<PropertyAccess>(); |
4492 | if (!poe->emitGet(prop->key().atom())) { |
4493 | // [stack] # if Super |
4494 | // [stack] THIS SUPERBASE PROP |
4495 | // [stack] # otherwise |
4496 | // [stack] OBJ PROP |
4497 | return false; |
4498 | } |
4499 | break; |
4500 | } |
4501 | case ParseNodeKind::ElemExpr: { |
4502 | if (!eoe->emitGet()) { |
4503 | // [stack] KEY THIS OBJ ELEM |
4504 | return false; |
4505 | } |
4506 | break; |
4507 | } |
4508 | case ParseNodeKind::PrivateMemberExpr: { |
4509 | if (!xoe->emitGet()) { |
4510 | // [stack] OBJ KEY VALUE |
4511 | return false; |
4512 | } |
4513 | break; |
4514 | } |
4515 | case ParseNodeKind::CallExpr: |
4516 | // We just emitted a JSOp::ThrowMsg and popped the call's return |
4517 | // value. Push a random value to make sure the stack depth is |
4518 | // correct. |
4519 | if (!emit1(JSOp::Null)) { |
4520 | // [stack] NULL |
4521 | return false; |
4522 | } |
4523 | break; |
4524 | default:; |
4525 | } |
4526 | } |
4527 | |
4528 | switch (lhs->getKind()) { |
4529 | case ParseNodeKind::Name: |
4530 | if (!noe->prepareForRhs()) { |
4531 | // [stack] ENV? VAL? |
4532 | return false; |
4533 | } |
4534 | offset += noe->emittedBindOp(); |
4535 | break; |
4536 | case ParseNodeKind::ArgumentsLength: |
4537 | case ParseNodeKind::DotExpr: |
4538 | if (!poe->prepareForRhs()) { |
4539 | // [stack] # if Simple Assignment with Super |
4540 | // [stack] THIS SUPERBASE |
4541 | // [stack] # if Simple Assignment with other |
4542 | // [stack] OBJ |
4543 | // [stack] # if Compound Assignment with Super |
4544 | // [stack] THIS SUPERBASE PROP |
4545 | // [stack] # if Compound Assignment with other |
4546 | // [stack] OBJ PROP |
4547 | return false; |
4548 | } |
4549 | break; |
4550 | case ParseNodeKind::ElemExpr: |
4551 | if (!eoe->prepareForRhs()) { |
4552 | // [stack] # if Simple Assignment with Super |
4553 | // [stack] THIS KEY SUPERBASE |
4554 | // [stack] # if Simple Assignment with other |
4555 | // [stack] OBJ KEY |
4556 | // [stack] # if Compound Assignment with Super |
4557 | // [stack] THIS KEY SUPERBASE ELEM |
4558 | // [stack] # if Compound Assignment with other |
4559 | // [stack] OBJ KEY ELEM |
4560 | return false; |
4561 | } |
4562 | break; |
4563 | case ParseNodeKind::PrivateMemberExpr: |
4564 | // no stack adjustment needed |
4565 | break; |
4566 | default: |
4567 | break; |
4568 | } |
4569 | |
4570 | if (rhs) { |
4571 | if (!emitAssignmentRhs(rhs, anonFunctionName)) { |
4572 | // [stack] ... VAL? RHS |
4573 | return false; |
4574 | } |
4575 | } else { |
4576 | // Assumption: Things with pre-emitted RHS values never need to be named. |
4577 | if (!emitAssignmentRhs(offset)) { |
4578 | // [stack] ... VAL? RHS |
4579 | return false; |
4580 | } |
4581 | } |
4582 | |
4583 | /* If += etc., emit the binary operator with a hint for the decompiler. */ |
4584 | if (isCompound) { |
4585 | if (!emit1(compoundOp)) { |
4586 | // [stack] ... VAL |
4587 | return false; |
4588 | } |
4589 | if (!emit1(JSOp::NopIsAssignOp)) { |
4590 | // [stack] ... VAL |
4591 | return false; |
4592 | } |
4593 | } |
4594 | |
4595 | /* Finally, emit the specialized assignment bytecode. */ |
4596 | switch (lhs->getKind()) { |
4597 | case ParseNodeKind::Name: { |
4598 | if (!noe->emitAssignment()) { |
4599 | // [stack] VAL |
4600 | return false; |
4601 | } |
4602 | break; |
4603 | } |
4604 | case ParseNodeKind::ArgumentsLength: |
4605 | case ParseNodeKind::DotExpr: { |
4606 | PropertyAccess* prop = &lhs->as<PropertyAccess>(); |
4607 | if (!poe->emitAssignment(prop->key().atom())) { |
4608 | // [stack] VAL |
4609 | return false; |
4610 | } |
4611 | break; |
4612 | } |
4613 | case ParseNodeKind::CallExpr: |
4614 | // We threw above, so nothing to do here. |
4615 | break; |
4616 | case ParseNodeKind::ElemExpr: { |
4617 | if (!eoe->emitAssignment()) { |
4618 | // [stack] VAL |
4619 | return false; |
4620 | } |
4621 | break; |
4622 | } |
4623 | case ParseNodeKind::PrivateMemberExpr: |
4624 | if (!xoe->emitAssignment()) { |
4625 | // [stack] VAL |
4626 | return false; |
4627 | } |
4628 | break; |
4629 | case ParseNodeKind::ArrayExpr: |
4630 | case ParseNodeKind::ObjectExpr: |
4631 | if (!emitDestructuringOps(&lhs->as<ListNode>(), |
4632 | DestructuringFlavor::Assignment)) { |
4633 | return false; |
4634 | } |
4635 | break; |
4636 | default: |
4637 | MOZ_ASSERT(0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(0)>::isValid, "invalid assertion condition"); if ( (__builtin_expect(!!(!(!!(0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("0", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4637); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0" ")"); do { *((volatile int*)__null) = 4637; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); |
4638 | } |
4639 | return true; |
4640 | } |
4641 | |
4642 | bool BytecodeEmitter::emitShortCircuitAssignment(AssignmentNode* node) { |
4643 | TDZCheckCache tdzCache(this); |
4644 | |
4645 | JSOp op; |
4646 | switch (node->getKind()) { |
4647 | case ParseNodeKind::CoalesceAssignExpr: |
4648 | op = JSOp::Coalesce; |
4649 | break; |
4650 | case ParseNodeKind::OrAssignExpr: |
4651 | op = JSOp::Or; |
4652 | break; |
4653 | case ParseNodeKind::AndAssignExpr: |
4654 | op = JSOp::And; |
4655 | break; |
4656 | default: |
4657 | MOZ_CRASH("Unexpected ParseNodeKind")do { do { } while (false); MOZ_ReportCrash("" "Unexpected ParseNodeKind" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4657); AnnotateMozCrashReason("MOZ_CRASH(" "Unexpected ParseNodeKind" ")"); do { *((volatile int*)__null) = 4657; __attribute__((nomerge )) ::abort(); } while (false); } while (false); |
4658 | } |
4659 | |
4660 | ParseNode* lhs = node->left(); |
4661 | ParseNode* rhs = node->right(); |
4662 | |
4663 | // |name| is used within NameOpEmitter, so its lifetime must surpass |noe|. |
4664 | TaggedParserAtomIndex name; |
4665 | |
4666 | // Select the appropriate emitter based on the left-hand side. |
4667 | Maybe<NameOpEmitter> noe; |
4668 | Maybe<PropOpEmitter> poe; |
4669 | Maybe<ElemOpEmitter> eoe; |
4670 | Maybe<PrivateOpEmitter> xoe; |
4671 | |
4672 | int32_t depth = bytecodeSection().stackDepth(); |
4673 | |
4674 | // Number of values pushed onto the stack in addition to the lhs value. |
4675 | int32_t numPushed; |
4676 | |
4677 | // Evaluate the left-hand side expression and compute any stack values needed |
4678 | // for the assignment. |
4679 | switch (lhs->getKind()) { |
4680 | case ParseNodeKind::Name: { |
4681 | name = lhs->as<NameNode>().name(); |
4682 | noe.emplace(this, name, NameOpEmitter::Kind::CompoundAssignment); |
4683 | |
4684 | if (!noe->prepareForRhs()) { |
4685 | // [stack] ENV? LHS |
4686 | return false; |
4687 | } |
4688 | |
4689 | numPushed = noe->emittedBindOp(); |
4690 | break; |
4691 | } |
4692 | case ParseNodeKind::ArgumentsLength: |
4693 | case ParseNodeKind::DotExpr: { |
4694 | PropertyAccess* prop = &lhs->as<PropertyAccess>(); |
4695 | bool isSuper = prop->isSuper(); |
4696 | |
4697 | poe.emplace(this, PropOpEmitter::Kind::CompoundAssignment, |
4698 | isSuper ? PropOpEmitter::ObjKind::Super |
4699 | : PropOpEmitter::ObjKind::Other); |
4700 | |
4701 | if (!poe->prepareForObj()) { |
4702 | return false; |
4703 | } |
4704 | |
4705 | if (isSuper) { |
4706 | UnaryNode* base = &prop->expression().as<UnaryNode>(); |
4707 | if (!emitGetThisForSuperBase(base)) { |
4708 | // [stack] THIS SUPERBASE |
4709 | return false; |
4710 | } |
4711 | } else { |
4712 | if (!emitTree(&prop->expression())) { |
4713 | // [stack] OBJ |
4714 | return false; |
4715 | } |
4716 | } |
4717 | |
4718 | if (!poe->emitGet(prop->key().atom())) { |
4719 | // [stack] # if Super |
4720 | // [stack] THIS SUPERBASE LHS |
4721 | // [stack] # otherwise |
4722 | // [stack] OBJ LHS |
4723 | return false; |
4724 | } |
4725 | |
4726 | if (!poe->prepareForRhs()) { |
4727 | // [stack] # if Super |
4728 | // [stack] THIS SUPERBASE LHS |
4729 | // [stack] # otherwise |
4730 | // [stack] OBJ LHS |
4731 | return false; |
4732 | } |
4733 | |
4734 | numPushed = 1 + isSuper; |
4735 | break; |
4736 | } |
4737 | |
4738 | case ParseNodeKind::ElemExpr: { |
4739 | PropertyByValue* elem = &lhs->as<PropertyByValue>(); |
4740 | bool isSuper = elem->isSuper(); |
4741 | MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!elem->key().isKind(ParseNodeKind::PrivateName))> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!elem->key().isKind(ParseNodeKind::PrivateName))) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!elem->key().isKind(ParseNodeKind::PrivateName)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4741); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)" ")"); do { *((volatile int*)__null) = 4741; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4742 | eoe.emplace(this, ElemOpEmitter::Kind::CompoundAssignment, |
4743 | isSuper ? ElemOpEmitter::ObjKind::Super |
4744 | : ElemOpEmitter::ObjKind::Other); |
4745 | |
4746 | if (!emitElemObjAndKey(elem, *eoe)) { |
4747 | // [stack] # if Super |
4748 | // [stack] THIS KEY |
4749 | // [stack] # otherwise |
4750 | // [stack] OBJ KEY |
4751 | return false; |
4752 | } |
4753 | |
4754 | if (!eoe->emitGet()) { |
4755 | // [stack] # if Super |
4756 | // [stack] THIS KEY SUPERBASE LHS |
4757 | // [stack] # otherwise |
4758 | // [stack] OBJ KEY LHS |
4759 | return false; |
4760 | } |
4761 | |
4762 | if (!eoe->prepareForRhs()) { |
4763 | // [stack] # if Super |
4764 | // [stack] THIS KEY SUPERBASE LHS |
4765 | // [stack] # otherwise |
4766 | // [stack] OBJ KEY LHS |
4767 | return false; |
4768 | } |
4769 | |
4770 | numPushed = 2 + isSuper; |
4771 | break; |
4772 | } |
4773 | |
4774 | case ParseNodeKind::PrivateMemberExpr: { |
4775 | PrivateMemberAccess* privateExpr = &lhs->as<PrivateMemberAccess>(); |
4776 | xoe.emplace(this, PrivateOpEmitter::Kind::CompoundAssignment, |
4777 | privateExpr->privateName().name()); |
4778 | if (!emitTree(&privateExpr->expression())) { |
4779 | // [stack] OBJ |
4780 | return false; |
4781 | } |
4782 | if (!xoe->emitReference()) { |
4783 | // [stack] OBJ NAME |
4784 | return false; |
4785 | } |
4786 | if (!xoe->emitGet()) { |
4787 | // [stack] OBJ NAME LHS |
4788 | return false; |
4789 | } |
4790 | numPushed = xoe->numReferenceSlots(); |
4791 | break; |
4792 | } |
4793 | |
4794 | default: |
4795 | MOZ_CRASH()do { do { } while (false); MOZ_ReportCrash("" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4795); AnnotateMozCrashReason("MOZ_CRASH(" ")"); do { *((volatile int*)__null) = 4795; __attribute__((nomerge)) ::abort(); } while (false); } while (false); |
4796 | } |
4797 | |
4798 | MOZ_ASSERT(bytecodeSection().stackDepth() == depth + numPushed + 1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(bytecodeSection().stackDepth() == depth + numPushed + 1)>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(bytecodeSection().stackDepth() == depth + numPushed + 1))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("bytecodeSection().stackDepth() == depth + numPushed + 1", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4798); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == depth + numPushed + 1" ")"); do { *((volatile int*)__null) = 4798; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4799 | |
4800 | // Test for the short-circuit condition. |
4801 | JumpList jump; |
4802 | if (!emitJump(op, &jump)) { |
4803 | // [stack] ... LHS |
4804 | return false; |
4805 | } |
4806 | |
4807 | // The short-circuit condition wasn't fulfilled, pop the left-hand side value |
4808 | // which was kept on the stack. |
4809 | if (!emit1(JSOp::Pop)) { |
4810 | // [stack] ... |
4811 | return false; |
4812 | } |
4813 | |
4814 | if (!emitAssignmentRhs(rhs, name)) { |
4815 | // [stack] ... RHS |
4816 | return false; |
4817 | } |
4818 | |
4819 | // Perform the actual assignment. |
4820 | switch (lhs->getKind()) { |
4821 | case ParseNodeKind::Name: { |
4822 | if (!noe->emitAssignment()) { |
4823 | // [stack] RHS |
4824 | return false; |
4825 | } |
4826 | break; |
4827 | } |
4828 | case ParseNodeKind::ArgumentsLength: |
4829 | case ParseNodeKind::DotExpr: { |
4830 | PropertyAccess* prop = &lhs->as<PropertyAccess>(); |
4831 | |
4832 | if (!poe->emitAssignment(prop->key().atom())) { |
4833 | // [stack] RHS |
4834 | return false; |
4835 | } |
4836 | break; |
4837 | } |
4838 | |
4839 | case ParseNodeKind::ElemExpr: { |
4840 | if (!eoe->emitAssignment()) { |
4841 | // [stack] RHS |
4842 | return false; |
4843 | } |
4844 | break; |
4845 | } |
4846 | |
4847 | case ParseNodeKind::PrivateMemberExpr: |
4848 | if (!xoe->emitAssignment()) { |
4849 | // [stack] RHS |
4850 | return false; |
4851 | } |
4852 | break; |
4853 | |
4854 | default: |
4855 | MOZ_CRASH()do { do { } while (false); MOZ_ReportCrash("" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4855); AnnotateMozCrashReason("MOZ_CRASH(" ")"); do { *((volatile int*)__null) = 4855; __attribute__((nomerge)) ::abort(); } while (false); } while (false); |
4856 | } |
4857 | |
4858 | MOZ_ASSERT(bytecodeSection().stackDepth() == depth + 1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(bytecodeSection().stackDepth() == depth + 1)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(bytecodeSection().stackDepth() == depth + 1))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("bytecodeSection().stackDepth() == depth + 1" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4858); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == depth + 1" ")"); do { *((volatile int*)__null) = 4858; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4859 | |
4860 | // Join with the short-circuit jump and pop anything left on the stack. |
4861 | if (numPushed > 0) { |
4862 | JumpList jumpAroundPop; |
4863 | if (!emitJump(JSOp::Goto, &jumpAroundPop)) { |
4864 | // [stack] RHS |
4865 | return false; |
4866 | } |
4867 | |
4868 | if (!emitJumpTargetAndPatch(jump)) { |
4869 | // [stack] ... LHS |
4870 | return false; |
4871 | } |
4872 | |
4873 | // Reconstruct the stack depth after the jump. |
4874 | bytecodeSection().setStackDepth(depth + 1 + numPushed); |
4875 | |
4876 | // Move the left-hand side value to the bottom and pop the rest. |
4877 | if (!emitUnpickN(numPushed)) { |
4878 | // [stack] LHS ... |
4879 | return false; |
4880 | } |
4881 | if (!emitPopN(numPushed)) { |
4882 | // [stack] LHS |
4883 | return false; |
4884 | } |
4885 | |
4886 | if (!emitJumpTargetAndPatch(jumpAroundPop)) { |
4887 | // [stack] LHS | RHS |
4888 | return false; |
4889 | } |
4890 | } else { |
4891 | if (!emitJumpTargetAndPatch(jump)) { |
4892 | // [stack] LHS | RHS |
4893 | return false; |
4894 | } |
4895 | } |
4896 | |
4897 | MOZ_ASSERT(bytecodeSection().stackDepth() == depth + 1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(bytecodeSection().stackDepth() == depth + 1)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(bytecodeSection().stackDepth() == depth + 1))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("bytecodeSection().stackDepth() == depth + 1" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4897); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == depth + 1" ")"); do { *((volatile int*)__null) = 4897; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4898 | |
4899 | return true; |
4900 | } |
4901 | |
4902 | bool BytecodeEmitter::emitCallSiteObjectArray(ObjLiteralWriter& writer, |
4903 | ListNode* cookedOrRaw, |
4904 | ParseNode* head, uint32_t count) { |
4905 | DebugOnly<size_t> idx = 0; |
4906 | for (ParseNode* pn : cookedOrRaw->contentsFrom(head)) { |
4907 | MOZ_ASSERT(pn->isKind(ParseNodeKind::TemplateStringExpr) ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->isKind(ParseNodeKind::TemplateStringExpr) || pn ->isKind(ParseNodeKind::RawUndefinedExpr))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->isKind(ParseNodeKind:: TemplateStringExpr) || pn->isKind(ParseNodeKind::RawUndefinedExpr )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("pn->isKind(ParseNodeKind::TemplateStringExpr) || pn->isKind(ParseNodeKind::RawUndefinedExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4908); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->isKind(ParseNodeKind::TemplateStringExpr) || pn->isKind(ParseNodeKind::RawUndefinedExpr)" ")"); do { *((volatile int*)__null) = 4908; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
4908 | pn->isKind(ParseNodeKind::RawUndefinedExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->isKind(ParseNodeKind::TemplateStringExpr) || pn ->isKind(ParseNodeKind::RawUndefinedExpr))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->isKind(ParseNodeKind:: TemplateStringExpr) || pn->isKind(ParseNodeKind::RawUndefinedExpr )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("pn->isKind(ParseNodeKind::TemplateStringExpr) || pn->isKind(ParseNodeKind::RawUndefinedExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4908); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->isKind(ParseNodeKind::TemplateStringExpr) || pn->isKind(ParseNodeKind::RawUndefinedExpr)" ")"); do { *((volatile int*)__null) = 4908; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4909 | |
4910 | if (!emitObjLiteralValue(writer, pn)) { |
4911 | return false; |
4912 | } |
4913 | idx++; |
4914 | } |
4915 | MOZ_ASSERT(idx == count)do { static_assert( mozilla::detail::AssertionConditionType< decltype(idx == count)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(idx == count))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("idx == count", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4915); AnnotateMozCrashReason("MOZ_ASSERT" "(" "idx == count" ")"); do { *((volatile int*)__null) = 4915; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4916 | |
4917 | return true; |
4918 | } |
4919 | |
4920 | bool BytecodeEmitter::emitCallSiteObject(CallSiteNode* callSiteObj) { |
4921 | constexpr JSOp op = JSOp::CallSiteObj; |
4922 | |
4923 | // The first element of a call-site node is the raw-values list. Skip over it. |
4924 | ListNode* raw = callSiteObj->rawNodes(); |
4925 | MOZ_ASSERT(raw->isKind(ParseNodeKind::ArrayExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(raw->isKind(ParseNodeKind::ArrayExpr))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(raw->isKind(ParseNodeKind::ArrayExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("raw->isKind(ParseNodeKind::ArrayExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4925); AnnotateMozCrashReason("MOZ_ASSERT" "(" "raw->isKind(ParseNodeKind::ArrayExpr)" ")"); do { *((volatile int*)__null) = 4925; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4926 | ParseNode* head = callSiteObj->head()->pn_next; |
4927 | |
4928 | uint32_t count = callSiteObj->count() - 1; |
4929 | MOZ_ASSERT(count == raw->count())do { static_assert( mozilla::detail::AssertionConditionType< decltype(count == raw->count())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(count == raw->count()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("count == raw->count()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4929); AnnotateMozCrashReason("MOZ_ASSERT" "(" "count == raw->count()" ")"); do { *((volatile int*)__null) = 4929; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4930 | |
4931 | ObjLiteralWriter writer; |
4932 | writer.beginCallSiteObj(op); |
4933 | writer.beginDenseArrayElements(); |
4934 | |
4935 | // Write elements of the two arrays: the 'cooked' values followed by the |
4936 | // 'raw' values. |
4937 | MOZ_RELEASE_ASSERT(count < UINT32_MAX / 2,do { static_assert( mozilla::detail::AssertionConditionType< decltype(count < (4294967295U) / 2)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(count < (4294967295U) / 2 ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "count < (4294967295U) / 2" " (" "Number of elements for both arrays must fit in uint32_t" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4938); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "count < (4294967295U) / 2" ") (" "Number of elements for both arrays must fit in uint32_t" ")"); do { *((volatile int*)__null) = 4938; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
4938 | "Number of elements for both arrays must fit in uint32_t")do { static_assert( mozilla::detail::AssertionConditionType< decltype(count < (4294967295U) / 2)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(count < (4294967295U) / 2 ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "count < (4294967295U) / 2" " (" "Number of elements for both arrays must fit in uint32_t" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4938); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "count < (4294967295U) / 2" ") (" "Number of elements for both arrays must fit in uint32_t" ")"); do { *((volatile int*)__null) = 4938; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4939 | if (!emitCallSiteObjectArray(writer, callSiteObj, head, count)) { |
4940 | return false; |
4941 | } |
4942 | if (!emitCallSiteObjectArray(writer, raw, raw->head(), count)) { |
4943 | return false; |
4944 | } |
4945 | |
4946 | GCThingIndex cookedIndex; |
4947 | if (!addObjLiteralData(writer, &cookedIndex)) { |
4948 | return false; |
4949 | } |
4950 | |
4951 | MOZ_ASSERT(sc->hasCallSiteObj())do { static_assert( mozilla::detail::AssertionConditionType< decltype(sc->hasCallSiteObj())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(sc->hasCallSiteObj()))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("sc->hasCallSiteObj()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4951); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->hasCallSiteObj()" ")"); do { *((volatile int*)__null) = 4951; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4952 | |
4953 | return emitInternedObjectOp(cookedIndex, op); |
4954 | } |
4955 | |
4956 | bool BytecodeEmitter::emitCatch(BinaryNode* catchClause) { |
4957 | // We must be nested under a try-finally statement. |
4958 | MOZ_ASSERT(innermostNestableControl->is<TryFinallyControl>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(innermostNestableControl->is<TryFinallyControl >())>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(innermostNestableControl->is<TryFinallyControl >()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("innermostNestableControl->is<TryFinallyControl>()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4958); AnnotateMozCrashReason("MOZ_ASSERT" "(" "innermostNestableControl->is<TryFinallyControl>()" ")"); do { *((volatile int*)__null) = 4958; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4959 | |
4960 | ParseNode* param = catchClause->left(); |
4961 | if (!param) { |
4962 | // Catch parameter was omitted; just discard the exception. |
4963 | if (!emit1(JSOp::Pop)) { |
4964 | return false; |
4965 | } |
4966 | } else { |
4967 | switch (param->getKind()) { |
4968 | case ParseNodeKind::ArrayExpr: |
4969 | case ParseNodeKind::ObjectExpr: |
4970 | if (!emitDestructuringOps(¶m->as<ListNode>(), |
4971 | DestructuringFlavor::Declaration)) { |
4972 | return false; |
4973 | } |
4974 | if (!emit1(JSOp::Pop)) { |
4975 | return false; |
4976 | } |
4977 | break; |
4978 | |
4979 | case ParseNodeKind::Name: |
4980 | if (!emitLexicalInitialization(¶m->as<NameNode>())) { |
4981 | return false; |
4982 | } |
4983 | if (!emit1(JSOp::Pop)) { |
4984 | return false; |
4985 | } |
4986 | break; |
4987 | |
4988 | default: |
4989 | MOZ_ASSERT(0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(0)>::isValid, "invalid assertion condition"); if ( (__builtin_expect(!!(!(!!(0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("0", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4989); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0" ")"); do { *((volatile int*)__null) = 4989; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); |
4990 | } |
4991 | } |
4992 | |
4993 | /* Emit the catch body. */ |
4994 | return emitTree(catchClause->right()); |
4995 | } |
4996 | |
4997 | // Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See the |
4998 | // comment on EmitSwitch. |
4999 | MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitTry(TryNode* tryNode) { |
5000 | LexicalScopeNode* catchScope = tryNode->catchScope(); |
5001 | ParseNode* finallyNode = tryNode->finallyBlock(); |
5002 | |
5003 | TryEmitter::Kind kind; |
5004 | if (catchScope) { |
5005 | if (finallyNode) { |
5006 | kind = TryEmitter::Kind::TryCatchFinally; |
5007 | } else { |
5008 | kind = TryEmitter::Kind::TryCatch; |
5009 | } |
5010 | } else { |
5011 | MOZ_ASSERT(finallyNode)do { static_assert( mozilla::detail::AssertionConditionType< decltype(finallyNode)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(finallyNode))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("finallyNode", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5011); AnnotateMozCrashReason("MOZ_ASSERT" "(" "finallyNode" ")"); do { *((volatile int*)__null) = 5011; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5012 | kind = TryEmitter::Kind::TryFinally; |
5013 | } |
5014 | TryEmitter tryCatch(this, kind, TryEmitter::ControlKind::Syntactic); |
5015 | |
5016 | if (!tryCatch.emitTry()) { |
5017 | return false; |
5018 | } |
5019 | |
5020 | if (!emitTree(tryNode->body())) { |
5021 | return false; |
5022 | } |
5023 | |
5024 | // If this try has a catch block, emit it. |
5025 | if (catchScope) { |
5026 | // The emitted code for a catch block looks like: |
5027 | // |
5028 | // [pushlexicalenv] only if any local aliased |
5029 | // exception |
5030 | // setlocal 0; pop assign or possibly destructure exception |
5031 | // < catch block contents > |
5032 | // debugleaveblock |
5033 | // [poplexicalenv] only if any local aliased |
5034 | // if there is a finally block: |
5035 | // goto <finally> |
5036 | // [jump target for returning from finally] |
5037 | // goto <after finally> |
5038 | if (!tryCatch.emitCatch()) { |
5039 | return false; |
5040 | } |
5041 | |
5042 | // Emit the lexical scope and catch body. |
5043 | if (!emitTree(catchScope)) { |
5044 | return false; |
5045 | } |
5046 | } |
5047 | |
5048 | // Emit the finally handler, if there is one. |
5049 | if (finallyNode) { |
5050 | if (!tryCatch.emitFinally(Some(finallyNode->pn_pos.begin))) { |
5051 | return false; |
5052 | } |
5053 | |
5054 | if (!emitTree(finallyNode)) { |
5055 | return false; |
5056 | } |
5057 | } |
5058 | |
5059 | if (!tryCatch.emitEnd()) { |
5060 | return false; |
5061 | } |
5062 | |
5063 | return true; |
5064 | } |
5065 | |
5066 | [[nodiscard]] bool BytecodeEmitter::emitJumpToFinally(JumpList* jump, |
5067 | uint32_t idx) { |
5068 | // Push the continuation index. |
5069 | if (!emitNumberOp(idx)) { |
5070 | return false; |
5071 | } |
5072 | |
5073 | // Push |exception_stack|. |
5074 | if (!emit1(JSOp::Null)) { |
5075 | return false; |
5076 | } |
5077 | |
5078 | // Push |throwing|. |
5079 | if (!emit1(JSOp::False)) { |
5080 | return false; |
5081 | } |
5082 | |
5083 | // Jump to the finally block. |
5084 | if (!emitJumpNoFallthrough(JSOp::Goto, jump)) { |
5085 | return false; |
5086 | } |
5087 | |
5088 | return true; |
5089 | } |
5090 | |
5091 | bool BytecodeEmitter::emitIf(TernaryNode* ifNode) { |
5092 | IfEmitter ifThenElse(this); |
5093 | |
5094 | if (!ifThenElse.emitIf(Some(ifNode->kid1()->pn_pos.begin))) { |
5095 | return false; |
5096 | } |
5097 | |
5098 | if_again: |
5099 | ParseNode* testNode = ifNode->kid1(); |
5100 | auto conditionKind = IfEmitter::ConditionKind::Positive; |
5101 | if (testNode->isKind(ParseNodeKind::NotExpr)) { |
5102 | testNode = testNode->as<UnaryNode>().kid(); |
5103 | conditionKind = IfEmitter::ConditionKind::Negative; |
5104 | } |
5105 | |
5106 | if (!markStepBreakpoint()) { |
5107 | return false; |
5108 | } |
5109 | |
5110 | // Emit code for the condition before pushing stmtInfo. |
5111 | // NOTE: NotExpr of testNode may be unwrapped, and in that case the negation |
5112 | // is handled by conditionKind. |
5113 | if (!emitTree(testNode)) { |
5114 | return false; |
5115 | } |
5116 | |
5117 | ParseNode* elseNode = ifNode->kid3(); |
5118 | if (elseNode) { |
5119 | if (!ifThenElse.emitThenElse(conditionKind)) { |
5120 | return false; |
5121 | } |
5122 | } else { |
5123 | if (!ifThenElse.emitThen(conditionKind)) { |
5124 | return false; |
5125 | } |
5126 | } |
5127 | |
5128 | /* Emit code for the then part. */ |
5129 | if (!emitTree(ifNode->kid2())) { |
5130 | return false; |
5131 | } |
5132 | |
5133 | if (elseNode) { |
5134 | if (elseNode->isKind(ParseNodeKind::IfStmt)) { |
5135 | ifNode = &elseNode->as<TernaryNode>(); |
5136 | |
5137 | if (!ifThenElse.emitElseIf(Some(ifNode->kid1()->pn_pos.begin))) { |
5138 | return false; |
5139 | } |
5140 | |
5141 | goto if_again; |
5142 | } |
5143 | |
5144 | if (!ifThenElse.emitElse()) { |
5145 | return false; |
5146 | } |
5147 | |
5148 | /* Emit code for the else part. */ |
5149 | if (!emitTree(elseNode)) { |
5150 | return false; |
5151 | } |
5152 | } |
5153 | |
5154 | if (!ifThenElse.emitEnd()) { |
5155 | return false; |
5156 | } |
5157 | |
5158 | return true; |
5159 | } |
5160 | |
5161 | bool BytecodeEmitter::emitHoistedFunctionsInList(ListNode* stmtList) { |
5162 | MOZ_ASSERT(stmtList->hasTopLevelFunctionDeclarations())do { static_assert( mozilla::detail::AssertionConditionType< decltype(stmtList->hasTopLevelFunctionDeclarations())>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(stmtList->hasTopLevelFunctionDeclarations()))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("stmtList->hasTopLevelFunctionDeclarations()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5162); AnnotateMozCrashReason("MOZ_ASSERT" "(" "stmtList->hasTopLevelFunctionDeclarations()" ")"); do { *((volatile int*)__null) = 5162; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5163 | |
5164 | // We can call this multiple times for sloppy eval scopes. |
5165 | if (stmtList->emittedTopLevelFunctionDeclarations()) { |
5166 | return true; |
5167 | } |
5168 | |
5169 | stmtList->setEmittedTopLevelFunctionDeclarations(); |
5170 | |
5171 | for (ParseNode* stmt : stmtList->contents()) { |
5172 | ParseNode* maybeFun = stmt; |
5173 | |
5174 | if (!sc->strict()) { |
5175 | while (maybeFun->isKind(ParseNodeKind::LabelStmt)) { |
5176 | maybeFun = maybeFun->as<LabeledStatement>().statement(); |
5177 | } |
5178 | } |
5179 | |
5180 | if (maybeFun->is<FunctionNode>() && |
5181 | maybeFun->as<FunctionNode>().functionIsHoisted()) { |
5182 | if (!emitTree(maybeFun)) { |
5183 | return false; |
5184 | } |
5185 | } |
5186 | } |
5187 | |
5188 | return true; |
5189 | } |
5190 | |
5191 | bool BytecodeEmitter::emitLexicalScopeBody( |
5192 | ParseNode* body, EmitLineNumberNote emitLineNote /* = EMIT_LINENOTE */) { |
5193 | if (body->isKind(ParseNodeKind::StatementList) && |
5194 | body->as<ListNode>().hasTopLevelFunctionDeclarations()) { |
5195 | // This block contains function statements whose definitions are |
5196 | // hoisted to the top of the block. Emit these as a separate pass |
5197 | // before the rest of the block. |
5198 | if (!emitHoistedFunctionsInList(&body->as<ListNode>())) { |
5199 | return false; |
5200 | } |
5201 | } |
5202 | |
5203 | // Line notes were updated by emitLexicalScope or emitScript. |
5204 | return emitTree(body, ValueUsage::WantValue, emitLineNote); |
5205 | } |
5206 | |
5207 | // Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See |
5208 | // the comment on emitSwitch. |
5209 | MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitLexicalScope( |
5210 | LexicalScopeNode* lexicalScope) { |
5211 | LexicalScopeEmitter lse(this); |
5212 | |
5213 | ParseNode* body = lexicalScope->scopeBody(); |
5214 | if (lexicalScope->isEmptyScope()) { |
5215 | if (!lse.emitEmptyScope()) { |
5216 | return false; |
5217 | } |
5218 | |
5219 | if (!emitLexicalScopeBody(body)) { |
5220 | return false; |
5221 | } |
5222 | |
5223 | if (!lse.emitEnd()) { |
5224 | return false; |
5225 | } |
5226 | |
5227 | return true; |
5228 | } |
5229 | |
5230 | // We are about to emit some bytecode for what the spec calls "declaration |
5231 | // instantiation". Assign these instructions to the opening `{` of the |
5232 | // block. (Using the location of each declaration we're instantiating is |
5233 | // too weird when stepping in the debugger.) |
5234 | if (!ParseNodeRequiresSpecialLineNumberNotes(body)) { |
5235 | if (!updateSourceCoordNotes(lexicalScope->pn_pos.begin)) { |
5236 | return false; |
5237 | } |
5238 | } |
5239 | |
5240 | ScopeKind kind; |
5241 | if (body->isKind(ParseNodeKind::Catch)) { |
5242 | BinaryNode* catchNode = &body->as<BinaryNode>(); |
5243 | kind = |
5244 | (!catchNode->left() || catchNode->left()->isKind(ParseNodeKind::Name)) |
5245 | ? ScopeKind::SimpleCatch |
5246 | : ScopeKind::Catch; |
5247 | } else { |
5248 | kind = lexicalScope->kind(); |
5249 | } |
5250 | |
5251 | if (!lse.emitScope(kind, lexicalScope->scopeBindings())) { |
5252 | return false; |
5253 | } |
5254 | |
5255 | if (body->isKind(ParseNodeKind::ForStmt)) { |
5256 | // for loops need to emit JSOp::FreshenLexicalEnv/JSOp::RecreateLexicalEnv |
5257 | // if there are lexical declarations in the head. Signal this by passing a |
5258 | // non-nullptr lexical scope. |
5259 | if (!emitFor(&body->as<ForNode>(), &lse.emitterScope())) { |
5260 | return false; |
5261 | } |
5262 | } else { |
5263 | if (!emitLexicalScopeBody(body, SUPPRESS_LINENOTE)) { |
5264 | return false; |
5265 | } |
5266 | } |
5267 | |
5268 | if (!lse.emitEnd()) { |
5269 | return false; |
5270 | } |
5271 | return true; |
5272 | } |
5273 | |
5274 | bool BytecodeEmitter::emitWith(BinaryNode* withNode) { |
5275 | // Ensure that the column of the 'with' is set properly. |
5276 | if (!updateSourceCoordNotes(withNode->left()->pn_pos.begin)) { |
5277 | return false; |
5278 | } |
5279 | |
5280 | if (!markStepBreakpoint()) { |
5281 | return false; |
5282 | } |
5283 | |
5284 | if (!emitTree(withNode->left())) { |
5285 | return false; |
5286 | } |
5287 | |
5288 | EmitterScope emitterScope(this); |
5289 | if (!emitterScope.enterWith(this)) { |
5290 | return false; |
5291 | } |
5292 | |
5293 | if (!emitTree(withNode->right())) { |
5294 | return false; |
5295 | } |
5296 | |
5297 | return emitterScope.leave(this); |
5298 | } |
5299 | |
5300 | bool BytecodeEmitter::emitCopyDataProperties(CopyOption option) { |
5301 | DebugOnly<int32_t> depth = bytecodeSection().stackDepth(); |
5302 | |
5303 | uint32_t argc; |
5304 | if (option == CopyOption::Filtered) { |
5305 | MOZ_ASSERT(depth > 2)do { static_assert( mozilla::detail::AssertionConditionType< decltype(depth > 2)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(depth > 2))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("depth > 2", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5305); AnnotateMozCrashReason("MOZ_ASSERT" "(" "depth > 2" ")"); do { *((volatile int*)__null) = 5305; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5306 | // [stack] TARGET SOURCE SET |
5307 | argc = 3; |
5308 | |
5309 | if (!emitAtomOp(JSOp::GetIntrinsic, |
5310 | TaggedParserAtomIndex::WellKnown::CopyDataProperties())) { |
5311 | // [stack] TARGET SOURCE SET COPYDATAPROPERTIES |
5312 | return false; |
5313 | } |
5314 | } else { |
5315 | MOZ_ASSERT(depth > 1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(depth > 1)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(depth > 1))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("depth > 1", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5315); AnnotateMozCrashReason("MOZ_ASSERT" "(" "depth > 1" ")"); do { *((volatile int*)__null) = 5315; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5316 | // [stack] TARGET SOURCE |
5317 | argc = 2; |
5318 | |
5319 | if (!emitAtomOp( |
5320 | JSOp::GetIntrinsic, |
5321 | TaggedParserAtomIndex::WellKnown::CopyDataPropertiesUnfiltered())) { |
5322 | // [stack] TARGET SOURCE COPYDATAPROPERTIES |
5323 | return false; |
5324 | } |
5325 | } |
5326 | |
5327 | if (!emit1(JSOp::Undefined)) { |
5328 | // [stack] TARGET SOURCE SET? COPYDATAPROPERTIES |
5329 | // UNDEFINED |
5330 | return false; |
5331 | } |
5332 | if (!emit2(JSOp::Pick, argc + 1)) { |
5333 | // [stack] SOURCE SET? COPYDATAPROPERTIES UNDEFINED |
5334 | // TARGET |
5335 | return false; |
5336 | } |
5337 | if (!emit2(JSOp::Pick, argc + 1)) { |
5338 | // [stack] SET? COPYDATAPROPERTIES UNDEFINED TARGET |
5339 | // SOURCE |
5340 | return false; |
5341 | } |
5342 | if (option == CopyOption::Filtered) { |
5343 | if (!emit2(JSOp::Pick, argc + 1)) { |
5344 | // [stack] COPYDATAPROPERTIES UNDEFINED TARGET SOURCE SET |
5345 | return false; |
5346 | } |
5347 | } |
5348 | // Callee is always self-hosted instrinsic, and cannot be content function. |
5349 | if (!emitCall(JSOp::CallIgnoresRv, argc)) { |
5350 | // [stack] IGNORED |
5351 | return false; |
5352 | } |
5353 | |
5354 | if (!emit1(JSOp::Pop)) { |
5355 | // [stack] |
5356 | return false; |
5357 | } |
5358 | |
5359 | MOZ_ASSERT(depth - int(argc) == bytecodeSection().stackDepth())do { static_assert( mozilla::detail::AssertionConditionType< decltype(depth - int(argc) == bytecodeSection().stackDepth()) >::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(depth - int(argc) == bytecodeSection().stackDepth()) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("depth - int(argc) == bytecodeSection().stackDepth()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5359); AnnotateMozCrashReason("MOZ_ASSERT" "(" "depth - int(argc) == bytecodeSection().stackDepth()" ")"); do { *((volatile int*)__null) = 5359; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5360 | return true; |
5361 | } |
5362 | |
5363 | bool BytecodeEmitter::emitBigIntOp(BigIntLiteral* bigint) { |
5364 | GCThingIndex index; |
5365 | if (!perScriptData().gcThingList().append(bigint, &index)) { |
5366 | return false; |
5367 | } |
5368 | return emitGCIndexOp(JSOp::BigInt, index); |
5369 | } |
5370 | |
5371 | bool BytecodeEmitter::emitIterable(ParseNode* value, |
5372 | SelfHostedIter selfHostedIter, |
5373 | IteratorKind iterKind) { |
5374 | MOZ_ASSERT(getSelfHostedIterFor(value) == selfHostedIter)do { static_assert( mozilla::detail::AssertionConditionType< decltype(getSelfHostedIterFor(value) == selfHostedIter)>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(getSelfHostedIterFor(value) == selfHostedIter))), 0) )) { do { } while (false); MOZ_ReportAssertionFailure("getSelfHostedIterFor(value) == selfHostedIter" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5374); AnnotateMozCrashReason("MOZ_ASSERT" "(" "getSelfHostedIterFor(value) == selfHostedIter" ")"); do { *((volatile int*)__null) = 5374; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5375 | |
5376 | if (!emitTree(value)) { |
5377 | // [stack] ITERABLE |
5378 | return false; |
5379 | } |
5380 | |
5381 | switch (selfHostedIter) { |
5382 | case SelfHostedIter::Deny: |
5383 | case SelfHostedIter::AllowContent: |
5384 | // [stack] ITERABLE |
5385 | return true; |
5386 | |
5387 | case SelfHostedIter::AllowContentWith: { |
5388 | // This is the following case: |
5389 | // |
5390 | // for (const nextValue of allowContentIterWith(items, usingIterator)) { |
5391 | // |
5392 | // `items` is emitted by `emitTree(value)` above, and the result is on the |
5393 | // stack as ITERABLE. |
5394 | // `usingIterator` is the value of `items[Symbol.iterator]`, that's |
5395 | // already retrieved. |
5396 | ListNode* argsList = value->as<CallNode>().args(); |
5397 | MOZ_ASSERT_IF(iterKind == IteratorKind::Sync, argsList->count() == 2)do { if (iterKind == IteratorKind::Sync) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(argsList ->count() == 2)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(argsList->count() == 2))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 2" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5397); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2" ")"); do { *((volatile int*)__null) = 5397; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
5398 | MOZ_ASSERT_IF(iterKind == IteratorKind::Async, argsList->count() == 3)do { if (iterKind == IteratorKind::Async) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(argsList ->count() == 3)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(argsList->count() == 3))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 3" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5398); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 3" ")"); do { *((volatile int*)__null) = 5398; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
5399 | |
5400 | if (!emitTree(argsList->head()->pn_next)) { |
5401 | // [stack] ITERABLE ITERFN |
5402 | return false; |
5403 | } |
5404 | |
5405 | // Async iterator has two possible iterators: An async iterator and a sync |
5406 | // iterator. |
5407 | if (iterKind == IteratorKind::Async) { |
5408 | if (!emitTree(argsList->head()->pn_next->pn_next)) { |
5409 | // [stack] ITERABLE ASYNC_ITERFN SYNC_ITERFN |
5410 | return false; |
5411 | } |
5412 | } |
5413 | |
5414 | // [stack] ITERABLE ASYNC_ITERFN? SYNC_ITERFN |
5415 | return true; |
5416 | } |
5417 | |
5418 | case SelfHostedIter::AllowContentWithNext: { |
5419 | // This is the following case: |
5420 | // |
5421 | // for (const nextValue of allowContentIterWithNext(iterator, next)) { |
5422 | // |
5423 | // `iterator` is emitted by `emitTree(value)` above, and the result is on |
5424 | // the stack as ITER. |
5425 | // `next` is the value of `iterator.next`, that's already retrieved. |
5426 | ListNode* argsList = value->as<CallNode>().args(); |
5427 | MOZ_ASSERT(argsList->count() == 2)do { static_assert( mozilla::detail::AssertionConditionType< decltype(argsList->count() == 2)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(argsList->count() == 2))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 2" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5427); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2" ")"); do { *((volatile int*)__null) = 5427; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5428 | |
5429 | if (!emitTree(argsList->head()->pn_next)) { |
5430 | // [stack] ITER NEXT |
5431 | return false; |
5432 | } |
5433 | |
5434 | if (!emit1(JSOp::Swap)) { |
5435 | // [stack] NEXT ITER |
5436 | return false; |
5437 | } |
5438 | |
5439 | // [stack] NEXT ITER |
5440 | return true; |
5441 | } |
5442 | } |
5443 | |
5444 | MOZ_CRASH("invalid self-hosted iteration kind")do { do { } while (false); MOZ_ReportCrash("" "invalid self-hosted iteration kind" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5444); AnnotateMozCrashReason("MOZ_CRASH(" "invalid self-hosted iteration kind" ")"); do { *((volatile int*)__null) = 5444; __attribute__((nomerge )) ::abort(); } while (false); } while (false); |
5445 | } |
5446 | |
5447 | bool BytecodeEmitter::emitIterator(SelfHostedIter selfHostedIter) { |
5448 | MOZ_ASSERT(selfHostedIter != SelfHostedIter::Deny ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter ::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" " (" "[Symbol.iterator]() call is prohibited in self-hosted code " "because it can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5451); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" ") (" "[Symbol.iterator]() call is prohibited in self-hosted code " "because it can run user-modifiable iteration code" ")"); do { *((volatile int*)__null) = 5451; __attribute__((nomerge)) :: abort(); } while (false); } } while (false) |
5449 | emitterMode != BytecodeEmitter::SelfHosting,do { static_assert( mozilla::detail::AssertionConditionType< decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter ::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" " (" "[Symbol.iterator]() call is prohibited in self-hosted code " "because it can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5451); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" ") (" "[Symbol.iterator]() call is prohibited in self-hosted code " "because it can run user-modifiable iteration code" ")"); do { *((volatile int*)__null) = 5451; __attribute__((nomerge)) :: abort(); } while (false); } } while (false) |
5450 | "[Symbol.iterator]() call is prohibited in self-hosted code "do { static_assert( mozilla::detail::AssertionConditionType< decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter ::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" " (" "[Symbol.iterator]() call is prohibited in self-hosted code " "because it can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5451); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" ") (" "[Symbol.iterator]() call is prohibited in self-hosted code " "because it can run user-modifiable iteration code" ")"); do { *((volatile int*)__null) = 5451; __attribute__((nomerge)) :: abort(); } while (false); } } while (false) |
5451 | "because it can run user-modifiable iteration code")do { static_assert( mozilla::detail::AssertionConditionType< decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter ::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" " (" "[Symbol.iterator]() call is prohibited in self-hosted code " "because it can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5451); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" ") (" "[Symbol.iterator]() call is prohibited in self-hosted code " "because it can run user-modifiable iteration code" ")"); do { *((volatile int*)__null) = 5451; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); |
5452 | |
5453 | if (selfHostedIter == SelfHostedIter::AllowContentWithNext) { |
5454 | // [stack] NEXT ITER |
5455 | |
5456 | // Nothing to do, stack already contains the iterator and its `next` method. |
5457 | return true; |
5458 | } |
5459 | |
5460 | if (selfHostedIter != SelfHostedIter::AllowContentWith) { |
5461 | // [stack] OBJ |
5462 | |
5463 | // Convert iterable to iterator. |
5464 | if (!emit1(JSOp::Dup)) { |
5465 | // [stack] OBJ OBJ |
5466 | return false; |
5467 | } |
5468 | if (!emit2(JSOp::Symbol, uint8_t(JS::SymbolCode::iterator))) { |
5469 | // [stack] OBJ OBJ @@ITERATOR |
5470 | return false; |
5471 | } |
5472 | if (!emitElemOpBase(JSOp::GetElem)) { |
5473 | // [stack] OBJ ITERFN |
5474 | return false; |
5475 | } |
5476 | } |
5477 | |
5478 | if (!emit1(JSOp::Swap)) { |
5479 | // [stack] ITERFN OBJ |
5480 | return false; |
5481 | } |
5482 | if (!emitCall(getIterCallOp(JSOp::CallIter, selfHostedIter), 0)) { |
5483 | // [stack] ITER |
5484 | return false; |
5485 | } |
5486 | if (!emitCheckIsObj(CheckIsObjectKind::GetIterator)) { |
5487 | // [stack] ITER |
5488 | return false; |
5489 | } |
5490 | if (!emit1(JSOp::Dup)) { |
5491 | // [stack] ITER ITER |
5492 | return false; |
5493 | } |
5494 | if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::next())) { |
5495 | // [stack] ITER NEXT |
5496 | return false; |
5497 | } |
5498 | if (!emit1(JSOp::Swap)) { |
5499 | // [stack] NEXT ITER |
5500 | return false; |
5501 | } |
5502 | return true; |
5503 | } |
5504 | |
5505 | bool BytecodeEmitter::emitAsyncIterator(SelfHostedIter selfHostedIter) { |
5506 | MOZ_ASSERT(selfHostedIter != SelfHostedIter::AllowContentWithNext)do { static_assert( mozilla::detail::AssertionConditionType< decltype(selfHostedIter != SelfHostedIter::AllowContentWithNext )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(selfHostedIter != SelfHostedIter::AllowContentWithNext ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "selfHostedIter != SelfHostedIter::AllowContentWithNext", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5506); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::AllowContentWithNext" ")"); do { *((volatile int*)__null) = 5506; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5507 | MOZ_ASSERT(selfHostedIter != SelfHostedIter::Deny ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter ::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" " (" "[Symbol.asyncIterator]() call is prohibited in self-hosted code " "because it can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5510); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" ") (" "[Symbol.asyncIterator]() call is prohibited in self-hosted code " "because it can run user-modifiable iteration code" ")"); do { *((volatile int*)__null) = 5510; __attribute__((nomerge)) :: abort(); } while (false); } } while (false) |
5508 | emitterMode != BytecodeEmitter::SelfHosting,do { static_assert( mozilla::detail::AssertionConditionType< decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter ::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" " (" "[Symbol.asyncIterator]() call is prohibited in self-hosted code " "because it can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5510); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" ") (" "[Symbol.asyncIterator]() call is prohibited in self-hosted code " "because it can run user-modifiable iteration code" ")"); do { *((volatile int*)__null) = 5510; __attribute__((nomerge)) :: abort(); } while (false); } } while (false) |
5509 | "[Symbol.asyncIterator]() call is prohibited in self-hosted code "do { static_assert( mozilla::detail::AssertionConditionType< decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter ::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" " (" "[Symbol.asyncIterator]() call is prohibited in self-hosted code " "because it can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5510); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" ") (" "[Symbol.asyncIterator]() call is prohibited in self-hosted code " "because it can run user-modifiable iteration code" ")"); do { *((volatile int*)__null) = 5510; __attribute__((nomerge)) :: abort(); } while (false); } } while (false) |
5510 | "because it can run user-modifiable iteration code")do { static_assert( mozilla::detail::AssertionConditionType< decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter ::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" " (" "[Symbol.asyncIterator]() call is prohibited in self-hosted code " "because it can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5510); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" ") (" "[Symbol.asyncIterator]() call is prohibited in self-hosted code " "because it can run user-modifiable iteration code" ")"); do { *((volatile int*)__null) = 5510; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); |
5511 | |
5512 | if (selfHostedIter != SelfHostedIter::AllowContentWith) { |
5513 | // [stack] OBJ |
5514 | |
5515 | // Convert iterable to iterator. |
5516 | if (!emit1(JSOp::Dup)) { |
5517 | // [stack] OBJ OBJ |
5518 | return false; |
5519 | } |
5520 | if (!emit2(JSOp::Symbol, uint8_t(JS::SymbolCode::asyncIterator))) { |
5521 | // [stack] OBJ OBJ @@ASYNCITERATOR |
5522 | return false; |
5523 | } |
5524 | if (!emitElemOpBase(JSOp::GetElem)) { |
5525 | // [stack] OBJ ASYNC_ITERFN |
5526 | return false; |
5527 | } |
5528 | } else { |
5529 | // [stack] OBJ ASYNC_ITERFN SYNC_ITERFN |
5530 | |
5531 | if (!emitElemOpBase(JSOp::Swap)) { |
5532 | // [stack] OBJ SYNC_ITERFN ASYNC_ITERFN |
5533 | return false; |
5534 | } |
5535 | } |
5536 | |
5537 | InternalIfEmitter ifAsyncIterIsUndefined(this); |
5538 | if (!emit1(JSOp::IsNullOrUndefined)) { |
5539 | // [stack] OBJ SYNC_ITERFN? ASYNC_ITERFN NULL-OR-UNDEF |
5540 | return false; |
5541 | } |
5542 | if (!ifAsyncIterIsUndefined.emitThenElse()) { |
5543 | // [stack] OBJ SYNC_ITERFN? ASYNC_ITERFN |
5544 | return false; |
5545 | } |
5546 | |
5547 | if (!emit1(JSOp::Pop)) { |
5548 | // [stack] OBJ SYNC_ITERFN? |
5549 | return false; |
5550 | } |
5551 | |
5552 | if (selfHostedIter != SelfHostedIter::AllowContentWith) { |
5553 | if (!emit1(JSOp::Dup)) { |
5554 | // [stack] OBJ OBJ |
5555 | return false; |
5556 | } |
5557 | if (!emit2(JSOp::Symbol, uint8_t(JS::SymbolCode::iterator))) { |
5558 | // [stack] OBJ OBJ @@ITERATOR |
5559 | return false; |
5560 | } |
5561 | if (!emitElemOpBase(JSOp::GetElem)) { |
5562 | // [stack] OBJ SYNC_ITERFN |
5563 | return false; |
5564 | } |
5565 | } else { |
5566 | // [stack] OBJ SYNC_ITERFN |
5567 | } |
5568 | |
5569 | if (!emit1(JSOp::Swap)) { |
5570 | // [stack] SYNC_ITERFN OBJ |
5571 | return false; |
5572 | } |
5573 | if (!emitCall(getIterCallOp(JSOp::CallIter, selfHostedIter), 0)) { |
5574 | // [stack] ITER |
5575 | return false; |
5576 | } |
5577 | if (!emitCheckIsObj(CheckIsObjectKind::GetIterator)) { |
5578 | // [stack] ITER |
5579 | return false; |
5580 | } |
5581 | |
5582 | if (!emit1(JSOp::Dup)) { |
5583 | // [stack] ITER ITER |
5584 | return false; |
5585 | } |
5586 | if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::next())) { |
5587 | // [stack] ITER SYNCNEXT |
5588 | return false; |
5589 | } |
5590 | |
5591 | if (!emit1(JSOp::ToAsyncIter)) { |
5592 | // [stack] ITER |
5593 | return false; |
5594 | } |
5595 | |
5596 | if (!ifAsyncIterIsUndefined.emitElse()) { |
5597 | // [stack] OBJ SYNC_ITERFN? ASYNC_ITERFN |
5598 | return false; |
5599 | } |
5600 | |
5601 | if (selfHostedIter == SelfHostedIter::AllowContentWith) { |
5602 | if (!emit1(JSOp::Swap)) { |
5603 | // [stack] OBJ ASYNC_ITERFN SYNC_ITERFN |
5604 | return false; |
5605 | } |
5606 | if (!emit1(JSOp::Pop)) { |
5607 | // [stack] OBJ ASYNC_ITERFN |
5608 | return false; |
5609 | } |
5610 | } |
5611 | |
5612 | if (!emit1(JSOp::Swap)) { |
5613 | // [stack] ASYNC_ITERFN OBJ |
5614 | return false; |
5615 | } |
5616 | if (!emitCall(getIterCallOp(JSOp::CallIter, selfHostedIter), 0)) { |
5617 | // [stack] ITER |
5618 | return false; |
5619 | } |
5620 | if (!emitCheckIsObj(CheckIsObjectKind::GetAsyncIterator)) { |
5621 | // [stack] ITER |
5622 | return false; |
5623 | } |
5624 | |
5625 | if (!ifAsyncIterIsUndefined.emitEnd()) { |
5626 | // [stack] ITER |
5627 | return false; |
5628 | } |
5629 | |
5630 | if (!emit1(JSOp::Dup)) { |
5631 | // [stack] ITER ITER |
5632 | return false; |
5633 | } |
5634 | if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::next())) { |
5635 | // [stack] ITER NEXT |
5636 | return false; |
5637 | } |
5638 | if (!emit1(JSOp::Swap)) { |
5639 | // [stack] NEXT ITER |
5640 | return false; |
5641 | } |
5642 | |
5643 | return true; |
5644 | } |
5645 | |
5646 | bool BytecodeEmitter::emitSpread(SelfHostedIter selfHostedIter) { |
5647 | // [stack] NEXT ITER ARR I |
5648 | return emitSpread(selfHostedIter, 2, JSOp::InitElemInc); |
5649 | // [stack] ARR FINAL_INDEX |
5650 | } |
5651 | |
5652 | bool BytecodeEmitter::emitSpread(SelfHostedIter selfHostedIter, |
5653 | int spreadeeStackItems, JSOp storeElementOp) { |
5654 | LoopControl loopInfo(this, StatementKind::Spread); |
5655 | // In the [stack] annotations, (spreadee) can be "ARR I" (when spreading |
5656 | // into an array or into call parameters, or "TUPLE" (when spreading into a |
5657 | // tuple) |
5658 | |
5659 | if (!loopInfo.emitLoopHead(this, Nothing())) { |
5660 | // [stack] NEXT ITER (spreadee) |
5661 | return false; |
5662 | } |
5663 | |
5664 | { |
5665 | #ifdef DEBUG1 |
5666 | auto loopDepth = bytecodeSection().stackDepth(); |
5667 | #endif |
5668 | |
5669 | // Spread operations can't contain |continue|, so don't bother setting loop |
5670 | // and enclosing "update" offsets, as we do with for-loops. |
5671 | |
5672 | if (!emitDupAt(spreadeeStackItems + 1, 2)) { |
5673 | // [stack] NEXT ITER (spreadee) NEXT ITER |
5674 | return false; |
5675 | } |
5676 | if (!emitIteratorNext(Nothing(), IteratorKind::Sync, selfHostedIter)) { |
5677 | // [stack] NEXT ITER (spreadee) RESULT |
5678 | return false; |
5679 | } |
5680 | if (!emit1(JSOp::Dup)) { |
5681 | // [stack] NEXT ITER (spreadee) RESULT RESULT |
5682 | return false; |
5683 | } |
5684 | if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::done())) { |
5685 | // [stack] NEXT ITER (spreadee) RESULT DONE |
5686 | return false; |
5687 | } |
5688 | if (!emitJump(JSOp::JumpIfTrue, &loopInfo.breaks)) { |
5689 | // [stack] NEXT ITER (spreadee) RESULT |
5690 | return false; |
5691 | } |
5692 | |
5693 | // Emit code to assign result.value to the iteration variable. |
5694 | if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::value())) { |
5695 | // [stack] NEXT ITER (spreadee) VALUE |
5696 | return false; |
5697 | } |
5698 | if (!emit1(storeElementOp)) { |
5699 | // [stack] NEXT ITER (spreadee) |
5700 | return false; |
5701 | } |
5702 | |
5703 | if (!loopInfo.emitLoopEnd(this, JSOp::Goto, TryNoteKind::ForOf)) { |
5704 | // [stack] NEXT ITER (spreadee) |
5705 | return false; |
5706 | } |
5707 | |
5708 | MOZ_ASSERT(bytecodeSection().stackDepth() == loopDepth)do { static_assert( mozilla::detail::AssertionConditionType< decltype(bytecodeSection().stackDepth() == loopDepth)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(bytecodeSection().stackDepth() == loopDepth))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("bytecodeSection().stackDepth() == loopDepth" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5708); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == loopDepth" ")"); do { *((volatile int*)__null) = 5708; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5709 | } |
5710 | |
5711 | // When we leave the loop body and jump to this point, the result value is |
5712 | // still on the stack. Account for that by updating the stack depth |
5713 | // manually. |
5714 | bytecodeSection().setStackDepth(bytecodeSection().stackDepth() + 1); |
5715 | |
5716 | // No continues should occur in spreads. |
5717 | MOZ_ASSERT(!loopInfo.continues.offset.valid())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!loopInfo.continues.offset.valid())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!loopInfo.continues.offset.valid ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!loopInfo.continues.offset.valid()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5717); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!loopInfo.continues.offset.valid()" ")"); do { *((volatile int*)__null) = 5717; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5718 | |
5719 | if (!emit2(JSOp::Pick, spreadeeStackItems + 2)) { |
5720 | // [stack] ITER (spreadee) RESULT NEXT |
5721 | return false; |
5722 | } |
5723 | if (!emit2(JSOp::Pick, spreadeeStackItems + 2)) { |
5724 | // [stack] (spreadee) RESULT NEXT ITER |
5725 | return false; |
5726 | } |
5727 | |
5728 | return emitPopN(3); |
5729 | // [stack] (spreadee) |
5730 | } |
5731 | |
5732 | bool BytecodeEmitter::emitInitializeForInOrOfTarget(TernaryNode* forHead) { |
5733 | MOZ_ASSERT(forHead->isKind(ParseNodeKind::ForIn) ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(forHead->isKind(ParseNodeKind::ForIn) || forHead-> isKind(ParseNodeKind::ForOf))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(forHead->isKind(ParseNodeKind ::ForIn) || forHead->isKind(ParseNodeKind::ForOf)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("forHead->isKind(ParseNodeKind::ForIn) || forHead->isKind(ParseNodeKind::ForOf)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5734); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forHead->isKind(ParseNodeKind::ForIn) || forHead->isKind(ParseNodeKind::ForOf)" ")"); do { *((volatile int*)__null) = 5734; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
5734 | forHead->isKind(ParseNodeKind::ForOf))do { static_assert( mozilla::detail::AssertionConditionType< decltype(forHead->isKind(ParseNodeKind::ForIn) || forHead-> isKind(ParseNodeKind::ForOf))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(forHead->isKind(ParseNodeKind ::ForIn) || forHead->isKind(ParseNodeKind::ForOf)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("forHead->isKind(ParseNodeKind::ForIn) || forHead->isKind(ParseNodeKind::ForOf)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5734); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forHead->isKind(ParseNodeKind::ForIn) || forHead->isKind(ParseNodeKind::ForOf)" ")"); do { *((volatile int*)__null) = 5734; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5735 | |
5736 | MOZ_ASSERT(bytecodeSection().stackDepth() >= 1,do { static_assert( mozilla::detail::AssertionConditionType< decltype(bytecodeSection().stackDepth() >= 1)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(bytecodeSection().stackDepth() >= 1))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("bytecodeSection().stackDepth() >= 1" " (" "must have a per-iteration value for initializing" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5737); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() >= 1" ") (" "must have a per-iteration value for initializing" ")" ); do { *((volatile int*)__null) = 5737; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
5737 | "must have a per-iteration value for initializing")do { static_assert( mozilla::detail::AssertionConditionType< decltype(bytecodeSection().stackDepth() >= 1)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(bytecodeSection().stackDepth() >= 1))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("bytecodeSection().stackDepth() >= 1" " (" "must have a per-iteration value for initializing" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5737); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() >= 1" ") (" "must have a per-iteration value for initializing" ")" ); do { *((volatile int*)__null) = 5737; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5738 | |
5739 | ParseNode* target = forHead->kid1(); |
5740 | MOZ_ASSERT(!forHead->kid2())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!forHead->kid2())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!forHead->kid2()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!forHead->kid2()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5740); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!forHead->kid2()" ")"); do { *((volatile int*)__null) = 5740; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5741 | |
5742 | // If the for-in/of loop didn't have a variable declaration, per-loop |
5743 | // initialization is just assigning the iteration value to a target |
5744 | // expression. |
5745 | if (!target->is<DeclarationListNode>()) { |
5746 | return emitAssignmentOrInit(ParseNodeKind::AssignExpr, target, nullptr); |
5747 | // [stack] ... ITERVAL |
5748 | } |
5749 | |
5750 | // Otherwise, per-loop initialization is (possibly) declaration |
5751 | // initialization. If the declaration is a lexical declaration, it must be |
5752 | // initialized. If the declaration is a variable declaration, an |
5753 | // assignment to that name (which does *not* necessarily assign to the |
5754 | // variable!) must be generated. |
5755 | |
5756 | auto* declarationList = &target->as<DeclarationListNode>(); |
5757 | if (!updateSourceCoordNotes(declarationList->pn_pos.begin)) { |
5758 | return false; |
5759 | } |
5760 | |
5761 | target = declarationList->singleBinding(); |
5762 | |
5763 | NameNode* nameNode = nullptr; |
5764 | if (target->isKind(ParseNodeKind::Name)) { |
5765 | nameNode = &target->as<NameNode>(); |
5766 | } else if (target->isKind(ParseNodeKind::AssignExpr)) { |
5767 | BinaryNode* assignNode = &target->as<BinaryNode>(); |
5768 | if (assignNode->left()->is<NameNode>()) { |
5769 | nameNode = &assignNode->left()->as<NameNode>(); |
5770 | } |
5771 | } |
5772 | |
5773 | if (nameNode) { |
5774 | auto nameAtom = nameNode->name(); |
5775 | NameOpEmitter noe(this, nameAtom, NameOpEmitter::Kind::Initialize); |
5776 | if (!noe.prepareForRhs()) { |
5777 | return false; |
5778 | } |
5779 | if (noe.emittedBindOp()) { |
5780 | // Per-iteration initialization in for-in/of loops computes the |
5781 | // iteration value *before* initializing. Thus the initializing |
5782 | // value may be buried under a bind-specific value on the stack. |
5783 | // Swap it to the top of the stack. |
5784 | MOZ_ASSERT(bytecodeSection().stackDepth() >= 2)do { static_assert( mozilla::detail::AssertionConditionType< decltype(bytecodeSection().stackDepth() >= 2)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(bytecodeSection().stackDepth() >= 2))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("bytecodeSection().stackDepth() >= 2" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5784); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() >= 2" ")"); do { *((volatile int*)__null) = 5784; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5785 | if (!emit1(JSOp::Swap)) { |
5786 | return false; |
5787 | } |
5788 | } else { |
5789 | // In cases of emitting a frame slot or environment slot, |
5790 | // nothing needs be done. |
5791 | MOZ_ASSERT(bytecodeSection().stackDepth() >= 1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(bytecodeSection().stackDepth() >= 1)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(bytecodeSection().stackDepth() >= 1))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("bytecodeSection().stackDepth() >= 1" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5791); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() >= 1" ")"); do { *((volatile int*)__null) = 5791; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5792 | } |
5793 | |
5794 | #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT |
5795 | if (declarationList->isKind(ParseNodeKind::UsingDecl)) { |
5796 | if (!innermostEmitterScope()->prepareForDisposableAssignment( |
5797 | UsingHint::Sync)) { |
5798 | // [stack] ENV? V |
5799 | return false; |
5800 | } |
5801 | } else if (declarationList->isKind(ParseNodeKind::AwaitUsingDecl)) { |
5802 | if (!innermostEmitterScope()->prepareForDisposableAssignment( |
5803 | UsingHint::Async)) { |
5804 | // [stack] ENV? V |
5805 | return false; |
5806 | } |
5807 | } |
5808 | #endif |
5809 | |
5810 | if (!noe.emitAssignment()) { |
5811 | return false; |
5812 | } |
5813 | |
5814 | // The caller handles removing the iteration value from the stack. |
5815 | return true; |
5816 | } |
5817 | |
5818 | MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType< decltype(!target->isKind(ParseNodeKind::AssignExpr))>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!target->isKind(ParseNodeKind::AssignExpr)))), 0) )) { do { } while (false); MOZ_ReportAssertionFailure("!target->isKind(ParseNodeKind::AssignExpr)" " (" "for-in/of loop destructuring declarations can't have initializers" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5820); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!target->isKind(ParseNodeKind::AssignExpr)" ") (" "for-in/of loop destructuring declarations can't have initializers" ")"); do { *((volatile int*)__null) = 5820; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
5819 | !target->isKind(ParseNodeKind::AssignExpr),do { static_assert( mozilla::detail::AssertionConditionType< decltype(!target->isKind(ParseNodeKind::AssignExpr))>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!target->isKind(ParseNodeKind::AssignExpr)))), 0) )) { do { } while (false); MOZ_ReportAssertionFailure("!target->isKind(ParseNodeKind::AssignExpr)" " (" "for-in/of loop destructuring declarations can't have initializers" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5820); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!target->isKind(ParseNodeKind::AssignExpr)" ") (" "for-in/of loop destructuring declarations can't have initializers" ")"); do { *((volatile int*)__null) = 5820; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
5820 | "for-in/of loop destructuring declarations can't have initializers")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!target->isKind(ParseNodeKind::AssignExpr))>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!target->isKind(ParseNodeKind::AssignExpr)))), 0) )) { do { } while (false); MOZ_ReportAssertionFailure("!target->isKind(ParseNodeKind::AssignExpr)" " (" "for-in/of loop destructuring declarations can't have initializers" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5820); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!target->isKind(ParseNodeKind::AssignExpr)" ") (" "for-in/of loop destructuring declarations can't have initializers" ")"); do { *((volatile int*)__null) = 5820; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5821 | |
5822 | MOZ_ASSERT(target->isKind(ParseNodeKind::ArrayExpr) ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(target->isKind(ParseNodeKind::ArrayExpr) || target ->isKind(ParseNodeKind::ObjectExpr))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(target->isKind(ParseNodeKind ::ArrayExpr) || target->isKind(ParseNodeKind::ObjectExpr)) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("target->isKind(ParseNodeKind::ArrayExpr) || target->isKind(ParseNodeKind::ObjectExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5823); AnnotateMozCrashReason("MOZ_ASSERT" "(" "target->isKind(ParseNodeKind::ArrayExpr) || target->isKind(ParseNodeKind::ObjectExpr)" ")"); do { *((volatile int*)__null) = 5823; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
5823 | target->isKind(ParseNodeKind::ObjectExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(target->isKind(ParseNodeKind::ArrayExpr) || target ->isKind(ParseNodeKind::ObjectExpr))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(target->isKind(ParseNodeKind ::ArrayExpr) || target->isKind(ParseNodeKind::ObjectExpr)) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("target->isKind(ParseNodeKind::ArrayExpr) || target->isKind(ParseNodeKind::ObjectExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5823); AnnotateMozCrashReason("MOZ_ASSERT" "(" "target->isKind(ParseNodeKind::ArrayExpr) || target->isKind(ParseNodeKind::ObjectExpr)" ")"); do { *((volatile int*)__null) = 5823; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5824 | return emitDestructuringOps(&target->as<ListNode>(), |
5825 | DestructuringFlavor::Declaration); |
5826 | } |
5827 | |
5828 | bool BytecodeEmitter::emitForOf(ForNode* forOfLoop, |
5829 | const EmitterScope* headLexicalEmitterScope) { |
5830 | MOZ_ASSERT(forOfLoop->isKind(ParseNodeKind::ForStmt))do { static_assert( mozilla::detail::AssertionConditionType< decltype(forOfLoop->isKind(ParseNodeKind::ForStmt))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(forOfLoop->isKind(ParseNodeKind::ForStmt)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("forOfLoop->isKind(ParseNodeKind::ForStmt)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5830); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfLoop->isKind(ParseNodeKind::ForStmt)" ")"); do { *((volatile int*)__null) = 5830; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5831 | |
5832 | TernaryNode* forOfHead = forOfLoop->head(); |
5833 | MOZ_ASSERT(forOfHead->isKind(ParseNodeKind::ForOf))do { static_assert( mozilla::detail::AssertionConditionType< decltype(forOfHead->isKind(ParseNodeKind::ForOf))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(forOfHead->isKind(ParseNodeKind::ForOf)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("forOfHead->isKind(ParseNodeKind::ForOf)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5833); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfHead->isKind(ParseNodeKind::ForOf)" ")"); do { *((volatile int*)__null) = 5833; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5834 | |
5835 | unsigned iflags = forOfLoop->iflags(); |
5836 | IteratorKind iterKind = |
5837 | (iflags & JSITER_FORAWAITOF0x80) ? IteratorKind::Async : IteratorKind::Sync; |
5838 | MOZ_ASSERT_IF(iterKind == IteratorKind::Async, sc->isSuspendableContext())do { if (iterKind == IteratorKind::Async) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(sc-> isSuspendableContext())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(sc->isSuspendableContext( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("sc->isSuspendableContext()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5838); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isSuspendableContext()" ")"); do { *((volatile int*)__null) = 5838; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
5839 | MOZ_ASSERT_IF(iterKind == IteratorKind::Async,do { if (iterKind == IteratorKind::Async) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(sc-> asSuspendableContext()->isAsync())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(sc->asSuspendableContext( )->isAsync()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("sc->asSuspendableContext()->isAsync()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5840); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->asSuspendableContext()->isAsync()" ")"); do { *((volatile int*)__null) = 5840; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
5840 | sc->asSuspendableContext()->isAsync())do { if (iterKind == IteratorKind::Async) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(sc-> asSuspendableContext()->isAsync())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(sc->asSuspendableContext( )->isAsync()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("sc->asSuspendableContext()->isAsync()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5840); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->asSuspendableContext()->isAsync()" ")"); do { *((volatile int*)__null) = 5840; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
5841 | |
5842 | ParseNode* forHeadExpr = forOfHead->kid3(); |
5843 | |
5844 | // Certain builtins (e.g. Array.from) are implemented in self-hosting |
5845 | // as for-of loops. |
5846 | auto selfHostedIter = getSelfHostedIterFor(forHeadExpr); |
5847 | ForOfEmitter forOf( |
5848 | this, headLexicalEmitterScope, selfHostedIter, iterKind |
5849 | #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT |
5850 | , |
5851 | forOfHead->kid1()->isKind(ParseNodeKind::UsingDecl) || |
5852 | forOfHead->kid1()->isKind(ParseNodeKind::AwaitUsingDecl) |
5853 | ? ForOfEmitter::HasUsingDeclarationInHead::Yes |
5854 | : ForOfEmitter::HasUsingDeclarationInHead::No |
5855 | #endif |
5856 | ); |
5857 | |
5858 | if (!forOf.emitIterated()) { |
5859 | // [stack] |
5860 | return false; |
5861 | } |
5862 | |
5863 | if (!updateSourceCoordNotes(forHeadExpr->pn_pos.begin)) { |
5864 | return false; |
5865 | } |
5866 | if (!markStepBreakpoint()) { |
5867 | return false; |
5868 | } |
5869 | if (!emitIterable(forHeadExpr, selfHostedIter, iterKind)) { |
5870 | // [stack] ITERABLE |
5871 | return false; |
5872 | } |
5873 | |
5874 | if (headLexicalEmitterScope) { |
5875 | DebugOnly<ParseNode*> forOfTarget = forOfHead->kid1(); |
5876 | MOZ_ASSERT(forOfTarget->isKind(ParseNodeKind::LetDecl) ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget ->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget ->isKind(ParseNodeKind::AwaitUsingDecl)endif)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget ->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget ->isKind(ParseNodeKind::AwaitUsingDecl)endif))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)endif" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5882); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)endif" ")"); do { *((volatile int*)__null) = 5882; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
5877 | forOfTarget->isKind(ParseNodeKind::ConstDecl)do { static_assert( mozilla::detail::AssertionConditionType< decltype(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget ->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget ->isKind(ParseNodeKind::AwaitUsingDecl)endif)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget ->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget ->isKind(ParseNodeKind::AwaitUsingDecl)endif))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)endif" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5882); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)endif" ")"); do { *((volatile int*)__null) = 5882; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
5878 | #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENTdo { static_assert( mozilla::detail::AssertionConditionType< decltype(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget ->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget ->isKind(ParseNodeKind::AwaitUsingDecl)endif)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget ->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget ->isKind(ParseNodeKind::AwaitUsingDecl)endif))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)endif" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5882); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)endif" ")"); do { *((volatile int*)__null) = 5882; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
5879 | || forOfTarget->isKind(ParseNodeKind::UsingDecl) ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget ->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget ->isKind(ParseNodeKind::AwaitUsingDecl)endif)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget ->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget ->isKind(ParseNodeKind::AwaitUsingDecl)endif))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)endif" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5882); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)endif" ")"); do { *((volatile int*)__null) = 5882; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
5880 | forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)do { static_assert( mozilla::detail::AssertionConditionType< decltype(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget ->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget ->isKind(ParseNodeKind::AwaitUsingDecl)endif)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget ->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget ->isKind(ParseNodeKind::AwaitUsingDecl)endif))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)endif" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5882); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)endif" ")"); do { *((volatile int*)__null) = 5882; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
5881 | #endifdo { static_assert( mozilla::detail::AssertionConditionType< decltype(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget ->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget ->isKind(ParseNodeKind::AwaitUsingDecl)endif)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget ->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget ->isKind(ParseNodeKind::AwaitUsingDecl)endif))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)endif" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5882); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)endif" ")"); do { *((volatile int*)__null) = 5882; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
5882 | )do { static_assert( mozilla::detail::AssertionConditionType< decltype(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget ->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget ->isKind(ParseNodeKind::AwaitUsingDecl)endif)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget ->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget ->isKind(ParseNodeKind::AwaitUsingDecl)endif))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)endif" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5882); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl) || forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl)endif" ")"); do { *((volatile int*)__null) = 5882; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5883 | } |
5884 | |
5885 | if (!forOf.emitInitialize(forOfHead->pn_pos.begin)) { |
5886 | // [stack] NEXT ITER VALUE |
5887 | return false; |
5888 | } |
5889 | |
5890 | if (!emitInitializeForInOrOfTarget(forOfHead)) { |
5891 | // [stack] NEXT ITER VALUE |
5892 | return false; |
5893 | } |
5894 | |
5895 | if (!forOf.emitBody()) { |
5896 | // [stack] NEXT ITER UNDEF |
5897 | return false; |
5898 | } |
5899 | |
5900 | // Perform the loop body. |
5901 | ParseNode* forBody = forOfLoop->body(); |
5902 | if (!emitTree(forBody)) { |
5903 | // [stack] NEXT ITER UNDEF |
5904 | return false; |
5905 | } |
5906 | |
5907 | if (!forOf.emitEnd(forHeadExpr->pn_pos.begin)) { |
5908 | // [stack] |
5909 | return false; |
5910 | } |
5911 | |
5912 | return true; |
5913 | } |
5914 | |
5915 | bool BytecodeEmitter::emitForIn(ForNode* forInLoop, |
5916 | const EmitterScope* headLexicalEmitterScope) { |
5917 | TernaryNode* forInHead = forInLoop->head(); |
5918 | MOZ_ASSERT(forInHead->isKind(ParseNodeKind::ForIn))do { static_assert( mozilla::detail::AssertionConditionType< decltype(forInHead->isKind(ParseNodeKind::ForIn))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(forInHead->isKind(ParseNodeKind::ForIn)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("forInHead->isKind(ParseNodeKind::ForIn)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5918); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInHead->isKind(ParseNodeKind::ForIn)" ")"); do { *((volatile int*)__null) = 5918; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5919 | |
5920 | ForInEmitter forIn(this, headLexicalEmitterScope); |
5921 | |
5922 | // Annex B: Evaluate the var-initializer expression if present. |
5923 | // |for (var i = initializer in expr) { ... }| |
5924 | ParseNode* forInTarget = forInHead->kid1(); |
5925 | if (forInTarget->is<DeclarationListNode>()) { |
5926 | auto* declarationList = &forInTarget->as<DeclarationListNode>(); |
5927 | |
5928 | ParseNode* decl = declarationList->singleBinding(); |
5929 | if (decl->isKind(ParseNodeKind::AssignExpr)) { |
5930 | BinaryNode* assignNode = &decl->as<BinaryNode>(); |
5931 | if (assignNode->left()->is<NameNode>()) { |
5932 | NameNode* nameNode = &assignNode->left()->as<NameNode>(); |
5933 | ParseNode* initializer = assignNode->right(); |
5934 | MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType< decltype(forInTarget->isKind(ParseNodeKind::VarStmt))>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(forInTarget->isKind(ParseNodeKind::VarStmt)))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("forInTarget->isKind(ParseNodeKind::VarStmt)" " (" "for-in initializers are only permitted for |var| declarations" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5936); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInTarget->isKind(ParseNodeKind::VarStmt)" ") (" "for-in initializers are only permitted for |var| declarations" ")"); do { *((volatile int*)__null) = 5936; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
5935 | forInTarget->isKind(ParseNodeKind::VarStmt),do { static_assert( mozilla::detail::AssertionConditionType< decltype(forInTarget->isKind(ParseNodeKind::VarStmt))>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(forInTarget->isKind(ParseNodeKind::VarStmt)))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("forInTarget->isKind(ParseNodeKind::VarStmt)" " (" "for-in initializers are only permitted for |var| declarations" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5936); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInTarget->isKind(ParseNodeKind::VarStmt)" ") (" "for-in initializers are only permitted for |var| declarations" ")"); do { *((volatile int*)__null) = 5936; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
5936 | "for-in initializers are only permitted for |var| declarations")do { static_assert( mozilla::detail::AssertionConditionType< decltype(forInTarget->isKind(ParseNodeKind::VarStmt))>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(forInTarget->isKind(ParseNodeKind::VarStmt)))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("forInTarget->isKind(ParseNodeKind::VarStmt)" " (" "for-in initializers are only permitted for |var| declarations" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5936); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInTarget->isKind(ParseNodeKind::VarStmt)" ") (" "for-in initializers are only permitted for |var| declarations" ")"); do { *((volatile int*)__null) = 5936; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5937 | |
5938 | if (!updateSourceCoordNotes(decl->pn_pos.begin)) { |
5939 | return false; |
5940 | } |
5941 | |
5942 | auto nameAtom = nameNode->name(); |
5943 | NameOpEmitter noe(this, nameAtom, NameOpEmitter::Kind::Initialize); |
5944 | if (!noe.prepareForRhs()) { |
5945 | return false; |
5946 | } |
5947 | if (!emitInitializer(initializer, nameNode)) { |
5948 | return false; |
5949 | } |
5950 | if (!noe.emitAssignment()) { |
5951 | return false; |
5952 | } |
5953 | |
5954 | // Pop the initializer. |
5955 | if (!emit1(JSOp::Pop)) { |
5956 | return false; |
5957 | } |
5958 | } |
5959 | } |
5960 | } |
5961 | |
5962 | if (!forIn.emitIterated()) { |
5963 | // [stack] |
5964 | return false; |
5965 | } |
5966 | |
5967 | // Evaluate the expression being iterated. |
5968 | ParseNode* expr = forInHead->kid3(); |
5969 | |
5970 | if (!updateSourceCoordNotes(expr->pn_pos.begin)) { |
5971 | return false; |
5972 | } |
5973 | if (!markStepBreakpoint()) { |
5974 | return false; |
5975 | } |
5976 | if (!emitTree(expr)) { |
5977 | // [stack] EXPR |
5978 | return false; |
5979 | } |
5980 | |
5981 | MOZ_ASSERT(forInLoop->iflags() == 0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(forInLoop->iflags() == 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(forInLoop->iflags() == 0) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("forInLoop->iflags() == 0" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5981); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInLoop->iflags() == 0" ")"); do { *((volatile int*)__null) = 5981; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5982 | |
5983 | MOZ_ASSERT_IF(headLexicalEmitterScope,do { if (headLexicalEmitterScope) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(forInTarget-> isKind(ParseNodeKind::LetDecl) || forInTarget->isKind(ParseNodeKind ::ConstDecl))>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(forInTarget->isKind(ParseNodeKind ::LetDecl) || forInTarget->isKind(ParseNodeKind::ConstDecl )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("forInTarget->isKind(ParseNodeKind::LetDecl) || forInTarget->isKind(ParseNodeKind::ConstDecl)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5985); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInTarget->isKind(ParseNodeKind::LetDecl) || forInTarget->isKind(ParseNodeKind::ConstDecl)" ")"); do { *((volatile int*)__null) = 5985; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
5984 | forInTarget->isKind(ParseNodeKind::LetDecl) ||do { if (headLexicalEmitterScope) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(forInTarget-> isKind(ParseNodeKind::LetDecl) || forInTarget->isKind(ParseNodeKind ::ConstDecl))>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(forInTarget->isKind(ParseNodeKind ::LetDecl) || forInTarget->isKind(ParseNodeKind::ConstDecl )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("forInTarget->isKind(ParseNodeKind::LetDecl) || forInTarget->isKind(ParseNodeKind::ConstDecl)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5985); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInTarget->isKind(ParseNodeKind::LetDecl) || forInTarget->isKind(ParseNodeKind::ConstDecl)" ")"); do { *((volatile int*)__null) = 5985; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
5985 | forInTarget->isKind(ParseNodeKind::ConstDecl))do { if (headLexicalEmitterScope) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(forInTarget-> isKind(ParseNodeKind::LetDecl) || forInTarget->isKind(ParseNodeKind ::ConstDecl))>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(forInTarget->isKind(ParseNodeKind ::LetDecl) || forInTarget->isKind(ParseNodeKind::ConstDecl )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("forInTarget->isKind(ParseNodeKind::LetDecl) || forInTarget->isKind(ParseNodeKind::ConstDecl)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5985); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInTarget->isKind(ParseNodeKind::LetDecl) || forInTarget->isKind(ParseNodeKind::ConstDecl)" ")"); do { *((volatile int*)__null) = 5985; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
5986 | |
5987 | if (!forIn.emitInitialize()) { |
5988 | // [stack] ITER ITERVAL |
5989 | return false; |
5990 | } |
5991 | |
5992 | if (!emitInitializeForInOrOfTarget(forInHead)) { |
5993 | // [stack] ITER ITERVAL |
5994 | return false; |
5995 | } |
5996 | |
5997 | if (!forIn.emitBody()) { |
5998 | // [stack] ITER ITERVAL |
5999 | return false; |
6000 | } |
6001 | |
6002 | // Perform the loop body. |
6003 | ParseNode* forBody = forInLoop->body(); |
6004 | if (!emitTree(forBody)) { |
6005 | // [stack] ITER ITERVAL |
6006 | return false; |
6007 | } |
6008 | |
6009 | if (!forIn.emitEnd(forInHead->pn_pos.begin)) { |
6010 | // [stack] |
6011 | return false; |
6012 | } |
6013 | |
6014 | return true; |
6015 | } |
6016 | |
6017 | /* C-style `for (init; cond; update) ...` loop. */ |
6018 | bool BytecodeEmitter::emitCStyleFor( |
6019 | ForNode* forNode, const EmitterScope* headLexicalEmitterScope) { |
6020 | TernaryNode* forHead = forNode->head(); |
6021 | ParseNode* forBody = forNode->body(); |
6022 | ParseNode* init = forHead->kid1(); |
6023 | ParseNode* cond = forHead->kid2(); |
6024 | ParseNode* update = forHead->kid3(); |
6025 | bool isLet = init && init->isKind(ParseNodeKind::LetDecl); |
6026 | |
6027 | CForEmitter cfor(this, isLet ? headLexicalEmitterScope : nullptr); |
6028 | |
6029 | if (!cfor.emitInit(init ? Some(init->pn_pos.begin) : Nothing())) { |
6030 | // [stack] |
6031 | return false; |
6032 | } |
6033 | |
6034 | // If the head of this for-loop declared any lexical variables, the parser |
6035 | // wrapped this ParseNodeKind::For node in a ParseNodeKind::LexicalScope |
6036 | // representing the implicit scope of those variables. By the time we get |
6037 | // here, we have already entered that scope. So far, so good. |
6038 | if (init) { |
6039 | // Emit the `init` clause, whether it's an expression or a variable |
6040 | // declaration. (The loop variables were hoisted into an enclosing |
6041 | // scope, but we still need to emit code for the initializers.) |
6042 | if (init->is<DeclarationListNode>()) { |
6043 | MOZ_ASSERT(!init->as<DeclarationListNode>().empty())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!init->as<DeclarationListNode>().empty())> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!init->as<DeclarationListNode>().empty()))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("!init->as<DeclarationListNode>().empty()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6043); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!init->as<DeclarationListNode>().empty()" ")"); do { *((volatile int*)__null) = 6043; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6044 | |
6045 | if (!emitTree(init)) { |
6046 | // [stack] |
6047 | return false; |
6048 | } |
6049 | } else { |
6050 | if (!updateSourceCoordNotes(init->pn_pos.begin)) { |
6051 | return false; |
6052 | } |
6053 | if (!markStepBreakpoint()) { |
6054 | return false; |
6055 | } |
6056 | |
6057 | // 'init' is an expression, not a declaration. emitTree left its |
6058 | // value on the stack. |
6059 | if (!emitTree(init, ValueUsage::IgnoreValue)) { |
6060 | // [stack] VAL |
6061 | return false; |
6062 | } |
6063 | if (!emit1(JSOp::Pop)) { |
6064 | // [stack] |
6065 | return false; |
6066 | } |
6067 | } |
6068 | } |
6069 | |
6070 | if (!cfor.emitCond(cond ? Some(cond->pn_pos.begin) : Nothing())) { |
6071 | // [stack] |
6072 | return false; |
6073 | } |
6074 | |
6075 | if (cond) { |
6076 | if (!updateSourceCoordNotes(cond->pn_pos.begin)) { |
6077 | return false; |
6078 | } |
6079 | if (!markStepBreakpoint()) { |
6080 | return false; |
6081 | } |
6082 | if (!emitTree(cond)) { |
6083 | // [stack] VAL |
6084 | return false; |
6085 | } |
6086 | } |
6087 | |
6088 | if (!cfor.emitBody(cond ? CForEmitter::Cond::Present |
6089 | : CForEmitter::Cond::Missing)) { |
6090 | // [stack] |
6091 | return false; |
6092 | } |
6093 | |
6094 | if (!emitTree(forBody)) { |
6095 | // [stack] |
6096 | return false; |
6097 | } |
6098 | |
6099 | if (!cfor.emitUpdate( |
6100 | update ? CForEmitter::Update::Present : CForEmitter::Update::Missing, |
6101 | update ? Some(update->pn_pos.begin) : Nothing())) { |
6102 | // [stack] |
6103 | return false; |
6104 | } |
6105 | |
6106 | // Check for update code to do before the condition (if any). |
6107 | if (update) { |
6108 | if (!updateSourceCoordNotes(update->pn_pos.begin)) { |
6109 | return false; |
6110 | } |
6111 | if (!markStepBreakpoint()) { |
6112 | return false; |
6113 | } |
6114 | if (!emitTree(update, ValueUsage::IgnoreValue)) { |
6115 | // [stack] VAL |
6116 | return false; |
6117 | } |
6118 | } |
6119 | |
6120 | if (!cfor.emitEnd(forNode->pn_pos.begin)) { |
6121 | // [stack] |
6122 | return false; |
6123 | } |
6124 | |
6125 | return true; |
6126 | } |
6127 | |
6128 | bool BytecodeEmitter::emitFor(ForNode* forNode, |
6129 | const EmitterScope* headLexicalEmitterScope) { |
6130 | if (forNode->head()->isKind(ParseNodeKind::ForHead)) { |
6131 | return emitCStyleFor(forNode, headLexicalEmitterScope); |
6132 | } |
6133 | |
6134 | if (!updateLineNumberNotes(forNode->pn_pos.begin)) { |
6135 | return false; |
6136 | } |
6137 | |
6138 | if (forNode->head()->isKind(ParseNodeKind::ForIn)) { |
6139 | return emitForIn(forNode, headLexicalEmitterScope); |
6140 | } |
6141 | |
6142 | MOZ_ASSERT(forNode->head()->isKind(ParseNodeKind::ForOf))do { static_assert( mozilla::detail::AssertionConditionType< decltype(forNode->head()->isKind(ParseNodeKind::ForOf)) >::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(forNode->head()->isKind(ParseNodeKind::ForOf)) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("forNode->head()->isKind(ParseNodeKind::ForOf)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6142); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forNode->head()->isKind(ParseNodeKind::ForOf)" ")"); do { *((volatile int*)__null) = 6142; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6143 | return emitForOf(forNode, headLexicalEmitterScope); |
6144 | } |
6145 | |
6146 | MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitFunction( |
6147 | FunctionNode* funNode, bool needsProto /* = false */) { |
6148 | FunctionBox* funbox = funNode->funbox(); |
6149 | |
6150 | // [stack] |
6151 | |
6152 | FunctionEmitter fe(this, funbox, funNode->syntaxKind(), |
6153 | funNode->functionIsHoisted() |
6154 | ? FunctionEmitter::IsHoisted::Yes |
6155 | : FunctionEmitter::IsHoisted::No); |
6156 | |
6157 | // |wasEmittedByEnclosingScript| flag is set to true once the function has |
6158 | // been emitted. Function definitions that need hoisting to the top of the |
6159 | // function will be seen by emitFunction in two places. |
6160 | if (funbox->wasEmittedByEnclosingScript()) { |
6161 | if (!fe.emitAgain()) { |
6162 | // [stack] |
6163 | return false; |
6164 | } |
6165 | MOZ_ASSERT(funNode->functionIsHoisted())do { static_assert( mozilla::detail::AssertionConditionType< decltype(funNode->functionIsHoisted())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(funNode->functionIsHoisted ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("funNode->functionIsHoisted()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6165); AnnotateMozCrashReason("MOZ_ASSERT" "(" "funNode->functionIsHoisted()" ")"); do { *((volatile int*)__null) = 6165; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6166 | } else if (funbox->isInterpreted()) { |
6167 | if (!funbox->emitBytecode) { |
6168 | return fe.emitLazy(); |
6169 | // [stack] FUN? |
6170 | } |
6171 | |
6172 | if (!fe.prepareForNonLazy()) { |
6173 | // [stack] |
6174 | return false; |
6175 | } |
6176 | |
6177 | BytecodeEmitter bce2(this, funbox); |
6178 | if (!bce2.init(funNode->pn_pos)) { |
6179 | return false; |
6180 | } |
6181 | |
6182 | /* We measured the max scope depth when we parsed the function. */ |
6183 | if (!bce2.emitFunctionScript(funNode)) { |
6184 | return false; |
6185 | } |
6186 | |
6187 | if (!fe.emitNonLazyEnd()) { |
6188 | // [stack] FUN? |
6189 | return false; |
6190 | } |
6191 | } else { |
6192 | if (!fe.emitAsmJSModule()) { |
6193 | // [stack] |
6194 | return false; |
6195 | } |
6196 | } |
6197 | |
6198 | // Track the last emitted top-level self-hosted function, so that intrinsics |
6199 | // can adjust attributes at parse time. |
6200 | // |
6201 | // NOTE: We also disallow lambda functions in the top-level body. This is done |
6202 | // to simplify handling of the self-hosted stencil. Within normal function |
6203 | // declarations there are no such restrictions. |
6204 | if (emitterMode == EmitterMode::SelfHosting) { |
6205 | if (sc->isTopLevelContext()) { |
6206 | MOZ_ASSERT(!funbox->isLambda())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!funbox->isLambda())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!funbox->isLambda()))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("!funbox->isLambda()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6206); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!funbox->isLambda()" ")"); do { *((volatile int*)__null) = 6206; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6207 | MOZ_ASSERT(funbox->explicitName())do { static_assert( mozilla::detail::AssertionConditionType< decltype(funbox->explicitName())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(funbox->explicitName()))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("funbox->explicitName()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6207); AnnotateMozCrashReason("MOZ_ASSERT" "(" "funbox->explicitName()" ")"); do { *((volatile int*)__null) = 6207; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6208 | prevSelfHostedTopLevelFunction = funbox; |
6209 | } |
6210 | } |
6211 | |
6212 | return true; |
6213 | } |
6214 | |
6215 | bool BytecodeEmitter::emitDo(BinaryNode* doNode) { |
6216 | ParseNode* bodyNode = doNode->left(); |
6217 | |
6218 | DoWhileEmitter doWhile(this); |
6219 | if (!doWhile.emitBody(doNode->pn_pos.begin, getOffsetForLoop(bodyNode))) { |
6220 | return false; |
6221 | } |
6222 | |
6223 | if (!emitTree(bodyNode)) { |
6224 | return false; |
6225 | } |
6226 | |
6227 | if (!doWhile.emitCond()) { |
6228 | return false; |
6229 | } |
6230 | |
6231 | ParseNode* condNode = doNode->right(); |
6232 | if (!updateSourceCoordNotes(condNode->pn_pos.begin)) { |
6233 | return false; |
6234 | } |
6235 | if (!markStepBreakpoint()) { |
6236 | return false; |
6237 | } |
6238 | if (!emitTree(condNode)) { |
6239 | return false; |
6240 | } |
6241 | |
6242 | if (!doWhile.emitEnd()) { |
6243 | return false; |
6244 | } |
6245 | |
6246 | return true; |
6247 | } |
6248 | |
6249 | bool BytecodeEmitter::emitWhile(BinaryNode* whileNode) { |
6250 | ParseNode* bodyNode = whileNode->right(); |
6251 | |
6252 | WhileEmitter wh(this); |
6253 | |
6254 | ParseNode* condNode = whileNode->left(); |
6255 | if (!wh.emitCond(whileNode->pn_pos.begin, getOffsetForLoop(condNode), |
6256 | whileNode->pn_pos.end)) { |
6257 | return false; |
6258 | } |
6259 | |
6260 | if (!updateSourceCoordNotes(condNode->pn_pos.begin)) { |
6261 | return false; |
6262 | } |
6263 | if (!markStepBreakpoint()) { |
6264 | return false; |
6265 | } |
6266 | if (!emitTree(condNode)) { |
6267 | return false; |
6268 | } |
6269 | |
6270 | if (!wh.emitBody()) { |
6271 | return false; |
6272 | } |
6273 | if (!emitTree(bodyNode)) { |
6274 | return false; |
6275 | } |
6276 | |
6277 | if (!wh.emitEnd()) { |
6278 | return false; |
6279 | } |
6280 | |
6281 | return true; |
6282 | } |
6283 | |
6284 | bool BytecodeEmitter::emitBreak(TaggedParserAtomIndex label) { |
6285 | BreakableControl* target; |
6286 | if (label) { |
6287 | // Any statement with the matching label may be the break target. |
6288 | auto hasSameLabel = [label](LabelControl* labelControl) { |
6289 | return labelControl->label() == label; |
6290 | }; |
6291 | target = findInnermostNestableControl<LabelControl>(hasSameLabel); |
6292 | } else { |
6293 | auto isNotLabel = [](BreakableControl* control) { |
6294 | return !control->is<LabelControl>(); |
6295 | }; |
6296 | target = findInnermostNestableControl<BreakableControl>(isNotLabel); |
6297 | } |
6298 | |
6299 | return emitGoto(target, GotoKind::Break); |
6300 | } |
6301 | |
6302 | bool BytecodeEmitter::emitContinue(TaggedParserAtomIndex label) { |
6303 | LoopControl* target = nullptr; |
6304 | if (label) { |
6305 | // Find the loop statement enclosed by the matching label. |
6306 | NestableControl* control = innermostNestableControl; |
6307 | while (!control->is<LabelControl>() || |
6308 | control->as<LabelControl>().label() != label) { |
6309 | if (control->is<LoopControl>()) { |
6310 | target = &control->as<LoopControl>(); |
6311 | } |
6312 | control = control->enclosing(); |
6313 | } |
6314 | } else { |
6315 | target = findInnermostNestableControl<LoopControl>(); |
6316 | } |
6317 | return emitGoto(target, GotoKind::Continue); |
6318 | } |
6319 | |
6320 | bool BytecodeEmitter::emitGetFunctionThis(NameNode* thisName) { |
6321 | MOZ_ASSERT(sc->hasFunctionThisBinding())do { static_assert( mozilla::detail::AssertionConditionType< decltype(sc->hasFunctionThisBinding())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(sc->hasFunctionThisBinding ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("sc->hasFunctionThisBinding()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6321); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->hasFunctionThisBinding()" ")"); do { *((volatile int*)__null) = 6321; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6322 | MOZ_ASSERT(thisName->isName(TaggedParserAtomIndex::WellKnown::dot_this_()))do { static_assert( mozilla::detail::AssertionConditionType< decltype(thisName->isName(TaggedParserAtomIndex::WellKnown ::dot_this_()))>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(thisName->isName(TaggedParserAtomIndex ::WellKnown::dot_this_())))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("thisName->isName(TaggedParserAtomIndex::WellKnown::dot_this_())" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6322); AnnotateMozCrashReason("MOZ_ASSERT" "(" "thisName->isName(TaggedParserAtomIndex::WellKnown::dot_this_())" ")"); do { *((volatile int*)__null) = 6322; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6323 | |
6324 | if (!updateLineNumberNotes(thisName->pn_pos.begin)) { |
6325 | return false; |
6326 | } |
6327 | |
6328 | if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_this_())) { |
6329 | // [stack] THIS |
6330 | return false; |
6331 | } |
6332 | if (sc->needsThisTDZChecks()) { |
6333 | if (!emit1(JSOp::CheckThis)) { |
6334 | // [stack] THIS |
6335 | return false; |
6336 | } |
6337 | } |
6338 | |
6339 | return true; |
6340 | } |
6341 | |
6342 | bool BytecodeEmitter::emitGetThisForSuperBase(UnaryNode* superBase) { |
6343 | MOZ_ASSERT(superBase->isKind(ParseNodeKind::SuperBase))do { static_assert( mozilla::detail::AssertionConditionType< decltype(superBase->isKind(ParseNodeKind::SuperBase))>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(superBase->isKind(ParseNodeKind::SuperBase)))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("superBase->isKind(ParseNodeKind::SuperBase)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6343); AnnotateMozCrashReason("MOZ_ASSERT" "(" "superBase->isKind(ParseNodeKind::SuperBase)" ")"); do { *((volatile int*)__null) = 6343; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6344 | NameNode* nameNode = &superBase->kid()->as<NameNode>(); |
6345 | return emitGetFunctionThis(nameNode); |
6346 | // [stack] THIS |
6347 | } |
6348 | |
6349 | bool BytecodeEmitter::emitThisLiteral(ThisLiteral* pn) { |
6350 | if (ParseNode* kid = pn->kid()) { |
6351 | NameNode* thisName = &kid->as<NameNode>(); |
6352 | return emitGetFunctionThis(thisName); |
6353 | // [stack] THIS |
6354 | } |
6355 | |
6356 | if (sc->thisBinding() == ThisBinding::Module) { |
6357 | return emit1(JSOp::Undefined); |
6358 | // [stack] UNDEF |
6359 | } |
6360 | |
6361 | MOZ_ASSERT(sc->thisBinding() == ThisBinding::Global)do { static_assert( mozilla::detail::AssertionConditionType< decltype(sc->thisBinding() == ThisBinding::Global)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(sc->thisBinding() == ThisBinding::Global))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("sc->thisBinding() == ThisBinding::Global" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6361); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->thisBinding() == ThisBinding::Global" ")"); do { *((volatile int*)__null) = 6361; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6362 | |
6363 | MOZ_ASSERT(outermostScope().hasNonSyntacticScopeOnChain() ==do { static_assert( mozilla::detail::AssertionConditionType< decltype(outermostScope().hasNonSyntacticScopeOnChain() == sc ->hasNonSyntacticScope())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(outermostScope().hasNonSyntacticScopeOnChain () == sc->hasNonSyntacticScope()))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("outermostScope().hasNonSyntacticScopeOnChain() == sc->hasNonSyntacticScope()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6364); AnnotateMozCrashReason("MOZ_ASSERT" "(" "outermostScope().hasNonSyntacticScopeOnChain() == sc->hasNonSyntacticScope()" ")"); do { *((volatile int*)__null) = 6364; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
6364 | sc->hasNonSyntacticScope())do { static_assert( mozilla::detail::AssertionConditionType< decltype(outermostScope().hasNonSyntacticScopeOnChain() == sc ->hasNonSyntacticScope())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(outermostScope().hasNonSyntacticScopeOnChain () == sc->hasNonSyntacticScope()))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("outermostScope().hasNonSyntacticScopeOnChain() == sc->hasNonSyntacticScope()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6364); AnnotateMozCrashReason("MOZ_ASSERT" "(" "outermostScope().hasNonSyntacticScopeOnChain() == sc->hasNonSyntacticScope()" ")"); do { *((volatile int*)__null) = 6364; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6365 | if (sc->hasNonSyntacticScope()) { |
6366 | return emit1(JSOp::NonSyntacticGlobalThis); |
6367 | // [stack] THIS |
6368 | } |
6369 | |
6370 | return emit1(JSOp::GlobalThis); |
6371 | // [stack] THIS |
6372 | } |
6373 | |
6374 | bool BytecodeEmitter::emitCheckDerivedClassConstructorReturn() { |
6375 | MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType< decltype(lookupName(TaggedParserAtomIndex::WellKnown::dot_this_ ()).hasKnownSlot())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(lookupName(TaggedParserAtomIndex ::WellKnown::dot_this_()).hasKnownSlot()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("lookupName(TaggedParserAtomIndex::WellKnown::dot_this_()).hasKnownSlot()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6376); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lookupName(TaggedParserAtomIndex::WellKnown::dot_this_()).hasKnownSlot()" ")"); do { *((volatile int*)__null) = 6376; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
6376 | lookupName(TaggedParserAtomIndex::WellKnown::dot_this_()).hasKnownSlot())do { static_assert( mozilla::detail::AssertionConditionType< decltype(lookupName(TaggedParserAtomIndex::WellKnown::dot_this_ ()).hasKnownSlot())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(lookupName(TaggedParserAtomIndex ::WellKnown::dot_this_()).hasKnownSlot()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("lookupName(TaggedParserAtomIndex::WellKnown::dot_this_()).hasKnownSlot()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6376); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lookupName(TaggedParserAtomIndex::WellKnown::dot_this_()).hasKnownSlot()" ")"); do { *((volatile int*)__null) = 6376; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6377 | if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_this_())) { |
6378 | return false; |
6379 | } |
6380 | if (!emit1(JSOp::CheckReturn)) { |
6381 | return false; |
6382 | } |
6383 | if (!emit1(JSOp::SetRval)) { |
6384 | return false; |
6385 | } |
6386 | return true; |
6387 | } |
6388 | |
6389 | bool BytecodeEmitter::emitNewTarget() { |
6390 | MOZ_ASSERT(sc->allowNewTarget())do { static_assert( mozilla::detail::AssertionConditionType< decltype(sc->allowNewTarget())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(sc->allowNewTarget()))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("sc->allowNewTarget()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6390); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->allowNewTarget()" ")"); do { *((volatile int*)__null) = 6390; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6391 | |
6392 | if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_newTarget_())) { |
6393 | // [stack] NEW.TARGET |
6394 | return false; |
6395 | } |
6396 | return true; |
6397 | } |
6398 | |
6399 | bool BytecodeEmitter::emitNewTarget(NewTargetNode* pn) { |
6400 | MOZ_ASSERT(pn->newTargetName()->isName(do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->newTargetName()->isName( TaggedParserAtomIndex ::WellKnown::dot_newTarget_()))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->newTargetName()->isName ( TaggedParserAtomIndex::WellKnown::dot_newTarget_())))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("pn->newTargetName()->isName( TaggedParserAtomIndex::WellKnown::dot_newTarget_())" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6401); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->newTargetName()->isName( TaggedParserAtomIndex::WellKnown::dot_newTarget_())" ")"); do { *((volatile int*)__null) = 6401; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
6401 | TaggedParserAtomIndex::WellKnown::dot_newTarget_()))do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->newTargetName()->isName( TaggedParserAtomIndex ::WellKnown::dot_newTarget_()))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->newTargetName()->isName ( TaggedParserAtomIndex::WellKnown::dot_newTarget_())))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("pn->newTargetName()->isName( TaggedParserAtomIndex::WellKnown::dot_newTarget_())" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6401); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->newTargetName()->isName( TaggedParserAtomIndex::WellKnown::dot_newTarget_())" ")"); do { *((volatile int*)__null) = 6401; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6402 | |
6403 | return emitNewTarget(); |
6404 | } |
6405 | |
6406 | bool BytecodeEmitter::emitNewTarget(CallNode* pn) { |
6407 | MOZ_ASSERT(pn->callOp() == JSOp::SuperCall ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->callOp() == JSOp::SuperCall || pn->callOp( ) == JSOp::SpreadSuperCall)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->callOp() == JSOp::SuperCall || pn->callOp() == JSOp::SpreadSuperCall))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("pn->callOp() == JSOp::SuperCall || pn->callOp() == JSOp::SpreadSuperCall" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6408); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->callOp() == JSOp::SuperCall || pn->callOp() == JSOp::SpreadSuperCall" ")"); do { *((volatile int*)__null) = 6408; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
6408 | pn->callOp() == JSOp::SpreadSuperCall)do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->callOp() == JSOp::SuperCall || pn->callOp( ) == JSOp::SpreadSuperCall)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->callOp() == JSOp::SuperCall || pn->callOp() == JSOp::SpreadSuperCall))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("pn->callOp() == JSOp::SuperCall || pn->callOp() == JSOp::SpreadSuperCall" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6408); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->callOp() == JSOp::SuperCall || pn->callOp() == JSOp::SpreadSuperCall" ")"); do { *((volatile int*)__null) = 6408; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6409 | |
6410 | // The parser is responsible for marking the "new.target" binding as being |
6411 | // implicitly used in super() calls. |
6412 | return emitNewTarget(); |
6413 | } |
6414 | |
6415 | bool BytecodeEmitter::emitReturn(UnaryNode* returnNode) { |
6416 | if (!updateSourceCoordNotes(returnNode->pn_pos.begin)) { |
6417 | return false; |
6418 | } |
6419 | |
6420 | if (!markStepBreakpoint()) { |
6421 | return false; |
6422 | } |
6423 | |
6424 | /* Push a return value */ |
6425 | if (ParseNode* expr = returnNode->kid()) { |
6426 | if (!emitTree(expr)) { |
6427 | return false; |
6428 | } |
6429 | |
6430 | if (sc->asSuspendableContext()->isAsync() && |
6431 | sc->asSuspendableContext()->isGenerator()) { |
6432 | if (!emitAwaitInInnermostScope()) { |
6433 | return false; |
6434 | } |
6435 | } |
6436 | } else { |
6437 | /* No explicit return value provided */ |
6438 | if (!emit1(JSOp::Undefined)) { |
6439 | return false; |
6440 | } |
6441 | } |
6442 | |
6443 | // We know functionBodyEndPos is set because "return" is only |
6444 | // valid in a function, and so we've passed through |
6445 | // emitFunctionScript. |
6446 | if (!updateSourceCoordNotes(*functionBodyEndPos)) { |
6447 | return false; |
6448 | } |
6449 | |
6450 | /* |
6451 | * The return value is currently on the stack. We would like to |
6452 | * generate JSOp::Return, but if we have work to do before returning, |
6453 | * we will instead generate JSOp::SetRval / JSOp::RetRval. |
6454 | * |
6455 | * We don't know whether we will need fixup code until after calling |
6456 | * prepareForNonLocalJumpToOutermost, so we start by generating |
6457 | * JSOp::SetRval, then mutate it to JSOp::Return in finishReturn if it |
6458 | * wasn't needed. |
6459 | */ |
6460 | BytecodeOffset setRvalOffset = bytecodeSection().offset(); |
6461 | if (!emit1(JSOp::SetRval)) { |
6462 | return false; |
6463 | } |
6464 | |
6465 | NonLocalExitControl nle(this, NonLocalExitKind::Return); |
6466 | return nle.emitReturn(setRvalOffset); |
6467 | } |
6468 | |
6469 | bool BytecodeEmitter::finishReturn(BytecodeOffset setRvalOffset) { |
6470 | // The return value is currently in rval. Depending on the current function, |
6471 | // we may have to do additional work before returning: |
6472 | // - Derived class constructors must check if the return value is an object. |
6473 | // - Generators and async functions must do a final yield. |
6474 | // - Non-async generators must return the value as an iterator result: |
6475 | // { value: <rval>, done: true } |
6476 | // - Non-generator async functions must resolve the function's result promise |
6477 | // with the value. |
6478 | // |
6479 | // If we have not generated any code since the SetRval that stored the return |
6480 | // value, we can also optimize the bytecode by rewriting that SetRval as a |
6481 | // JSOp::Return. See |emitReturn| above. |
6482 | |
6483 | bool isDerivedClassConstructor = |
6484 | sc->isFunctionBox() && sc->asFunctionBox()->isDerivedClassConstructor(); |
6485 | bool needsFinalYield = |
6486 | sc->isFunctionBox() && sc->asFunctionBox()->needsFinalYield(); |
6487 | bool isSimpleReturn = |
6488 | setRvalOffset.valid() && |
6489 | setRvalOffset + BytecodeOffsetDiff(JSOpLength_SetRval) == |
6490 | bytecodeSection().offset(); |
6491 | |
6492 | if (isDerivedClassConstructor) { |
6493 | MOZ_ASSERT(!needsFinalYield)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!needsFinalYield)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!needsFinalYield))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!needsFinalYield" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6493); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!needsFinalYield" ")"); do { *((volatile int*)__null) = 6493; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6494 | if (!emitJump(JSOp::Goto, &endOfDerivedClassConstructorBody)) { |
6495 | return false; |
6496 | } |
6497 | return true; |
6498 | } |
6499 | |
6500 | if (needsFinalYield) { |
6501 | if (!emitJump(JSOp::Goto, &finalYields)) { |
6502 | return false; |
6503 | } |
6504 | return true; |
6505 | } |
6506 | |
6507 | if (isSimpleReturn) { |
6508 | MOZ_ASSERT(JSOp(bytecodeSection().code()[setRvalOffset.value()]) ==do { static_assert( mozilla::detail::AssertionConditionType< decltype(JSOp(bytecodeSection().code()[setRvalOffset.value()] ) == JSOp::SetRval)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(JSOp(bytecodeSection().code( )[setRvalOffset.value()]) == JSOp::SetRval))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("JSOp(bytecodeSection().code()[setRvalOffset.value()]) == JSOp::SetRval" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6509); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JSOp(bytecodeSection().code()[setRvalOffset.value()]) == JSOp::SetRval" ")"); do { *((volatile int*)__null) = 6509; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
6509 | JSOp::SetRval)do { static_assert( mozilla::detail::AssertionConditionType< decltype(JSOp(bytecodeSection().code()[setRvalOffset.value()] ) == JSOp::SetRval)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(JSOp(bytecodeSection().code( )[setRvalOffset.value()]) == JSOp::SetRval))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("JSOp(bytecodeSection().code()[setRvalOffset.value()]) == JSOp::SetRval" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6509); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JSOp(bytecodeSection().code()[setRvalOffset.value()]) == JSOp::SetRval" ")"); do { *((volatile int*)__null) = 6509; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6510 | bytecodeSection().code()[setRvalOffset.value()] = jsbytecode(JSOp::Return); |
6511 | return true; |
6512 | } |
6513 | |
6514 | // Nothing special needs to be done. |
6515 | return emitReturnRval(); |
6516 | } |
6517 | |
6518 | bool BytecodeEmitter::emitGetDotGeneratorInScope(EmitterScope& currentScope) { |
6519 | if (!sc->isFunction() && sc->isModuleContext() && |
6520 | sc->asModuleContext()->isAsync()) { |
6521 | NameLocation loc = *locationOfNameBoundInScopeType<ModuleScope>( |
6522 | TaggedParserAtomIndex::WellKnown::dot_generator_(), ¤tScope); |
6523 | return emitGetNameAtLocation( |
6524 | TaggedParserAtomIndex::WellKnown::dot_generator_(), loc); |
6525 | } |
6526 | NameLocation loc = *locationOfNameBoundInScopeType<FunctionScope>( |
6527 | TaggedParserAtomIndex::WellKnown::dot_generator_(), ¤tScope); |
6528 | return emitGetNameAtLocation( |
6529 | TaggedParserAtomIndex::WellKnown::dot_generator_(), loc); |
6530 | } |
6531 | |
6532 | bool BytecodeEmitter::emitInitialYield(UnaryNode* yieldNode) { |
6533 | if (!emitTree(yieldNode->kid())) { |
6534 | return false; |
6535 | } |
6536 | |
6537 | if (!emitYieldOp(JSOp::InitialYield)) { |
6538 | // [stack] RVAL GENERATOR RESUMEKIND |
6539 | return false; |
6540 | } |
6541 | if (!emit1(JSOp::CheckResumeKind)) { |
6542 | // [stack] RVAL |
6543 | return false; |
6544 | } |
6545 | if (!emit1(JSOp::Pop)) { |
6546 | // [stack] |
6547 | return false; |
6548 | } |
6549 | |
6550 | return true; |
6551 | } |
6552 | |
6553 | bool BytecodeEmitter::emitYield(UnaryNode* yieldNode) { |
6554 | MOZ_ASSERT(sc->isFunctionBox())do { static_assert( mozilla::detail::AssertionConditionType< decltype(sc->isFunctionBox())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(sc->isFunctionBox()))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("sc->isFunctionBox()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6554); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isFunctionBox()" ")"); do { *((volatile int*)__null) = 6554; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6555 | MOZ_ASSERT(sc->asFunctionBox()->isGenerator())do { static_assert( mozilla::detail::AssertionConditionType< decltype(sc->asFunctionBox()->isGenerator())>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(sc->asFunctionBox()->isGenerator()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("sc->asFunctionBox()->isGenerator()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6555); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->asFunctionBox()->isGenerator()" ")"); do { *((volatile int*)__null) = 6555; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6556 | MOZ_ASSERT(yieldNode->isKind(ParseNodeKind::YieldExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(yieldNode->isKind(ParseNodeKind::YieldExpr))>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(yieldNode->isKind(ParseNodeKind::YieldExpr)))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("yieldNode->isKind(ParseNodeKind::YieldExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6556); AnnotateMozCrashReason("MOZ_ASSERT" "(" "yieldNode->isKind(ParseNodeKind::YieldExpr)" ")"); do { *((volatile int*)__null) = 6556; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6557 | |
6558 | bool needsIteratorResult = sc->asFunctionBox()->needsIteratorResult(); |
6559 | if (needsIteratorResult) { |
6560 | if (!emitPrepareIteratorResult()) { |
6561 | // [stack] ITEROBJ |
6562 | return false; |
6563 | } |
6564 | } |
6565 | if (ParseNode* expr = yieldNode->kid()) { |
6566 | if (!emitTree(expr)) { |
6567 | // [stack] ITEROBJ? VAL |
6568 | return false; |
6569 | } |
6570 | } else { |
6571 | if (!emit1(JSOp::Undefined)) { |
6572 | // [stack] ITEROBJ? UNDEFINED |
6573 | return false; |
6574 | } |
6575 | } |
6576 | |
6577 | if (sc->asSuspendableContext()->isAsync()) { |
6578 | MOZ_ASSERT(!needsIteratorResult)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!needsIteratorResult)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!needsIteratorResult))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("!needsIteratorResult" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6578); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!needsIteratorResult" ")"); do { *((volatile int*)__null) = 6578; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6579 | if (!emitAwaitInInnermostScope()) { |
6580 | // [stack] RESULT |
6581 | return false; |
6582 | } |
6583 | } |
6584 | |
6585 | if (needsIteratorResult) { |
6586 | if (!emitFinishIteratorResult(false)) { |
6587 | // [stack] ITEROBJ |
6588 | return false; |
6589 | } |
6590 | } |
6591 | |
6592 | if (!emitGetDotGeneratorInInnermostScope()) { |
6593 | // [stack] # if needsIteratorResult |
6594 | // [stack] ITEROBJ .GENERATOR |
6595 | // [stack] # else |
6596 | // [stack] RESULT .GENERATOR |
6597 | return false; |
6598 | } |
6599 | |
6600 | if (!emitYieldOp(JSOp::Yield)) { |
6601 | // [stack] YIELDRESULT GENERATOR RESUMEKIND |
6602 | return false; |
6603 | } |
6604 | |
6605 | if (!emit1(JSOp::CheckResumeKind)) { |
6606 | // [stack] YIELDRESULT |
6607 | return false; |
6608 | } |
6609 | |
6610 | return true; |
6611 | } |
6612 | |
6613 | bool BytecodeEmitter::emitAwaitInInnermostScope(UnaryNode* awaitNode) { |
6614 | MOZ_ASSERT(sc->isSuspendableContext())do { static_assert( mozilla::detail::AssertionConditionType< decltype(sc->isSuspendableContext())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(sc->isSuspendableContext( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("sc->isSuspendableContext()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6614); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isSuspendableContext()" ")"); do { *((volatile int*)__null) = 6614; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6615 | MOZ_ASSERT(awaitNode->isKind(ParseNodeKind::AwaitExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(awaitNode->isKind(ParseNodeKind::AwaitExpr))>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(awaitNode->isKind(ParseNodeKind::AwaitExpr)))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("awaitNode->isKind(ParseNodeKind::AwaitExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6615); AnnotateMozCrashReason("MOZ_ASSERT" "(" "awaitNode->isKind(ParseNodeKind::AwaitExpr)" ")"); do { *((volatile int*)__null) = 6615; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6616 | |
6617 | if (!emitTree(awaitNode->kid())) { |
6618 | return false; |
6619 | } |
6620 | return emitAwaitInInnermostScope(); |
6621 | } |
6622 | |
6623 | bool BytecodeEmitter::emitAwaitInScope(EmitterScope& currentScope) { |
6624 | if (!emit1(JSOp::CanSkipAwait)) { |
6625 | // [stack] VALUE CANSKIP |
6626 | return false; |
6627 | } |
6628 | |
6629 | if (!emit1(JSOp::MaybeExtractAwaitValue)) { |
6630 | // [stack] VALUE_OR_RESOLVED CANSKIP |
6631 | return false; |
6632 | } |
6633 | |
6634 | InternalIfEmitter ifCanSkip(this); |
6635 | if (!ifCanSkip.emitThen(IfEmitter::ConditionKind::Negative)) { |
6636 | // [stack] VALUE_OR_RESOLVED |
6637 | return false; |
6638 | } |
6639 | |
6640 | if (sc->asSuspendableContext()->needsPromiseResult()) { |
6641 | if (!emitGetDotGeneratorInScope(currentScope)) { |
6642 | // [stack] VALUE GENERATOR |
6643 | return false; |
6644 | } |
6645 | if (!emit1(JSOp::AsyncAwait)) { |
6646 | // [stack] PROMISE |
6647 | return false; |
6648 | } |
6649 | } |
6650 | |
6651 | if (!emitGetDotGeneratorInScope(currentScope)) { |
6652 | // [stack] VALUE|PROMISE GENERATOR |
6653 | return false; |
6654 | } |
6655 | if (!emitYieldOp(JSOp::Await)) { |
6656 | // [stack] RESOLVED GENERATOR RESUMEKIND |
6657 | return false; |
6658 | } |
6659 | if (!emit1(JSOp::CheckResumeKind)) { |
6660 | // [stack] RESOLVED |
6661 | return false; |
6662 | } |
6663 | |
6664 | if (!ifCanSkip.emitEnd()) { |
6665 | return false; |
6666 | } |
6667 | |
6668 | MOZ_ASSERT(ifCanSkip.popped() == 0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(ifCanSkip.popped() == 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(ifCanSkip.popped() == 0))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("ifCanSkip.popped() == 0" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6668); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ifCanSkip.popped() == 0" ")"); do { *((volatile int*)__null) = 6668; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6669 | |
6670 | return true; |
6671 | } |
6672 | |
6673 | // ES2019 draft rev 49b781ec80117b60f73327ef3054703a3111e40c |
6674 | // 14.4.14 Runtime Semantics: Evaluation |
6675 | // YieldExpression : yield* AssignmentExpression |
6676 | bool BytecodeEmitter::emitYieldStar(ParseNode* iter) { |
6677 | MOZ_ASSERT(getSelfHostedIterFor(iter) == SelfHostedIter::Deny,do { static_assert( mozilla::detail::AssertionConditionType< decltype(getSelfHostedIterFor(iter) == SelfHostedIter::Deny)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(getSelfHostedIterFor(iter) == SelfHostedIter::Deny)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("getSelfHostedIterFor(iter) == SelfHostedIter::Deny" " (" "yield* is prohibited in self-hosted code because it can run " "user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6679); AnnotateMozCrashReason("MOZ_ASSERT" "(" "getSelfHostedIterFor(iter) == SelfHostedIter::Deny" ") (" "yield* is prohibited in self-hosted code because it can run " "user-modifiable iteration code" ")"); do { *((volatile int* )__null) = 6679; __attribute__((nomerge)) ::abort(); } while ( false); } } while (false) |
6678 | "yield* is prohibited in self-hosted code because it can run "do { static_assert( mozilla::detail::AssertionConditionType< decltype(getSelfHostedIterFor(iter) == SelfHostedIter::Deny)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(getSelfHostedIterFor(iter) == SelfHostedIter::Deny)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("getSelfHostedIterFor(iter) == SelfHostedIter::Deny" " (" "yield* is prohibited in self-hosted code because it can run " "user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6679); AnnotateMozCrashReason("MOZ_ASSERT" "(" "getSelfHostedIterFor(iter) == SelfHostedIter::Deny" ") (" "yield* is prohibited in self-hosted code because it can run " "user-modifiable iteration code" ")"); do { *((volatile int* )__null) = 6679; __attribute__((nomerge)) ::abort(); } while ( false); } } while (false) |
6679 | "user-modifiable iteration code")do { static_assert( mozilla::detail::AssertionConditionType< decltype(getSelfHostedIterFor(iter) == SelfHostedIter::Deny)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(getSelfHostedIterFor(iter) == SelfHostedIter::Deny)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("getSelfHostedIterFor(iter) == SelfHostedIter::Deny" " (" "yield* is prohibited in self-hosted code because it can run " "user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6679); AnnotateMozCrashReason("MOZ_ASSERT" "(" "getSelfHostedIterFor(iter) == SelfHostedIter::Deny" ") (" "yield* is prohibited in self-hosted code because it can run " "user-modifiable iteration code" ")"); do { *((volatile int* )__null) = 6679; __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
6680 | |
6681 | MOZ_ASSERT(sc->isSuspendableContext())do { static_assert( mozilla::detail::AssertionConditionType< decltype(sc->isSuspendableContext())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(sc->isSuspendableContext( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("sc->isSuspendableContext()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6681); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isSuspendableContext()" ")"); do { *((volatile int*)__null) = 6681; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6682 | MOZ_ASSERT(sc->asSuspendableContext()->isGenerator())do { static_assert( mozilla::detail::AssertionConditionType< decltype(sc->asSuspendableContext()->isGenerator())> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(sc->asSuspendableContext()->isGenerator()))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("sc->asSuspendableContext()->isGenerator()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6682); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->asSuspendableContext()->isGenerator()" ")"); do { *((volatile int*)__null) = 6682; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6683 | |
6684 | // Step 1. |
6685 | IteratorKind iterKind = sc->asSuspendableContext()->isAsync() |
6686 | ? IteratorKind::Async |
6687 | : IteratorKind::Sync; |
6688 | bool needsIteratorResult = sc->asSuspendableContext()->needsIteratorResult(); |
6689 | |
6690 | // Steps 2-5. |
6691 | if (!emitTree(iter)) { |
6692 | // [stack] ITERABLE |
6693 | return false; |
6694 | } |
6695 | if (iterKind == IteratorKind::Async) { |
6696 | if (!emitAsyncIterator(SelfHostedIter::Deny)) { |
6697 | // [stack] NEXT ITER |
6698 | return false; |
6699 | } |
6700 | } else { |
6701 | if (!emitIterator(SelfHostedIter::Deny)) { |
6702 | // [stack] NEXT ITER |
6703 | return false; |
6704 | } |
6705 | } |
6706 | |
6707 | // Step 6. |
6708 | // Start with NormalCompletion(undefined). |
6709 | if (!emit1(JSOp::Undefined)) { |
6710 | // [stack] NEXT ITER RECEIVED |
6711 | return false; |
6712 | } |
6713 | if (!emitPushResumeKind(GeneratorResumeKind::Next)) { |
6714 | // [stack] NEXT ITER RECEIVED RESUMEKIND |
6715 | return false; |
6716 | } |
6717 | |
6718 | const int32_t startDepth = bytecodeSection().stackDepth(); |
6719 | MOZ_ASSERT(startDepth >= 4)do { static_assert( mozilla::detail::AssertionConditionType< decltype(startDepth >= 4)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(startDepth >= 4))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("startDepth >= 4" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6719); AnnotateMozCrashReason("MOZ_ASSERT" "(" "startDepth >= 4" ")"); do { *((volatile int*)__null) = 6719; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6720 | |
6721 | // Step 7 is a loop. |
6722 | LoopControl loopInfo(this, StatementKind::YieldStar); |
6723 | if (!loopInfo.emitLoopHead(this, Nothing())) { |
6724 | // [stack] NEXT ITER RECEIVED RESUMEKIND |
6725 | return false; |
6726 | } |
6727 | |
6728 | // Step 7.a. Check for Normal completion. |
6729 | if (!emit1(JSOp::Dup)) { |
6730 | // [stack] NEXT ITER RECEIVED RESUMEKIND RESUMEKIND |
6731 | return false; |
6732 | } |
6733 | if (!emitPushResumeKind(GeneratorResumeKind::Next)) { |
6734 | // [stack] NEXT ITER RECEIVED RESUMEKIND RESUMEKIND NORMAL |
6735 | return false; |
6736 | } |
6737 | if (!emit1(JSOp::StrictEq)) { |
6738 | // [stack] NEXT ITER RECEIVED RESUMEKIND IS_NORMAL |
6739 | return false; |
6740 | } |
6741 | |
6742 | InternalIfEmitter ifKind(this); |
6743 | if (!ifKind.emitThenElse()) { |
6744 | // [stack] NEXT ITER RECEIVED RESUMEKIND |
6745 | return false; |
6746 | } |
6747 | { |
6748 | if (!emit1(JSOp::Pop)) { |
6749 | // [stack] NEXT ITER RECEIVED |
6750 | return false; |
6751 | } |
6752 | |
6753 | // Step 7.a.i. |
6754 | // result = iter.next(received) |
6755 | if (!emit2(JSOp::Unpick, 2)) { |
6756 | // [stack] RECEIVED NEXT ITER |
6757 | return false; |
6758 | } |
6759 | if (!emit1(JSOp::Dup2)) { |
6760 | // [stack] RECEIVED NEXT ITER NEXT ITER |
6761 | return false; |
6762 | } |
6763 | if (!emit2(JSOp::Pick, 4)) { |
6764 | // [stack] NEXT ITER NEXT ITER RECEIVED |
6765 | return false; |
6766 | } |
6767 | if (!emitCall(JSOp::Call, 1, iter)) { |
6768 | // [stack] NEXT ITER RESULT |
6769 | return false; |
6770 | } |
6771 | |
6772 | // Step 7.a.ii. |
6773 | if (iterKind == IteratorKind::Async) { |
6774 | if (!emitAwaitInInnermostScope()) { |
6775 | // [stack] NEXT ITER RESULT |
6776 | return false; |
6777 | } |
6778 | } |
6779 | |
6780 | // Step 7.a.iii. |
6781 | if (!emitCheckIsObj(CheckIsObjectKind::IteratorNext)) { |
6782 | // [stack] NEXT ITER RESULT |
6783 | return false; |
6784 | } |
6785 | |
6786 | // Bytecode for steps 7.a.iv-vii is emitted after the ifKind if-else because |
6787 | // it's shared with other branches. |
6788 | } |
6789 | |
6790 | // Step 7.b. Check for Throw completion. |
6791 | if (!ifKind.emitElseIf(Nothing())) { |
6792 | // [stack] NEXT ITER RECEIVED RESUMEKIND |
6793 | return false; |
6794 | } |
6795 | if (!emit1(JSOp::Dup)) { |
6796 | // [stack] NEXT ITER RECEIVED RESUMEKIND RESUMEKIND |
6797 | return false; |
6798 | } |
6799 | if (!emitPushResumeKind(GeneratorResumeKind::Throw)) { |
6800 | // [stack] NEXT ITER RECEIVED RESUMEKIND RESUMEKIND THROW |
6801 | return false; |
6802 | } |
6803 | if (!emit1(JSOp::StrictEq)) { |
6804 | // [stack] NEXT ITER RECEIVED RESUMEKIND IS_THROW |
6805 | return false; |
6806 | } |
6807 | if (!ifKind.emitThenElse()) { |
6808 | // [stack] NEXT ITER RECEIVED RESUMEKIND |
6809 | return false; |
6810 | } |
6811 | { |
6812 | if (!emit1(JSOp::Pop)) { |
6813 | // [stack] NEXT ITER RECEIVED |
6814 | return false; |
6815 | } |
6816 | // Step 7.b.i. |
6817 | if (!emitDupAt(1)) { |
6818 | // [stack] NEXT ITER RECEIVED ITER |
6819 | return false; |
6820 | } |
6821 | if (!emit1(JSOp::Dup)) { |
6822 | // [stack] NEXT ITER RECEIVED ITER ITER |
6823 | return false; |
6824 | } |
6825 | if (!emitAtomOp(JSOp::GetProp, |
6826 | TaggedParserAtomIndex::WellKnown::throw_())) { |
6827 | // [stack] NEXT ITER RECEIVED ITER THROW |
6828 | return false; |
6829 | } |
6830 | |
6831 | // Step 7.b.ii. |
6832 | InternalIfEmitter ifThrowMethodIsNotDefined(this); |
6833 | if (!emit1(JSOp::IsNullOrUndefined)) { |
6834 | // [stack] NEXT ITER RECEIVED ITER THROW NULL-OR-UNDEF |
6835 | return false; |
6836 | } |
6837 | |
6838 | if (!ifThrowMethodIsNotDefined.emitThenElse( |
6839 | IfEmitter::ConditionKind::Negative)) { |
6840 | // [stack] NEXT ITER RECEIVED ITER THROW |
6841 | return false; |
6842 | } |
6843 | |
6844 | // Step 7.b.ii.1. |
6845 | // RESULT = ITER.throw(EXCEPTION) |
6846 | if (!emit1(JSOp::Swap)) { |
6847 | // [stack] NEXT ITER RECEIVED THROW ITER |
6848 | return false; |
6849 | } |
6850 | if (!emit2(JSOp::Pick, 2)) { |
6851 | // [stack] NEXT ITER THROW ITER RECEIVED |
6852 | return false; |
6853 | } |
6854 | if (!emitCall(JSOp::Call, 1, iter)) { |
6855 | // [stack] NEXT ITER RESULT |
6856 | return false; |
6857 | } |
6858 | |
6859 | // Step 7.b.ii.2. |
6860 | if (iterKind == IteratorKind::Async) { |
6861 | if (!emitAwaitInInnermostScope()) { |
6862 | // [stack] NEXT ITER RESULT |
6863 | return false; |
6864 | } |
6865 | } |
6866 | |
6867 | // Step 7.b.ii.4. |
6868 | if (!emitCheckIsObj(CheckIsObjectKind::IteratorThrow)) { |
6869 | // [stack] NEXT ITER RESULT |
6870 | return false; |
6871 | } |
6872 | |
6873 | // Bytecode for steps 7.b.ii.5-8 is emitted after the ifKind if-else because |
6874 | // it's shared with other branches. |
6875 | |
6876 | // Step 7.b.iii. |
6877 | if (!ifThrowMethodIsNotDefined.emitElse()) { |
6878 | // [stack] NEXT ITER RECEIVED ITER THROW |
6879 | return false; |
6880 | } |
6881 | if (!emit1(JSOp::Pop)) { |
6882 | // [stack] NEXT ITER RECEIVED ITER |
6883 | return false; |
6884 | } |
6885 | |
6886 | // Steps 7.b.iii.1-4. |
6887 | // |
6888 | // If the iterator does not have a "throw" method, it calls IteratorClose |
6889 | // and then throws a TypeError. |
6890 | if (!emitIteratorCloseInInnermostScope(iterKind, CompletionKind::Normal)) { |
6891 | // [stack] NEXT ITER RECEIVED ITER |
6892 | return false; |
6893 | } |
6894 | // Steps 7.b.iii.5-6. |
6895 | if (!emit2(JSOp::ThrowMsg, uint8_t(ThrowMsgKind::IteratorNoThrow))) { |
6896 | // [stack] NEXT ITER RECEIVED ITER |
6897 | // [stack] # throw |
6898 | return false; |
6899 | } |
6900 | |
6901 | if (!ifThrowMethodIsNotDefined.emitEnd()) { |
6902 | return false; |
6903 | } |
6904 | } |
6905 | |
6906 | // Step 7.c. It must be a Return completion. |
6907 | if (!ifKind.emitElse()) { |
6908 | // [stack] NEXT ITER RECEIVED RESUMEKIND |
6909 | return false; |
6910 | } |
6911 | { |
6912 | if (!emit1(JSOp::Pop)) { |
6913 | // [stack] NEXT ITER RECEIVED |
6914 | return false; |
6915 | } |
6916 | |
6917 | // Step 7.c.i. |
6918 | // |
6919 | // Call iterator.return() for receiving a "forced return" completion from |
6920 | // the generator. |
6921 | |
6922 | // Step 7.c.ii. |
6923 | // |
6924 | // Get the "return" method. |
6925 | if (!emitDupAt(1)) { |
6926 | // [stack] NEXT ITER RECEIVED ITER |
6927 | return false; |
6928 | } |
6929 | if (!emit1(JSOp::Dup)) { |
6930 | // [stack] NEXT ITER RECEIVED ITER ITER |
6931 | return false; |
6932 | } |
6933 | if (!emitAtomOp(JSOp::GetProp, |
6934 | TaggedParserAtomIndex::WellKnown::return_())) { |
6935 | // [stack] NEXT ITER RECEIVED ITER RET |
6936 | return false; |
6937 | } |
6938 | |
6939 | // Step 7.c.iii. |
6940 | // |
6941 | // Do nothing if "return" is undefined or null. |
6942 | InternalIfEmitter ifReturnMethodIsDefined(this); |
6943 | if (!emit1(JSOp::IsNullOrUndefined)) { |
6944 | // [stack] NEXT ITER RECEIVED ITER RET NULL-OR-UNDEF |
6945 | return false; |
6946 | } |
6947 | |
6948 | // Step 7.c.iv. |
6949 | // |
6950 | // Call "return" with the argument passed to Generator.prototype.return. |
6951 | if (!ifReturnMethodIsDefined.emitThenElse( |
6952 | IfEmitter::ConditionKind::Negative)) { |
6953 | // [stack] NEXT ITER RECEIVED ITER RET |
6954 | return false; |
6955 | } |
6956 | if (!emit1(JSOp::Swap)) { |
6957 | // [stack] NEXT ITER RECEIVED RET ITER |
6958 | return false; |
6959 | } |
6960 | if (!emit2(JSOp::Pick, 2)) { |
6961 | // [stack] NEXT ITER RET ITER RECEIVED |
6962 | return false; |
6963 | } |
6964 | if (needsIteratorResult) { |
6965 | if (!emitAtomOp(JSOp::GetProp, |
6966 | TaggedParserAtomIndex::WellKnown::value())) { |
6967 | // [stack] NEXT ITER RET ITER VAL |
6968 | return false; |
6969 | } |
6970 | } |
6971 | if (!emitCall(JSOp::Call, 1)) { |
6972 | // [stack] NEXT ITER RESULT |
6973 | return false; |
6974 | } |
6975 | |
6976 | // Step 7.c.v. |
6977 | if (iterKind == IteratorKind::Async) { |
6978 | if (!emitAwaitInInnermostScope()) { |
6979 | // [stack] NEXT ITER RESULT |
6980 | return false; |
6981 | } |
6982 | } |
6983 | |
6984 | // Step 7.c.vi. |
6985 | if (!emitCheckIsObj(CheckIsObjectKind::IteratorReturn)) { |
6986 | // [stack] NEXT ITER RESULT |
6987 | return false; |
6988 | } |
6989 | |
6990 | // Check if the returned object from iterator.return() is done. If not, |
6991 | // continue yielding. |
6992 | |
6993 | // Steps 7.c.vii-viii. |
6994 | InternalIfEmitter ifReturnDone(this); |
6995 | if (!emit1(JSOp::Dup)) { |
6996 | // [stack] NEXT ITER RESULT RESULT |
6997 | return false; |
6998 | } |
6999 | if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::done())) { |
7000 | // [stack] NEXT ITER RESULT DONE |
7001 | return false; |
7002 | } |
7003 | if (!ifReturnDone.emitThenElse()) { |
7004 | // [stack] NEXT ITER RESULT |
7005 | return false; |
7006 | } |
7007 | |
7008 | // Step 7.c.viii.1. |
7009 | if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::value())) { |
7010 | // [stack] NEXT ITER VALUE |
7011 | return false; |
7012 | } |
7013 | if (needsIteratorResult) { |
7014 | if (!emitPrepareIteratorResult()) { |
7015 | // [stack] NEXT ITER VALUE RESULT |
7016 | return false; |
7017 | } |
7018 | if (!emit1(JSOp::Swap)) { |
7019 | // [stack] NEXT ITER RESULT VALUE |
7020 | return false; |
7021 | } |
7022 | if (!emitFinishIteratorResult(true)) { |
7023 | // [stack] NEXT ITER RESULT |
7024 | return false; |
7025 | } |
7026 | } |
7027 | |
7028 | if (!ifReturnDone.emitElse()) { |
7029 | // [stack] NEXT ITER RESULT |
7030 | return false; |
7031 | } |
7032 | |
7033 | // Jump to continue label for steps 7.c.ix-x. |
7034 | if (!emitJump(JSOp::Goto, &loopInfo.continues)) { |
7035 | // [stack] NEXT ITER RESULT |
7036 | return false; |
7037 | } |
7038 | |
7039 | if (!ifReturnDone.emitEnd()) { |
7040 | // [stack] NEXT ITER RESULT |
7041 | return false; |
7042 | } |
7043 | |
7044 | // Step 7.c.iii. |
7045 | if (!ifReturnMethodIsDefined.emitElse()) { |
7046 | // [stack] NEXT ITER RECEIVED ITER RET |
7047 | return false; |
7048 | } |
7049 | if (!emitPopN(2)) { |
7050 | // [stack] NEXT ITER RECEIVED |
7051 | return false; |
7052 | } |
7053 | if (iterKind == IteratorKind::Async) { |
7054 | // Step 7.c.iii.1. |
7055 | if (!emitAwaitInInnermostScope()) { |
7056 | // [stack] NEXT ITER RECEIVED |
7057 | return false; |
7058 | } |
7059 | } |
7060 | if (!ifReturnMethodIsDefined.emitEnd()) { |
7061 | // [stack] NEXT ITER RECEIVED |
7062 | return false; |
7063 | } |
7064 | |
7065 | // Perform a "forced generator return". |
7066 | // |
7067 | // Step 7.c.iii.2. |
7068 | // Step 7.c.viii.2. |
7069 | if (!emitGetDotGeneratorInInnermostScope()) { |
7070 | // [stack] NEXT ITER RESULT GENOBJ |
7071 | return false; |
7072 | } |
7073 | if (!emitPushResumeKind(GeneratorResumeKind::Return)) { |
7074 | // [stack] NEXT ITER RESULT GENOBJ RESUMEKIND |
7075 | return false; |
7076 | } |
7077 | if (!emit1(JSOp::CheckResumeKind)) { |
7078 | // [stack] NEXT ITER RESULT GENOBJ RESUMEKIND |
7079 | return false; |
7080 | } |
7081 | } |
7082 | |
7083 | if (!ifKind.emitEnd()) { |
7084 | // [stack] NEXT ITER RESULT |
7085 | return false; |
7086 | } |
7087 | |
7088 | // Shared tail for Normal/Throw completions. |
7089 | // |
7090 | // Steps 7.a.iv-v. |
7091 | // Steps 7.b.ii.5-6. |
7092 | // |
7093 | // [stack] NEXT ITER RESULT |
7094 | |
7095 | // if (result.done) break; |
7096 | if (!emit1(JSOp::Dup)) { |
7097 | // [stack] NEXT ITER RESULT RESULT |
7098 | return false; |
7099 | } |
7100 | if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::done())) { |
7101 | // [stack] NEXT ITER RESULT DONE |
7102 | return false; |
7103 | } |
7104 | if (!emitJump(JSOp::JumpIfTrue, &loopInfo.breaks)) { |
7105 | // [stack] NEXT ITER RESULT |
7106 | return false; |
7107 | } |
7108 | |
7109 | // Steps 7.a.vi-vii. |
7110 | // Steps 7.b.ii.7-8. |
7111 | // Steps 7.c.ix-x. |
7112 | if (!loopInfo.emitContinueTarget(this)) { |
7113 | // [stack] NEXT ITER RESULT |
7114 | return false; |
7115 | } |
7116 | if (iterKind == IteratorKind::Async) { |
7117 | if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::value())) { |
7118 | // [stack] NEXT ITER RESULT |
7119 | return false; |
7120 | } |
7121 | } |
7122 | if (!emitGetDotGeneratorInInnermostScope()) { |
7123 | // [stack] NEXT ITER RESULT GENOBJ |
7124 | return false; |
7125 | } |
7126 | if (!emitYieldOp(JSOp::Yield)) { |
7127 | // [stack] NEXT ITER RVAL GENOBJ RESUMEKIND |
7128 | return false; |
7129 | } |
7130 | if (!emit1(JSOp::Swap)) { |
7131 | // [stack] NEXT ITER RVAL RESUMEKIND GENOBJ |
7132 | return false; |
7133 | } |
7134 | if (!emit1(JSOp::Pop)) { |
7135 | // [stack] NEXT ITER RVAL RESUMEKIND |
7136 | return false; |
7137 | } |
7138 | if (!loopInfo.emitLoopEnd(this, JSOp::Goto, TryNoteKind::Loop)) { |
7139 | // [stack] NEXT ITER RVAL RESUMEKIND |
7140 | return false; |
7141 | } |
7142 | |
7143 | // Jumps to this point have 3 (instead of 4) values on the stack. |
7144 | MOZ_ASSERT(bytecodeSection().stackDepth() == startDepth)do { static_assert( mozilla::detail::AssertionConditionType< decltype(bytecodeSection().stackDepth() == startDepth)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(bytecodeSection().stackDepth() == startDepth))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("bytecodeSection().stackDepth() == startDepth" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7144); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == startDepth" ")"); do { *((volatile int*)__null) = 7144; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7145 | bytecodeSection().setStackDepth(startDepth - 1); |
7146 | |
7147 | // [stack] NEXT ITER RESULT |
7148 | |
7149 | // Step 7.a.v.1. |
7150 | // Step 7.b.ii.6.a. |
7151 | // |
7152 | // result.value |
7153 | if (!emit2(JSOp::Unpick, 2)) { |
7154 | // [stack] RESULT NEXT ITER |
7155 | return false; |
7156 | } |
7157 | if (!emitPopN(2)) { |
7158 | // [stack] RESULT |
7159 | return false; |
7160 | } |
7161 | if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::value())) { |
7162 | // [stack] VALUE |
7163 | return false; |
7164 | } |
7165 | |
7166 | MOZ_ASSERT(bytecodeSection().stackDepth() == startDepth - 3)do { static_assert( mozilla::detail::AssertionConditionType< decltype(bytecodeSection().stackDepth() == startDepth - 3)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(bytecodeSection().stackDepth() == startDepth - 3))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("bytecodeSection().stackDepth() == startDepth - 3" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7166); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == startDepth - 3" ")"); do { *((volatile int*)__null) = 7166; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7167 | |
7168 | return true; |
7169 | } |
7170 | |
7171 | bool BytecodeEmitter::emitStatementList(ListNode* stmtList) { |
7172 | for (ParseNode* stmt : stmtList->contents()) { |
7173 | if (!emitTree(stmt)) { |
7174 | return false; |
7175 | } |
7176 | } |
7177 | return true; |
7178 | } |
7179 | |
7180 | bool BytecodeEmitter::emitExpressionStatement(UnaryNode* exprStmt) { |
7181 | MOZ_ASSERT(exprStmt->isKind(ParseNodeKind::ExpressionStmt))do { static_assert( mozilla::detail::AssertionConditionType< decltype(exprStmt->isKind(ParseNodeKind::ExpressionStmt))> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(exprStmt->isKind(ParseNodeKind::ExpressionStmt))) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("exprStmt->isKind(ParseNodeKind::ExpressionStmt)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7181); AnnotateMozCrashReason("MOZ_ASSERT" "(" "exprStmt->isKind(ParseNodeKind::ExpressionStmt)" ")"); do { *((volatile int*)__null) = 7181; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7182 | |
7183 | /* |
7184 | * Top-level or called-from-a-native JS_Execute/EvaluateScript, |
7185 | * debugger, and eval frames may need the value of the ultimate |
7186 | * expression statement as the script's result, despite the fact |
7187 | * that it appears useless to the compiler. |
7188 | * |
7189 | * API users may also set the ReadOnlyCompileOptions::noScriptRval option when |
7190 | * calling JS_Compile* to suppress JSOp::SetRval. |
7191 | */ |
7192 | bool wantval = false; |
7193 | bool useful = false; |
7194 | if (sc->isTopLevelContext()) { |
7195 | useful = wantval = !sc->noScriptRval(); |
7196 | } |
7197 | |
7198 | /* Don't eliminate expressions with side effects. */ |
7199 | ParseNode* expr = exprStmt->kid(); |
7200 | if (!useful) { |
7201 | if (!checkSideEffects(expr, &useful)) { |
7202 | return false; |
7203 | } |
7204 | |
7205 | /* |
7206 | * Don't eliminate apparently useless expressions if they are labeled |
7207 | * expression statements. The startOffset() test catches the case |
7208 | * where we are nesting in emitTree for a labeled compound statement. |
7209 | */ |
7210 | if (innermostNestableControl && |
7211 | innermostNestableControl->is<LabelControl>() && |
7212 | innermostNestableControl->as<LabelControl>().startOffset() >= |
7213 | bytecodeSection().offset()) { |
7214 | useful = true; |
7215 | } |
7216 | } |
7217 | |
7218 | if (useful) { |
7219 | ValueUsage valueUsage = |
7220 | wantval ? ValueUsage::WantValue : ValueUsage::IgnoreValue; |
7221 | ExpressionStatementEmitter ese(this, valueUsage); |
7222 | if (!ese.prepareForExpr(exprStmt->pn_pos.begin)) { |
7223 | return false; |
7224 | } |
7225 | if (!markStepBreakpoint()) { |
7226 | return false; |
7227 | } |
7228 | if (!emitTree(expr, valueUsage)) { |
7229 | return false; |
7230 | } |
7231 | if (!ese.emitEnd()) { |
7232 | return false; |
7233 | } |
7234 | } |
7235 | |
7236 | return true; |
7237 | } |
7238 | |
7239 | bool BytecodeEmitter::emitDeleteName(UnaryNode* deleteNode) { |
7240 | MOZ_ASSERT(deleteNode->isKind(ParseNodeKind::DeleteNameExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(deleteNode->isKind(ParseNodeKind::DeleteNameExpr) )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(deleteNode->isKind(ParseNodeKind::DeleteNameExpr) ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "deleteNode->isKind(ParseNodeKind::DeleteNameExpr)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7240); AnnotateMozCrashReason("MOZ_ASSERT" "(" "deleteNode->isKind(ParseNodeKind::DeleteNameExpr)" ")"); do { *((volatile int*)__null) = 7240; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7241 | |
7242 | NameNode* nameExpr = &deleteNode->kid()->as<NameNode>(); |
7243 | MOZ_ASSERT(nameExpr->isKind(ParseNodeKind::Name))do { static_assert( mozilla::detail::AssertionConditionType< decltype(nameExpr->isKind(ParseNodeKind::Name))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(nameExpr->isKind(ParseNodeKind::Name)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("nameExpr->isKind(ParseNodeKind::Name)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7243); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nameExpr->isKind(ParseNodeKind::Name)" ")"); do { *((volatile int*)__null) = 7243; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7244 | |
7245 | return emitAtomOp(JSOp::DelName, nameExpr->atom()); |
7246 | } |
7247 | |
7248 | bool BytecodeEmitter::emitDeleteProperty(UnaryNode* deleteNode) { |
7249 | MOZ_ASSERT(deleteNode->isKind(ParseNodeKind::DeletePropExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(deleteNode->isKind(ParseNodeKind::DeletePropExpr) )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(deleteNode->isKind(ParseNodeKind::DeletePropExpr) ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "deleteNode->isKind(ParseNodeKind::DeletePropExpr)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7249); AnnotateMozCrashReason("MOZ_ASSERT" "(" "deleteNode->isKind(ParseNodeKind::DeletePropExpr)" ")"); do { *((volatile int*)__null) = 7249; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7250 | |
7251 | PropertyAccess* propExpr = &deleteNode->kid()->as<PropertyAccess>(); |
7252 | PropOpEmitter poe(this, PropOpEmitter::Kind::Delete, |
7253 | propExpr->as<PropertyAccess>().isSuper() |
7254 | ? PropOpEmitter::ObjKind::Super |
7255 | : PropOpEmitter::ObjKind::Other); |
7256 | |
7257 | if (!poe.prepareForObj()) { |
7258 | return false; |
7259 | } |
7260 | |
7261 | if (propExpr->isSuper()) { |
7262 | // The expression |delete super.foo;| has to evaluate |super.foo|, which |
7263 | // could throw if |this| hasn't yet been set by a |super(...)| call. |
7264 | auto* base = &propExpr->expression().as<UnaryNode>(); |
7265 | if (!emitGetThisForSuperBase(base)) { |
7266 | // [stack] THIS |
7267 | return false; |
7268 | } |
7269 | } else { |
7270 | if (!emitPropLHS(propExpr)) { |
7271 | // [stack] OBJ |
7272 | return false; |
7273 | } |
7274 | } |
7275 | |
7276 | if (!poe.emitDelete(propExpr->key().atom())) { |
7277 | // [stack] # if Super |
7278 | // [stack] THIS |
7279 | // [stack] # otherwise |
7280 | // [stack] SUCCEEDED |
7281 | return false; |
7282 | } |
7283 | |
7284 | return true; |
7285 | } |
7286 | |
7287 | bool BytecodeEmitter::emitDeleteElement(UnaryNode* deleteNode) { |
7288 | MOZ_ASSERT(deleteNode->isKind(ParseNodeKind::DeleteElemExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(deleteNode->isKind(ParseNodeKind::DeleteElemExpr) )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(deleteNode->isKind(ParseNodeKind::DeleteElemExpr) ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "deleteNode->isKind(ParseNodeKind::DeleteElemExpr)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7288); AnnotateMozCrashReason("MOZ_ASSERT" "(" "deleteNode->isKind(ParseNodeKind::DeleteElemExpr)" ")"); do { *((volatile int*)__null) = 7288; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7289 | |
7290 | auto* elemExpr = &deleteNode->kid()->as<PropertyByValue>(); |
7291 | bool isSuper = elemExpr->isSuper(); |
7292 | MOZ_ASSERT(!elemExpr->key().isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!elemExpr->key().isKind(ParseNodeKind::PrivateName ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!elemExpr->key().isKind(ParseNodeKind::PrivateName )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!elemExpr->key().isKind(ParseNodeKind::PrivateName)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7292); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elemExpr->key().isKind(ParseNodeKind::PrivateName)" ")"); do { *((volatile int*)__null) = 7292; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7293 | ElemOpEmitter eoe( |
7294 | this, ElemOpEmitter::Kind::Delete, |
7295 | isSuper ? ElemOpEmitter::ObjKind::Super : ElemOpEmitter::ObjKind::Other); |
7296 | |
7297 | if (!emitElemObjAndKey(elemExpr, eoe)) { |
7298 | // [stack] # if Super |
7299 | // [stack] THIS KEY |
7300 | // [stack] # otherwise |
7301 | // [stack] OBJ KEY |
7302 | return false; |
7303 | } |
7304 | |
7305 | if (!eoe.emitDelete()) { |
7306 | // [stack] # if Super |
7307 | // [stack] THIS |
7308 | // [stack] # otherwise |
7309 | // [stack] SUCCEEDED |
7310 | return false; |
7311 | } |
7312 | |
7313 | return true; |
7314 | } |
7315 | |
7316 | bool BytecodeEmitter::emitDeleteExpression(UnaryNode* deleteNode) { |
7317 | MOZ_ASSERT(deleteNode->isKind(ParseNodeKind::DeleteExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(deleteNode->isKind(ParseNodeKind::DeleteExpr))> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(deleteNode->isKind(ParseNodeKind::DeleteExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("deleteNode->isKind(ParseNodeKind::DeleteExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7317); AnnotateMozCrashReason("MOZ_ASSERT" "(" "deleteNode->isKind(ParseNodeKind::DeleteExpr)" ")"); do { *((volatile int*)__null) = 7317; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7318 | |
7319 | ParseNode* expression = deleteNode->kid(); |
7320 | |
7321 | // If useless, just emit JSOp::True; otherwise convert |delete <expr>| to |
7322 | // effectively |<expr>, true|. |
7323 | bool useful = false; |
7324 | if (!checkSideEffects(expression, &useful)) { |
7325 | return false; |
7326 | } |
7327 | |
7328 | if (useful) { |
7329 | if (!emitTree(expression)) { |
7330 | return false; |
7331 | } |
7332 | if (!emit1(JSOp::Pop)) { |
7333 | return false; |
7334 | } |
7335 | } |
7336 | |
7337 | return emit1(JSOp::True); |
7338 | } |
7339 | |
7340 | bool BytecodeEmitter::emitDeleteOptionalChain(UnaryNode* deleteNode) { |
7341 | MOZ_ASSERT(deleteNode->isKind(ParseNodeKind::DeleteOptionalChainExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(deleteNode->isKind(ParseNodeKind::DeleteOptionalChainExpr ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(deleteNode->isKind(ParseNodeKind::DeleteOptionalChainExpr )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("deleteNode->isKind(ParseNodeKind::DeleteOptionalChainExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7341); AnnotateMozCrashReason("MOZ_ASSERT" "(" "deleteNode->isKind(ParseNodeKind::DeleteOptionalChainExpr)" ")"); do { *((volatile int*)__null) = 7341; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7342 | |
7343 | OptionalEmitter oe(this, bytecodeSection().stackDepth()); |
7344 | |
7345 | ParseNode* kid = deleteNode->kid(); |
7346 | switch (kid->getKind()) { |
7347 | case ParseNodeKind::ElemExpr: |
7348 | case ParseNodeKind::OptionalElemExpr: { |
7349 | auto* elemExpr = &kid->as<PropertyByValueBase>(); |
7350 | if (!emitDeleteElementInOptChain(elemExpr, oe)) { |
7351 | // [stack] # If shortcircuit |
7352 | // [stack] UNDEFINED-OR-NULL |
7353 | // [stack] # otherwise |
7354 | // [stack] SUCCEEDED |
7355 | return false; |
7356 | } |
7357 | |
7358 | break; |
7359 | } |
7360 | case ParseNodeKind::ArgumentsLength: |
7361 | case ParseNodeKind::DotExpr: |
7362 | case ParseNodeKind::OptionalDotExpr: { |
7363 | auto* propExpr = &kid->as<PropertyAccessBase>(); |
7364 | if (!emitDeletePropertyInOptChain(propExpr, oe)) { |
7365 | // [stack] # If shortcircuit |
7366 | // [stack] UNDEFINED-OR-NULL |
7367 | // [stack] # otherwise |
7368 | // [stack] SUCCEEDED |
7369 | return false; |
7370 | } |
7371 | break; |
7372 | } |
7373 | default: |
7374 | MOZ_ASSERT_UNREACHABLE("Unrecognized optional delete ParseNodeKind")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "Unrecognized optional delete ParseNodeKind" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7374); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "Unrecognized optional delete ParseNodeKind" ")"); do { *((volatile int*)__null) = 7374; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7375 | } |
7376 | |
7377 | if (!oe.emitOptionalJumpTarget(JSOp::True)) { |
7378 | // [stack] # If shortcircuit |
7379 | // [stack] TRUE |
7380 | // [stack] # otherwise |
7381 | // [stack] SUCCEEDED |
7382 | return false; |
7383 | } |
7384 | |
7385 | return true; |
7386 | } |
7387 | |
7388 | bool BytecodeEmitter::emitDeletePropertyInOptChain(PropertyAccessBase* propExpr, |
7389 | OptionalEmitter& oe) { |
7390 | MOZ_ASSERT_IF(propExpr->is<PropertyAccess>(),do { if (propExpr->is<PropertyAccess>()) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(!propExpr ->as<PropertyAccess>().isSuper())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!propExpr->as<PropertyAccess >().isSuper()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!propExpr->as<PropertyAccess>().isSuper()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7391); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!propExpr->as<PropertyAccess>().isSuper()" ")"); do { *((volatile int*)__null) = 7391; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
7391 | !propExpr->as<PropertyAccess>().isSuper())do { if (propExpr->is<PropertyAccess>()) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(!propExpr ->as<PropertyAccess>().isSuper())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!propExpr->as<PropertyAccess >().isSuper()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!propExpr->as<PropertyAccess>().isSuper()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7391); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!propExpr->as<PropertyAccess>().isSuper()" ")"); do { *((volatile int*)__null) = 7391; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
7392 | PropOpEmitter poe(this, PropOpEmitter::Kind::Delete, |
7393 | PropOpEmitter::ObjKind::Other); |
7394 | |
7395 | if (!poe.prepareForObj()) { |
7396 | // [stack] |
7397 | return false; |
7398 | } |
7399 | if (!emitOptionalTree(&propExpr->expression(), oe)) { |
7400 | // [stack] OBJ |
7401 | return false; |
7402 | } |
7403 | if (propExpr->isKind(ParseNodeKind::OptionalDotExpr)) { |
7404 | if (!oe.emitJumpShortCircuit()) { |
7405 | // [stack] # if Jump |
7406 | // [stack] UNDEFINED-OR-NULL |
7407 | // [stack] # otherwise |
7408 | // [stack] OBJ |
7409 | return false; |
7410 | } |
7411 | } |
7412 | |
7413 | if (!poe.emitDelete(propExpr->key().atom())) { |
7414 | // [stack] SUCCEEDED |
7415 | return false; |
7416 | } |
7417 | |
7418 | return true; |
7419 | } |
7420 | |
7421 | bool BytecodeEmitter::emitDeleteElementInOptChain(PropertyByValueBase* elemExpr, |
7422 | OptionalEmitter& oe) { |
7423 | MOZ_ASSERT_IF(elemExpr->is<PropertyByValue>(),do { if (elemExpr->is<PropertyByValue>()) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(!elemExpr ->as<PropertyByValue>().isSuper())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!elemExpr->as<PropertyByValue >().isSuper()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!elemExpr->as<PropertyByValue>().isSuper()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7424); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elemExpr->as<PropertyByValue>().isSuper()" ")"); do { *((volatile int*)__null) = 7424; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
7424 | !elemExpr->as<PropertyByValue>().isSuper())do { if (elemExpr->is<PropertyByValue>()) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(!elemExpr ->as<PropertyByValue>().isSuper())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!elemExpr->as<PropertyByValue >().isSuper()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!elemExpr->as<PropertyByValue>().isSuper()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7424); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elemExpr->as<PropertyByValue>().isSuper()" ")"); do { *((volatile int*)__null) = 7424; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
7425 | ElemOpEmitter eoe(this, ElemOpEmitter::Kind::Delete, |
7426 | ElemOpEmitter::ObjKind::Other); |
7427 | |
7428 | if (!eoe.prepareForObj()) { |
7429 | // [stack] |
7430 | return false; |
7431 | } |
7432 | |
7433 | if (!emitOptionalTree(&elemExpr->expression(), oe)) { |
7434 | // [stack] OBJ |
7435 | return false; |
7436 | } |
7437 | |
7438 | if (elemExpr->isKind(ParseNodeKind::OptionalElemExpr)) { |
7439 | if (!oe.emitJumpShortCircuit()) { |
7440 | // [stack] # if Jump |
7441 | // [stack] UNDEFINED-OR-NULL |
7442 | // [stack] # otherwise |
7443 | // [stack] OBJ |
7444 | return false; |
7445 | } |
7446 | } |
7447 | |
7448 | if (!eoe.prepareForKey()) { |
7449 | // [stack] OBJ |
7450 | return false; |
7451 | } |
7452 | |
7453 | if (!emitTree(&elemExpr->key())) { |
7454 | // [stack] OBJ KEY |
7455 | return false; |
7456 | } |
7457 | |
7458 | if (!eoe.emitDelete()) { |
7459 | // [stack] SUCCEEDED |
7460 | return false; |
7461 | } |
7462 | |
7463 | return true; |
7464 | } |
7465 | |
7466 | bool BytecodeEmitter::emitDebugCheckSelfHosted() { |
7467 | // [stack] CALLEE |
7468 | |
7469 | #ifdef DEBUG1 |
7470 | if (!emit1(JSOp::DebugCheckSelfHosted)) { |
7471 | // [stack] CALLEE |
7472 | return false; |
7473 | } |
7474 | #endif |
7475 | |
7476 | return true; |
7477 | } |
7478 | |
7479 | bool BytecodeEmitter::emitSelfHostedCallFunction(CallNode* callNode, JSOp op) { |
7480 | // Special-casing of callFunction to emit bytecode that directly |
7481 | // invokes the callee with the correct |this| object and arguments. |
7482 | // callFunction(fun, thisArg, arg0, arg1) thus becomes: |
7483 | // - emit lookup for fun |
7484 | // - emit lookup for thisArg |
7485 | // - emit lookups for arg0, arg1 |
7486 | // |
7487 | // argc is set to the amount of actually emitted args and the |
7488 | // emitting of args below is disabled by setting emitArgs to false. |
7489 | NameNode* calleeNode = &callNode->callee()->as<NameNode>(); |
7490 | ListNode* argsList = callNode->args(); |
7491 | |
7492 | MOZ_ASSERT(argsList->count() >= 2)do { static_assert( mozilla::detail::AssertionConditionType< decltype(argsList->count() >= 2)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(argsList->count() >= 2 ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "argsList->count() >= 2", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7492); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() >= 2" ")"); do { *((volatile int*)__null) = 7492; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7493 | |
7494 | MOZ_ASSERT(callNode->callOp() == JSOp::Call)do { static_assert( mozilla::detail::AssertionConditionType< decltype(callNode->callOp() == JSOp::Call)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(callNode->callOp() == JSOp ::Call))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("callNode->callOp() == JSOp::Call", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7494); AnnotateMozCrashReason("MOZ_ASSERT" "(" "callNode->callOp() == JSOp::Call" ")"); do { *((volatile int*)__null) = 7494; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7495 | |
7496 | bool constructing = |
7497 | calleeNode->name() == |
7498 | TaggedParserAtomIndex::WellKnown::constructContentFunction(); |
7499 | ParseNode* funNode = argsList->head(); |
7500 | |
7501 | if (!emitTree(funNode)) { |
7502 | // [stack] CALLEE |
7503 | return false; |
7504 | } |
7505 | |
7506 | #ifdef DEBUG1 |
7507 | MOZ_ASSERT(op == JSOp::Call || op == JSOp::CallContent ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(op == JSOp::Call || op == JSOp::CallContent || op == JSOp::NewContent)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(op == JSOp::Call || op == JSOp ::CallContent || op == JSOp::NewContent))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("op == JSOp::Call || op == JSOp::CallContent || op == JSOp::NewContent" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7508); AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::Call || op == JSOp::CallContent || op == JSOp::NewContent" ")"); do { *((volatile int*)__null) = 7508; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
7508 | op == JSOp::NewContent)do { static_assert( mozilla::detail::AssertionConditionType< decltype(op == JSOp::Call || op == JSOp::CallContent || op == JSOp::NewContent)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(op == JSOp::Call || op == JSOp ::CallContent || op == JSOp::NewContent))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("op == JSOp::Call || op == JSOp::CallContent || op == JSOp::NewContent" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7508); AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::Call || op == JSOp::CallContent || op == JSOp::NewContent" ")"); do { *((volatile int*)__null) = 7508; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7509 | if (op == JSOp::Call) { |
7510 | if (!emitDebugCheckSelfHosted()) { |
7511 | // [stack] CALLEE |
7512 | return false; |
7513 | } |
7514 | } |
7515 | #endif |
7516 | |
7517 | ParseNode* thisOrNewTarget = funNode->pn_next; |
7518 | if (constructing) { |
7519 | // Save off the new.target value, but here emit a proper |this| for a |
7520 | // constructing call. |
7521 | if (!emit1(JSOp::IsConstructing)) { |
7522 | // [stack] CALLEE IS_CONSTRUCTING |
7523 | return false; |
7524 | } |
7525 | } else { |
7526 | // It's |this|, emit it. |
7527 | if (!emitTree(thisOrNewTarget)) { |
7528 | // [stack] CALLEE THIS |
7529 | return false; |
7530 | } |
7531 | } |
7532 | |
7533 | for (ParseNode* argpn : argsList->contentsFrom(thisOrNewTarget->pn_next)) { |
7534 | if (!emitTree(argpn)) { |
7535 | // [stack] CALLEE ... ARGS... |
7536 | return false; |
7537 | } |
7538 | } |
7539 | |
7540 | if (constructing) { |
7541 | if (!emitTree(thisOrNewTarget)) { |
7542 | // [stack] CALLEE IS_CONSTRUCTING ARGS... NEW.TARGET |
7543 | return false; |
7544 | } |
7545 | } |
7546 | |
7547 | uint32_t argc = argsList->count() - 2; |
7548 | if (!emitCall(op, argc)) { |
7549 | // [stack] RVAL |
7550 | return false; |
7551 | } |
7552 | |
7553 | return true; |
7554 | } |
7555 | |
7556 | bool BytecodeEmitter::emitSelfHostedResumeGenerator(CallNode* callNode) { |
7557 | ListNode* argsList = callNode->args(); |
7558 | |
7559 | // Syntax: resumeGenerator(gen, value, 'next'|'throw'|'return') |
7560 | MOZ_ASSERT(argsList->count() == 3)do { static_assert( mozilla::detail::AssertionConditionType< decltype(argsList->count() == 3)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(argsList->count() == 3))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 3" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7560); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 3" ")"); do { *((volatile int*)__null) = 7560; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7561 | |
7562 | ParseNode* genNode = argsList->head(); |
7563 | if (!emitTree(genNode)) { |
7564 | // [stack] GENERATOR |
7565 | return false; |
7566 | } |
7567 | |
7568 | ParseNode* valNode = genNode->pn_next; |
7569 | if (!emitTree(valNode)) { |
7570 | // [stack] GENERATOR VALUE |
7571 | return false; |
7572 | } |
7573 | |
7574 | ParseNode* kindNode = valNode->pn_next; |
7575 | MOZ_ASSERT(kindNode->isKind(ParseNodeKind::StringExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(kindNode->isKind(ParseNodeKind::StringExpr))>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(kindNode->isKind(ParseNodeKind::StringExpr)))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("kindNode->isKind(ParseNodeKind::StringExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7575); AnnotateMozCrashReason("MOZ_ASSERT" "(" "kindNode->isKind(ParseNodeKind::StringExpr)" ")"); do { *((volatile int*)__null) = 7575; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7576 | GeneratorResumeKind kind = |
7577 | ParserAtomToResumeKind(kindNode->as<NameNode>().atom()); |
7578 | MOZ_ASSERT(!kindNode->pn_next)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!kindNode->pn_next)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!kindNode->pn_next))), 0) )) { do { } while (false); MOZ_ReportAssertionFailure("!kindNode->pn_next" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7578); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!kindNode->pn_next" ")"); do { *((volatile int*)__null) = 7578; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7579 | |
7580 | if (!emitPushResumeKind(kind)) { |
7581 | // [stack] GENERATOR VALUE RESUMEKIND |
7582 | return false; |
7583 | } |
7584 | |
7585 | if (!emit1(JSOp::Resume)) { |
7586 | // [stack] RVAL |
7587 | return false; |
7588 | } |
7589 | |
7590 | return true; |
7591 | } |
7592 | |
7593 | bool BytecodeEmitter::emitSelfHostedForceInterpreter() { |
7594 | // JSScript::hasForceInterpreterOp() relies on JSOp::ForceInterpreter being |
7595 | // the first bytecode op in the script. |
7596 | MOZ_ASSERT(bytecodeSection().code().empty())do { static_assert( mozilla::detail::AssertionConditionType< decltype(bytecodeSection().code().empty())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(bytecodeSection().code().empty ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("bytecodeSection().code().empty()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7596); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().code().empty()" ")"); do { *((volatile int*)__null) = 7596; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7597 | |
7598 | if (!emit1(JSOp::ForceInterpreter)) { |
7599 | return false; |
7600 | } |
7601 | if (!emit1(JSOp::Undefined)) { |
7602 | return false; |
7603 | } |
7604 | |
7605 | return true; |
7606 | } |
7607 | |
7608 | bool BytecodeEmitter::emitSelfHostedAllowContentIter(CallNode* callNode) { |
7609 | ListNode* argsList = callNode->args(); |
7610 | |
7611 | MOZ_ASSERT(argsList->count() == 1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(argsList->count() == 1)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(argsList->count() == 1))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 1" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7611); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1" ")"); do { *((volatile int*)__null) = 7611; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7612 | |
7613 | // We're just here as a sentinel. Pass the value through directly. |
7614 | return emitTree(argsList->head()); |
7615 | } |
7616 | |
7617 | bool BytecodeEmitter::emitSelfHostedAllowContentIterWith(CallNode* callNode) { |
7618 | ListNode* argsList = callNode->args(); |
7619 | |
7620 | MOZ_ASSERT(argsList->count() == 2 || argsList->count() == 3)do { static_assert( mozilla::detail::AssertionConditionType< decltype(argsList->count() == 2 || argsList->count() == 3)>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(argsList->count() == 2 || argsList->count() == 3))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("argsList->count() == 2 || argsList->count() == 3", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7620); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2 || argsList->count() == 3" ")"); do { *((volatile int*)__null) = 7620; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7621 | |
7622 | // We're just here as a sentinel. Pass the value through directly. |
7623 | return emitTree(argsList->head()); |
7624 | } |
7625 | |
7626 | bool BytecodeEmitter::emitSelfHostedAllowContentIterWithNext( |
7627 | CallNode* callNode) { |
7628 | ListNode* argsList = callNode->args(); |
7629 | |
7630 | MOZ_ASSERT(argsList->count() == 2)do { static_assert( mozilla::detail::AssertionConditionType< decltype(argsList->count() == 2)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(argsList->count() == 2))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 2" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7630); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2" ")"); do { *((volatile int*)__null) = 7630; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7631 | |
7632 | // We're just here as a sentinel. Pass the value through directly. |
7633 | return emitTree(argsList->head()); |
7634 | } |
7635 | |
7636 | bool BytecodeEmitter::emitSelfHostedDefineDataProperty(CallNode* callNode) { |
7637 | ListNode* argsList = callNode->args(); |
7638 | |
7639 | // Only optimize when 3 arguments are passed. |
7640 | MOZ_ASSERT(argsList->count() == 3)do { static_assert( mozilla::detail::AssertionConditionType< decltype(argsList->count() == 3)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(argsList->count() == 3))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 3" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7640); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 3" ")"); do { *((volatile int*)__null) = 7640; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7641 | |
7642 | ParseNode* objNode = argsList->head(); |
7643 | if (!emitTree(objNode)) { |
7644 | return false; |
7645 | } |
7646 | |
7647 | ParseNode* idNode = objNode->pn_next; |
7648 | if (!emitTree(idNode)) { |
7649 | return false; |
7650 | } |
7651 | |
7652 | ParseNode* valNode = idNode->pn_next; |
7653 | if (!emitTree(valNode)) { |
7654 | return false; |
7655 | } |
7656 | |
7657 | // This will leave the object on the stack instead of pushing |undefined|, |
7658 | // but that's fine because the self-hosted code doesn't use the return |
7659 | // value. |
7660 | return emit1(JSOp::InitElem); |
7661 | } |
7662 | |
7663 | bool BytecodeEmitter::emitSelfHostedHasOwn(CallNode* callNode) { |
7664 | ListNode* argsList = callNode->args(); |
7665 | |
7666 | MOZ_ASSERT(argsList->count() == 2)do { static_assert( mozilla::detail::AssertionConditionType< decltype(argsList->count() == 2)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(argsList->count() == 2))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 2" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7666); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2" ")"); do { *((volatile int*)__null) = 7666; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7667 | |
7668 | ParseNode* idNode = argsList->head(); |
7669 | if (!emitTree(idNode)) { |
7670 | return false; |
7671 | } |
7672 | |
7673 | ParseNode* objNode = idNode->pn_next; |
7674 | if (!emitTree(objNode)) { |
7675 | return false; |
7676 | } |
7677 | |
7678 | return emit1(JSOp::HasOwn); |
7679 | } |
7680 | |
7681 | bool BytecodeEmitter::emitSelfHostedGetPropertySuper(CallNode* callNode) { |
7682 | ListNode* argsList = callNode->args(); |
7683 | |
7684 | MOZ_ASSERT(argsList->count() == 3)do { static_assert( mozilla::detail::AssertionConditionType< decltype(argsList->count() == 3)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(argsList->count() == 3))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 3" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7684); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 3" ")"); do { *((volatile int*)__null) = 7684; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7685 | |
7686 | ParseNode* objNode = argsList->head(); |
7687 | ParseNode* idNode = objNode->pn_next; |
7688 | ParseNode* receiverNode = idNode->pn_next; |
7689 | |
7690 | if (!emitTree(receiverNode)) { |
7691 | return false; |
7692 | } |
7693 | |
7694 | if (!emitTree(idNode)) { |
7695 | return false; |
7696 | } |
7697 | |
7698 | if (!emitTree(objNode)) { |
7699 | return false; |
7700 | } |
7701 | |
7702 | return emitElemOpBase(JSOp::GetElemSuper); |
7703 | } |
7704 | |
7705 | bool BytecodeEmitter::emitSelfHostedToNumeric(CallNode* callNode) { |
7706 | ListNode* argsList = callNode->args(); |
7707 | |
7708 | MOZ_ASSERT(argsList->count() == 1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(argsList->count() == 1)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(argsList->count() == 1))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 1" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7708); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1" ")"); do { *((volatile int*)__null) = 7708; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7709 | |
7710 | ParseNode* argNode = argsList->head(); |
7711 | |
7712 | if (!emitTree(argNode)) { |
7713 | return false; |
7714 | } |
7715 | |
7716 | return emit1(JSOp::ToNumeric); |
7717 | } |
7718 | |
7719 | bool BytecodeEmitter::emitSelfHostedToString(CallNode* callNode) { |
7720 | ListNode* argsList = callNode->args(); |
7721 | |
7722 | MOZ_ASSERT(argsList->count() == 1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(argsList->count() == 1)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(argsList->count() == 1))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 1" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7722); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1" ")"); do { *((volatile int*)__null) = 7722; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7723 | |
7724 | ParseNode* argNode = argsList->head(); |
7725 | |
7726 | if (!emitTree(argNode)) { |
7727 | return false; |
7728 | } |
7729 | |
7730 | return emit1(JSOp::ToString); |
7731 | } |
7732 | |
7733 | bool BytecodeEmitter::emitSelfHostedIsNullOrUndefined(CallNode* callNode) { |
7734 | ListNode* argsList = callNode->args(); |
7735 | |
7736 | MOZ_ASSERT(argsList->count() == 1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(argsList->count() == 1)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(argsList->count() == 1))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 1" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7736); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1" ")"); do { *((volatile int*)__null) = 7736; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7737 | |
7738 | ParseNode* argNode = argsList->head(); |
7739 | |
7740 | if (!emitTree(argNode)) { |
7741 | // [stack] ARG |
7742 | return false; |
7743 | } |
7744 | if (!emit1(JSOp::IsNullOrUndefined)) { |
7745 | // [stack] ARG IS_NULL_OR_UNDEF |
7746 | return false; |
7747 | } |
7748 | if (!emit1(JSOp::Swap)) { |
7749 | // [stack] IS_NULL_OR_UNDEF ARG |
7750 | return false; |
7751 | } |
7752 | if (!emit1(JSOp::Pop)) { |
7753 | // [stack] IS_NULL_OR_UNDEF |
7754 | return false; |
7755 | } |
7756 | return true; |
7757 | } |
7758 | |
7759 | bool BytecodeEmitter::emitSelfHostedIteratorClose(CallNode* callNode) { |
7760 | ListNode* argsList = callNode->args(); |
7761 | MOZ_ASSERT(argsList->count() == 1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(argsList->count() == 1)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(argsList->count() == 1))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 1" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7761); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1" ")"); do { *((volatile int*)__null) = 7761; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7762 | |
7763 | ParseNode* argNode = argsList->head(); |
7764 | if (!emitTree(argNode)) { |
7765 | // [stack] ARG |
7766 | return false; |
7767 | } |
7768 | |
7769 | if (!emit2(JSOp::CloseIter, uint8_t(CompletionKind::Normal))) { |
7770 | // [stack] |
7771 | return false; |
7772 | } |
7773 | |
7774 | // This is still a call node, so we must generate a stack value. |
7775 | if (!emit1(JSOp::Undefined)) { |
7776 | // [stack] RVAL |
7777 | return false; |
7778 | } |
7779 | |
7780 | return true; |
7781 | } |
7782 | |
7783 | bool BytecodeEmitter::emitSelfHostedGetBuiltinConstructorOrPrototype( |
7784 | CallNode* callNode, bool isConstructor) { |
7785 | ListNode* argsList = callNode->args(); |
7786 | |
7787 | MOZ_ASSERT(argsList->count() == 1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(argsList->count() == 1)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(argsList->count() == 1))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 1" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7787); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1" ")"); do { *((volatile int*)__null) = 7787; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7788 | |
7789 | ParseNode* argNode = argsList->head(); |
7790 | |
7791 | if (!argNode->isKind(ParseNodeKind::StringExpr)) { |
7792 | reportError(callNode, JSMSG_UNEXPECTED_TYPE, "built-in name", |
7793 | "not a string constant"); |
7794 | return false; |
7795 | } |
7796 | |
7797 | auto name = argNode->as<NameNode>().atom(); |
7798 | |
7799 | BuiltinObjectKind kind; |
7800 | if (isConstructor) { |
7801 | kind = BuiltinConstructorForName(name); |
7802 | } else { |
7803 | kind = BuiltinPrototypeForName(name); |
7804 | } |
7805 | |
7806 | if (kind == BuiltinObjectKind::None) { |
7807 | reportError(callNode, JSMSG_UNEXPECTED_TYPE, "built-in name", |
7808 | "not a valid built-in"); |
7809 | return false; |
7810 | } |
7811 | |
7812 | return emitBuiltinObject(kind); |
7813 | } |
7814 | |
7815 | bool BytecodeEmitter::emitSelfHostedGetBuiltinConstructor(CallNode* callNode) { |
7816 | return emitSelfHostedGetBuiltinConstructorOrPrototype( |
7817 | callNode, /* isConstructor = */ true); |
7818 | } |
7819 | |
7820 | bool BytecodeEmitter::emitSelfHostedGetBuiltinPrototype(CallNode* callNode) { |
7821 | return emitSelfHostedGetBuiltinConstructorOrPrototype( |
7822 | callNode, /* isConstructor = */ false); |
7823 | } |
7824 | |
7825 | JS::SymbolCode ParserAtomToSymbolCode(TaggedParserAtomIndex atom) { |
7826 | // NOTE: This is a linear search, but the set of entries is quite small and |
7827 | // this is only used for initial self-hosted parse. |
7828 | #define MATCH_WELL_KNOWN_SYMBOL(NAME) \ |
7829 | if (atom == TaggedParserAtomIndex::WellKnown::NAME()) { \ |
7830 | return JS::SymbolCode::NAME; \ |
7831 | } |
7832 | JS_FOR_EACH_WELL_KNOWN_SYMBOL(MATCH_WELL_KNOWN_SYMBOL)MATCH_WELL_KNOWN_SYMBOL(isConcatSpreadable) MATCH_WELL_KNOWN_SYMBOL (iterator) MATCH_WELL_KNOWN_SYMBOL(match) MATCH_WELL_KNOWN_SYMBOL (replace) MATCH_WELL_KNOWN_SYMBOL(search) MATCH_WELL_KNOWN_SYMBOL (species) MATCH_WELL_KNOWN_SYMBOL(hasInstance) MATCH_WELL_KNOWN_SYMBOL (split) MATCH_WELL_KNOWN_SYMBOL(toPrimitive) MATCH_WELL_KNOWN_SYMBOL (toStringTag) MATCH_WELL_KNOWN_SYMBOL(unscopables) MATCH_WELL_KNOWN_SYMBOL (asyncIterator) MATCH_WELL_KNOWN_SYMBOL(matchAll) |
7833 | #undef MATCH_WELL_KNOWN_SYMBOL |
7834 | |
7835 | return JS::SymbolCode::Limit; |
7836 | } |
7837 | |
7838 | bool BytecodeEmitter::emitSelfHostedGetBuiltinSymbol(CallNode* callNode) { |
7839 | ListNode* argsList = callNode->args(); |
7840 | |
7841 | MOZ_ASSERT(argsList->count() == 1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(argsList->count() == 1)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(argsList->count() == 1))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 1" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7841); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1" ")"); do { *((volatile int*)__null) = 7841; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7842 | |
7843 | ParseNode* argNode = argsList->head(); |
7844 | |
7845 | if (!argNode->isKind(ParseNodeKind::StringExpr)) { |
7846 | reportError(callNode, JSMSG_UNEXPECTED_TYPE, "built-in name", |
7847 | "not a string constant"); |
7848 | return false; |
7849 | } |
7850 | |
7851 | auto name = argNode->as<NameNode>().atom(); |
7852 | |
7853 | JS::SymbolCode code = ParserAtomToSymbolCode(name); |
7854 | if (code == JS::SymbolCode::Limit) { |
7855 | reportError(callNode, JSMSG_UNEXPECTED_TYPE, "built-in name", |
7856 | "not a valid built-in"); |
7857 | return false; |
7858 | } |
7859 | |
7860 | return emit2(JSOp::Symbol, uint8_t(code)); |
7861 | } |
7862 | |
7863 | bool BytecodeEmitter::emitSelfHostedArgumentsLength(CallNode* callNode) { |
7864 | MOZ_ASSERT(!sc->asFunctionBox()->needsArgsObj())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!sc->asFunctionBox()->needsArgsObj())>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(!sc->asFunctionBox()->needsArgsObj()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!sc->asFunctionBox()->needsArgsObj()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7864); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sc->asFunctionBox()->needsArgsObj()" ")"); do { *((volatile int*)__null) = 7864; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7865 | sc->asFunctionBox()->setUsesArgumentsIntrinsics(); |
7866 | |
7867 | MOZ_ASSERT(callNode->args()->count() == 0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(callNode->args()->count() == 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(callNode->args()->count () == 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("callNode->args()->count() == 0", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7867); AnnotateMozCrashReason("MOZ_ASSERT" "(" "callNode->args()->count() == 0" ")"); do { *((volatile int*)__null) = 7867; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7868 | |
7869 | return emit1(JSOp::ArgumentsLength); |
7870 | } |
7871 | |
7872 | bool BytecodeEmitter::emitSelfHostedGetArgument(CallNode* callNode) { |
7873 | MOZ_ASSERT(!sc->asFunctionBox()->needsArgsObj())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!sc->asFunctionBox()->needsArgsObj())>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(!sc->asFunctionBox()->needsArgsObj()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!sc->asFunctionBox()->needsArgsObj()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7873); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sc->asFunctionBox()->needsArgsObj()" ")"); do { *((volatile int*)__null) = 7873; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7874 | sc->asFunctionBox()->setUsesArgumentsIntrinsics(); |
7875 | |
7876 | ListNode* argsList = callNode->args(); |
7877 | MOZ_ASSERT(argsList->count() == 1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(argsList->count() == 1)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(argsList->count() == 1))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 1" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7877); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1" ")"); do { *((volatile int*)__null) = 7877; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7878 | |
7879 | ParseNode* argNode = argsList->head(); |
7880 | if (!emitTree(argNode)) { |
7881 | return false; |
7882 | } |
7883 | |
7884 | return emit1(JSOp::GetActualArg); |
7885 | } |
7886 | |
7887 | #ifdef DEBUG1 |
7888 | void BytecodeEmitter::assertSelfHostedExpectedTopLevel(ParseNode* node) { |
7889 | // The function argument is expected to be a simple binding/function name. |
7890 | // Eg. `function foo() { }; SpecialIntrinsic(foo)` |
7891 | MOZ_ASSERT(node->isKind(ParseNodeKind::Name),do { static_assert( mozilla::detail::AssertionConditionType< decltype(node->isKind(ParseNodeKind::Name))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(node->isKind(ParseNodeKind ::Name)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("node->isKind(ParseNodeKind::Name)" " (" "argument must be a function name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7892); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::Name)" ") (" "argument must be a function name" ")"); do { *((volatile int*)__null) = 7892; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
7892 | "argument must be a function name")do { static_assert( mozilla::detail::AssertionConditionType< decltype(node->isKind(ParseNodeKind::Name))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(node->isKind(ParseNodeKind ::Name)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("node->isKind(ParseNodeKind::Name)" " (" "argument must be a function name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7892); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::Name)" ") (" "argument must be a function name" ")"); do { *((volatile int*)__null) = 7892; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
7893 | TaggedParserAtomIndex targetName = node->as<NameNode>().name(); |
7894 | |
7895 | // The special intrinsics must follow the target functions definition. A |
7896 | // simple assert is fine here since any hoisted function will cause a non-null |
7897 | // value to be set here. |
7898 | MOZ_ASSERT(prevSelfHostedTopLevelFunction)do { static_assert( mozilla::detail::AssertionConditionType< decltype(prevSelfHostedTopLevelFunction)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(prevSelfHostedTopLevelFunction ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "prevSelfHostedTopLevelFunction", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7898); AnnotateMozCrashReason("MOZ_ASSERT" "(" "prevSelfHostedTopLevelFunction" ")"); do { *((volatile int*)__null) = 7898; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7899 | |
7900 | // The target function must match the most recently defined top-level |
7901 | // self-hosted function. |
7902 | MOZ_ASSERT(prevSelfHostedTopLevelFunction->explicitName() == targetName,do { static_assert( mozilla::detail::AssertionConditionType< decltype(prevSelfHostedTopLevelFunction->explicitName() == targetName)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(prevSelfHostedTopLevelFunction-> explicitName() == targetName))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("prevSelfHostedTopLevelFunction->explicitName() == targetName" " (" "selfhost decorator must immediately follow target function" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7903); AnnotateMozCrashReason("MOZ_ASSERT" "(" "prevSelfHostedTopLevelFunction->explicitName() == targetName" ") (" "selfhost decorator must immediately follow target function" ")"); do { *((volatile int*)__null) = 7903; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
7903 | "selfhost decorator must immediately follow target function")do { static_assert( mozilla::detail::AssertionConditionType< decltype(prevSelfHostedTopLevelFunction->explicitName() == targetName)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(prevSelfHostedTopLevelFunction-> explicitName() == targetName))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("prevSelfHostedTopLevelFunction->explicitName() == targetName" " (" "selfhost decorator must immediately follow target function" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7903); AnnotateMozCrashReason("MOZ_ASSERT" "(" "prevSelfHostedTopLevelFunction->explicitName() == targetName" ") (" "selfhost decorator must immediately follow target function" ")"); do { *((volatile int*)__null) = 7903; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7904 | } |
7905 | #endif |
7906 | |
7907 | bool BytecodeEmitter::emitSelfHostedSetIsInlinableLargeFunction( |
7908 | CallNode* callNode) { |
7909 | #ifdef DEBUG1 |
7910 | ListNode* argsList = callNode->args(); |
7911 | |
7912 | MOZ_ASSERT(argsList->count() == 1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(argsList->count() == 1)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(argsList->count() == 1))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 1" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7912); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1" ")"); do { *((volatile int*)__null) = 7912; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7913 | |
7914 | assertSelfHostedExpectedTopLevel(argsList->head()); |
7915 | #endif |
7916 | |
7917 | MOZ_ASSERT(prevSelfHostedTopLevelFunction->isInitialCompilation)do { static_assert( mozilla::detail::AssertionConditionType< decltype(prevSelfHostedTopLevelFunction->isInitialCompilation )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(prevSelfHostedTopLevelFunction->isInitialCompilation ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "prevSelfHostedTopLevelFunction->isInitialCompilation", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7917); AnnotateMozCrashReason("MOZ_ASSERT" "(" "prevSelfHostedTopLevelFunction->isInitialCompilation" ")"); do { *((volatile int*)__null) = 7917; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7918 | prevSelfHostedTopLevelFunction->setIsInlinableLargeFunction(); |
7919 | |
7920 | // This is still a call node, so we must generate a stack value. |
7921 | return emit1(JSOp::Undefined); |
7922 | } |
7923 | |
7924 | bool BytecodeEmitter::emitSelfHostedSetCanonicalName(CallNode* callNode) { |
7925 | ListNode* argsList = callNode->args(); |
7926 | |
7927 | MOZ_ASSERT(argsList->count() == 2)do { static_assert( mozilla::detail::AssertionConditionType< decltype(argsList->count() == 2)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(argsList->count() == 2))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 2" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7927); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2" ")"); do { *((volatile int*)__null) = 7927; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7928 | |
7929 | #ifdef DEBUG1 |
7930 | assertSelfHostedExpectedTopLevel(argsList->head()); |
7931 | #endif |
7932 | |
7933 | ParseNode* nameNode = argsList->last(); |
7934 | MOZ_ASSERT(nameNode->isKind(ParseNodeKind::StringExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(nameNode->isKind(ParseNodeKind::StringExpr))>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(nameNode->isKind(ParseNodeKind::StringExpr)))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("nameNode->isKind(ParseNodeKind::StringExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7934); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nameNode->isKind(ParseNodeKind::StringExpr)" ")"); do { *((volatile int*)__null) = 7934; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7935 | TaggedParserAtomIndex specName = nameNode->as<NameNode>().atom(); |
7936 | // Canonical name must be atomized. |
7937 | compilationState.parserAtoms.markUsedByStencil(specName, |
7938 | ParserAtom::Atomize::Yes); |
7939 | |
7940 | // Store the canonical name for instantiation. |
7941 | prevSelfHostedTopLevelFunction->functionStencil().setSelfHostedCanonicalName( |
7942 | specName); |
7943 | |
7944 | return emit1(JSOp::Undefined); |
7945 | } |
7946 | |
7947 | #ifdef DEBUG1 |
7948 | void BytecodeEmitter::assertSelfHostedUnsafeGetReservedSlot( |
7949 | ListNode* argsList) { |
7950 | MOZ_ASSERT(argsList->count() == 2)do { static_assert( mozilla::detail::AssertionConditionType< decltype(argsList->count() == 2)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(argsList->count() == 2))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 2" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7950); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2" ")"); do { *((volatile int*)__null) = 7950; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7951 | |
7952 | ParseNode* objNode = argsList->head(); |
7953 | ParseNode* slotNode = objNode->pn_next; |
7954 | |
7955 | // Ensure that the slot argument is fixed, this is required by the JITs. |
7956 | MOZ_ASSERT(slotNode->isKind(ParseNodeKind::NumberExpr),do { static_assert( mozilla::detail::AssertionConditionType< decltype(slotNode->isKind(ParseNodeKind::NumberExpr))>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(slotNode->isKind(ParseNodeKind::NumberExpr)))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("slotNode->isKind(ParseNodeKind::NumberExpr)" " (" "slot argument must be a constant" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7957); AnnotateMozCrashReason("MOZ_ASSERT" "(" "slotNode->isKind(ParseNodeKind::NumberExpr)" ") (" "slot argument must be a constant" ")"); do { *((volatile int*)__null) = 7957; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
7957 | "slot argument must be a constant")do { static_assert( mozilla::detail::AssertionConditionType< decltype(slotNode->isKind(ParseNodeKind::NumberExpr))>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(slotNode->isKind(ParseNodeKind::NumberExpr)))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("slotNode->isKind(ParseNodeKind::NumberExpr)" " (" "slot argument must be a constant" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7957); AnnotateMozCrashReason("MOZ_ASSERT" "(" "slotNode->isKind(ParseNodeKind::NumberExpr)" ") (" "slot argument must be a constant" ")"); do { *((volatile int*)__null) = 7957; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
7958 | } |
7959 | |
7960 | void BytecodeEmitter::assertSelfHostedUnsafeSetReservedSlot( |
7961 | ListNode* argsList) { |
7962 | MOZ_ASSERT(argsList->count() == 3)do { static_assert( mozilla::detail::AssertionConditionType< decltype(argsList->count() == 3)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(argsList->count() == 3))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 3" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7962); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 3" ")"); do { *((volatile int*)__null) = 7962; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7963 | |
7964 | ParseNode* objNode = argsList->head(); |
7965 | ParseNode* slotNode = objNode->pn_next; |
7966 | |
7967 | // Ensure that the slot argument is fixed, this is required by the JITs. |
7968 | MOZ_ASSERT(slotNode->isKind(ParseNodeKind::NumberExpr),do { static_assert( mozilla::detail::AssertionConditionType< decltype(slotNode->isKind(ParseNodeKind::NumberExpr))>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(slotNode->isKind(ParseNodeKind::NumberExpr)))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("slotNode->isKind(ParseNodeKind::NumberExpr)" " (" "slot argument must be a constant" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7969); AnnotateMozCrashReason("MOZ_ASSERT" "(" "slotNode->isKind(ParseNodeKind::NumberExpr)" ") (" "slot argument must be a constant" ")"); do { *((volatile int*)__null) = 7969; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
7969 | "slot argument must be a constant")do { static_assert( mozilla::detail::AssertionConditionType< decltype(slotNode->isKind(ParseNodeKind::NumberExpr))>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(slotNode->isKind(ParseNodeKind::NumberExpr)))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("slotNode->isKind(ParseNodeKind::NumberExpr)" " (" "slot argument must be a constant" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7969); AnnotateMozCrashReason("MOZ_ASSERT" "(" "slotNode->isKind(ParseNodeKind::NumberExpr)" ") (" "slot argument must be a constant" ")"); do { *((volatile int*)__null) = 7969; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
7970 | } |
7971 | #endif |
7972 | |
7973 | /* A version of emitCalleeAndThis for the optional cases: |
7974 | * * a?.() |
7975 | * * a?.b() |
7976 | * * a?.["b"]() |
7977 | * * (a?.b)() |
7978 | * * a?.#b() |
7979 | * |
7980 | * See emitCallOrNew and emitOptionalCall for more context. |
7981 | */ |
7982 | bool BytecodeEmitter::emitOptionalCalleeAndThis(ParseNode* callee, |
7983 | CallNode* call, |
7984 | CallOrNewEmitter& cone, |
7985 | OptionalEmitter& oe) { |
7986 | AutoCheckRecursionLimit recursion(fc); |
7987 | if (!recursion.check(fc)) { |
7988 | return false; |
7989 | } |
7990 | |
7991 | switch (ParseNodeKind kind = callee->getKind()) { |
7992 | case ParseNodeKind::Name: { |
7993 | auto name = callee->as<NameNode>().name(); |
7994 | if (!cone.emitNameCallee(name)) { |
7995 | // [stack] CALLEE THIS |
7996 | return false; |
7997 | } |
7998 | break; |
7999 | } |
8000 | |
8001 | case ParseNodeKind::OptionalDotExpr: { |
8002 | MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting)do { static_assert( mozilla::detail::AssertionConditionType< decltype(emitterMode != BytecodeEmitter::SelfHosting)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(emitterMode != BytecodeEmitter::SelfHosting))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("emitterMode != BytecodeEmitter::SelfHosting" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8002); AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode != BytecodeEmitter::SelfHosting" ")"); do { *((volatile int*)__null) = 8002; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8003 | OptionalPropertyAccess* prop = &callee->as<OptionalPropertyAccess>(); |
8004 | bool isSuper = false; |
8005 | |
8006 | PropOpEmitter& poe = cone.prepareForPropCallee(isSuper); |
8007 | if (!emitOptionalDotExpression(prop, poe, isSuper, oe)) { |
8008 | // [stack] CALLEE THIS |
8009 | return false; |
8010 | } |
8011 | break; |
8012 | } |
8013 | case ParseNodeKind::ArgumentsLength: |
8014 | case ParseNodeKind::DotExpr: { |
8015 | MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting)do { static_assert( mozilla::detail::AssertionConditionType< decltype(emitterMode != BytecodeEmitter::SelfHosting)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(emitterMode != BytecodeEmitter::SelfHosting))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("emitterMode != BytecodeEmitter::SelfHosting" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8015); AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode != BytecodeEmitter::SelfHosting" ")"); do { *((volatile int*)__null) = 8015; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8016 | PropertyAccess* prop = &callee->as<PropertyAccess>(); |
8017 | bool isSuper = prop->isSuper(); |
8018 | |
8019 | PropOpEmitter& poe = cone.prepareForPropCallee(isSuper); |
8020 | if (!emitOptionalDotExpression(prop, poe, isSuper, oe)) { |
8021 | // [stack] CALLEE THIS |
8022 | return false; |
8023 | } |
8024 | break; |
8025 | } |
8026 | |
8027 | case ParseNodeKind::OptionalElemExpr: { |
8028 | OptionalPropertyByValue* elem = &callee->as<OptionalPropertyByValue>(); |
8029 | bool isSuper = false; |
8030 | MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!elem->key().isKind(ParseNodeKind::PrivateName))> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!elem->key().isKind(ParseNodeKind::PrivateName))) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!elem->key().isKind(ParseNodeKind::PrivateName)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8030); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)" ")"); do { *((volatile int*)__null) = 8030; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8031 | ElemOpEmitter& eoe = cone.prepareForElemCallee(isSuper); |
8032 | if (!emitOptionalElemExpression(elem, eoe, isSuper, oe)) { |
8033 | // [stack] CALLEE THIS |
8034 | return false; |
8035 | } |
8036 | break; |
8037 | } |
8038 | case ParseNodeKind::ElemExpr: { |
8039 | PropertyByValue* elem = &callee->as<PropertyByValue>(); |
8040 | bool isSuper = elem->isSuper(); |
8041 | MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!elem->key().isKind(ParseNodeKind::PrivateName))> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!elem->key().isKind(ParseNodeKind::PrivateName))) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!elem->key().isKind(ParseNodeKind::PrivateName)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8041); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)" ")"); do { *((volatile int*)__null) = 8041; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8042 | ElemOpEmitter& eoe = cone.prepareForElemCallee(isSuper); |
8043 | if (!emitOptionalElemExpression(elem, eoe, isSuper, oe)) { |
8044 | // [stack] CALLEE THIS |
8045 | return false; |
8046 | } |
8047 | break; |
8048 | } |
8049 | |
8050 | case ParseNodeKind::PrivateMemberExpr: |
8051 | case ParseNodeKind::OptionalPrivateMemberExpr: { |
8052 | PrivateMemberAccessBase* privateExpr = |
8053 | &callee->as<PrivateMemberAccessBase>(); |
8054 | PrivateOpEmitter& xoe = |
8055 | cone.prepareForPrivateCallee(privateExpr->privateName().name()); |
8056 | if (!emitOptionalPrivateExpression(privateExpr, xoe, oe)) { |
8057 | // [stack] CALLEE THIS |
8058 | return false; |
8059 | } |
8060 | break; |
8061 | } |
8062 | |
8063 | case ParseNodeKind::Function: |
8064 | if (!cone.prepareForFunctionCallee()) { |
8065 | return false; |
8066 | } |
8067 | if (!emitOptionalTree(callee, oe)) { |
8068 | // [stack] CALLEE |
8069 | return false; |
8070 | } |
8071 | break; |
8072 | |
8073 | case ParseNodeKind::OptionalChain: { |
8074 | return emitCalleeAndThisForOptionalChain(&callee->as<UnaryNode>(), call, |
8075 | cone); |
8076 | } |
8077 | |
8078 | default: |
8079 | MOZ_RELEASE_ASSERT(kind != ParseNodeKind::SuperBase)do { static_assert( mozilla::detail::AssertionConditionType< decltype(kind != ParseNodeKind::SuperBase)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(kind != ParseNodeKind::SuperBase ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "kind != ParseNodeKind::SuperBase", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8079); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "kind != ParseNodeKind::SuperBase" ")"); do { *((volatile int*)__null) = 8079; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8080 | |
8081 | if (!cone.prepareForOtherCallee()) { |
8082 | return false; |
8083 | } |
8084 | if (!emitOptionalTree(callee, oe)) { |
8085 | // [stack] CALLEE |
8086 | return false; |
8087 | } |
8088 | break; |
8089 | } |
8090 | |
8091 | if (!cone.emitThis()) { |
8092 | // [stack] CALLEE THIS |
8093 | return false; |
8094 | } |
8095 | |
8096 | return true; |
8097 | } |
8098 | |
8099 | bool BytecodeEmitter::emitCalleeAndThis(ParseNode* callee, CallNode* maybeCall, |
8100 | CallOrNewEmitter& cone) { |
8101 | MOZ_ASSERT_IF(maybeCall, maybeCall->callee() == callee)do { if (maybeCall) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(maybeCall->callee() == callee)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(maybeCall->callee() == callee ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "maybeCall->callee() == callee", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8101); AnnotateMozCrashReason("MOZ_ASSERT" "(" "maybeCall->callee() == callee" ")"); do { *((volatile int*)__null) = 8101; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
8102 | |
8103 | switch (callee->getKind()) { |
8104 | case ParseNodeKind::Name: { |
8105 | auto name = callee->as<NameNode>().name(); |
8106 | if (!cone.emitNameCallee(name)) { |
8107 | // [stack] CALLEE THIS? |
8108 | return false; |
8109 | } |
8110 | break; |
8111 | } |
8112 | case ParseNodeKind::ArgumentsLength: |
8113 | case ParseNodeKind::DotExpr: { |
8114 | MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting)do { static_assert( mozilla::detail::AssertionConditionType< decltype(emitterMode != BytecodeEmitter::SelfHosting)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(emitterMode != BytecodeEmitter::SelfHosting))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("emitterMode != BytecodeEmitter::SelfHosting" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8114); AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode != BytecodeEmitter::SelfHosting" ")"); do { *((volatile int*)__null) = 8114; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8115 | PropertyAccess* prop = &callee->as<PropertyAccess>(); |
8116 | bool isSuper = prop->isSuper(); |
8117 | |
8118 | PropOpEmitter& poe = cone.prepareForPropCallee(isSuper); |
8119 | if (!poe.prepareForObj()) { |
8120 | return false; |
8121 | } |
8122 | if (isSuper) { |
8123 | UnaryNode* base = &prop->expression().as<UnaryNode>(); |
8124 | if (!emitGetThisForSuperBase(base)) { |
8125 | // [stack] THIS |
8126 | return false; |
8127 | } |
8128 | } else { |
8129 | if (!emitPropLHS(prop)) { |
8130 | // [stack] OBJ |
8131 | return false; |
8132 | } |
8133 | } |
8134 | if (!poe.emitGet(prop->key().atom())) { |
8135 | // [stack] CALLEE THIS? |
8136 | return false; |
8137 | } |
8138 | |
8139 | break; |
8140 | } |
8141 | case ParseNodeKind::ElemExpr: { |
8142 | MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting)do { static_assert( mozilla::detail::AssertionConditionType< decltype(emitterMode != BytecodeEmitter::SelfHosting)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(emitterMode != BytecodeEmitter::SelfHosting))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("emitterMode != BytecodeEmitter::SelfHosting" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8142); AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode != BytecodeEmitter::SelfHosting" ")"); do { *((volatile int*)__null) = 8142; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8143 | PropertyByValue* elem = &callee->as<PropertyByValue>(); |
8144 | bool isSuper = elem->isSuper(); |
8145 | MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!elem->key().isKind(ParseNodeKind::PrivateName))> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!elem->key().isKind(ParseNodeKind::PrivateName))) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!elem->key().isKind(ParseNodeKind::PrivateName)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8145); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)" ")"); do { *((volatile int*)__null) = 8145; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8146 | ElemOpEmitter& eoe = cone.prepareForElemCallee(isSuper); |
8147 | if (!emitElemObjAndKey(elem, eoe)) { |
8148 | // [stack] # if Super |
8149 | // [stack] THIS? THIS KEY |
8150 | // [stack] # otherwise |
8151 | // [stack] OBJ? OBJ KEY |
8152 | return false; |
8153 | } |
8154 | if (!eoe.emitGet()) { |
8155 | // [stack] CALLEE THIS? |
8156 | return false; |
8157 | } |
8158 | |
8159 | break; |
8160 | } |
8161 | case ParseNodeKind::PrivateMemberExpr: { |
8162 | MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting)do { static_assert( mozilla::detail::AssertionConditionType< decltype(emitterMode != BytecodeEmitter::SelfHosting)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(emitterMode != BytecodeEmitter::SelfHosting))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("emitterMode != BytecodeEmitter::SelfHosting" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8162); AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode != BytecodeEmitter::SelfHosting" ")"); do { *((volatile int*)__null) = 8162; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8163 | PrivateMemberAccessBase* privateExpr = |
8164 | &callee->as<PrivateMemberAccessBase>(); |
8165 | PrivateOpEmitter& xoe = |
8166 | cone.prepareForPrivateCallee(privateExpr->privateName().name()); |
8167 | if (!emitTree(&privateExpr->expression())) { |
8168 | // [stack] OBJ |
8169 | return false; |
8170 | } |
8171 | if (!xoe.emitReference()) { |
8172 | // [stack] OBJ NAME |
8173 | return false; |
8174 | } |
8175 | if (!xoe.emitGetForCallOrNew()) { |
8176 | // [stack] CALLEE THIS |
8177 | return false; |
8178 | } |
8179 | |
8180 | break; |
8181 | } |
8182 | case ParseNodeKind::Function: |
8183 | if (!cone.prepareForFunctionCallee()) { |
8184 | return false; |
8185 | } |
8186 | if (!emitTree(callee)) { |
8187 | // [stack] CALLEE |
8188 | return false; |
8189 | } |
8190 | break; |
8191 | case ParseNodeKind::SuperBase: |
8192 | MOZ_ASSERT(maybeCall)do { static_assert( mozilla::detail::AssertionConditionType< decltype(maybeCall)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(maybeCall))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("maybeCall", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8192); AnnotateMozCrashReason("MOZ_ASSERT" "(" "maybeCall" ")" ); do { *((volatile int*)__null) = 8192; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8193 | MOZ_ASSERT(maybeCall->isKind(ParseNodeKind::SuperCallExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(maybeCall->isKind(ParseNodeKind::SuperCallExpr))> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(maybeCall->isKind(ParseNodeKind::SuperCallExpr))) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("maybeCall->isKind(ParseNodeKind::SuperCallExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8193); AnnotateMozCrashReason("MOZ_ASSERT" "(" "maybeCall->isKind(ParseNodeKind::SuperCallExpr)" ")"); do { *((volatile int*)__null) = 8193; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8194 | MOZ_ASSERT(callee->isKind(ParseNodeKind::SuperBase))do { static_assert( mozilla::detail::AssertionConditionType< decltype(callee->isKind(ParseNodeKind::SuperBase))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(callee->isKind(ParseNodeKind::SuperBase)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("callee->isKind(ParseNodeKind::SuperBase)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8194); AnnotateMozCrashReason("MOZ_ASSERT" "(" "callee->isKind(ParseNodeKind::SuperBase)" ")"); do { *((volatile int*)__null) = 8194; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8195 | if (!cone.emitSuperCallee()) { |
8196 | // [stack] CALLEE IsConstructing |
8197 | return false; |
8198 | } |
8199 | break; |
8200 | case ParseNodeKind::OptionalChain: { |
8201 | MOZ_ASSERT(maybeCall)do { static_assert( mozilla::detail::AssertionConditionType< decltype(maybeCall)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(maybeCall))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("maybeCall", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8201); AnnotateMozCrashReason("MOZ_ASSERT" "(" "maybeCall" ")" ); do { *((volatile int*)__null) = 8201; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8202 | return emitCalleeAndThisForOptionalChain(&callee->as<UnaryNode>(), |
8203 | maybeCall, cone); |
8204 | } |
8205 | default: |
8206 | if (!cone.prepareForOtherCallee()) { |
8207 | return false; |
8208 | } |
8209 | if (!emitTree(callee)) { |
8210 | return false; |
8211 | } |
8212 | break; |
8213 | } |
8214 | |
8215 | if (!cone.emitThis()) { |
8216 | // [stack] CALLEE THIS |
8217 | return false; |
8218 | } |
8219 | |
8220 | return true; |
8221 | } |
8222 | |
8223 | ParseNode* BytecodeEmitter::getCoordNode(ParseNode* callNode, |
8224 | ParseNode* calleeNode, JSOp op, |
8225 | ListNode* argsList) const { |
8226 | ParseNode* coordNode = callNode; |
8227 | if (op == JSOp::Call || op == JSOp::SpreadCall) { |
8228 | // Default to using the location of the `(` itself. |
8229 | // obj[expr]() // expression |
8230 | // ^ // column coord |
8231 | coordNode = argsList; |
8232 | |
8233 | switch (calleeNode->getKind()) { |
8234 | case ParseNodeKind::ArgumentsLength: |
8235 | case ParseNodeKind::DotExpr: |
8236 | // Use the position of a property access identifier. |
8237 | // |
8238 | // obj().aprop() // expression |
8239 | // ^ // column coord |
8240 | // |
8241 | // Note: Because of the constant folding logic in FoldElement, |
8242 | // this case also applies for constant string properties. |
8243 | // |
8244 | // obj()['aprop']() // expression |
8245 | // ^ // column coord |
8246 | coordNode = &calleeNode->as<PropertyAccess>().key(); |
8247 | break; |
8248 | case ParseNodeKind::Name: { |
8249 | // Use the start of callee name unless it is at a separator |
8250 | // or has no args. |
8251 | // |
8252 | // 2 + obj() // expression |
8253 | // ^ // column coord |
8254 | // |
8255 | if (argsList->empty() || |
8256 | !bytecodeSection().atSeparator(calleeNode->pn_pos.begin)) { |
8257 | // Use the start of callee names. |
8258 | coordNode = calleeNode; |
8259 | } |
8260 | break; |
8261 | } |
8262 | |
8263 | default: |
8264 | break; |
8265 | } |
8266 | } |
8267 | return coordNode; |
8268 | } |
8269 | |
8270 | bool BytecodeEmitter::emitArguments(ListNode* argsList, bool isCall, |
8271 | bool isSpread, CallOrNewEmitter& cone) { |
8272 | uint32_t argc = argsList->count(); |
8273 | if (argc >= ARGC_LIMIT) { |
8274 | reportError(argsList, |
8275 | isCall ? JSMSG_TOO_MANY_FUN_ARGS : JSMSG_TOO_MANY_CON_ARGS); |
8276 | return false; |
8277 | } |
8278 | if (!isSpread) { |
8279 | if (!cone.prepareForNonSpreadArguments()) { |
8280 | // [stack] CALLEE THIS |
8281 | return false; |
8282 | } |
8283 | for (ParseNode* arg : argsList->contents()) { |
8284 | if (!updateSourceCoordNotesIfNonLiteral(arg)) { |
8285 | return false; |
8286 | } |
8287 | if (!emitTree(arg)) { |
8288 | // [stack] CALLEE THIS ARG* |
8289 | return false; |
8290 | } |
8291 | } |
8292 | } else if (cone.wantSpreadOperand()) { |
8293 | auto* spreadNode = &argsList->head()->as<UnaryNode>(); |
8294 | if (!updateSourceCoordNotesIfNonLiteral(spreadNode->kid())) { |
8295 | return false; |
8296 | } |
8297 | if (!emitTree(spreadNode->kid())) { |
8298 | // [stack] CALLEE THIS ARG0 |
8299 | return false; |
8300 | } |
8301 | |
8302 | if (!cone.emitSpreadArgumentsTest()) { |
8303 | // [stack] CALLEE THIS ARG0 |
8304 | return false; |
8305 | } |
8306 | |
8307 | if (cone.wantSpreadIteration()) { |
8308 | if (!emitSpreadIntoArray(spreadNode)) { |
8309 | // [stack] CALLEE THIS ARR |
8310 | return false; |
8311 | } |
8312 | } |
8313 | |
8314 | if (!cone.emitSpreadArgumentsTestEnd()) { |
8315 | // [stack] CALLEE THIS ARR |
8316 | return false; |
8317 | } |
8318 | } else { |
8319 | if (!cone.prepareForSpreadArguments()) { |
8320 | // [stack] CALLEE THIS |
8321 | return false; |
8322 | } |
8323 | if (!emitArray(argsList)) { |
8324 | // [stack] CALLEE THIS ARR |
8325 | return false; |
8326 | } |
8327 | } |
8328 | |
8329 | return true; |
8330 | } |
8331 | |
8332 | bool BytecodeEmitter::emitOptionalCall(CallNode* callNode, OptionalEmitter& oe, |
8333 | ValueUsage valueUsage) { |
8334 | /* |
8335 | * A modified version of emitCallOrNew that handles optional calls. |
8336 | * |
8337 | * These include the following: |
8338 | * a?.() |
8339 | * a.b?.() |
8340 | * a.["b"]?.() |
8341 | * (a?.b)?.() |
8342 | * |
8343 | * See CallOrNewEmitter for more context. |
8344 | */ |
8345 | ParseNode* calleeNode = callNode->callee(); |
8346 | ListNode* argsList = callNode->args(); |
8347 | bool isSpread = IsSpreadOp(callNode->callOp()); |
8348 | JSOp op = callNode->callOp(); |
8349 | uint32_t argc = argsList->count(); |
8350 | bool isOptimizableSpread = isSpread && argc == 1; |
8351 | |
8352 | CallOrNewEmitter cone(this, op, |
8353 | isOptimizableSpread |
8354 | ? CallOrNewEmitter::ArgumentsKind::SingleSpread |
8355 | : CallOrNewEmitter::ArgumentsKind::Other, |
8356 | valueUsage); |
8357 | |
8358 | ParseNode* coordNode = getCoordNode(callNode, calleeNode, op, argsList); |
8359 | |
8360 | if (!emitOptionalCalleeAndThis(calleeNode, callNode, cone, oe)) { |
8361 | // [stack] CALLEE THIS |
8362 | return false; |
8363 | } |
8364 | |
8365 | if (callNode->isKind(ParseNodeKind::OptionalCallExpr)) { |
8366 | if (!oe.emitJumpShortCircuitForCall()) { |
8367 | // [stack] CALLEE THIS |
8368 | return false; |
8369 | } |
8370 | } |
8371 | |
8372 | if (!emitArguments(argsList, /* isCall = */ true, isSpread, cone)) { |
8373 | // [stack] CALLEE THIS ARGS... |
8374 | return false; |
8375 | } |
8376 | |
8377 | if (!cone.emitEnd(argc, coordNode->pn_pos.begin)) { |
8378 | // [stack] RVAL |
8379 | return false; |
8380 | } |
8381 | |
8382 | return true; |
8383 | } |
8384 | |
8385 | bool BytecodeEmitter::emitCallOrNew(CallNode* callNode, ValueUsage valueUsage) { |
8386 | /* |
8387 | * Emit callable invocation or operator new (constructor call) code. |
8388 | * First, emit code for the left operand to evaluate the callable or |
8389 | * constructable object expression. |
8390 | * |
8391 | * Then (or in a call case that has no explicit reference-base |
8392 | * object) we emit JSOp::Undefined to produce the undefined |this| |
8393 | * value required for calls (which non-strict mode functions |
8394 | * will box into the global object). |
8395 | */ |
8396 | bool isCall = callNode->isKind(ParseNodeKind::CallExpr) || |
8397 | callNode->isKind(ParseNodeKind::TaggedTemplateExpr); |
8398 | ParseNode* calleeNode = callNode->callee(); |
8399 | ListNode* argsList = callNode->args(); |
8400 | JSOp op = callNode->callOp(); |
8401 | |
8402 | if (calleeNode->isKind(ParseNodeKind::Name) && |
8403 | emitterMode == BytecodeEmitter::SelfHosting && op == JSOp::Call) { |
8404 | // Calls to "forceInterpreter", "callFunction", |
8405 | // "callContentFunction", or "resumeGenerator" in self-hosted |
8406 | // code generate inline bytecode. |
8407 | // |
8408 | // NOTE: The list of special instruction names has to be kept in sync with |
8409 | // "js/src/builtin/.eslintrc.js". |
8410 | auto calleeName = calleeNode->as<NameNode>().name(); |
8411 | if (calleeName == TaggedParserAtomIndex::WellKnown::callFunction()) { |
8412 | return emitSelfHostedCallFunction(callNode, JSOp::Call); |
8413 | } |
8414 | if (calleeName == TaggedParserAtomIndex::WellKnown::callContentFunction()) { |
8415 | return emitSelfHostedCallFunction(callNode, JSOp::CallContent); |
8416 | } |
8417 | if (calleeName == |
8418 | TaggedParserAtomIndex::WellKnown::constructContentFunction()) { |
8419 | return emitSelfHostedCallFunction(callNode, JSOp::NewContent); |
8420 | } |
8421 | if (calleeName == TaggedParserAtomIndex::WellKnown::resumeGenerator()) { |
8422 | return emitSelfHostedResumeGenerator(callNode); |
8423 | } |
8424 | if (calleeName == TaggedParserAtomIndex::WellKnown::forceInterpreter()) { |
8425 | return emitSelfHostedForceInterpreter(); |
8426 | } |
8427 | if (calleeName == TaggedParserAtomIndex::WellKnown::allowContentIter()) { |
8428 | return emitSelfHostedAllowContentIter(callNode); |
8429 | } |
8430 | if (calleeName == |
8431 | TaggedParserAtomIndex::WellKnown::allowContentIterWith()) { |
8432 | return emitSelfHostedAllowContentIterWith(callNode); |
8433 | } |
8434 | if (calleeName == |
8435 | TaggedParserAtomIndex::WellKnown::allowContentIterWithNext()) { |
8436 | return emitSelfHostedAllowContentIterWithNext(callNode); |
8437 | } |
8438 | if (calleeName == TaggedParserAtomIndex::WellKnown::DefineDataProperty() && |
8439 | argsList->count() == 3) { |
8440 | return emitSelfHostedDefineDataProperty(callNode); |
8441 | } |
8442 | if (calleeName == TaggedParserAtomIndex::WellKnown::hasOwn()) { |
8443 | return emitSelfHostedHasOwn(callNode); |
8444 | } |
8445 | if (calleeName == TaggedParserAtomIndex::WellKnown::getPropertySuper()) { |
8446 | return emitSelfHostedGetPropertySuper(callNode); |
8447 | } |
8448 | if (calleeName == TaggedParserAtomIndex::WellKnown::ToNumeric()) { |
8449 | return emitSelfHostedToNumeric(callNode); |
8450 | } |
8451 | if (calleeName == TaggedParserAtomIndex::WellKnown::ToString()) { |
8452 | return emitSelfHostedToString(callNode); |
8453 | } |
8454 | if (calleeName == |
8455 | TaggedParserAtomIndex::WellKnown::GetBuiltinConstructor()) { |
8456 | return emitSelfHostedGetBuiltinConstructor(callNode); |
8457 | } |
8458 | if (calleeName == TaggedParserAtomIndex::WellKnown::GetBuiltinPrototype()) { |
8459 | return emitSelfHostedGetBuiltinPrototype(callNode); |
8460 | } |
8461 | if (calleeName == TaggedParserAtomIndex::WellKnown::GetBuiltinSymbol()) { |
8462 | return emitSelfHostedGetBuiltinSymbol(callNode); |
8463 | } |
8464 | if (calleeName == TaggedParserAtomIndex::WellKnown::ArgumentsLength()) { |
8465 | return emitSelfHostedArgumentsLength(callNode); |
8466 | } |
8467 | if (calleeName == TaggedParserAtomIndex::WellKnown::GetArgument()) { |
8468 | return emitSelfHostedGetArgument(callNode); |
8469 | } |
8470 | if (calleeName == |
8471 | TaggedParserAtomIndex::WellKnown::SetIsInlinableLargeFunction()) { |
8472 | return emitSelfHostedSetIsInlinableLargeFunction(callNode); |
8473 | } |
8474 | if (calleeName == TaggedParserAtomIndex::WellKnown::SetCanonicalName()) { |
8475 | return emitSelfHostedSetCanonicalName(callNode); |
8476 | } |
8477 | if (calleeName == TaggedParserAtomIndex::WellKnown::IsNullOrUndefined()) { |
8478 | return emitSelfHostedIsNullOrUndefined(callNode); |
8479 | } |
8480 | if (calleeName == TaggedParserAtomIndex::WellKnown::IteratorClose()) { |
8481 | return emitSelfHostedIteratorClose(callNode); |
8482 | } |
8483 | #ifdef DEBUG1 |
8484 | if (calleeName == |
8485 | TaggedParserAtomIndex::WellKnown::UnsafeGetReservedSlot() || |
8486 | calleeName == TaggedParserAtomIndex::WellKnown:: |
8487 | UnsafeGetObjectFromReservedSlot() || |
8488 | calleeName == TaggedParserAtomIndex::WellKnown:: |
8489 | UnsafeGetInt32FromReservedSlot() || |
8490 | calleeName == TaggedParserAtomIndex::WellKnown:: |
8491 | UnsafeGetStringFromReservedSlot()) { |
8492 | // Make sure that this call is correct, but don't emit any special code. |
8493 | assertSelfHostedUnsafeGetReservedSlot(argsList); |
8494 | } |
8495 | if (calleeName == |
8496 | TaggedParserAtomIndex::WellKnown::UnsafeSetReservedSlot()) { |
8497 | // Make sure that this call is correct, but don't emit any special code. |
8498 | assertSelfHostedUnsafeSetReservedSlot(argsList); |
8499 | } |
8500 | #endif |
8501 | // Fall through |
8502 | } |
8503 | |
8504 | uint32_t argc = argsList->count(); |
8505 | bool isSpread = IsSpreadOp(op); |
8506 | bool isOptimizableSpread = isSpread && argc == 1; |
8507 | bool isDefaultDerivedClassConstructor = |
8508 | sc->isFunctionBox() && sc->asFunctionBox()->isDerivedClassConstructor() && |
8509 | sc->asFunctionBox()->isSyntheticFunction(); |
8510 | MOZ_ASSERT_IF(isDefaultDerivedClassConstructor, isOptimizableSpread)do { if (isDefaultDerivedClassConstructor) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(isOptimizableSpread )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(isOptimizableSpread))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("isOptimizableSpread", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8510); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isOptimizableSpread" ")"); do { *((volatile int*)__null) = 8510; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
8511 | CallOrNewEmitter cone( |
8512 | this, op, |
8513 | isOptimizableSpread |
8514 | ? isDefaultDerivedClassConstructor |
8515 | ? CallOrNewEmitter::ArgumentsKind::PassthroughRest |
8516 | : CallOrNewEmitter::ArgumentsKind::SingleSpread |
8517 | : CallOrNewEmitter::ArgumentsKind::Other, |
8518 | valueUsage); |
8519 | |
8520 | if (!emitCalleeAndThis(calleeNode, callNode, cone)) { |
8521 | // [stack] CALLEE THIS |
8522 | return false; |
8523 | } |
8524 | if (!emitArguments(argsList, isCall, isSpread, cone)) { |
8525 | // [stack] CALLEE THIS ARGS... |
8526 | return false; |
8527 | } |
8528 | |
8529 | // Push new.target for construct calls. |
8530 | if (IsConstructOp(op)) { |
8531 | if (op == JSOp::SuperCall || op == JSOp::SpreadSuperCall) { |
8532 | if (!emitNewTarget(callNode)) { |
8533 | // [stack] CALLEE THIS ARGS.. NEW.TARGET |
8534 | return false; |
8535 | } |
8536 | } else { |
8537 | // Repush the callee as new.target |
8538 | uint32_t effectiveArgc = isSpread ? 1 : argc; |
8539 | if (!emitDupAt(effectiveArgc + 1)) { |
8540 | // [stack] CALLEE THIS ARGS.. CALLEE |
8541 | return false; |
8542 | } |
8543 | } |
8544 | } |
8545 | |
8546 | ParseNode* coordNode = getCoordNode(callNode, calleeNode, op, argsList); |
8547 | |
8548 | if (!cone.emitEnd(argc, coordNode->pn_pos.begin)) { |
8549 | // [stack] RVAL |
8550 | return false; |
8551 | } |
8552 | |
8553 | return true; |
8554 | } |
8555 | |
8556 | // This list must be kept in the same order in several places: |
8557 | // - The binary operators in ParseNode.h , |
8558 | // - the binary operators in TokenKind.h |
8559 | // - the precedence list in Parser.cpp |
8560 | static const JSOp ParseNodeKindToJSOp[] = { |
8561 | // Some binary ops require special code generation (PrivateIn); |
8562 | // these should not use BinaryOpParseNodeKindToJSOp. This table fills those |
8563 | // slots with Nops to make the rest of the table lookup work. |
8564 | JSOp::Coalesce, JSOp::Or, JSOp::And, JSOp::BitOr, JSOp::BitXor, |
8565 | JSOp::BitAnd, JSOp::StrictEq, JSOp::Eq, JSOp::StrictNe, JSOp::Ne, |
8566 | JSOp::Lt, JSOp::Le, JSOp::Gt, JSOp::Ge, JSOp::Instanceof, |
8567 | JSOp::In, JSOp::Nop, JSOp::Lsh, JSOp::Rsh, JSOp::Ursh, |
8568 | JSOp::Add, JSOp::Sub, JSOp::Mul, JSOp::Div, JSOp::Mod, |
8569 | JSOp::Pow}; |
8570 | |
8571 | static inline JSOp BinaryOpParseNodeKindToJSOp(ParseNodeKind pnk) { |
8572 | MOZ_ASSERT(pnk >= ParseNodeKind::BinOpFirst)do { static_assert( mozilla::detail::AssertionConditionType< decltype(pnk >= ParseNodeKind::BinOpFirst)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pnk >= ParseNodeKind::BinOpFirst ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "pnk >= ParseNodeKind::BinOpFirst", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8572); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pnk >= ParseNodeKind::BinOpFirst" ")"); do { *((volatile int*)__null) = 8572; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8573 | MOZ_ASSERT(pnk <= ParseNodeKind::BinOpLast)do { static_assert( mozilla::detail::AssertionConditionType< decltype(pnk <= ParseNodeKind::BinOpLast)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pnk <= ParseNodeKind::BinOpLast ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "pnk <= ParseNodeKind::BinOpLast", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8573); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pnk <= ParseNodeKind::BinOpLast" ")"); do { *((volatile int*)__null) = 8573; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8574 | int parseNodeFirst = size_t(ParseNodeKind::BinOpFirst); |
8575 | #ifdef DEBUG1 |
8576 | int jsopArraySize = std::size(ParseNodeKindToJSOp); |
8577 | int parseNodeKindListSize = |
8578 | size_t(ParseNodeKind::BinOpLast) - parseNodeFirst + 1; |
8579 | MOZ_ASSERT(jsopArraySize == parseNodeKindListSize)do { static_assert( mozilla::detail::AssertionConditionType< decltype(jsopArraySize == parseNodeKindListSize)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(jsopArraySize == parseNodeKindListSize))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("jsopArraySize == parseNodeKindListSize" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8579); AnnotateMozCrashReason("MOZ_ASSERT" "(" "jsopArraySize == parseNodeKindListSize" ")"); do { *((volatile int*)__null) = 8579; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8580 | // Ensure we don't use this to find an op for a parse node |
8581 | // requiring special emission rules. |
8582 | MOZ_ASSERT(ParseNodeKindToJSOp[size_t(pnk) - parseNodeFirst] != JSOp::Nop)do { static_assert( mozilla::detail::AssertionConditionType< decltype(ParseNodeKindToJSOp[size_t(pnk) - parseNodeFirst] != JSOp::Nop)>::isValid, "invalid assertion condition"); if ( (__builtin_expect(!!(!(!!(ParseNodeKindToJSOp[size_t(pnk) - parseNodeFirst ] != JSOp::Nop))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("ParseNodeKindToJSOp[size_t(pnk) - parseNodeFirst] != JSOp::Nop" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8582); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ParseNodeKindToJSOp[size_t(pnk) - parseNodeFirst] != JSOp::Nop" ")"); do { *((volatile int*)__null) = 8582; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8583 | #endif |
8584 | return ParseNodeKindToJSOp[size_t(pnk) - parseNodeFirst]; |
8585 | } |
8586 | |
8587 | bool BytecodeEmitter::emitRightAssociative(ListNode* node) { |
8588 | // ** is the only right-associative operator. |
8589 | MOZ_ASSERT(node->isKind(ParseNodeKind::PowExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(node->isKind(ParseNodeKind::PowExpr))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(node->isKind(ParseNodeKind::PowExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("node->isKind(ParseNodeKind::PowExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8589); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::PowExpr)" ")"); do { *((volatile int*)__null) = 8589; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8590 | |
8591 | // Right-associative operator chain. |
8592 | for (ParseNode* subexpr : node->contents()) { |
8593 | if (!updateSourceCoordNotesIfNonLiteral(subexpr)) { |
8594 | return false; |
8595 | } |
8596 | if (!emitTree(subexpr)) { |
8597 | return false; |
8598 | } |
8599 | } |
8600 | for (uint32_t i = 0; i < node->count() - 1; i++) { |
8601 | if (!emit1(JSOp::Pow)) { |
8602 | return false; |
8603 | } |
8604 | } |
8605 | return true; |
8606 | } |
8607 | |
8608 | bool BytecodeEmitter::emitLeftAssociative(ListNode* node) { |
8609 | // Left-associative operator chain. |
8610 | if (!emitTree(node->head())) { |
8611 | return false; |
8612 | } |
8613 | JSOp op = BinaryOpParseNodeKindToJSOp(node->getKind()); |
8614 | ParseNode* nextExpr = node->head()->pn_next; |
8615 | do { |
8616 | if (!updateSourceCoordNotesIfNonLiteral(nextExpr)) { |
8617 | return false; |
8618 | } |
8619 | if (!emitTree(nextExpr)) { |
8620 | return false; |
8621 | } |
8622 | if (!emit1(op)) { |
8623 | return false; |
8624 | } |
8625 | } while ((nextExpr = nextExpr->pn_next)); |
8626 | return true; |
8627 | } |
8628 | |
8629 | bool BytecodeEmitter::emitPrivateInExpr(ListNode* node) { |
8630 | MOZ_ASSERT(node->head()->isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType< decltype(node->head()->isKind(ParseNodeKind::PrivateName ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(node->head()->isKind(ParseNodeKind::PrivateName )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("node->head()->isKind(ParseNodeKind::PrivateName)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8630); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->head()->isKind(ParseNodeKind::PrivateName)" ")"); do { *((volatile int*)__null) = 8630; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8631 | |
8632 | NameNode& privateNameNode = node->head()->as<NameNode>(); |
8633 | TaggedParserAtomIndex privateName = privateNameNode.name(); |
8634 | |
8635 | PrivateOpEmitter xoe(this, PrivateOpEmitter::Kind::ErgonomicBrandCheck, |
8636 | privateName); |
8637 | |
8638 | ParseNode* valueNode = node->head()->pn_next; |
8639 | MOZ_ASSERT(valueNode->pn_next == nullptr)do { static_assert( mozilla::detail::AssertionConditionType< decltype(valueNode->pn_next == nullptr)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(valueNode->pn_next == nullptr ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "valueNode->pn_next == nullptr", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8639); AnnotateMozCrashReason("MOZ_ASSERT" "(" "valueNode->pn_next == nullptr" ")"); do { *((volatile int*)__null) = 8639; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8640 | |
8641 | if (!emitTree(valueNode)) { |
8642 | // [stack] OBJ |
8643 | return false; |
8644 | } |
8645 | |
8646 | if (!xoe.emitReference()) { |
8647 | // [stack] OBJ BRAND if private method |
8648 | // [stack] OBJ NAME if private field or accessor. |
8649 | return false; |
8650 | } |
8651 | |
8652 | if (!xoe.emitBrandCheck()) { |
8653 | // [stack] OBJ BRAND BOOL if private method |
8654 | // [stack] OBJ NAME BOOL if private field or accessor. |
8655 | return false; |
8656 | } |
8657 | |
8658 | if (!emitUnpickN(2)) { |
8659 | // [stack] BOOL OBJ BRAND if private method |
8660 | // [stack] BOOL OBJ NAME if private field or accessor. |
8661 | return false; |
8662 | } |
8663 | |
8664 | if (!emitPopN(2)) { |
8665 | // [stack] BOOL |
8666 | return false; |
8667 | } |
8668 | |
8669 | return true; |
8670 | } |
8671 | |
8672 | /* |
8673 | * Special `emitTree` for Optional Chaining case. |
8674 | * Examples of this are `emitOptionalChain`, `emitDeleteOptionalChain` and |
8675 | * `emitCalleeAndThisForOptionalChain`. |
8676 | */ |
8677 | bool BytecodeEmitter::emitOptionalTree( |
8678 | ParseNode* pn, OptionalEmitter& oe, |
8679 | ValueUsage valueUsage /* = ValueUsage::WantValue */) { |
8680 | AutoCheckRecursionLimit recursion(fc); |
8681 | if (!recursion.check(fc)) { |
8682 | return false; |
8683 | } |
8684 | ParseNodeKind kind = pn->getKind(); |
8685 | switch (kind) { |
8686 | case ParseNodeKind::OptionalDotExpr: { |
8687 | OptionalPropertyAccess* prop = &pn->as<OptionalPropertyAccess>(); |
8688 | bool isSuper = false; |
8689 | PropOpEmitter poe(this, PropOpEmitter::Kind::Get, |
8690 | PropOpEmitter::ObjKind::Other); |
8691 | if (!emitOptionalDotExpression(prop, poe, isSuper, oe)) { |
8692 | return false; |
8693 | } |
8694 | break; |
8695 | } |
8696 | case ParseNodeKind::ArgumentsLength: |
8697 | case ParseNodeKind::DotExpr: { |
8698 | PropertyAccess* prop = &pn->as<PropertyAccess>(); |
8699 | bool isSuper = prop->isSuper(); |
8700 | PropOpEmitter poe(this, PropOpEmitter::Kind::Get, |
8701 | isSuper ? PropOpEmitter::ObjKind::Super |
8702 | : PropOpEmitter::ObjKind::Other); |
8703 | if (!emitOptionalDotExpression(prop, poe, isSuper, oe)) { |
8704 | return false; |
8705 | } |
8706 | break; |
8707 | } |
8708 | |
8709 | case ParseNodeKind::OptionalElemExpr: { |
8710 | OptionalPropertyByValue* elem = &pn->as<OptionalPropertyByValue>(); |
8711 | bool isSuper = false; |
8712 | MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!elem->key().isKind(ParseNodeKind::PrivateName))> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!elem->key().isKind(ParseNodeKind::PrivateName))) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!elem->key().isKind(ParseNodeKind::PrivateName)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8712); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)" ")"); do { *((volatile int*)__null) = 8712; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8713 | ElemOpEmitter eoe(this, ElemOpEmitter::Kind::Get, |
8714 | ElemOpEmitter::ObjKind::Other); |
8715 | |
8716 | if (!emitOptionalElemExpression(elem, eoe, isSuper, oe)) { |
8717 | return false; |
8718 | } |
8719 | break; |
8720 | } |
8721 | case ParseNodeKind::ElemExpr: { |
8722 | PropertyByValue* elem = &pn->as<PropertyByValue>(); |
8723 | bool isSuper = elem->isSuper(); |
8724 | MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!elem->key().isKind(ParseNodeKind::PrivateName))> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!elem->key().isKind(ParseNodeKind::PrivateName))) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!elem->key().isKind(ParseNodeKind::PrivateName)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8724); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)" ")"); do { *((volatile int*)__null) = 8724; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8725 | ElemOpEmitter eoe(this, ElemOpEmitter::Kind::Get, |
8726 | isSuper ? ElemOpEmitter::ObjKind::Super |
8727 | : ElemOpEmitter::ObjKind::Other); |
8728 | |
8729 | if (!emitOptionalElemExpression(elem, eoe, isSuper, oe)) { |
8730 | return false; |
8731 | } |
8732 | break; |
8733 | } |
8734 | case ParseNodeKind::PrivateMemberExpr: |
8735 | case ParseNodeKind::OptionalPrivateMemberExpr: { |
8736 | PrivateMemberAccessBase* privateExpr = &pn->as<PrivateMemberAccessBase>(); |
8737 | PrivateOpEmitter xoe(this, PrivateOpEmitter::Kind::Get, |
8738 | privateExpr->privateName().name()); |
8739 | if (!emitOptionalPrivateExpression(privateExpr, xoe, oe)) { |
8740 | return false; |
8741 | } |
8742 | break; |
8743 | } |
8744 | case ParseNodeKind::CallExpr: |
8745 | case ParseNodeKind::OptionalCallExpr: |
8746 | if (!emitOptionalCall(&pn->as<CallNode>(), oe, valueUsage)) { |
8747 | return false; |
8748 | } |
8749 | break; |
8750 | // List of accepted ParseNodeKinds that might appear only at the beginning |
8751 | // of an Optional Chain. |
8752 | // For example, a taggedTemplateExpr node might occur if we have |
8753 | // `test`?.b, with `test` as the taggedTemplateExpr ParseNode. |
8754 | default: |
8755 | #ifdef DEBUG1 |
8756 | // https://tc39.es/ecma262/#sec-primary-expression |
8757 | bool isPrimaryExpression = |
8758 | kind == ParseNodeKind::ThisExpr || kind == ParseNodeKind::Name || |
8759 | kind == ParseNodeKind::PrivateName || |
8760 | kind == ParseNodeKind::NullExpr || kind == ParseNodeKind::TrueExpr || |
8761 | kind == ParseNodeKind::FalseExpr || |
8762 | kind == ParseNodeKind::NumberExpr || |
8763 | kind == ParseNodeKind::BigIntExpr || |
8764 | kind == ParseNodeKind::StringExpr || |
8765 | kind == ParseNodeKind::ArrayExpr || |
8766 | kind == ParseNodeKind::ObjectExpr || |
8767 | kind == ParseNodeKind::Function || kind == ParseNodeKind::ClassDecl || |
8768 | kind == ParseNodeKind::RegExpExpr || |
8769 | kind == ParseNodeKind::TemplateStringExpr || |
8770 | kind == ParseNodeKind::TemplateStringListExpr || |
8771 | kind == ParseNodeKind::RawUndefinedExpr || pn->isInParens(); |
8772 | |
8773 | // https://tc39.es/ecma262/#sec-left-hand-side-expressions |
8774 | bool isMemberExpression = isPrimaryExpression || |
8775 | kind == ParseNodeKind::TaggedTemplateExpr || |
8776 | kind == ParseNodeKind::NewExpr || |
8777 | kind == ParseNodeKind::NewTargetExpr || |
8778 | kind == ParseNodeKind::ImportMetaExpr; |
8779 | |
8780 | bool isCallExpression = kind == ParseNodeKind::SetThis || |
8781 | kind == ParseNodeKind::CallImportExpr; |
8782 | |
8783 | MOZ_ASSERT(isMemberExpression || isCallExpression,do { static_assert( mozilla::detail::AssertionConditionType< decltype(isMemberExpression || isCallExpression)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(isMemberExpression || isCallExpression))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("isMemberExpression || isCallExpression" " (" "Unknown ParseNodeKind for OptionalChain" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8784); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isMemberExpression || isCallExpression" ") (" "Unknown ParseNodeKind for OptionalChain" ")"); do { * ((volatile int*)__null) = 8784; __attribute__((nomerge)) ::abort (); } while (false); } } while (false) |
8784 | "Unknown ParseNodeKind for OptionalChain")do { static_assert( mozilla::detail::AssertionConditionType< decltype(isMemberExpression || isCallExpression)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(isMemberExpression || isCallExpression))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("isMemberExpression || isCallExpression" " (" "Unknown ParseNodeKind for OptionalChain" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8784); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isMemberExpression || isCallExpression" ") (" "Unknown ParseNodeKind for OptionalChain" ")"); do { * ((volatile int*)__null) = 8784; __attribute__((nomerge)) ::abort (); } while (false); } } while (false); |
8785 | #endif |
8786 | return emitTree(pn); |
8787 | } |
8788 | return true; |
8789 | } |
8790 | |
8791 | // Handle the case of a call made on a OptionalChainParseNode. |
8792 | // For example `(a?.b)()` and `(a?.b)?.()`. |
8793 | bool BytecodeEmitter::emitCalleeAndThisForOptionalChain( |
8794 | UnaryNode* optionalChain, CallNode* callNode, CallOrNewEmitter& cone) { |
8795 | ParseNode* calleeNode = optionalChain->kid(); |
8796 | |
8797 | // Create a new OptionalEmitter, in order to emit the right bytecode |
8798 | // in isolation. |
8799 | OptionalEmitter oe(this, bytecodeSection().stackDepth()); |
8800 | |
8801 | if (!emitOptionalCalleeAndThis(calleeNode, callNode, cone, oe)) { |
8802 | // [stack] CALLEE THIS |
8803 | return false; |
8804 | } |
8805 | |
8806 | // complete the jump if necessary. This will set both the "this" value |
8807 | // and the "callee" value to undefined, if the callee is undefined. It |
8808 | // does not matter much what the this value is, the function call will |
8809 | // fail if it is not optional, and be set to undefined otherwise. |
8810 | if (!oe.emitOptionalJumpTarget(JSOp::Undefined, |
8811 | OptionalEmitter::Kind::Reference)) { |
8812 | // [stack] # If shortcircuit |
8813 | // [stack] UNDEFINED UNDEFINED |
8814 | // [stack] # otherwise |
8815 | // [stack] CALLEE THIS |
8816 | return false; |
8817 | } |
8818 | return true; |
8819 | } |
8820 | |
8821 | bool BytecodeEmitter::emitOptionalChain(UnaryNode* optionalChain, |
8822 | ValueUsage valueUsage) { |
8823 | ParseNode* expr = optionalChain->kid(); |
8824 | |
8825 | OptionalEmitter oe(this, bytecodeSection().stackDepth()); |
8826 | |
8827 | if (!emitOptionalTree(expr, oe, valueUsage)) { |
8828 | // [stack] VAL |
8829 | return false; |
8830 | } |
8831 | |
8832 | if (!oe.emitOptionalJumpTarget(JSOp::Undefined)) { |
8833 | // [stack] # If shortcircuit |
8834 | // [stack] UNDEFINED |
8835 | // [stack] # otherwise |
8836 | // [stack] VAL |
8837 | return false; |
8838 | } |
8839 | |
8840 | return true; |
8841 | } |
8842 | |
8843 | bool BytecodeEmitter::emitOptionalDotExpression(PropertyAccessBase* prop, |
8844 | PropOpEmitter& poe, |
8845 | bool isSuper, |
8846 | OptionalEmitter& oe) { |
8847 | if (!poe.prepareForObj()) { |
8848 | // [stack] |
8849 | return false; |
8850 | } |
8851 | |
8852 | if (isSuper) { |
8853 | UnaryNode* base = &prop->expression().as<UnaryNode>(); |
8854 | if (!emitGetThisForSuperBase(base)) { |
8855 | // [stack] OBJ |
8856 | return false; |
8857 | } |
8858 | } else { |
8859 | if (!emitOptionalTree(&prop->expression(), oe)) { |
8860 | // [stack] OBJ |
8861 | return false; |
8862 | } |
8863 | } |
8864 | |
8865 | if (prop->isKind(ParseNodeKind::OptionalDotExpr)) { |
8866 | MOZ_ASSERT(!isSuper)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!isSuper)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!isSuper))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!isSuper", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8866); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!isSuper" ")" ); do { *((volatile int*)__null) = 8866; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8867 | if (!oe.emitJumpShortCircuit()) { |
8868 | // [stack] # if Jump |
8869 | // [stack] UNDEFINED-OR-NULL |
8870 | // [stack] # otherwise |
8871 | // [stack] OBJ |
8872 | return false; |
8873 | } |
8874 | } |
8875 | |
8876 | if (!poe.emitGet(prop->key().atom())) { |
8877 | // [stack] PROP |
8878 | return false; |
8879 | } |
8880 | |
8881 | return true; |
8882 | } |
8883 | |
8884 | bool BytecodeEmitter::emitOptionalElemExpression(PropertyByValueBase* elem, |
8885 | ElemOpEmitter& eoe, |
8886 | bool isSuper, |
8887 | OptionalEmitter& oe) { |
8888 | if (!eoe.prepareForObj()) { |
8889 | // [stack] |
8890 | return false; |
8891 | } |
8892 | |
8893 | if (isSuper) { |
8894 | UnaryNode* base = &elem->expression().as<UnaryNode>(); |
8895 | if (!emitGetThisForSuperBase(base)) { |
8896 | // [stack] OBJ |
8897 | return false; |
8898 | } |
8899 | } else { |
8900 | if (!emitOptionalTree(&elem->expression(), oe)) { |
8901 | // [stack] OBJ |
8902 | return false; |
8903 | } |
8904 | } |
8905 | |
8906 | if (elem->isKind(ParseNodeKind::OptionalElemExpr)) { |
8907 | MOZ_ASSERT(!isSuper)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!isSuper)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!isSuper))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!isSuper", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8907); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!isSuper" ")" ); do { *((volatile int*)__null) = 8907; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8908 | if (!oe.emitJumpShortCircuit()) { |
8909 | // [stack] # if Jump |
8910 | // [stack] UNDEFINED-OR-NULL |
8911 | // [stack] # otherwise |
8912 | // [stack] OBJ |
8913 | return false; |
8914 | } |
8915 | } |
8916 | |
8917 | if (!eoe.prepareForKey()) { |
8918 | // [stack] OBJ? OBJ |
8919 | return false; |
8920 | } |
8921 | |
8922 | if (!emitTree(&elem->key())) { |
8923 | // [stack] OBJ? OBJ KEY |
8924 | return false; |
8925 | } |
8926 | |
8927 | if (!eoe.emitGet()) { |
8928 | // [stack] ELEM |
8929 | return false; |
8930 | } |
8931 | |
8932 | return true; |
8933 | } |
8934 | |
8935 | bool BytecodeEmitter::emitOptionalPrivateExpression( |
8936 | PrivateMemberAccessBase* privateExpr, PrivateOpEmitter& xoe, |
8937 | OptionalEmitter& oe) { |
8938 | if (!emitOptionalTree(&privateExpr->expression(), oe)) { |
8939 | // [stack] OBJ |
8940 | return false; |
8941 | } |
8942 | |
8943 | if (privateExpr->isKind(ParseNodeKind::OptionalPrivateMemberExpr)) { |
8944 | if (!oe.emitJumpShortCircuit()) { |
8945 | // [stack] # if Jump |
8946 | // [stack] UNDEFINED-OR-NULL |
8947 | // [stack] # otherwise |
8948 | // [stack] OBJ |
8949 | return false; |
8950 | } |
8951 | } |
8952 | |
8953 | if (!xoe.emitReference()) { |
8954 | // [stack] OBJ NAME |
8955 | return false; |
8956 | } |
8957 | if (!xoe.emitGet()) { |
8958 | // [stack] CALLEE THIS # if call |
8959 | // [stack] VALUE # otherwise |
8960 | return false; |
8961 | } |
8962 | |
8963 | return true; |
8964 | } |
8965 | |
8966 | bool BytecodeEmitter::emitShortCircuit(ListNode* node, ValueUsage valueUsage) { |
8967 | MOZ_ASSERT(node->isKind(ParseNodeKind::OrExpr) ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(node->isKind(ParseNodeKind::OrExpr) || node->isKind (ParseNodeKind::CoalesceExpr) || node->isKind(ParseNodeKind ::AndExpr))>::isValid, "invalid assertion condition"); if ( (__builtin_expect(!!(!(!!(node->isKind(ParseNodeKind::OrExpr ) || node->isKind(ParseNodeKind::CoalesceExpr) || node-> isKind(ParseNodeKind::AndExpr)))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("node->isKind(ParseNodeKind::OrExpr) || node->isKind(ParseNodeKind::CoalesceExpr) || node->isKind(ParseNodeKind::AndExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8969); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::OrExpr) || node->isKind(ParseNodeKind::CoalesceExpr) || node->isKind(ParseNodeKind::AndExpr)" ")"); do { *((volatile int*)__null) = 8969; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
8968 | node->isKind(ParseNodeKind::CoalesceExpr) ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(node->isKind(ParseNodeKind::OrExpr) || node->isKind (ParseNodeKind::CoalesceExpr) || node->isKind(ParseNodeKind ::AndExpr))>::isValid, "invalid assertion condition"); if ( (__builtin_expect(!!(!(!!(node->isKind(ParseNodeKind::OrExpr ) || node->isKind(ParseNodeKind::CoalesceExpr) || node-> isKind(ParseNodeKind::AndExpr)))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("node->isKind(ParseNodeKind::OrExpr) || node->isKind(ParseNodeKind::CoalesceExpr) || node->isKind(ParseNodeKind::AndExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8969); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::OrExpr) || node->isKind(ParseNodeKind::CoalesceExpr) || node->isKind(ParseNodeKind::AndExpr)" ")"); do { *((volatile int*)__null) = 8969; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
8969 | node->isKind(ParseNodeKind::AndExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(node->isKind(ParseNodeKind::OrExpr) || node->isKind (ParseNodeKind::CoalesceExpr) || node->isKind(ParseNodeKind ::AndExpr))>::isValid, "invalid assertion condition"); if ( (__builtin_expect(!!(!(!!(node->isKind(ParseNodeKind::OrExpr ) || node->isKind(ParseNodeKind::CoalesceExpr) || node-> isKind(ParseNodeKind::AndExpr)))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("node->isKind(ParseNodeKind::OrExpr) || node->isKind(ParseNodeKind::CoalesceExpr) || node->isKind(ParseNodeKind::AndExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8969); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::OrExpr) || node->isKind(ParseNodeKind::CoalesceExpr) || node->isKind(ParseNodeKind::AndExpr)" ")"); do { *((volatile int*)__null) = 8969; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8970 | |
8971 | /* |
8972 | * JSOp::Or converts the operand on the stack to boolean, leaves the original |
8973 | * value on the stack and jumps if true; otherwise it falls into the next |
8974 | * bytecode, which pops the left operand and then evaluates the right operand. |
8975 | * The jump goes around the right operand evaluation. |
8976 | * |
8977 | * JSOp::And converts the operand on the stack to boolean and jumps if false; |
8978 | * otherwise it falls into the right operand's bytecode. |
8979 | */ |
8980 | |
8981 | TDZCheckCache tdzCache(this); |
8982 | |
8983 | JSOp op; |
8984 | switch (node->getKind()) { |
8985 | case ParseNodeKind::OrExpr: |
8986 | op = JSOp::Or; |
8987 | break; |
8988 | case ParseNodeKind::CoalesceExpr: |
8989 | op = JSOp::Coalesce; |
8990 | break; |
8991 | case ParseNodeKind::AndExpr: |
8992 | op = JSOp::And; |
8993 | break; |
8994 | default: |
8995 | MOZ_CRASH("Unexpected ParseNodeKind")do { do { } while (false); MOZ_ReportCrash("" "Unexpected ParseNodeKind" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8995); AnnotateMozCrashReason("MOZ_CRASH(" "Unexpected ParseNodeKind" ")"); do { *((volatile int*)__null) = 8995; __attribute__((nomerge )) ::abort(); } while (false); } while (false); |
8996 | } |
8997 | |
8998 | JumpList jump; |
8999 | |
9000 | // Left-associative operator chain: avoid too much recursion. |
9001 | // |
9002 | // Emit all nodes but the last. |
9003 | for (ParseNode* expr : node->contentsTo(node->last())) { |
9004 | if (!emitTree(expr)) { |
9005 | return false; |
9006 | } |
9007 | if (!emitJump(op, &jump)) { |
9008 | return false; |
9009 | } |
9010 | if (!emit1(JSOp::Pop)) { |
9011 | return false; |
9012 | } |
9013 | } |
9014 | |
9015 | // Emit the last node |
9016 | if (!emitTree(node->last(), valueUsage)) { |
9017 | return false; |
9018 | } |
9019 | |
9020 | if (!emitJumpTargetAndPatch(jump)) { |
9021 | return false; |
9022 | } |
9023 | return true; |
9024 | } |
9025 | |
9026 | bool BytecodeEmitter::emitSequenceExpr(ListNode* node, ValueUsage valueUsage) { |
9027 | for (ParseNode* child : node->contentsTo(node->last())) { |
9028 | if (!updateSourceCoordNotes(child->pn_pos.begin)) { |
9029 | return false; |
9030 | } |
9031 | if (!emitTree(child, ValueUsage::IgnoreValue)) { |
9032 | return false; |
9033 | } |
9034 | if (!emit1(JSOp::Pop)) { |
9035 | return false; |
9036 | } |
9037 | } |
9038 | |
9039 | ParseNode* child = node->last(); |
9040 | if (!updateSourceCoordNotes(child->pn_pos.begin)) { |
9041 | return false; |
9042 | } |
9043 | if (!emitTree(child, valueUsage)) { |
9044 | return false; |
9045 | } |
9046 | return true; |
9047 | } |
9048 | |
9049 | // Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See |
9050 | // the comment on emitSwitch. |
9051 | MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitIncOrDec(UnaryNode* incDec, |
9052 | ValueUsage valueUsage) { |
9053 | switch (incDec->kid()->getKind()) { |
9054 | case ParseNodeKind::ArgumentsLength: |
9055 | case ParseNodeKind::DotExpr: |
9056 | return emitPropIncDec(incDec, valueUsage); |
9057 | case ParseNodeKind::ElemExpr: |
9058 | return emitElemIncDec(incDec, valueUsage); |
9059 | case ParseNodeKind::PrivateMemberExpr: |
9060 | return emitPrivateIncDec(incDec, valueUsage); |
9061 | case ParseNodeKind::CallExpr: |
9062 | return emitCallIncDec(incDec); |
9063 | default: |
9064 | return emitNameIncDec(incDec, valueUsage); |
9065 | } |
9066 | } |
9067 | |
9068 | // Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See |
9069 | // the comment on emitSwitch. |
9070 | MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitLabeledStatement( |
9071 | const LabeledStatement* labeledStmt) { |
9072 | auto name = labeledStmt->label(); |
9073 | LabelEmitter label(this); |
9074 | |
9075 | label.emitLabel(name); |
9076 | |
9077 | if (!emitTree(labeledStmt->statement())) { |
9078 | return false; |
9079 | } |
9080 | if (!label.emitEnd()) { |
9081 | return false; |
9082 | } |
9083 | |
9084 | return true; |
9085 | } |
9086 | |
9087 | bool BytecodeEmitter::emitConditionalExpression( |
9088 | ConditionalExpression& conditional, ValueUsage valueUsage) { |
9089 | CondEmitter cond(this); |
9090 | if (!cond.emitCond()) { |
9091 | return false; |
9092 | } |
9093 | |
9094 | ParseNode* conditionNode = &conditional.condition(); |
9095 | auto conditionKind = IfEmitter::ConditionKind::Positive; |
9096 | if (conditionNode->isKind(ParseNodeKind::NotExpr)) { |
9097 | conditionNode = conditionNode->as<UnaryNode>().kid(); |
9098 | conditionKind = IfEmitter::ConditionKind::Negative; |
9099 | } |
9100 | |
9101 | // NOTE: NotExpr of conditionNode may be unwrapped, and in that case the |
9102 | // negation is handled by conditionKind. |
9103 | if (!emitTree(conditionNode)) { |
9104 | return false; |
9105 | } |
9106 | |
9107 | if (!cond.emitThenElse(conditionKind)) { |
9108 | return false; |
9109 | } |
9110 | |
9111 | if (!emitTree(&conditional.thenExpression(), valueUsage)) { |
9112 | return false; |
9113 | } |
9114 | |
9115 | if (!cond.emitElse()) { |
9116 | return false; |
9117 | } |
9118 | |
9119 | if (!emitTree(&conditional.elseExpression(), valueUsage)) { |
9120 | return false; |
9121 | } |
9122 | |
9123 | if (!cond.emitEnd()) { |
9124 | return false; |
9125 | } |
9126 | MOZ_ASSERT(cond.pushed() == 1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(cond.pushed() == 1)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(cond.pushed() == 1))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("cond.pushed() == 1" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9126); AnnotateMozCrashReason("MOZ_ASSERT" "(" "cond.pushed() == 1" ")"); do { *((volatile int*)__null) = 9126; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9127 | |
9128 | return true; |
9129 | } |
9130 | |
9131 | // Check for an object-literal property list that can be handled by the |
9132 | // ObjLiteral writer. We ensure that for each `prop: value` pair, the key is a |
9133 | // constant name or numeric index, there is no accessor specified, and the value |
9134 | // can be encoded by an ObjLiteral instruction (constant number, string, |
9135 | // boolean, null/undefined). |
9136 | void BytecodeEmitter::isPropertyListObjLiteralCompatible( |
9137 | ListNode* obj, bool* withValues, bool* withoutValues) const { |
9138 | bool keysOK = true; |
9139 | bool valuesOK = true; |
9140 | uint32_t propCount = 0; |
9141 | |
9142 | for (ParseNode* propdef : obj->contents()) { |
9143 | if (!propdef->is<BinaryNode>()) { |
9144 | keysOK = false; |
9145 | break; |
9146 | } |
9147 | propCount++; |
9148 | |
9149 | BinaryNode* prop = &propdef->as<BinaryNode>(); |
9150 | ParseNode* key = prop->left(); |
9151 | ParseNode* value = prop->right(); |
9152 | |
9153 | // Computed keys not OK (ObjLiteral data stores constant keys). |
9154 | if (key->isKind(ParseNodeKind::ComputedName)) { |
9155 | keysOK = false; |
9156 | break; |
9157 | } |
9158 | |
9159 | // BigIntExprs should have been lowered to computed names at parse |
9160 | // time, and so should be excluded above. |
9161 | MOZ_ASSERT(!key->isKind(ParseNodeKind::BigIntExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!key->isKind(ParseNodeKind::BigIntExpr))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(!key->isKind(ParseNodeKind::BigIntExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!key->isKind(ParseNodeKind::BigIntExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9161); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!key->isKind(ParseNodeKind::BigIntExpr)" ")"); do { *((volatile int*)__null) = 9161; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9162 | |
9163 | // Numeric keys OK as long as they are integers and in range. |
9164 | if (key->isKind(ParseNodeKind::NumberExpr)) { |
9165 | double numValue = key->as<NumericLiteral>().value(); |
9166 | int32_t i = 0; |
9167 | if (!NumberIsInt32(numValue, &i)) { |
9168 | keysOK = false; |
9169 | break; |
9170 | } |
9171 | if (!ObjLiteralWriter::arrayIndexInRange(i)) { |
9172 | keysOK = false; |
9173 | break; |
9174 | } |
9175 | } |
9176 | |
9177 | MOZ_ASSERT(key->isKind(ParseNodeKind::ObjectPropertyName) ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(key->isKind(ParseNodeKind::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr) || key->isKind( ParseNodeKind::NumberExpr))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(key->isKind(ParseNodeKind ::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr ) || key->isKind(ParseNodeKind::NumberExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("key->isKind(ParseNodeKind::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9179); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr)" ")"); do { *((volatile int*)__null) = 9179; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
9178 | key->isKind(ParseNodeKind::StringExpr) ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(key->isKind(ParseNodeKind::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr) || key->isKind( ParseNodeKind::NumberExpr))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(key->isKind(ParseNodeKind ::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr ) || key->isKind(ParseNodeKind::NumberExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("key->isKind(ParseNodeKind::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9179); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr)" ")"); do { *((volatile int*)__null) = 9179; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
9179 | key->isKind(ParseNodeKind::NumberExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(key->isKind(ParseNodeKind::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr) || key->isKind( ParseNodeKind::NumberExpr))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(key->isKind(ParseNodeKind ::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr ) || key->isKind(ParseNodeKind::NumberExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("key->isKind(ParseNodeKind::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9179); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr)" ")"); do { *((volatile int*)__null) = 9179; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9180 | |
9181 | AccessorType accessorType = |
9182 | prop->is<PropertyDefinition>() |
9183 | ? prop->as<PropertyDefinition>().accessorType() |
9184 | : AccessorType::None; |
9185 | if (accessorType != AccessorType::None) { |
9186 | keysOK = false; |
9187 | break; |
9188 | } |
9189 | |
9190 | if (!isRHSObjLiteralCompatible(value)) { |
9191 | valuesOK = false; |
9192 | } |
9193 | } |
9194 | |
9195 | if (propCount > SharedPropMap::MaxPropsForNonDictionary) { |
9196 | // JSOp::NewObject cannot accept dictionary-mode objects. |
9197 | keysOK = false; |
9198 | } |
9199 | |
9200 | *withValues = keysOK && valuesOK; |
9201 | *withoutValues = keysOK; |
9202 | } |
9203 | |
9204 | bool BytecodeEmitter::isArrayObjLiteralCompatible(ListNode* array) const { |
9205 | for (ParseNode* elem : array->contents()) { |
9206 | if (elem->isKind(ParseNodeKind::Spread)) { |
9207 | return false; |
9208 | } |
9209 | if (!isRHSObjLiteralCompatible(elem)) { |
9210 | return false; |
9211 | } |
9212 | } |
9213 | return true; |
9214 | } |
9215 | |
9216 | bool BytecodeEmitter::emitPropertyList(ListNode* obj, PropertyEmitter& pe, |
9217 | PropListType type) { |
9218 | // [stack] CTOR? OBJ |
9219 | |
9220 | size_t curFieldKeyIndex = 0; |
9221 | size_t curStaticFieldKeyIndex = 0; |
9222 | for (ParseNode* propdef : obj->contents()) { |
9223 | if (propdef->is<ClassField>()) { |
9224 | MOZ_ASSERT(type == ClassBody)do { static_assert( mozilla::detail::AssertionConditionType< decltype(type == ClassBody)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(type == ClassBody))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("type == ClassBody" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9224); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == ClassBody" ")"); do { *((volatile int*)__null) = 9224; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9225 | // Only handle computing field keys here: the .initializers lambda array |
9226 | // is created elsewhere. |
9227 | ClassField* field = &propdef->as<ClassField>(); |
9228 | if (field->name().getKind() == ParseNodeKind::ComputedName) { |
9229 | auto fieldKeys = |
9230 | field->isStatic() |
9231 | ? TaggedParserAtomIndex::WellKnown::dot_staticFieldKeys_() |
9232 | : TaggedParserAtomIndex::WellKnown::dot_fieldKeys_(); |
9233 | if (!emitGetName(fieldKeys)) { |
9234 | // [stack] CTOR OBJ ARRAY |
9235 | return false; |
9236 | } |
9237 | |
9238 | ParseNode* nameExpr = field->name().as<UnaryNode>().kid(); |
9239 | |
9240 | if (!emitTree(nameExpr, ValueUsage::WantValue)) { |
9241 | // [stack] CTOR OBJ ARRAY KEY |
9242 | return false; |
9243 | } |
9244 | |
9245 | if (!emit1(JSOp::ToPropertyKey)) { |
9246 | // [stack] CTOR OBJ ARRAY KEY |
9247 | return false; |
9248 | } |
9249 | |
9250 | size_t fieldKeysIndex; |
9251 | if (field->isStatic()) { |
9252 | fieldKeysIndex = curStaticFieldKeyIndex++; |
9253 | } else { |
9254 | fieldKeysIndex = curFieldKeyIndex++; |
9255 | } |
9256 | |
9257 | if (!emitUint32Operand(JSOp::InitElemArray, fieldKeysIndex)) { |
9258 | // [stack] CTOR OBJ ARRAY |
9259 | return false; |
9260 | } |
9261 | |
9262 | if (!emit1(JSOp::Pop)) { |
9263 | // [stack] CTOR OBJ |
9264 | return false; |
9265 | } |
9266 | } |
9267 | continue; |
9268 | } |
9269 | |
9270 | if (propdef->isKind(ParseNodeKind::StaticClassBlock)) { |
9271 | // Static class blocks are emitted as part of |
9272 | // emitCreateMemberInitializers. |
9273 | continue; |
9274 | } |
9275 | |
9276 | if (propdef->is<LexicalScopeNode>()) { |
9277 | // Constructors are sometimes wrapped in LexicalScopeNodes. As we |
9278 | // already handled emitting the constructor, skip it. |
9279 | MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType< decltype(propdef->as<LexicalScopeNode>().scopeBody() ->is<ClassMethod>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(propdef->as<LexicalScopeNode >().scopeBody()->is<ClassMethod>()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("propdef->as<LexicalScopeNode>().scopeBody()->is<ClassMethod>()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9280); AnnotateMozCrashReason("MOZ_ASSERT" "(" "propdef->as<LexicalScopeNode>().scopeBody()->is<ClassMethod>()" ")"); do { *((volatile int*)__null) = 9280; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
9280 | propdef->as<LexicalScopeNode>().scopeBody()->is<ClassMethod>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(propdef->as<LexicalScopeNode>().scopeBody() ->is<ClassMethod>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(propdef->as<LexicalScopeNode >().scopeBody()->is<ClassMethod>()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("propdef->as<LexicalScopeNode>().scopeBody()->is<ClassMethod>()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9280); AnnotateMozCrashReason("MOZ_ASSERT" "(" "propdef->as<LexicalScopeNode>().scopeBody()->is<ClassMethod>()" ")"); do { *((volatile int*)__null) = 9280; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9281 | continue; |
9282 | } |
9283 | |
9284 | // Handle __proto__: v specially because *only* this form, and no other |
9285 | // involving "__proto__", performs [[Prototype]] mutation. |
9286 | if (propdef->isKind(ParseNodeKind::MutateProto)) { |
9287 | // [stack] OBJ |
9288 | MOZ_ASSERT(type == ObjectLiteral)do { static_assert( mozilla::detail::AssertionConditionType< decltype(type == ObjectLiteral)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(type == ObjectLiteral))), 0) )) { do { } while (false); MOZ_ReportAssertionFailure("type == ObjectLiteral" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9288); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == ObjectLiteral" ")"); do { *((volatile int*)__null) = 9288; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9289 | if (!pe.prepareForProtoValue(propdef->pn_pos.begin)) { |
9290 | // [stack] OBJ |
9291 | return false; |
9292 | } |
9293 | if (!emitTree(propdef->as<UnaryNode>().kid())) { |
9294 | // [stack] OBJ PROTO |
9295 | return false; |
9296 | } |
9297 | if (!pe.emitMutateProto()) { |
9298 | // [stack] OBJ |
9299 | return false; |
9300 | } |
9301 | continue; |
9302 | } |
9303 | |
9304 | if (propdef->isKind(ParseNodeKind::Spread)) { |
9305 | MOZ_ASSERT(type == ObjectLiteral)do { static_assert( mozilla::detail::AssertionConditionType< decltype(type == ObjectLiteral)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(type == ObjectLiteral))), 0) )) { do { } while (false); MOZ_ReportAssertionFailure("type == ObjectLiteral" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9305); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == ObjectLiteral" ")"); do { *((volatile int*)__null) = 9305; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9306 | // [stack] OBJ |
9307 | if (!pe.prepareForSpreadOperand(propdef->pn_pos.begin)) { |
9308 | // [stack] OBJ OBJ |
9309 | return false; |
9310 | } |
9311 | if (!emitTree(propdef->as<UnaryNode>().kid())) { |
9312 | // [stack] OBJ OBJ VAL |
9313 | return false; |
9314 | } |
9315 | if (!pe.emitSpread()) { |
9316 | // [stack] OBJ |
9317 | return false; |
9318 | } |
9319 | continue; |
9320 | } |
9321 | |
9322 | BinaryNode* prop = &propdef->as<BinaryNode>(); |
9323 | |
9324 | ParseNode* key = prop->left(); |
9325 | AccessorType accessorType; |
9326 | if (prop->is<ClassMethod>()) { |
9327 | ClassMethod& method = prop->as<ClassMethod>(); |
9328 | accessorType = method.accessorType(); |
9329 | |
9330 | if (!method.isStatic() && key->isKind(ParseNodeKind::PrivateName) && |
9331 | accessorType != AccessorType::None) { |
9332 | // Private non-static accessors are stamped onto instances from |
9333 | // initializers; see emitCreateMemberInitializers. |
9334 | continue; |
9335 | } |
9336 | } else if (prop->is<PropertyDefinition>()) { |
9337 | accessorType = prop->as<PropertyDefinition>().accessorType(); |
9338 | } else { |
9339 | accessorType = AccessorType::None; |
9340 | } |
9341 | |
9342 | auto emitValue = [this, &key, &prop, accessorType, &pe]() { |
9343 | // [stack] CTOR? OBJ CTOR? KEY? |
9344 | |
9345 | ParseNode* propVal = prop->right(); |
9346 | if (propVal->isDirectRHSAnonFunction()) { |
9347 | // The following branches except for the last `else` clause emit the |
9348 | // cases handled in NameResolver::resolveFun (see NameFunctions.cpp) |
9349 | if (key->isKind(ParseNodeKind::ObjectPropertyName) || |
9350 | key->isKind(ParseNodeKind::PrivateName) || |
9351 | key->isKind(ParseNodeKind::StringExpr)) { |
9352 | auto keyAtom = key->as<NameNode>().atom(); |
9353 | if (!emitAnonymousFunctionWithName(propVal, keyAtom)) { |
9354 | // [stack] CTOR? OBJ CTOR? VAL |
9355 | return false; |
9356 | } |
9357 | } else if (key->isKind(ParseNodeKind::NumberExpr)) { |
9358 | MOZ_ASSERT(accessorType == AccessorType::None)do { static_assert( mozilla::detail::AssertionConditionType< decltype(accessorType == AccessorType::None)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(accessorType == AccessorType ::None))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("accessorType == AccessorType::None", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9358); AnnotateMozCrashReason("MOZ_ASSERT" "(" "accessorType == AccessorType::None" ")"); do { *((volatile int*)__null) = 9358; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9359 | |
9360 | auto keyAtom = key->as<NumericLiteral>().toAtom(fc, parserAtoms()); |
9361 | if (!keyAtom) { |
9362 | return false; |
9363 | } |
9364 | if (!emitAnonymousFunctionWithName(propVal, keyAtom)) { |
9365 | // [stack] CTOR? OBJ CTOR? KEY VAL |
9366 | return false; |
9367 | } |
9368 | } else if (key->isKind(ParseNodeKind::ComputedName) && |
9369 | (key->as<UnaryNode>().kid()->isKind( |
9370 | ParseNodeKind::NumberExpr) || |
9371 | key->as<UnaryNode>().kid()->isKind( |
9372 | ParseNodeKind::StringExpr)) && |
9373 | accessorType == AccessorType::None) { |
9374 | ParseNode* keyKid = key->as<UnaryNode>().kid(); |
9375 | if (keyKid->isKind(ParseNodeKind::NumberExpr)) { |
9376 | auto keyAtom = |
9377 | keyKid->as<NumericLiteral>().toAtom(fc, parserAtoms()); |
9378 | if (!keyAtom) { |
9379 | return false; |
9380 | } |
9381 | if (!emitAnonymousFunctionWithName(propVal, keyAtom)) { |
9382 | // [stack] CTOR? OBJ CTOR? KEY VAL |
9383 | return false; |
9384 | } |
9385 | } else { |
9386 | MOZ_ASSERT(keyKid->isKind(ParseNodeKind::StringExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(keyKid->isKind(ParseNodeKind::StringExpr))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(keyKid->isKind(ParseNodeKind::StringExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("keyKid->isKind(ParseNodeKind::StringExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9386); AnnotateMozCrashReason("MOZ_ASSERT" "(" "keyKid->isKind(ParseNodeKind::StringExpr)" ")"); do { *((volatile int*)__null) = 9386; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9387 | auto keyAtom = keyKid->as<NameNode>().atom(); |
9388 | if (!emitAnonymousFunctionWithName(propVal, keyAtom)) { |
9389 | // [stack] CTOR? OBJ CTOR? KEY VAL |
9390 | return false; |
9391 | } |
9392 | } |
9393 | } else { |
9394 | // Either a proper computed property name or a synthetic computed |
9395 | // property name for BigInt keys. |
9396 | MOZ_ASSERT(key->isKind(ParseNodeKind::ComputedName))do { static_assert( mozilla::detail::AssertionConditionType< decltype(key->isKind(ParseNodeKind::ComputedName))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(key->isKind(ParseNodeKind::ComputedName)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("key->isKind(ParseNodeKind::ComputedName)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9396); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::ComputedName)" ")"); do { *((volatile int*)__null) = 9396; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9397 | |
9398 | FunctionPrefixKind prefix = |
9399 | accessorType == AccessorType::None ? FunctionPrefixKind::None |
9400 | : accessorType == AccessorType::Getter ? FunctionPrefixKind::Get |
9401 | : FunctionPrefixKind::Set; |
9402 | |
9403 | if (!emitAnonymousFunctionWithComputedName(propVal, prefix)) { |
9404 | // [stack] CTOR? OBJ CTOR? KEY VAL |
9405 | return false; |
9406 | } |
9407 | } |
9408 | } else { |
9409 | if (!emitTree(propVal)) { |
9410 | // [stack] CTOR? OBJ CTOR? KEY? VAL |
9411 | return false; |
9412 | } |
9413 | } |
9414 | |
9415 | if (propVal->is<FunctionNode>() && |
9416 | propVal->as<FunctionNode>().funbox()->needsHomeObject()) { |
9417 | if (!pe.emitInitHomeObject()) { |
9418 | // [stack] CTOR? OBJ CTOR? KEY? FUN |
9419 | return false; |
9420 | } |
9421 | } |
9422 | |
9423 | #ifdef ENABLE_DECORATORS |
9424 | if (prop->is<ClassMethod>()) { |
9425 | ClassMethod& method = prop->as<ClassMethod>(); |
9426 | if (method.decorators() && !method.decorators()->empty()) { |
9427 | DecoratorEmitter::Kind kind; |
9428 | switch (method.accessorType()) { |
9429 | case AccessorType::Getter: |
9430 | kind = DecoratorEmitter::Getter; |
9431 | break; |
9432 | case AccessorType::Setter: |
9433 | kind = DecoratorEmitter::Setter; |
9434 | break; |
9435 | case AccessorType::None: |
9436 | kind = DecoratorEmitter::Method; |
9437 | break; |
9438 | } |
9439 | |
9440 | if (!method.isStatic()) { |
9441 | bool hasKeyOnStack = key->isKind(ParseNodeKind::NumberExpr) || |
9442 | key->isKind(ParseNodeKind::ComputedName); |
9443 | if (!emitDupAt(hasKeyOnStack ? 4 : 3)) { |
9444 | // [stack] ADDINIT OBJ KEY? VAL ADDINIT |
9445 | return false; |
9446 | } |
9447 | } else { |
9448 | // TODO: See bug 1868220 for support for static methods. |
9449 | // Note: Key will be present if this has a private name. |
9450 | if (!emit1(JSOp::Undefined)) { |
9451 | // [stack] CTOR OBJ CTOR KEY? VAL ADDINIT |
9452 | return false; |
9453 | } |
9454 | } |
9455 | |
9456 | if (!emit1(JSOp::Swap)) { |
9457 | // [stack] ADDINIT CTOR? OBJ CTOR? KEY? ADDINIT VAL |
9458 | return false; |
9459 | } |
9460 | |
9461 | // The decorators are applied to the current value on the stack, |
9462 | // possibly replacing it. |
9463 | DecoratorEmitter de(this); |
9464 | if (!de.emitApplyDecoratorsToElementDefinition( |
9465 | kind, key, method.decorators(), method.isStatic())) { |
9466 | // [stack] ADDINIT CTOR? OBJ CTOR? KEY? ADDINIT VAL |
9467 | return false; |
9468 | } |
9469 | |
9470 | if (!emit1(JSOp::Swap)) { |
9471 | // [stack] ADDINIT CTOR? OBJ CTOR? KEY? VAL ADDINIT |
9472 | return false; |
9473 | } |
9474 | |
9475 | if (!emitPopN(1)) { |
9476 | // [stack] ADDINIT CTOR? OBJ CTOR? KEY? VAL |
9477 | return false; |
9478 | } |
9479 | } |
9480 | } |
9481 | #endif |
9482 | |
9483 | return true; |
9484 | }; |
9485 | |
9486 | PropertyEmitter::Kind kind = |
9487 | (type == ClassBody && propdef->as<ClassMethod>().isStatic()) |
9488 | ? PropertyEmitter::Kind::Static |
9489 | : PropertyEmitter::Kind::Prototype; |
9490 | if (key->isKind(ParseNodeKind::ObjectPropertyName) || |
9491 | key->isKind(ParseNodeKind::StringExpr)) { |
9492 | // [stack] CTOR? OBJ |
9493 | |
9494 | auto keyAtom = key->as<NameNode>().atom(); |
9495 | |
9496 | // emitClass took care of constructor already. |
9497 | if (type == ClassBody && |
9498 | keyAtom == TaggedParserAtomIndex::WellKnown::constructor() && |
9499 | !propdef->as<ClassMethod>().isStatic()) { |
9500 | continue; |
9501 | } |
9502 | |
9503 | if (!pe.prepareForPropValue(propdef->pn_pos.begin, kind)) { |
9504 | // [stack] CTOR? OBJ CTOR? |
9505 | return false; |
9506 | } |
9507 | |
9508 | if (!emitValue()) { |
9509 | // [stack] CTOR? OBJ CTOR? VAL |
9510 | return false; |
9511 | } |
9512 | |
9513 | if (!pe.emitInit(accessorType, keyAtom)) { |
9514 | // [stack] CTOR? OBJ |
9515 | return false; |
9516 | } |
9517 | |
9518 | continue; |
9519 | } |
9520 | |
9521 | if (key->isKind(ParseNodeKind::NumberExpr)) { |
9522 | // [stack] CTOR? OBJ |
9523 | if (!pe.prepareForIndexPropKey(propdef->pn_pos.begin, kind)) { |
9524 | // [stack] CTOR? OBJ CTOR? |
9525 | return false; |
9526 | } |
9527 | if (!emitNumberOp(key->as<NumericLiteral>().value())) { |
9528 | // [stack] CTOR? OBJ CTOR? KEY |
9529 | return false; |
9530 | } |
9531 | if (!pe.prepareForIndexPropValue()) { |
9532 | // [stack] CTOR? OBJ CTOR? KEY |
9533 | return false; |
9534 | } |
9535 | if (!emitValue()) { |
9536 | // [stack] CTOR? OBJ CTOR? KEY VAL |
9537 | return false; |
9538 | } |
9539 | |
9540 | if (!pe.emitInitIndexOrComputed(accessorType)) { |
9541 | // [stack] CTOR? OBJ |
9542 | return false; |
9543 | } |
9544 | |
9545 | continue; |
9546 | } |
9547 | |
9548 | if (key->isKind(ParseNodeKind::ComputedName)) { |
9549 | // Either a proper computed property name or a synthetic computed property |
9550 | // name for BigInt keys. |
9551 | |
9552 | // [stack] CTOR? OBJ |
9553 | |
9554 | if (!pe.prepareForComputedPropKey(propdef->pn_pos.begin, kind)) { |
9555 | // [stack] CTOR? OBJ CTOR? |
9556 | return false; |
9557 | } |
9558 | if (!emitTree(key->as<UnaryNode>().kid())) { |
9559 | // [stack] CTOR? OBJ CTOR? KEY |
9560 | return false; |
9561 | } |
9562 | if (!pe.prepareForComputedPropValue()) { |
9563 | // [stack] CTOR? OBJ CTOR? KEY |
9564 | return false; |
9565 | } |
9566 | if (!emitValue()) { |
9567 | // [stack] CTOR? OBJ CTOR? KEY VAL |
9568 | return false; |
9569 | } |
9570 | |
9571 | if (!pe.emitInitIndexOrComputed(accessorType)) { |
9572 | // [stack] CTOR? OBJ |
9573 | return false; |
9574 | } |
9575 | |
9576 | continue; |
9577 | } |
9578 | |
9579 | MOZ_ASSERT(key->isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType< decltype(key->isKind(ParseNodeKind::PrivateName))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(key->isKind(ParseNodeKind::PrivateName)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("key->isKind(ParseNodeKind::PrivateName)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9579); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::PrivateName)" ")"); do { *((volatile int*)__null) = 9579; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9580 | MOZ_ASSERT(type == ClassBody)do { static_assert( mozilla::detail::AssertionConditionType< decltype(type == ClassBody)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(type == ClassBody))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("type == ClassBody" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9580); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == ClassBody" ")"); do { *((volatile int*)__null) = 9580; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9581 | |
9582 | auto* privateName = &key->as<NameNode>(); |
9583 | |
9584 | if (kind == PropertyEmitter::Kind::Prototype) { |
9585 | MOZ_ASSERT(accessorType == AccessorType::None)do { static_assert( mozilla::detail::AssertionConditionType< decltype(accessorType == AccessorType::None)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(accessorType == AccessorType ::None))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("accessorType == AccessorType::None", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9585); AnnotateMozCrashReason("MOZ_ASSERT" "(" "accessorType == AccessorType::None" ")"); do { *((volatile int*)__null) = 9585; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9586 | if (!pe.prepareForPrivateMethod()) { |
9587 | // [stack] CTOR OBJ |
9588 | return false; |
9589 | } |
9590 | NameOpEmitter noe(this, privateName->atom(), |
9591 | NameOpEmitter::Kind::SimpleAssignment); |
9592 | |
9593 | // Ensure the NameOp emitter doesn't push an environment onto the stack, |
9594 | // because that would change the stack location of the home object. |
9595 | MOZ_ASSERT(noe.loc().kind() == NameLocation::Kind::FrameSlot ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(noe.loc().kind() == NameLocation::Kind::FrameSlot || noe.loc().kind() == NameLocation::Kind::EnvironmentCoordinate )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(noe.loc().kind() == NameLocation::Kind::FrameSlot || noe.loc().kind() == NameLocation::Kind::EnvironmentCoordinate ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "noe.loc().kind() == NameLocation::Kind::FrameSlot || noe.loc().kind() == NameLocation::Kind::EnvironmentCoordinate" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9596); AnnotateMozCrashReason("MOZ_ASSERT" "(" "noe.loc().kind() == NameLocation::Kind::FrameSlot || noe.loc().kind() == NameLocation::Kind::EnvironmentCoordinate" ")"); do { *((volatile int*)__null) = 9596; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
9596 | noe.loc().kind() == NameLocation::Kind::EnvironmentCoordinate)do { static_assert( mozilla::detail::AssertionConditionType< decltype(noe.loc().kind() == NameLocation::Kind::FrameSlot || noe.loc().kind() == NameLocation::Kind::EnvironmentCoordinate )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(noe.loc().kind() == NameLocation::Kind::FrameSlot || noe.loc().kind() == NameLocation::Kind::EnvironmentCoordinate ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "noe.loc().kind() == NameLocation::Kind::FrameSlot || noe.loc().kind() == NameLocation::Kind::EnvironmentCoordinate" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9596); AnnotateMozCrashReason("MOZ_ASSERT" "(" "noe.loc().kind() == NameLocation::Kind::FrameSlot || noe.loc().kind() == NameLocation::Kind::EnvironmentCoordinate" ")"); do { *((volatile int*)__null) = 9596; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9597 | |
9598 | if (!noe.prepareForRhs()) { |
9599 | // [stack] CTOR OBJ |
9600 | return false; |
9601 | } |
9602 | if (!emitValue()) { |
9603 | // [stack] CTOR OBJ METHOD |
9604 | return false; |
9605 | } |
9606 | if (!noe.emitAssignment()) { |
9607 | // [stack] CTOR OBJ METHOD |
9608 | return false; |
9609 | } |
9610 | if (!emit1(JSOp::Pop)) { |
9611 | // [stack] CTOR OBJ |
9612 | return false; |
9613 | } |
9614 | if (!pe.skipInit()) { |
9615 | // [stack] CTOR OBJ |
9616 | return false; |
9617 | } |
9618 | continue; |
9619 | } |
9620 | |
9621 | MOZ_ASSERT(kind == PropertyEmitter::Kind::Static)do { static_assert( mozilla::detail::AssertionConditionType< decltype(kind == PropertyEmitter::Kind::Static)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(! !(kind == PropertyEmitter::Kind::Static))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("kind == PropertyEmitter::Kind::Static" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9621); AnnotateMozCrashReason("MOZ_ASSERT" "(" "kind == PropertyEmitter::Kind::Static" ")"); do { *((volatile int*)__null) = 9621; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9622 | |
9623 | // [stack] CTOR OBJ |
9624 | |
9625 | if (!pe.prepareForPrivateStaticMethod(propdef->pn_pos.begin)) { |
9626 | // [stack] CTOR OBJ CTOR |
9627 | return false; |
9628 | } |
9629 | if (!emitGetPrivateName(privateName)) { |
9630 | // [stack] CTOR OBJ CTOR KEY |
9631 | return false; |
9632 | } |
9633 | if (!emitValue()) { |
9634 | // [stack] CTOR OBJ CTOR KEY VAL |
9635 | return false; |
9636 | } |
9637 | |
9638 | if (!pe.emitPrivateStaticMethod(accessorType)) { |
9639 | // [stack] CTOR OBJ |
9640 | return false; |
9641 | } |
9642 | |
9643 | if (privateName->privateNameKind() == PrivateNameKind::Setter) { |
9644 | if (!emitDupAt(1)) { |
9645 | // [stack] CTOR OBJ CTOR |
9646 | return false; |
9647 | } |
9648 | if (!emitGetPrivateName(privateName)) { |
9649 | // [stack] CTOR OBJ CTOR NAME |
9650 | return false; |
9651 | } |
9652 | if (!emitAtomOp(JSOp::GetIntrinsic, |
9653 | TaggedParserAtomIndex::WellKnown::NoPrivateGetter())) { |
9654 | // [stack] CTOR OBJ CTOR NAME FUN |
9655 | return false; |
9656 | } |
9657 | if (!emit1(JSOp::InitHiddenElemGetter)) { |
9658 | // [stack] CTOR OBJ CTOR |
9659 | return false; |
9660 | } |
9661 | if (!emit1(JSOp::Pop)) { |
9662 | // [stack] CTOR OBJ |
9663 | return false; |
9664 | } |
9665 | } |
9666 | } |
9667 | |
9668 | return true; |
9669 | } |
9670 | |
9671 | bool BytecodeEmitter::emitPropertyListObjLiteral(ListNode* obj, JSOp op, |
9672 | bool useObjLiteralValues) { |
9673 | ObjLiteralWriter writer; |
9674 | |
9675 | #ifdef DEBUG1 |
9676 | // In self-hosted JS, we check duplication only on debug build. |
9677 | mozilla::Maybe<mozilla::HashSet<frontend::TaggedParserAtomIndex, |
9678 | frontend::TaggedParserAtomIndexHasher>> |
9679 | selfHostedPropNames; |
9680 | if (emitterMode == BytecodeEmitter::SelfHosting) { |
9681 | selfHostedPropNames.emplace(); |
9682 | } |
9683 | #endif |
9684 | |
9685 | if (op == JSOp::Object) { |
9686 | writer.beginObject(op); |
9687 | } else { |
9688 | MOZ_ASSERT(op == JSOp::NewObject)do { static_assert( mozilla::detail::AssertionConditionType< decltype(op == JSOp::NewObject)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(op == JSOp::NewObject))), 0) )) { do { } while (false); MOZ_ReportAssertionFailure("op == JSOp::NewObject" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9688); AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::NewObject" ")"); do { *((volatile int*)__null) = 9688; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9689 | writer.beginShape(op); |
9690 | } |
9691 | |
9692 | for (ParseNode* propdef : obj->contents()) { |
9693 | BinaryNode* prop = &propdef->as<BinaryNode>(); |
9694 | ParseNode* key = prop->left(); |
9695 | |
9696 | if (key->is<NameNode>()) { |
9697 | if (emitterMode == BytecodeEmitter::SelfHosting) { |
9698 | auto propName = key->as<NameNode>().atom(); |
9699 | #ifdef DEBUG1 |
9700 | // Self-hosted JS shouldn't contain duplicate properties. |
9701 | auto p = selfHostedPropNames->lookupForAdd(propName); |
9702 | MOZ_ASSERT(!p)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!p)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(!p))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("!p", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9702); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!p" ")"); do { *((volatile int*)__null) = 9702; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); |
9703 | if (!selfHostedPropNames->add(p, propName)) { |
9704 | js::ReportOutOfMemory(fc); |
9705 | return false; |
9706 | } |
9707 | #endif |
9708 | writer.setPropNameNoDuplicateCheck(parserAtoms(), propName); |
9709 | } else { |
9710 | if (!writer.setPropName(parserAtoms(), key->as<NameNode>().atom())) { |
9711 | return false; |
9712 | } |
9713 | } |
9714 | } else { |
9715 | double numValue = key->as<NumericLiteral>().value(); |
9716 | int32_t i = 0; |
9717 | DebugOnly<bool> numIsInt = |
9718 | NumberIsInt32(numValue, &i); // checked previously. |
9719 | MOZ_ASSERT(numIsInt)do { static_assert( mozilla::detail::AssertionConditionType< decltype(numIsInt)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(numIsInt))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("numIsInt", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9719); AnnotateMozCrashReason("MOZ_ASSERT" "(" "numIsInt" ")" ); do { *((volatile int*)__null) = 9719; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9720 | MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType< decltype(ObjLiteralWriter::arrayIndexInRange(i))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(ObjLiteralWriter::arrayIndexInRange(i)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("ObjLiteralWriter::arrayIndexInRange(i)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9721); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ObjLiteralWriter::arrayIndexInRange(i)" ")"); do { *((volatile int*)__null) = 9721; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
9721 | ObjLiteralWriter::arrayIndexInRange(i))do { static_assert( mozilla::detail::AssertionConditionType< decltype(ObjLiteralWriter::arrayIndexInRange(i))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(ObjLiteralWriter::arrayIndexInRange(i)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("ObjLiteralWriter::arrayIndexInRange(i)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9721); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ObjLiteralWriter::arrayIndexInRange(i)" ")"); do { *((volatile int*)__null) = 9721; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); // checked previously. |
9722 | |
9723 | // Ignore indexed properties if we're not storing property values, and |
9724 | // rely on InitElem ops to define those. These properties will be either |
9725 | // dense elements (not possible to represent in the literal's shape) or |
9726 | // sparse elements (enumerated separately, so this doesn't affect property |
9727 | // iteration order). |
9728 | if (!useObjLiteralValues) { |
9729 | continue; |
9730 | } |
9731 | |
9732 | writer.setPropIndex(i); |
9733 | } |
9734 | |
9735 | if (useObjLiteralValues) { |
9736 | MOZ_ASSERT(op == JSOp::Object)do { static_assert( mozilla::detail::AssertionConditionType< decltype(op == JSOp::Object)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(op == JSOp::Object))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("op == JSOp::Object" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9736); AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::Object" ")"); do { *((volatile int*)__null) = 9736; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9737 | ParseNode* value = prop->right(); |
9738 | if (!emitObjLiteralValue(writer, value)) { |
9739 | return false; |
9740 | } |
9741 | } else { |
9742 | if (!writer.propWithUndefinedValue(fc)) { |
9743 | return false; |
9744 | } |
9745 | } |
9746 | } |
9747 | |
9748 | GCThingIndex index; |
9749 | if (!addObjLiteralData(writer, &index)) { |
9750 | return false; |
9751 | } |
9752 | |
9753 | // JSOp::Object may only be used by (top-level) run-once scripts. |
9754 | MOZ_ASSERT_IF(op == JSOp::Object,do { if (op == JSOp::Object) { do { static_assert( mozilla::detail ::AssertionConditionType<decltype(sc->isTopLevelContext () && sc->treatAsRunOnce())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(sc->isTopLevelContext() && sc->treatAsRunOnce()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("sc->isTopLevelContext() && sc->treatAsRunOnce()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9755); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isTopLevelContext() && sc->treatAsRunOnce()" ")"); do { *((volatile int*)__null) = 9755; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
9755 | sc->isTopLevelContext() && sc->treatAsRunOnce())do { if (op == JSOp::Object) { do { static_assert( mozilla::detail ::AssertionConditionType<decltype(sc->isTopLevelContext () && sc->treatAsRunOnce())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(sc->isTopLevelContext() && sc->treatAsRunOnce()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("sc->isTopLevelContext() && sc->treatAsRunOnce()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9755); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isTopLevelContext() && sc->treatAsRunOnce()" ")"); do { *((volatile int*)__null) = 9755; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
9756 | |
9757 | if (!emitGCIndexOp(op, index)) { |
9758 | // [stack] OBJ |
9759 | return false; |
9760 | } |
9761 | |
9762 | return true; |
9763 | } |
9764 | |
9765 | bool BytecodeEmitter::emitDestructuringRestExclusionSetObjLiteral( |
9766 | ListNode* pattern) { |
9767 | // Note: if we want to squeeze out a little more performance, we could switch |
9768 | // to the `JSOp::Object` opcode, because the exclusion set object is never |
9769 | // exposed to the user, so it's safe to bake the object into the bytecode. |
9770 | constexpr JSOp op = JSOp::NewObject; |
9771 | |
9772 | ObjLiteralWriter writer; |
9773 | writer.beginShape(op); |
9774 | |
9775 | for (ParseNode* member : pattern->contents()) { |
9776 | if (member->isKind(ParseNodeKind::Spread)) { |
9777 | MOZ_ASSERT(!member->pn_next, "unexpected trailing element after spread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!member->pn_next)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!member->pn_next))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!member->pn_next" " (" "unexpected trailing element after spread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9777); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!member->pn_next" ") (" "unexpected trailing element after spread" ")"); do { * ((volatile int*)__null) = 9777; __attribute__((nomerge)) ::abort (); } while (false); } } while (false); |
9778 | break; |
9779 | } |
9780 | |
9781 | TaggedParserAtomIndex atom; |
9782 | if (member->isKind(ParseNodeKind::MutateProto)) { |
9783 | atom = TaggedParserAtomIndex::WellKnown::proto_(); |
9784 | } else { |
9785 | ParseNode* key = member->as<BinaryNode>().left(); |
9786 | atom = key->as<NameNode>().atom(); |
9787 | } |
9788 | |
9789 | if (!writer.setPropName(parserAtoms(), atom)) { |
9790 | return false; |
9791 | } |
9792 | |
9793 | if (!writer.propWithUndefinedValue(fc)) { |
9794 | return false; |
9795 | } |
9796 | } |
9797 | |
9798 | GCThingIndex index; |
9799 | if (!addObjLiteralData(writer, &index)) { |
9800 | return false; |
9801 | } |
9802 | |
9803 | if (!emitGCIndexOp(op, index)) { |
9804 | // [stack] OBJ |
9805 | return false; |
9806 | } |
9807 | |
9808 | return true; |
9809 | } |
9810 | |
9811 | bool BytecodeEmitter::emitObjLiteralArray(ListNode* array) { |
9812 | MOZ_ASSERT(checkSingletonContext())do { static_assert( mozilla::detail::AssertionConditionType< decltype(checkSingletonContext())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(checkSingletonContext()))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("checkSingletonContext()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9812); AnnotateMozCrashReason("MOZ_ASSERT" "(" "checkSingletonContext()" ")"); do { *((volatile int*)__null) = 9812; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9813 | |
9814 | constexpr JSOp op = JSOp::Object; |
9815 | |
9816 | ObjLiteralWriter writer; |
9817 | writer.beginArray(op); |
9818 | |
9819 | writer.beginDenseArrayElements(); |
9820 | for (ParseNode* elem : array->contents()) { |
9821 | if (!emitObjLiteralValue(writer, elem)) { |
9822 | return false; |
9823 | } |
9824 | } |
9825 | |
9826 | GCThingIndex index; |
9827 | if (!addObjLiteralData(writer, &index)) { |
9828 | return false; |
9829 | } |
9830 | |
9831 | if (!emitGCIndexOp(op, index)) { |
9832 | // [stack] OBJ |
9833 | return false; |
9834 | } |
9835 | |
9836 | return true; |
9837 | } |
9838 | |
9839 | bool BytecodeEmitter::isRHSObjLiteralCompatible(ParseNode* value) const { |
9840 | return value->isKind(ParseNodeKind::NumberExpr) || |
9841 | value->isKind(ParseNodeKind::TrueExpr) || |
9842 | value->isKind(ParseNodeKind::FalseExpr) || |
9843 | value->isKind(ParseNodeKind::NullExpr) || |
9844 | value->isKind(ParseNodeKind::RawUndefinedExpr) || |
9845 | value->isKind(ParseNodeKind::StringExpr) || |
9846 | value->isKind(ParseNodeKind::TemplateStringExpr); |
9847 | } |
9848 | |
9849 | bool BytecodeEmitter::emitObjLiteralValue(ObjLiteralWriter& writer, |
9850 | ParseNode* value) { |
9851 | MOZ_ASSERT(isRHSObjLiteralCompatible(value))do { static_assert( mozilla::detail::AssertionConditionType< decltype(isRHSObjLiteralCompatible(value))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(isRHSObjLiteralCompatible(value )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("isRHSObjLiteralCompatible(value)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9851); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isRHSObjLiteralCompatible(value)" ")"); do { *((volatile int*)__null) = 9851; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9852 | if (value->isKind(ParseNodeKind::NumberExpr)) { |
9853 | double numValue = value->as<NumericLiteral>().value(); |
9854 | int32_t i = 0; |
9855 | js::Value v; |
9856 | if (NumberIsInt32(numValue, &i)) { |
9857 | v.setInt32(i); |
9858 | } else { |
9859 | v.setDouble(numValue); |
9860 | } |
9861 | if (!writer.propWithConstNumericValue(fc, v)) { |
9862 | return false; |
9863 | } |
9864 | } else if (value->isKind(ParseNodeKind::TrueExpr)) { |
9865 | if (!writer.propWithTrueValue(fc)) { |
9866 | return false; |
9867 | } |
9868 | } else if (value->isKind(ParseNodeKind::FalseExpr)) { |
9869 | if (!writer.propWithFalseValue(fc)) { |
9870 | return false; |
9871 | } |
9872 | } else if (value->isKind(ParseNodeKind::NullExpr)) { |
9873 | if (!writer.propWithNullValue(fc)) { |
9874 | return false; |
9875 | } |
9876 | } else if (value->isKind(ParseNodeKind::RawUndefinedExpr)) { |
9877 | if (!writer.propWithUndefinedValue(fc)) { |
9878 | return false; |
9879 | } |
9880 | } else if (value->isKind(ParseNodeKind::StringExpr) || |
9881 | value->isKind(ParseNodeKind::TemplateStringExpr)) { |
9882 | if (!writer.propWithAtomValue(fc, parserAtoms(), |
9883 | value->as<NameNode>().atom())) { |
9884 | return false; |
9885 | } |
9886 | } else { |
9887 | MOZ_CRASH("Unexpected parse node")do { do { } while (false); MOZ_ReportCrash("" "Unexpected parse node" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9887); AnnotateMozCrashReason("MOZ_CRASH(" "Unexpected parse node" ")"); do { *((volatile int*)__null) = 9887; __attribute__((nomerge )) ::abort(); } while (false); } while (false); |
9888 | } |
9889 | return true; |
9890 | } |
9891 | |
9892 | static bool NeedsPrivateBrand(ParseNode* member) { |
9893 | return member->is<ClassMethod>() && |
9894 | member->as<ClassMethod>().name().isKind(ParseNodeKind::PrivateName) && |
9895 | !member->as<ClassMethod>().isStatic(); |
9896 | } |
9897 | |
9898 | #ifdef ENABLE_DECORATORS |
9899 | static bool HasDecorators(ParseNode* member) { |
9900 | return member->is<ClassMethod>() && member->as<ClassMethod>().decorators(); |
9901 | } |
9902 | #endif |
9903 | |
9904 | mozilla::Maybe<MemberInitializers> BytecodeEmitter::setupMemberInitializers( |
9905 | ListNode* classMembers, FieldPlacement placement) const { |
9906 | bool isStatic = placement == FieldPlacement::Static; |
9907 | |
9908 | size_t numFields = 0; |
9909 | size_t numPrivateInitializers = 0; |
9910 | bool hasPrivateBrand = false; |
9911 | #ifdef ENABLE_DECORATORS |
9912 | bool hasDecorators = false; |
9913 | #endif |
9914 | for (ParseNode* member : classMembers->contents()) { |
9915 | if (NeedsFieldInitializer(member, isStatic)) { |
9916 | numFields++; |
9917 | } else if (NeedsAccessorInitializer(member, isStatic)) { |
9918 | numPrivateInitializers++; |
9919 | hasPrivateBrand = true; |
9920 | } else if (NeedsPrivateBrand(member)) { |
9921 | hasPrivateBrand = true; |
9922 | } |
9923 | #ifdef ENABLE_DECORATORS |
9924 | if (!hasDecorators && HasDecorators(member)) { |
9925 | hasDecorators = true; |
9926 | } |
9927 | #endif |
9928 | } |
9929 | |
9930 | // If there are more initializers than can be represented, return invalid. |
9931 | if (numFields + numPrivateInitializers > |
9932 | MemberInitializers::MaxInitializers) { |
9933 | return Nothing(); |
9934 | } |
9935 | return Some(MemberInitializers(hasPrivateBrand, |
9936 | #ifdef ENABLE_DECORATORS |
9937 | hasDecorators, |
9938 | #endif |
9939 | numFields + numPrivateInitializers)); |
9940 | } |
9941 | |
9942 | // Purpose of .fieldKeys: |
9943 | // Computed field names (`["x"] = 2;`) must be ran at class-evaluation time, |
9944 | // not object construction time. The transformation to do so is roughly as |
9945 | // follows: |
9946 | // |
9947 | // class C { |
9948 | // [keyExpr] = valueExpr; |
9949 | // } |
9950 | // --> |
9951 | // let .fieldKeys = [keyExpr]; |
9952 | // let .initializers = [ |
9953 | // () => { |
9954 | // this[.fieldKeys[0]] = valueExpr; |
9955 | // } |
9956 | // ]; |
9957 | // class C { |
9958 | // constructor() { |
9959 | // .initializers[0](); |
9960 | // } |
9961 | // } |
9962 | // |
9963 | // BytecodeEmitter::emitCreateFieldKeys does `let .fieldKeys = [...];` |
9964 | // BytecodeEmitter::emitPropertyList fills in the elements of the array. |
9965 | // See GeneralParser::fieldInitializer for the `this[.fieldKeys[0]]` part. |
9966 | bool BytecodeEmitter::emitCreateFieldKeys(ListNode* obj, |
9967 | FieldPlacement placement) { |
9968 | bool isStatic = placement == FieldPlacement::Static; |
9969 | auto isFieldWithComputedName = [isStatic](ParseNode* propdef) { |
9970 | return propdef->is<ClassField>() && |
9971 | propdef->as<ClassField>().isStatic() == isStatic && |
9972 | propdef->as<ClassField>().name().getKind() == |
9973 | ParseNodeKind::ComputedName; |
9974 | }; |
9975 | |
9976 | size_t numFieldKeys = std::count_if( |
9977 | obj->contents().begin(), obj->contents().end(), isFieldWithComputedName); |
9978 | if (numFieldKeys == 0) { |
9979 | return true; |
9980 | } |
9981 | |
9982 | auto fieldKeys = |
9983 | isStatic ? TaggedParserAtomIndex::WellKnown::dot_staticFieldKeys_() |
9984 | : TaggedParserAtomIndex::WellKnown::dot_fieldKeys_(); |
9985 | NameOpEmitter noe(this, fieldKeys, NameOpEmitter::Kind::Initialize); |
9986 | if (!noe.prepareForRhs()) { |
9987 | return false; |
9988 | } |
9989 | |
9990 | if (!emitUint32Operand(JSOp::NewArray, numFieldKeys)) { |
9991 | // [stack] ARRAY |
9992 | return false; |
9993 | } |
9994 | |
9995 | if (!noe.emitAssignment()) { |
9996 | // [stack] ARRAY |
9997 | return false; |
9998 | } |
9999 | |
10000 | if (!emit1(JSOp::Pop)) { |
10001 | // [stack] |
10002 | return false; |
10003 | } |
10004 | |
10005 | return true; |
10006 | } |
10007 | |
10008 | static bool HasInitializer(ParseNode* node, bool isStaticContext) { |
10009 | return (node->is<ClassField>() && |
10010 | node->as<ClassField>().isStatic() == isStaticContext) || |
10011 | (isStaticContext && node->is<StaticClassBlock>()); |
10012 | } |
10013 | |
10014 | static FunctionNode* GetInitializer(ParseNode* node, bool isStaticContext) { |
10015 | MOZ_ASSERT(HasInitializer(node, isStaticContext))do { static_assert( mozilla::detail::AssertionConditionType< decltype(HasInitializer(node, isStaticContext))>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(! !(HasInitializer(node, isStaticContext)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("HasInitializer(node, isStaticContext)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 10015); AnnotateMozCrashReason("MOZ_ASSERT" "(" "HasInitializer(node, isStaticContext)" ")"); do { *((volatile int*)__null) = 10015; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10016 | MOZ_ASSERT_IF(!node->is<ClassField>(), isStaticContext)do { if (!node->is<ClassField>()) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(isStaticContext )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(isStaticContext))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("isStaticContext", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 10016); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isStaticContext" ")"); do { *((volatile int*)__null) = 10016; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); } } while (false); |
10017 | return node->is<ClassField>() ? node->as<ClassField>().initializer() |
10018 | : node->as<StaticClassBlock>().function(); |
10019 | } |
10020 | |
10021 | static bool IsPrivateInstanceAccessor(const ClassMethod* classMethod) { |
10022 | return !classMethod->isStatic() && |
10023 | classMethod->name().isKind(ParseNodeKind::PrivateName) && |
10024 | classMethod->accessorType() != AccessorType::None; |
10025 | } |
10026 | |
10027 | bool BytecodeEmitter::emitCreateMemberInitializers(ClassEmitter& ce, |
10028 | ListNode* obj, |
10029 | FieldPlacement placement |
10030 | #ifdef ENABLE_DECORATORS |
10031 | , |
10032 | bool hasHeritage |
10033 | #endif |
10034 | ) { |
10035 | // FieldPlacement::Instance, hasHeritage == false |
10036 | // [stack] HOME |
10037 | // |
10038 | // FieldPlacement::Instance, hasHeritage == true |
10039 | // [stack] HOME HERIT |
10040 | // |
10041 | // FieldPlacement::Static |
10042 | // [stack] CTOR HOME |
10043 | #ifdef ENABLE_DECORATORS |
10044 | MOZ_ASSERT_IF(placement == FieldPlacement::Static, !hasHeritage)do { if (placement == FieldPlacement::Static) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(!hasHeritage )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!hasHeritage))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!hasHeritage", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 10044); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!hasHeritage" ")"); do { *((volatile int*)__null) = 10044; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); } } while (false); |
10045 | #endif |
10046 | mozilla::Maybe<MemberInitializers> memberInitializers = |
10047 | setupMemberInitializers(obj, placement); |
10048 | if (!memberInitializers) { |
10049 | ReportAllocationOverflow(fc); |
10050 | return false; |
10051 | } |
10052 | |
10053 | size_t numInitializers = memberInitializers->numMemberInitializers; |
10054 | if (numInitializers == 0) { |
10055 | return true; |
10056 | } |
10057 | |
10058 | bool isStatic = placement == FieldPlacement::Static; |
10059 | if (!ce.prepareForMemberInitializers(numInitializers, isStatic)) { |
10060 | // [stack] HOME HERIT? ARR |
10061 | // or: |
10062 | // [stack] CTOR HOME ARR |
10063 | return false; |
10064 | } |
10065 | |
10066 | // Private accessors could be used in the field initializers, so make sure |
10067 | // accessor initializers appear earlier in the .initializers array so they |
10068 | // run first. Static private methods are not initialized using initializers |
10069 | // (emitPropertyList emits bytecode to stamp them onto the constructor), so |
10070 | // skip this step if isStatic. |
10071 | if (!isStatic) { |
10072 | if (!emitPrivateMethodInitializers(ce, obj)) { |
10073 | return false; |
10074 | } |
10075 | } |
10076 | |
10077 | for (ParseNode* propdef : obj->contents()) { |
10078 | if (!HasInitializer(propdef, isStatic)) { |
10079 | continue; |
10080 | } |
10081 | |
10082 | FunctionNode* initializer = GetInitializer(propdef, isStatic); |
10083 | |
10084 | if (!ce.prepareForMemberInitializer()) { |
10085 | return false; |
10086 | } |
10087 | if (!emitTree(initializer)) { |
10088 | // [stack] HOME HERIT? ARR LAMBDA |
10089 | // or: |
10090 | // [stack] CTOR HOME ARR LAMBDA |
10091 | return false; |
10092 | } |
10093 | if (initializer->funbox()->needsHomeObject()) { |
10094 | MOZ_ASSERT(initializer->funbox()->allowSuperProperty())do { static_assert( mozilla::detail::AssertionConditionType< decltype(initializer->funbox()->allowSuperProperty())> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(initializer->funbox()->allowSuperProperty()))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("initializer->funbox()->allowSuperProperty()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 10094); AnnotateMozCrashReason("MOZ_ASSERT" "(" "initializer->funbox()->allowSuperProperty()" ")"); do { *((volatile int*)__null) = 10094; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10095 | if (!ce.emitMemberInitializerHomeObject(isStatic)) { |
10096 | // [stack] HOME HERIT? ARR LAMBDA |
10097 | // or: |
10098 | // [stack] CTOR HOME ARR LAMBDA |
10099 | return false; |
10100 | } |
10101 | } |
10102 | if (!ce.emitStoreMemberInitializer()) { |
10103 | // [stack] HOME HERIT? ARR |
10104 | // or: |
10105 | // [stack] CTOR HOME ARR |
10106 | return false; |
10107 | } |
10108 | } |
10109 | |
10110 | #ifdef ENABLE_DECORATORS |
10111 | // Index to use to append new initializers returned by decorators to the array |
10112 | if (!emitNumberOp(numInitializers)) { |
10113 | // [stack] HOME HERIT? ARR I |
10114 | // or: |
10115 | // [stack] CTOR HOME ARR I |
10116 | return false; |
10117 | } |
10118 | |
10119 | for (ParseNode* propdef : obj->contents()) { |
10120 | if (!propdef->is<ClassField>()) { |
10121 | continue; |
10122 | } |
10123 | ClassField* field = &propdef->as<ClassField>(); |
10124 | if (field->isStatic() != isStatic) { |
10125 | continue; |
10126 | } |
10127 | if (field->decorators() && !field->decorators()->empty()) { |
10128 | DecoratorEmitter de(this); |
10129 | if (!field->hasAccessor()) { |
10130 | if (!emitDupAt((hasHeritage || isStatic) ? 4 : 3)) { |
10131 | // [stack] ADDINIT HOME HERIT? ARR I ADDINIT |
10132 | // or: |
10133 | // [stack] ADDINIT CTOR HOME ARR I ADDINIT |
10134 | return false; |
10135 | } |
10136 | if (!de.emitApplyDecoratorsToFieldDefinition( |
10137 | &field->name(), field->decorators(), field->isStatic())) { |
10138 | // [stack] HOME HERIT? ARR I ADDINIT INITS |
10139 | // or: |
10140 | // [stack] CTOR HOME ARR I ADDINIT INITS |
10141 | return false; |
10142 | } |
10143 | if (!emit1(JSOp::Swap)) { |
10144 | // [stack] HOME HERIT? ARR I INITS ADDINIT |
10145 | // or: |
10146 | // [stack] CTOR HOME ARR I INITS ADDINIT |
10147 | return false; |
10148 | } |
10149 | if (!emitPopN(1)) { |
10150 | // [stack] ADDINIT HOME HERIT? ARR I INITS |
10151 | // or: |
10152 | // [stack] ADDINIT CTOR HOME ARR I INITS |
10153 | return false; |
10154 | } |
10155 | } else { |
10156 | ClassMethod* accessorGetterNode = field->accessorGetterNode(); |
10157 | auto accessorGetterKeyAtom = |
10158 | accessorGetterNode->left()->as<NameNode>().atom(); |
10159 | ClassMethod* accessorSetterNode = field->accessorSetterNode(); |
10160 | auto accessorSetterKeyAtom = |
10161 | accessorSetterNode->left()->as<NameNode>().atom(); |
10162 | if (!IsPrivateInstanceAccessor(accessorGetterNode)) { |
10163 | if (!emitTree(&accessorGetterNode->method())) { |
10164 | // [stack] ADDINIT HOME HERIT? ARR I GET |
10165 | // or: |
10166 | // [stack] ADDINIT CTOR HOME ARR I GET |
10167 | return false; |
10168 | } |
10169 | if (!emitTree(&accessorSetterNode->method())) { |
10170 | // [stack] ADDINIT HOME HERIT? ARR I GET |
10171 | // SET |
10172 | // or: |
10173 | // [stack] ADDINIT CTOR HOME ARR I GET SET |
10174 | return false; |
10175 | } |
10176 | } else { |
10177 | MOZ_ASSERT(IsPrivateInstanceAccessor(accessorSetterNode))do { static_assert( mozilla::detail::AssertionConditionType< decltype(IsPrivateInstanceAccessor(accessorSetterNode))>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(IsPrivateInstanceAccessor(accessorSetterNode)))), 0) )) { do { } while (false); MOZ_ReportAssertionFailure("IsPrivateInstanceAccessor(accessorSetterNode)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 10177); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsPrivateInstanceAccessor(accessorSetterNode)" ")"); do { *((volatile int*)__null) = 10177; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10178 | auto getAccessor = [this]( |
10179 | ClassMethod* classMethod, |
10180 | TaggedParserAtomIndex& updatedAtom) -> bool { |
10181 | // [stack] |
10182 | |
10183 | // Synthesize a name for the lexical variable that will store the |
10184 | // private method body. |
10185 | TaggedParserAtomIndex name = |
10186 | classMethod->name().as<NameNode>().atom(); |
10187 | AccessorType accessorType = classMethod->accessorType(); |
10188 | StringBuilder storedMethodName(fc); |
10189 | if (!storedMethodName.append(parserAtoms(), name)) { |
10190 | return false; |
10191 | } |
10192 | if (!storedMethodName.append(accessorType == AccessorType::Getter |
10193 | ? ".getter" |
10194 | : ".setter")) { |
10195 | return false; |
10196 | } |
10197 | updatedAtom = storedMethodName.finishParserAtom(parserAtoms(), fc); |
10198 | if (!updatedAtom) { |
10199 | return false; |
10200 | } |
10201 | |
10202 | return emitGetName(updatedAtom); |
10203 | // [stack] ACCESSOR |
10204 | }; |
10205 | |
10206 | if (!getAccessor(accessorGetterNode, accessorGetterKeyAtom)) { |
10207 | // [stack] ADDINIT HOME HERIT? ARR I GET |
10208 | // or: |
10209 | // [stack] ADDINIT CTOR HOME ARR I GET |
10210 | return false; |
10211 | }; |
10212 | |
10213 | if (!getAccessor(accessorSetterNode, accessorSetterKeyAtom)) { |
10214 | // [stack] ADDINIT HOME HERIT? ARR I GET SET |
10215 | // or: |
10216 | // [stack] ADDINIT CTOR HOME ARR I GET SET |
10217 | return false; |
10218 | }; |
10219 | } |
10220 | |
10221 | if (!emitDupAt((hasHeritage || isStatic) ? 6 : 5)) { |
10222 | // [stack] ADDINIT HOME HERIT? ARR I GET SET ADDINIT |
10223 | // or: |
10224 | // [stack] ADDINIT CTOR HOME ARR I GET SET ADDINIT |
10225 | return false; |
10226 | } |
10227 | |
10228 | if (!emitUnpickN(2)) { |
10229 | // [stack] ADDINIT HOME HERIT? ARR I ADDINIT GET SET |
10230 | // or: |
10231 | // [stack] ADDINIT CTOR HOME ARR I ADDINIT GET SET |
10232 | return false; |
10233 | } |
10234 | |
10235 | if (!de.emitApplyDecoratorsToAccessorDefinition( |
10236 | &field->name(), field->decorators(), field->isStatic())) { |
10237 | // [stack] ADDINIT HOME HERIT? ARR I ADDINIT GET SET INITS |
10238 | // or: |
10239 | // [stack] ADDINIT CTOR HOME ARR I ADDINIT GET SET INITS |
10240 | return false; |
10241 | } |
10242 | |
10243 | if (!emitPickN(3)) { |
10244 | // [stack] HOME HERIT? ARR I GET SET INITS ADDINIT |
10245 | // or: |
10246 | // [stack] CTOR HOME ARR I GET SET INITS ADDINIT |
10247 | return false; |
10248 | } |
10249 | |
10250 | if (!emitPopN(1)) { |
10251 | // [stack] ADDINIT HOME HERIT? ARR I GET SET INITS |
10252 | // or: |
10253 | // [stack] ADDINIT CTOR HOME ARR I GET SET INITS |
10254 | return false; |
10255 | } |
10256 | |
10257 | if (!emitUnpickN(2)) { |
10258 | // [stack] ADDINIT HOME HERIT? ARR I INITS GET SET |
10259 | // or: |
10260 | // [stack] ADDINIT CTOR HOME ARR I INITS GET SET |
10261 | return false; |
10262 | } |
10263 | |
10264 | if (!IsPrivateInstanceAccessor(accessorGetterNode)) { |
10265 | if (!isStatic) { |
10266 | if (!emitDupAt(hasHeritage ? 6 : 5)) { |
10267 | // [stack] ADDINIT HOME HERIT? ARR I INITS GET SET HOME |
10268 | return false; |
10269 | } |
10270 | } else { |
10271 | if (!emitDupAt(6)) { |
10272 | // [stack] ADDINIT CTOR HOME ARR I INITS GET SET CTOR |
10273 | return false; |
10274 | } |
10275 | if (!emitDupAt(6)) { |
10276 | // [stack] ADDINIT CTOR HOME ARR I INITS GET SET CTOR HOME |
10277 | return false; |
10278 | } |
10279 | } |
10280 | |
10281 | PropertyEmitter::Kind kind = field->isStatic() |
10282 | ? PropertyEmitter::Kind::Static |
10283 | : PropertyEmitter::Kind::Prototype; |
10284 | if (!accessorGetterNode->name().isKind(ParseNodeKind::PrivateName)) { |
10285 | MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType< decltype(!accessorSetterNode->name().isKind(ParseNodeKind:: PrivateName))>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(!accessorSetterNode->name().isKind (ParseNodeKind::PrivateName)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!accessorSetterNode->name().isKind(ParseNodeKind::PrivateName)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 10286); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!accessorSetterNode->name().isKind(ParseNodeKind::PrivateName)" ")"); do { *((volatile int*)__null) = 10286; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
10286 | !accessorSetterNode->name().isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!accessorSetterNode->name().isKind(ParseNodeKind:: PrivateName))>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(!accessorSetterNode->name().isKind (ParseNodeKind::PrivateName)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!accessorSetterNode->name().isKind(ParseNodeKind::PrivateName)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 10286); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!accessorSetterNode->name().isKind(ParseNodeKind::PrivateName)" ")"); do { *((volatile int*)__null) = 10286; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10287 | |
10288 | if (!ce.prepareForPropValue(propdef->pn_pos.begin, kind)) { |
10289 | // [stack] ADDINIT HOME HERIT? ARR I INITS GET SET HOME |
10290 | // or: |
10291 | // [stack] ADDINIT CTOR HOME ARR I INITS GET SET CTOR HOME CTOR |
10292 | return false; |
10293 | } |
10294 | if (!emitPickN(isStatic ? 3 : 1)) { |
10295 | // [stack] ADDINIT HOME HERIT? ARR I INITS GET HOME SET |
10296 | // or: |
10297 | // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME CTOR SET |
10298 | return false; |
10299 | } |
10300 | if (!ce.emitInit(AccessorType::Setter, accessorSetterKeyAtom)) { |
10301 | // [stack] ADDINIT HOME HERIT? ARR I INITS GET HOME |
10302 | // or: |
10303 | // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME |
10304 | return false; |
10305 | } |
10306 | |
10307 | if (!ce.prepareForPropValue(propdef->pn_pos.begin, kind)) { |
10308 | // [stack] ADDINIT HOME HERIT? ARR I INITS GET HOME |
10309 | // or: |
10310 | // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME CTOR |
10311 | return false; |
10312 | } |
10313 | if (!emitPickN(isStatic ? 3 : 1)) { |
10314 | // [stack] ADDINIT HOME HERIT? ARR I INITS HOME GET |
10315 | // or: |
10316 | // [stack] ADDINIT CTOR HOME ARR I INITS CTOR HOME CTOR GET |
10317 | return false; |
10318 | } |
10319 | if (!ce.emitInit(AccessorType::Getter, accessorGetterKeyAtom)) { |
10320 | // [stack] ADDINIT HOME HERIT? ARR I INITS HOME |
10321 | // or: |
10322 | // [stack] ADDINIT CTOR HOME ARR I INITS CTOR HOME |
10323 | return false; |
10324 | } |
10325 | } else { |
10326 | MOZ_ASSERT(isStatic)do { static_assert( mozilla::detail::AssertionConditionType< decltype(isStatic)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(isStatic))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("isStatic", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 10326); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isStatic" ")" ); do { *((volatile int*)__null) = 10326; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
10327 | // The getter and setter share the same name. |
10328 | if (!emitNewPrivateName(accessorSetterKeyAtom, |
10329 | accessorSetterKeyAtom)) { |
10330 | return false; |
10331 | } |
10332 | if (!ce.prepareForPrivateStaticMethod(propdef->pn_pos.begin)) { |
10333 | // [stack] ADDINIT CTOR HOME ARR I INITS GET SET CTOR HOME CTOR |
10334 | return false; |
10335 | } |
10336 | if (!emitGetPrivateName( |
10337 | &accessorSetterNode->name().as<NameNode>())) { |
10338 | // [stack] ADDINIT CTOR HOME ARR I INITS GET SET CTOR HOME CTOR |
10339 | // KEY |
10340 | return false; |
10341 | } |
10342 | if (!emitPickN(4)) { |
10343 | // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME CTOR KEY |
10344 | // SET |
10345 | return false; |
10346 | } |
10347 | if (!ce.emitPrivateStaticMethod(AccessorType::Setter)) { |
10348 | // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME |
10349 | return false; |
10350 | } |
10351 | |
10352 | if (!ce.prepareForPrivateStaticMethod(propdef->pn_pos.begin)) { |
10353 | // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME CTOR |
10354 | return false; |
10355 | } |
10356 | if (!emitGetPrivateName( |
10357 | &accessorGetterNode->name().as<NameNode>())) { |
10358 | // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME CTOR KEY |
10359 | return false; |
10360 | } |
10361 | if (!emitPickN(4)) { |
10362 | // [stack] ADDINIT CTOR HOME ARR I INITS CTOR HOME CTOR KEY GET |
10363 | return false; |
10364 | } |
10365 | if (!ce.emitPrivateStaticMethod(AccessorType::Getter)) { |
10366 | // [stack] ADDINIT CTOR HOME ARR I INITS CTOR HOME |
10367 | return false; |
10368 | } |
10369 | } |
10370 | |
10371 | if (!isStatic) { |
10372 | if (!emitPopN(1)) { |
10373 | // [stack] ADDINIT HOME HERIT? ARR I INITS |
10374 | return false; |
10375 | } |
10376 | } else { |
10377 | if (!emitPopN(2)) { |
10378 | // [stack] ADDINIT CTOR HOME ARR I INITS |
10379 | return false; |
10380 | } |
10381 | } |
10382 | } else { |
10383 | MOZ_ASSERT(IsPrivateInstanceAccessor(accessorSetterNode))do { static_assert( mozilla::detail::AssertionConditionType< decltype(IsPrivateInstanceAccessor(accessorSetterNode))>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(IsPrivateInstanceAccessor(accessorSetterNode)))), 0) )) { do { } while (false); MOZ_ReportAssertionFailure("IsPrivateInstanceAccessor(accessorSetterNode)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 10383); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsPrivateInstanceAccessor(accessorSetterNode)" ")"); do { *((volatile int*)__null) = 10383; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10384 | |
10385 | if (!emitLexicalInitialization(accessorSetterKeyAtom)) { |
10386 | // [stack] ADDINIT HOME HERIT? ARR I INITS GET SET |
10387 | // or: |
10388 | // [stack] ADDINIT CTOR HOME ARR I INITS GET SET |
10389 | return false; |
10390 | } |
10391 | |
10392 | if (!emitPopN(1)) { |
10393 | // [stack] ADDINIT HOME HERIT? ARR I INITS GET |
10394 | // or: |
10395 | // [stack] ADDINIT CTOR HOME ARR I INITS GET |
10396 | return false; |
10397 | } |
10398 | |
10399 | if (!emitLexicalInitialization(accessorGetterKeyAtom)) { |
10400 | // [stack] ADDINIT HOME HERIT? ARR I INITS GET |
10401 | // or: |
10402 | // [stack] ADDINIT CTOR HOME ARR I INITS GET |
10403 | return false; |
10404 | } |
10405 | |
10406 | if (!emitPopN(1)) { |
10407 | // [stack] ADDINIT HOME HERIT? ARR I INITS |
10408 | // or: |
10409 | // [stack] ADDINIT CTOR HOME ARR I INITS |
10410 | return false; |
10411 | } |
10412 | } |
10413 | } |
10414 | if (!emit1(JSOp::InitElemInc)) { |
10415 | // [stack] ADDINIT HOME HERIT? ARR I |
10416 | // or: |
10417 | // [stack] ADDINIT CTOR HOME ARR I |
10418 | return false; |
10419 | } |
10420 | } |
10421 | } |
10422 | |
10423 | // Pop I |
10424 | if (!emitPopN(1)) { |
10425 | // [stack] ADDINIT HOME HERIT? ARR |
10426 | // or: |
10427 | // [stack] ADDINIT CTOR HOME ARR |
10428 | return false; |
10429 | } |
10430 | #endif |
10431 | |
10432 | if (!ce.emitMemberInitializersEnd()) { |
10433 | // [stack] ADDINIT HOME HERIT? |
10434 | // or: |
10435 | // [stack] ADDINIT CTOR HOME |
10436 | return false; |
10437 | } |
10438 | |
10439 | return true; |
10440 | } |
10441 | |
10442 | bool BytecodeEmitter::emitPrivateMethodInitializers(ClassEmitter& ce, |
10443 | ListNode* obj) { |
10444 | for (ParseNode* propdef : obj->contents()) { |
10445 | if (!propdef->is<ClassMethod>()) { |
10446 | continue; |
10447 | } |
10448 | auto* classMethod = &propdef->as<ClassMethod>(); |
10449 | |
10450 | // Skip over anything which isn't a private instance accessor. |
10451 | if (!IsPrivateInstanceAccessor(classMethod)) { |
10452 | continue; |
10453 | } |
10454 | |
10455 | if (!ce.prepareForMemberInitializer()) { |
10456 | // [stack] HOMEOBJ HERITAGE? ARRAY |
10457 | // or: |
10458 | // [stack] CTOR HOMEOBJ ARRAY |
10459 | return false; |
10460 | } |
10461 | |
10462 | // Synthesize a name for the lexical variable that will store the |
10463 | // private method body. |
10464 | TaggedParserAtomIndex name = classMethod->name().as<NameNode>().atom(); |
10465 | AccessorType accessorType = classMethod->accessorType(); |
10466 | StringBuilder storedMethodName(fc); |
10467 | if (!storedMethodName.append(parserAtoms(), name)) { |
10468 | return false; |
10469 | } |
10470 | if (!storedMethodName.append( |
10471 | accessorType == AccessorType::Getter ? ".getter" : ".setter")) { |
10472 | return false; |
10473 | } |
10474 | auto storedMethodAtom = |
10475 | storedMethodName.finishParserAtom(parserAtoms(), fc); |
10476 | |
10477 | // Emit the private method body and store it as a lexical var. |
10478 | if (!emitFunction(&classMethod->method())) { |
10479 | // [stack] HOMEOBJ HERITAGE? ARRAY METHOD |
10480 | // or: |
10481 | // [stack] CTOR HOMEOBJ ARRAY METHOD |
10482 | return false; |
10483 | } |
10484 | // The private method body needs to access the home object, |
10485 | // and the CE knows where that is on the stack. |
10486 | if (classMethod->method().funbox()->needsHomeObject()) { |
10487 | if (!ce.emitMemberInitializerHomeObject(false)) { |
10488 | // [stack] HOMEOBJ HERITAGE? ARRAY METHOD |
10489 | // or: |
10490 | // [stack] CTOR HOMEOBJ ARRAY METHOD |
10491 | return false; |
10492 | } |
10493 | } |
10494 | if (!emitLexicalInitialization(storedMethodAtom)) { |
10495 | // [stack] HOMEOBJ HERITAGE? ARRAY METHOD |
10496 | // or: |
10497 | // [stack] CTOR HOMEOBJ ARRAY METHOD |
10498 | return false; |
10499 | } |
10500 | if (!emit1(JSOp::Pop)) { |
10501 | // [stack] HOMEOBJ HERITAGE? ARRAY |
10502 | // or: |
10503 | // [stack] CTOR HOMEOBJ ARRAY |
10504 | return false; |
10505 | } |
10506 | |
10507 | if (!emitPrivateMethodInitializer(classMethod, storedMethodAtom)) { |
10508 | // [stack] HOMEOBJ HERITAGE? ARRAY |
10509 | // or: |
10510 | // [stack] CTOR HOMEOBJ ARRAY |
10511 | return false; |
10512 | } |
10513 | |
10514 | // Store the emitted initializer function into the .initializers array. |
10515 | if (!ce.emitStoreMemberInitializer()) { |
10516 | // [stack] HOMEOBJ HERITAGE? ARRAY |
10517 | // or: |
10518 | // [stack] CTOR HOMEOBJ ARRAY |
10519 | return false; |
10520 | } |
10521 | } |
10522 | |
10523 | return true; |
10524 | } |
10525 | |
10526 | bool BytecodeEmitter::emitPrivateMethodInitializer( |
10527 | ClassMethod* classMethod, TaggedParserAtomIndex storedMethodAtom) { |
10528 | MOZ_ASSERT(IsPrivateInstanceAccessor(classMethod))do { static_assert( mozilla::detail::AssertionConditionType< decltype(IsPrivateInstanceAccessor(classMethod))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(IsPrivateInstanceAccessor(classMethod)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsPrivateInstanceAccessor(classMethod)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 10528); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsPrivateInstanceAccessor(classMethod)" ")"); do { *((volatile int*)__null) = 10528; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10529 | |
10530 | auto* name = &classMethod->name().as<NameNode>(); |
10531 | |
10532 | // Emit the synthesized initializer function. |
10533 | FunctionNode* funNode = classMethod->initializerIfPrivate(); |
10534 | MOZ_ASSERT(funNode)do { static_assert( mozilla::detail::AssertionConditionType< decltype(funNode)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(funNode))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("funNode", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 10534); AnnotateMozCrashReason("MOZ_ASSERT" "(" "funNode" ")" ); do { *((volatile int*)__null) = 10534; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
10535 | FunctionBox* funbox = funNode->funbox(); |
10536 | FunctionEmitter fe(this, funbox, funNode->syntaxKind(), |
10537 | FunctionEmitter::IsHoisted::No); |
10538 | if (!fe.prepareForNonLazy()) { |
10539 | // [stack] |
10540 | return false; |
10541 | } |
10542 | |
10543 | BytecodeEmitter bce2(this, funbox); |
10544 | if (!bce2.init(funNode->pn_pos)) { |
10545 | return false; |
10546 | } |
10547 | ParamsBodyNode* paramsBody = funNode->body(); |
10548 | FunctionScriptEmitter fse(&bce2, funbox, Nothing(), Nothing()); |
10549 | if (!fse.prepareForParameters()) { |
10550 | // [stack] |
10551 | return false; |
10552 | } |
10553 | if (!bce2.emitFunctionFormalParameters(paramsBody)) { |
10554 | // [stack] |
10555 | return false; |
10556 | } |
10557 | if (!fse.prepareForBody()) { |
10558 | // [stack] |
10559 | return false; |
10560 | } |
10561 | |
10562 | if (!bce2.emit1(JSOp::FunctionThis)) { |
10563 | // [stack] THIS |
10564 | return false; |
10565 | } |
10566 | if (!bce2.emitGetPrivateName(name)) { |
10567 | // [stack] THIS NAME |
10568 | return false; |
10569 | } |
10570 | if (!bce2.emitGetName(storedMethodAtom)) { |
10571 | // [stack] THIS NAME METHOD |
10572 | return false; |
10573 | } |
10574 | |
10575 | switch (name->privateNameKind()) { |
10576 | case PrivateNameKind::Setter: |
10577 | if (!bce2.emit1(JSOp::InitHiddenElemSetter)) { |
10578 | // [stack] THIS |
10579 | return false; |
10580 | } |
10581 | if (!bce2.emitGetPrivateName(name)) { |
10582 | // [stack] THIS NAME |
10583 | return false; |
10584 | } |
10585 | if (!bce2.emitAtomOp( |
10586 | JSOp::GetIntrinsic, |
10587 | TaggedParserAtomIndex::WellKnown::NoPrivateGetter())) { |
10588 | // [stack] THIS NAME FUN |
10589 | return false; |
10590 | } |
10591 | if (!bce2.emit1(JSOp::InitHiddenElemGetter)) { |
10592 | // [stack] THIS |
10593 | return false; |
10594 | } |
10595 | break; |
10596 | case PrivateNameKind::Getter: |
10597 | case PrivateNameKind::GetterSetter: |
10598 | if (classMethod->accessorType() == AccessorType::Getter) { |
10599 | if (!bce2.emit1(JSOp::InitHiddenElemGetter)) { |
10600 | // [stack] THIS |
10601 | return false; |
10602 | } |
10603 | } else { |
10604 | if (!bce2.emit1(JSOp::InitHiddenElemSetter)) { |
10605 | // [stack] THIS |
10606 | return false; |
10607 | } |
10608 | } |
10609 | break; |
10610 | default: |
10611 | MOZ_CRASH("Invalid op")do { do { } while (false); MOZ_ReportCrash("" "Invalid op", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 10611); AnnotateMozCrashReason("MOZ_CRASH(" "Invalid op" ")" ); do { *((volatile int*)__null) = 10611; __attribute__((nomerge )) ::abort(); } while (false); } while (false); |
10612 | } |
10613 | |
10614 | // Pop remaining THIS. |
10615 | if (!bce2.emit1(JSOp::Pop)) { |
10616 | // [stack] |
10617 | return false; |
10618 | } |
10619 | |
10620 | if (!fse.emitEndBody()) { |
10621 | // [stack] |
10622 | return false; |
10623 | } |
10624 | if (!fse.intoStencil()) { |
10625 | return false; |
10626 | } |
10627 | |
10628 | if (!fe.emitNonLazyEnd()) { |
10629 | // [stack] HOMEOBJ HERITAGE? ARRAY FUN |
10630 | // or: |
10631 | // [stack] CTOR HOMEOBJ ARRAY FUN |
10632 | return false; |
10633 | } |
10634 | |
10635 | return true; |
10636 | } |
10637 | |
10638 | const MemberInitializers& BytecodeEmitter::findMemberInitializersForCall() |
10639 | const { |
10640 | for (const auto* current = this; current; current = current->parent) { |
10641 | if (current->sc->isFunctionBox()) { |
10642 | FunctionBox* funbox = current->sc->asFunctionBox(); |
10643 | |
10644 | if (funbox->isArrow()) { |
10645 | continue; |
10646 | } |
10647 | |
10648 | // If we found a non-arrow / non-constructor we were never allowed to |
10649 | // expect fields in the first place. |
10650 | MOZ_RELEASE_ASSERT(funbox->isClassConstructor())do { static_assert( mozilla::detail::AssertionConditionType< decltype(funbox->isClassConstructor())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(funbox->isClassConstructor ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("funbox->isClassConstructor()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 10650); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "funbox->isClassConstructor()" ")"); do { *((volatile int*)__null) = 10650; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10651 | |
10652 | return funbox->useMemberInitializers() ? funbox->memberInitializers() |
10653 | : MemberInitializers::Empty(); |
10654 | } |
10655 | } |
10656 | |
10657 | MOZ_RELEASE_ASSERT(compilationState.scopeContext.memberInitializers)do { static_assert( mozilla::detail::AssertionConditionType< decltype(compilationState.scopeContext.memberInitializers)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(compilationState.scopeContext.memberInitializers))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("compilationState.scopeContext.memberInitializers" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 10657); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "compilationState.scopeContext.memberInitializers" ")"); do { *((volatile int*)__null) = 10657; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10658 | return *compilationState.scopeContext.memberInitializers; |
10659 | } |
10660 | |
10661 | bool BytecodeEmitter::emitInitializeInstanceMembers( |
10662 | bool isDerivedClassConstructor) { |
10663 | const MemberInitializers& memberInitializers = |
10664 | findMemberInitializersForCall(); |
10665 | MOZ_ASSERT(memberInitializers.valid)do { static_assert( mozilla::detail::AssertionConditionType< decltype(memberInitializers.valid)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(memberInitializers.valid))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("memberInitializers.valid" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 10665); AnnotateMozCrashReason("MOZ_ASSERT" "(" "memberInitializers.valid" ")"); do { *((volatile int*)__null) = 10665; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10666 | |
10667 | if (memberInitializers.hasPrivateBrand) { |
10668 | // This is guaranteed to run after super(), so we don't need TDZ checks. |
10669 | if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_this_())) { |
10670 | // [stack] THIS |
10671 | return false; |
10672 | } |
10673 | if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_privateBrand_())) { |
10674 | // [stack] THIS BRAND |
10675 | return false; |
10676 | } |
10677 | if (isDerivedClassConstructor) { |
10678 | if (!emitCheckPrivateField(ThrowCondition::ThrowHas, |
10679 | ThrowMsgKind::PrivateBrandDoubleInit)) { |
10680 | // [stack] THIS BRAND BOOL |
10681 | return false; |
10682 | } |
10683 | if (!emit1(JSOp::Pop)) { |
10684 | // [stack] THIS BRAND |
10685 | return false; |
10686 | } |
10687 | } |
10688 | if (!emit1(JSOp::Null)) { |
10689 | // [stack] THIS BRAND NULL |
10690 | return false; |
10691 | } |
10692 | if (!emit1(JSOp::InitHiddenElem)) { |
10693 | // [stack] THIS |
10694 | return false; |
10695 | } |
10696 | if (!emit1(JSOp::Pop)) { |
10697 | // [stack] |
10698 | return false; |
10699 | } |
10700 | } |
10701 | |
10702 | size_t numInitializers = memberInitializers.numMemberInitializers; |
10703 | if (numInitializers > 0) { |
10704 | if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_initializers_())) { |
10705 | // [stack] ARRAY |
10706 | return false; |
10707 | } |
10708 | |
10709 | for (size_t index = 0; index < numInitializers; index++) { |
10710 | if (index < numInitializers - 1) { |
10711 | // We Dup to keep the array around (it is consumed in the bytecode |
10712 | // below) for next iterations of this loop, except for the last |
10713 | // iteration, which avoids an extra Pop at the end of the loop. |
10714 | if (!emit1(JSOp::Dup)) { |
10715 | // [stack] ARRAY ARRAY |
10716 | return false; |
10717 | } |
10718 | } |
10719 | |
10720 | if (!emitNumberOp(index)) { |
10721 | // [stack] ARRAY? ARRAY INDEX |
10722 | return false; |
10723 | } |
10724 | |
10725 | if (!emit1(JSOp::GetElem)) { |
10726 | // [stack] ARRAY? FUNC |
10727 | return false; |
10728 | } |
10729 | |
10730 | // This is guaranteed to run after super(), so we don't need TDZ checks. |
10731 | if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_this_())) { |
10732 | // [stack] ARRAY? FUNC THIS |
10733 | return false; |
10734 | } |
10735 | |
10736 | // Callee is always internal function. |
10737 | if (!emitCall(JSOp::CallIgnoresRv, 0)) { |
10738 | // [stack] ARRAY? RVAL |
10739 | return false; |
10740 | } |
10741 | |
10742 | if (!emit1(JSOp::Pop)) { |
10743 | // [stack] ARRAY? |
10744 | return false; |
10745 | } |
10746 | } |
10747 | #ifdef ENABLE_DECORATORS |
10748 | if (memberInitializers.hasDecorators) { |
10749 | // Decorators Proposal |
10750 | // https://arai-a.github.io/ecma262-compare/?pr=2417&id=sec-initializeinstanceelements |
10751 | // 4. For each element e of elements, do |
10752 | // 4.a. If elementRecord.[[Kind]] is field or accessor, then |
10753 | // 4.a.i. Perform ? InitializeFieldOrAccessor(O, elementRecord). |
10754 | // |
10755 | |
10756 | // TODO: (See Bug 1817993) At the moment, we're applying the |
10757 | // initialization logic in two steps. The pre-decorator initialization |
10758 | // code runs, stores the initial value, and then we retrieve it here and |
10759 | // apply the initializers added by decorators. We should unify these two |
10760 | // steps. |
10761 | if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_initializers_())) { |
10762 | // [stack] ARRAY |
10763 | return false; |
10764 | } |
10765 | |
10766 | if (!emit1(JSOp::Dup)) { |
10767 | // [stack] ARRAY ARRAY |
10768 | return false; |
10769 | } |
10770 | |
10771 | if (!emitAtomOp(JSOp::GetProp, |
10772 | TaggedParserAtomIndex::WellKnown::length())) { |
10773 | // [stack] ARRAY LENGTH |
10774 | return false; |
10775 | } |
10776 | |
10777 | if (!emitNumberOp(static_cast<double>(numInitializers))) { |
10778 | // [stack] ARRAY LENGTH INDEX |
10779 | return false; |
10780 | } |
10781 | |
10782 | InternalWhileEmitter wh(this); |
10783 | // At this point, we have no context to determine offsets in the |
10784 | // code for this while statement. Ideally, it would correspond to |
10785 | // the field we're initializing. |
10786 | if (!wh.emitCond()) { |
10787 | // [stack] ARRAY LENGTH INDEX |
10788 | return false; |
10789 | } |
10790 | |
10791 | if (!emit1(JSOp::Dup)) { |
10792 | // [stack] ARRAY LENGTH INDEX INDEX |
10793 | return false; |
10794 | } |
10795 | |
10796 | if (!emitDupAt(2)) { |
10797 | // [stack] ARRAY LENGTH INDEX INDEX LENGTH |
10798 | return false; |
10799 | } |
10800 | |
10801 | if (!emit1(JSOp::Lt)) { |
10802 | // [stack] ARRAY LENGTH INDEX BOOL |
10803 | return false; |
10804 | } |
10805 | |
10806 | if (!wh.emitBody()) { |
10807 | // [stack] ARRAY LENGTH INDEX |
10808 | return false; |
10809 | } |
10810 | |
10811 | if (!emitDupAt(2)) { |
10812 | // [stack] ARRAY LENGTH INDEX ARRAY |
10813 | return false; |
10814 | } |
10815 | |
10816 | if (!emitDupAt(1)) { |
10817 | // [stack] ARRAY LENGTH INDEX ARRAY INDEX |
10818 | return false; |
10819 | } |
10820 | |
10821 | // Retrieve initializers for this field |
10822 | if (!emit1(JSOp::GetElem)) { |
10823 | // [stack] ARRAY LENGTH INDEX INITIALIZERS |
10824 | return false; |
10825 | } |
10826 | |
10827 | // This is guaranteed to run after super(), so we don't need TDZ checks. |
10828 | if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_this_())) { |
10829 | // [stack] ARRAY LENGTH INDEX INITIALIZERS THIS |
10830 | return false; |
10831 | } |
10832 | |
10833 | if (!emit1(JSOp::Swap)) { |
10834 | // [stack] ARRAY LENGTH INDEX THIS INITIALIZERS |
10835 | return false; |
10836 | } |
10837 | |
10838 | DecoratorEmitter de(this); |
10839 | if (!de.emitInitializeFieldOrAccessor()) { |
10840 | // [stack] ARRAY LENGTH INDEX |
10841 | return false; |
10842 | } |
10843 | |
10844 | if (!emit1(JSOp::Inc)) { |
10845 | // [stack] ARRAY LENGTH INDEX |
10846 | return false; |
10847 | } |
10848 | |
10849 | if (!wh.emitEnd()) { |
10850 | // [stack] ARRAY LENGTH INDEX |
10851 | return false; |
10852 | } |
10853 | |
10854 | if (!emitPopN(3)) { |
10855 | // [stack] |
10856 | return false; |
10857 | } |
10858 | // 5. Return unused. |
10859 | |
10860 | if (!de.emitCallExtraInitializers(TaggedParserAtomIndex::WellKnown:: |
10861 | dot_instanceExtraInitializers_())) { |
10862 | return false; |
10863 | } |
10864 | } |
10865 | #endif |
10866 | } |
10867 | return true; |
10868 | } |
10869 | |
10870 | bool BytecodeEmitter::emitInitializeStaticFields(ListNode* classMembers) { |
10871 | auto isStaticField = [](ParseNode* propdef) { |
10872 | return HasInitializer(propdef, true); |
10873 | }; |
10874 | size_t numFields = |
10875 | std::count_if(classMembers->contents().begin(), |
10876 | classMembers->contents().end(), isStaticField); |
10877 | |
10878 | if (numFields == 0) { |
10879 | return true; |
10880 | } |
10881 | |
10882 | if (!emitGetName( |
10883 | TaggedParserAtomIndex::WellKnown::dot_staticInitializers_())) { |
10884 | // [stack] CTOR ARRAY |
10885 | return false; |
10886 | } |
10887 | |
10888 | for (size_t fieldIndex = 0; fieldIndex < numFields; fieldIndex++) { |
10889 | bool hasNext = fieldIndex < numFields - 1; |
10890 | if (hasNext) { |
10891 | // We Dup to keep the array around (it is consumed in the bytecode below) |
10892 | // for next iterations of this loop, except for the last iteration, which |
10893 | // avoids an extra Pop at the end of the loop. |
10894 | if (!emit1(JSOp::Dup)) { |
10895 | // [stack] CTOR ARRAY ARRAY |
10896 | return false; |
10897 | } |
10898 | } |
10899 | |
10900 | if (!emitNumberOp(fieldIndex)) { |
10901 | // [stack] CTOR ARRAY? ARRAY INDEX |
10902 | return false; |
10903 | } |
10904 | |
10905 | if (!emit1(JSOp::GetElem)) { |
10906 | // [stack] CTOR ARRAY? FUNC |
10907 | return false; |
10908 | } |
10909 | |
10910 | if (!emitDupAt(1 + hasNext)) { |
10911 | // [stack] CTOR ARRAY? FUNC CTOR |
10912 | return false; |
10913 | } |
10914 | |
10915 | // Callee is always internal function. |
10916 | if (!emitCall(JSOp::CallIgnoresRv, 0)) { |
10917 | // [stack] CTOR ARRAY? RVAL |
10918 | return false; |
10919 | } |
10920 | |
10921 | if (!emit1(JSOp::Pop)) { |
10922 | // [stack] CTOR ARRAY? |
10923 | return false; |
10924 | } |
10925 | } |
10926 | |
10927 | #ifdef ENABLE_DECORATORS |
10928 | // Decorators Proposal |
10929 | // https://arai-a.github.io/ecma262-compare/?pr=2417&id=sec-initializeinstanceelements |
10930 | // 4. For each element e of elements, do |
10931 | // 4.a. If elementRecord.[[Kind]] is field or accessor, then |
10932 | // 4.a.i. Perform ? InitializeFieldOrAccessor(O, elementRecord). |
10933 | // |
10934 | |
10935 | // TODO: (See Bug 1817993) At the moment, we're applying the initialization |
10936 | // logic in two steps. The pre-decorator initialization code runs, stores |
10937 | // the initial value, and then we retrieve it here and apply the |
10938 | // initializers added by decorators. We should unify these two steps. |
10939 | if (!emitGetName( |
10940 | TaggedParserAtomIndex::WellKnown::dot_staticInitializers_())) { |
10941 | // [stack] CTOR ARRAY |
10942 | return false; |
10943 | } |
10944 | |
10945 | if (!emit1(JSOp::Dup)) { |
10946 | // [stack] CTOR ARRAY ARRAY |
10947 | return false; |
10948 | } |
10949 | |
10950 | if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::length())) { |
10951 | // [stack] CTOR ARRAY LENGTH |
10952 | return false; |
10953 | } |
10954 | |
10955 | if (!emitNumberOp(static_cast<double>(numFields))) { |
10956 | // [stack] CTOR ARRAY LENGTH INDEX |
10957 | return false; |
10958 | } |
10959 | |
10960 | InternalWhileEmitter wh(this); |
10961 | // At this point, we have no context to determine offsets in the |
10962 | // code for this while statement. Ideally, it would correspond to |
10963 | // the field we're initializing. |
10964 | if (!wh.emitCond()) { |
10965 | // [stack] CTOR ARRAY LENGTH INDEX |
10966 | return false; |
10967 | } |
10968 | |
10969 | if (!emit1(JSOp::Dup)) { |
10970 | // [stack] CTOR ARRAY LENGTH INDEX INDEX |
10971 | return false; |
10972 | } |
10973 | |
10974 | if (!emitDupAt(2)) { |
10975 | // [stack] CTOR ARRAY LENGTH INDEX INDEX LENGTH |
10976 | return false; |
10977 | } |
10978 | |
10979 | if (!emit1(JSOp::Lt)) { |
10980 | // [stack] CTOR ARRAY LENGTH INDEX BOOL |
10981 | return false; |
10982 | } |
10983 | |
10984 | if (!wh.emitBody()) { |
10985 | // [stack] CTOR ARRAY LENGTH INDEX |
10986 | return false; |
10987 | } |
10988 | |
10989 | if (!emitDupAt(2)) { |
10990 | // [stack] CTOR ARRAY LENGTH INDEX ARRAY |
10991 | return false; |
10992 | } |
10993 | |
10994 | if (!emitDupAt(1)) { |
10995 | // [stack] CTOR ARRAY LENGTH INDEX ARRAY INDEX |
10996 | return false; |
10997 | } |
10998 | |
10999 | // Retrieve initializers for this field |
11000 | if (!emit1(JSOp::GetElem)) { |
11001 | // [stack] CTOR ARRAY LENGTH INDEX INITIALIZERS |
11002 | return false; |
11003 | } |
11004 | |
11005 | if (!emitDupAt(4)) { |
11006 | // [stack] CTOR ARRAY LENGTH INDEX INITIALIZERS CTOR |
11007 | return false; |
11008 | } |
11009 | |
11010 | if (!emit1(JSOp::Swap)) { |
11011 | // [stack] CTOR ARRAY LENGTH INDEX CTOR INITIALIZERS |
11012 | return false; |
11013 | } |
11014 | |
11015 | DecoratorEmitter de(this); |
11016 | if (!de.emitInitializeFieldOrAccessor()) { |
11017 | // [stack] CTOR ARRAY LENGTH INDEX |
11018 | return false; |
11019 | } |
11020 | |
11021 | if (!emit1(JSOp::Inc)) { |
11022 | // [stack] CTOR ARRAY LENGTH INDEX |
11023 | return false; |
11024 | } |
11025 | |
11026 | if (!wh.emitEnd()) { |
11027 | // [stack] CTOR ARRAY LENGTH INDEX |
11028 | return false; |
11029 | } |
11030 | |
11031 | if (!emitPopN(3)) { |
11032 | // [stack] CTOR |
11033 | return false; |
11034 | } |
11035 | // 5. Return unused. |
11036 | #endif |
11037 | |
11038 | // Overwrite |.staticInitializers| and |.staticFieldKeys| with undefined to |
11039 | // avoid keeping the arrays alive indefinitely. |
11040 | auto clearStaticFieldSlot = [&](TaggedParserAtomIndex name) { |
11041 | NameOpEmitter noe(this, name, NameOpEmitter::Kind::SimpleAssignment); |
11042 | if (!noe.prepareForRhs()) { |
11043 | // [stack] ENV? VAL? |
11044 | return false; |
11045 | } |
11046 | |
11047 | if (!emit1(JSOp::Undefined)) { |
11048 | // [stack] ENV? VAL? UNDEFINED |
11049 | return false; |
11050 | } |
11051 | |
11052 | if (!noe.emitAssignment()) { |
11053 | // [stack] VAL |
11054 | return false; |
11055 | } |
11056 | |
11057 | if (!emit1(JSOp::Pop)) { |
11058 | // [stack] |
11059 | return false; |
11060 | } |
11061 | |
11062 | return true; |
11063 | }; |
11064 | |
11065 | if (!clearStaticFieldSlot( |
11066 | TaggedParserAtomIndex::WellKnown::dot_staticInitializers_())) { |
11067 | return false; |
11068 | } |
11069 | |
11070 | auto isStaticFieldWithComputedName = [](ParseNode* propdef) { |
11071 | return propdef->is<ClassField>() && propdef->as<ClassField>().isStatic() && |
11072 | propdef->as<ClassField>().name().getKind() == |
11073 | ParseNodeKind::ComputedName; |
11074 | }; |
11075 | |
11076 | if (std::any_of(classMembers->contents().begin(), |
11077 | classMembers->contents().end(), |
11078 | isStaticFieldWithComputedName)) { |
11079 | if (!clearStaticFieldSlot( |
11080 | TaggedParserAtomIndex::WellKnown::dot_staticFieldKeys_())) { |
11081 | return false; |
11082 | } |
11083 | } |
11084 | |
11085 | return true; |
11086 | } |
11087 | |
11088 | // Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See |
11089 | // the comment on emitSwitch. |
11090 | MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitObject(ListNode* objNode) { |
11091 | // Note: this method uses the ObjLiteralWriter and emits ObjLiteralStencil |
11092 | // objects into the GCThingList, which will evaluate them into real GC objects |
11093 | // or shapes during JSScript::fullyInitFromEmitter. Eventually we want |
11094 | // JSOp::Object to be a real opcode, but for now, performance constraints |
11095 | // limit us to evaluating object literals at the end of parse, when we're |
11096 | // allowed to allocate GC things. |
11097 | // |
11098 | // There are four cases here, in descending order of preference: |
11099 | // |
11100 | // 1. The list of property names is "normal" and constant (no computed |
11101 | // values, no integer indices), the values are all simple constants |
11102 | // (numbers, booleans, strings), *and* this occurs in a run-once |
11103 | // (singleton) context. In this case, we can emit ObjLiteral |
11104 | // instructions to build an object with values, and the object will be |
11105 | // attached to a JSOp::Object opcode, whose semantics are for the backend |
11106 | // to simply steal the object from the script. |
11107 | // |
11108 | // 2. The list of property names is "normal" and constant as above, *and* this |
11109 | // occurs in a run-once (singleton) context, but some values are complex |
11110 | // (computed expressions, sub-objects, functions, etc.). In this case, we |
11111 | // can still use JSOp::Object (because singleton context), but the object |
11112 | // has |undefined| property values and InitProp ops are emitted to set the |
11113 | // values. |
11114 | // |
11115 | // 3. The list of property names is "normal" and constant as above, but this |
11116 | // occurs in a non-run-once (non-singleton) context. In this case, we can |
11117 | // use the ObjLiteral functionality to describe an *empty* object (all |
11118 | // values left undefined) with the right fields, which will become a |
11119 | // JSOp::NewObject opcode using the object's shape to speed up the creation |
11120 | // of the object each time it executes. The emitted bytecode still needs |
11121 | // InitProp ops to set the values in this case. |
11122 | // |
11123 | // 4. Any other case. As a fallback, we use NewInit to create a new, empty |
11124 | // object (i.e., `{}`) and then emit bytecode to initialize its properties |
11125 | // one-by-one. |
11126 | |
11127 | bool useObjLiteral = false; |
11128 | bool useObjLiteralValues = false; |
11129 | isPropertyListObjLiteralCompatible(objNode, &useObjLiteralValues, |
11130 | &useObjLiteral); |
11131 | |
11132 | // [stack] |
11133 | // |
11134 | ObjectEmitter oe(this); |
11135 | if (useObjLiteral) { |
11136 | bool singleton = checkSingletonContext() && |
11137 | !objNode->hasNonConstInitializer() && objNode->head(); |
11138 | JSOp op; |
11139 | if (singleton) { |
11140 | // Case 1 or 2. |
11141 | op = JSOp::Object; |
11142 | } else { |
11143 | // Case 3. |
11144 | useObjLiteralValues = false; |
11145 | op = JSOp::NewObject; |
11146 | } |
11147 | |
11148 | // Use an ObjLiteral op. This will record ObjLiteral insns in the |
11149 | // objLiteralWriter's buffer and add a fixup to the list of ObjLiteral |
11150 | // fixups so that at GC-publish time at the end of parse, the full object |
11151 | // (case 1 or 2) or shape (case 3) can be allocated and the bytecode can be |
11152 | // patched to refer to it. |
11153 | if (!emitPropertyListObjLiteral(objNode, op, useObjLiteralValues)) { |
11154 | // [stack] OBJ |
11155 | return false; |
11156 | } |
11157 | // Put the ObjectEmitter in the right state. This tells it that there will |
11158 | // already be an object on the stack as a result of the (eventual) |
11159 | // NewObject or Object op, and prepares it to emit values if needed. |
11160 | if (!oe.emitObjectWithTemplateOnStack()) { |
11161 | // [stack] OBJ |
11162 | return false; |
11163 | } |
11164 | if (!useObjLiteralValues) { |
11165 | // Case 2 or 3 above: we still need to emit bytecode to fill in the |
11166 | // object's property values. |
11167 | if (!emitPropertyList(objNode, oe, ObjectLiteral)) { |
11168 | // [stack] OBJ |
11169 | return false; |
11170 | } |
11171 | } |
11172 | } else { |
11173 | // Case 4 above: no ObjLiteral use, just bytecode to build the object from |
11174 | // scratch. |
11175 | if (!oe.emitObject(objNode->count())) { |
11176 | // [stack] OBJ |
11177 | return false; |
11178 | } |
11179 | if (!emitPropertyList(objNode, oe, ObjectLiteral)) { |
11180 | // [stack] OBJ |
11181 | return false; |
11182 | } |
11183 | } |
11184 | |
11185 | if (!oe.emitEnd()) { |
11186 | // [stack] OBJ |
11187 | return false; |
11188 | } |
11189 | |
11190 | return true; |
11191 | } |
11192 | |
11193 | bool BytecodeEmitter::emitArrayLiteral(ListNode* array) { |
11194 | // Emit JSOp::Object if the array consists entirely of primitive values and we |
11195 | // are in a singleton context. |
11196 | if (checkSingletonContext() && !array->hasNonConstInitializer() && |
11197 | !array->empty() && isArrayObjLiteralCompatible(array)) { |
11198 | return emitObjLiteralArray(array); |
11199 | } |
11200 | |
11201 | return emitArray(array); |
11202 | } |
11203 | |
11204 | bool BytecodeEmitter::emitArray(ListNode* array) { |
11205 | /* |
11206 | * Emit code for [a, b, c] that is equivalent to constructing a new |
11207 | * array and in source order evaluating each element value and adding |
11208 | * it to the array, without invoking latent setters. We use the |
11209 | * JSOp::NewInit and JSOp::InitElemArray bytecodes to ignore setters and |
11210 | * to avoid dup'ing and popping the array as each element is added, as |
11211 | * JSOp::SetElem/JSOp::SetProp would do. |
11212 | */ |
11213 | |
11214 | uint32_t nspread = 0; |
11215 | for (ParseNode* elem : array->contents()) { |
11216 | if (elem->isKind(ParseNodeKind::Spread)) { |
11217 | nspread++; |
11218 | } |
11219 | } |
11220 | |
11221 | // Array literal's length is limited to NELEMENTS_LIMIT in parser. |
11222 | static_assert(NativeObject::MAX_DENSE_ELEMENTS_COUNT <= INT32_MAX(2147483647), |
11223 | "array literals' maximum length must not exceed limits " |
11224 | "required by BaselineCompiler::emit_NewArray, " |
11225 | "BaselineCompiler::emit_InitElemArray, " |
11226 | "and DoSetElemFallback's handling of JSOp::InitElemArray"); |
11227 | |
11228 | uint32_t count = array->count(); |
11229 | MOZ_ASSERT(count >= nspread)do { static_assert( mozilla::detail::AssertionConditionType< decltype(count >= nspread)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(count >= nspread))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("count >= nspread" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11229); AnnotateMozCrashReason("MOZ_ASSERT" "(" "count >= nspread" ")"); do { *((volatile int*)__null) = 11229; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
11230 | MOZ_ASSERT(count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT,do { static_assert( mozilla::detail::AssertionConditionType< decltype(count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT" " (" "the parser must throw an error if the array exceeds maximum " "length" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11232); AnnotateMozCrashReason("MOZ_ASSERT" "(" "count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT" ") (" "the parser must throw an error if the array exceeds maximum " "length" ")"); do { *((volatile int*)__null) = 11232; __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false) |
11231 | "the parser must throw an error if the array exceeds maximum "do { static_assert( mozilla::detail::AssertionConditionType< decltype(count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT" " (" "the parser must throw an error if the array exceeds maximum " "length" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11232); AnnotateMozCrashReason("MOZ_ASSERT" "(" "count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT" ") (" "the parser must throw an error if the array exceeds maximum " "length" ")"); do { *((volatile int*)__null) = 11232; __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false) |
11232 | "length")do { static_assert( mozilla::detail::AssertionConditionType< decltype(count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT" " (" "the parser must throw an error if the array exceeds maximum " "length" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11232); AnnotateMozCrashReason("MOZ_ASSERT" "(" "count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT" ") (" "the parser must throw an error if the array exceeds maximum " "length" ")"); do { *((volatile int*)__null) = 11232; __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false); |
11233 | |
11234 | // For arrays with spread, this is a very pessimistic allocation, the |
11235 | // minimum possible final size. |
11236 | if (!emitUint32Operand(JSOp::NewArray, count - nspread)) { |
11237 | // [stack] ARRAY |
11238 | return false; |
11239 | } |
11240 | |
11241 | uint32_t index = 0; |
11242 | bool afterSpread = false; |
11243 | for (ParseNode* elem : array->contents()) { |
11244 | if (elem->isKind(ParseNodeKind::Spread)) { |
11245 | if (!afterSpread) { |
11246 | afterSpread = true; |
11247 | if (!emitNumberOp(index)) { |
11248 | // [stack] ARRAY INDEX |
11249 | return false; |
11250 | } |
11251 | } |
11252 | |
11253 | ParseNode* expr = elem->as<UnaryNode>().kid(); |
11254 | SelfHostedIter selfHostedIter = getSelfHostedIterFor(expr); |
11255 | |
11256 | if (!updateSourceCoordNotes(elem->pn_pos.begin)) { |
11257 | return false; |
11258 | } |
11259 | if (!emitIterable(expr, selfHostedIter)) { |
11260 | // [stack] ARRAY INDEX ITERABLE |
11261 | return false; |
11262 | } |
11263 | if (!emitIterator(selfHostedIter)) { |
11264 | // [stack] ARRAY INDEX NEXT ITER |
11265 | return false; |
11266 | } |
11267 | if (!emit2(JSOp::Pick, 3)) { |
11268 | // [stack] INDEX NEXT ITER ARRAY |
11269 | return false; |
11270 | } |
11271 | if (!emit2(JSOp::Pick, 3)) { |
11272 | // [stack] NEXT ITER ARRAY INDEX |
11273 | return false; |
11274 | } |
11275 | if (!emitSpread(selfHostedIter)) { |
11276 | // [stack] ARRAY INDEX |
11277 | return false; |
11278 | } |
11279 | } else { |
11280 | if (!updateSourceCoordNotesIfNonLiteral(elem)) { |
11281 | return false; |
11282 | } |
11283 | if (elem->isKind(ParseNodeKind::Elision)) { |
11284 | if (!emit1(JSOp::Hole)) { |
11285 | return false; |
11286 | } |
11287 | } else { |
11288 | if (!emitTree(elem, ValueUsage::WantValue)) { |
11289 | // [stack] ARRAY INDEX? VALUE |
11290 | return false; |
11291 | } |
11292 | } |
11293 | |
11294 | if (afterSpread) { |
11295 | if (!emit1(JSOp::InitElemInc)) { |
11296 | // [stack] ARRAY (INDEX+1) |
11297 | return false; |
11298 | } |
11299 | } else { |
11300 | if (!emitUint32Operand(JSOp::InitElemArray, index)) { |
11301 | // [stack] ARRAY |
11302 | return false; |
11303 | } |
11304 | } |
11305 | } |
11306 | |
11307 | index++; |
11308 | } |
11309 | MOZ_ASSERT(index == count)do { static_assert( mozilla::detail::AssertionConditionType< decltype(index == count)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(index == count))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("index == count" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11309); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index == count" ")"); do { *((volatile int*)__null) = 11309; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
11310 | if (afterSpread) { |
11311 | if (!emit1(JSOp::Pop)) { |
11312 | // [stack] ARRAY |
11313 | return false; |
11314 | } |
11315 | } |
11316 | return true; |
11317 | } |
11318 | |
11319 | bool BytecodeEmitter::emitSpreadIntoArray(UnaryNode* elem) { |
11320 | MOZ_ASSERT(elem->isKind(ParseNodeKind::Spread))do { static_assert( mozilla::detail::AssertionConditionType< decltype(elem->isKind(ParseNodeKind::Spread))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(elem->isKind(ParseNodeKind::Spread)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("elem->isKind(ParseNodeKind::Spread)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11320); AnnotateMozCrashReason("MOZ_ASSERT" "(" "elem->isKind(ParseNodeKind::Spread)" ")"); do { *((volatile int*)__null) = 11320; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
11321 | |
11322 | if (!updateSourceCoordNotes(elem->pn_pos.begin)) { |
11323 | // [stack] VALUE |
11324 | return false; |
11325 | } |
11326 | |
11327 | SelfHostedIter selfHostedIter = getSelfHostedIterFor(elem->kid()); |
11328 | MOZ_ASSERT(selfHostedIter == SelfHostedIter::Deny ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(selfHostedIter == SelfHostedIter::Deny || selfHostedIter == SelfHostedIter::AllowContent)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(selfHostedIter == SelfHostedIter ::Deny || selfHostedIter == SelfHostedIter::AllowContent))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter == SelfHostedIter::Deny || selfHostedIter == SelfHostedIter::AllowContent" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11329); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter == SelfHostedIter::Deny || selfHostedIter == SelfHostedIter::AllowContent" ")"); do { *((volatile int*)__null) = 11329; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
11329 | selfHostedIter == SelfHostedIter::AllowContent)do { static_assert( mozilla::detail::AssertionConditionType< decltype(selfHostedIter == SelfHostedIter::Deny || selfHostedIter == SelfHostedIter::AllowContent)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(selfHostedIter == SelfHostedIter ::Deny || selfHostedIter == SelfHostedIter::AllowContent))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter == SelfHostedIter::Deny || selfHostedIter == SelfHostedIter::AllowContent" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11329); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter == SelfHostedIter::Deny || selfHostedIter == SelfHostedIter::AllowContent" ")"); do { *((volatile int*)__null) = 11329; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
11330 | |
11331 | if (!emitIterator(selfHostedIter)) { |
11332 | // [stack] NEXT ITER |
11333 | return false; |
11334 | } |
11335 | |
11336 | if (!emitUint32Operand(JSOp::NewArray, 0)) { |
11337 | // [stack] NEXT ITER ARRAY |
11338 | return false; |
11339 | } |
11340 | |
11341 | if (!emitNumberOp(0)) { |
11342 | // [stack] NEXT ITER ARRAY INDEX |
11343 | return false; |
11344 | } |
11345 | |
11346 | if (!emitSpread(selfHostedIter)) { |
11347 | // [stack] ARRAY INDEX |
11348 | return false; |
11349 | } |
11350 | |
11351 | if (!emit1(JSOp::Pop)) { |
11352 | // [stack] ARRAY |
11353 | return false; |
11354 | } |
11355 | return true; |
11356 | } |
11357 | |
11358 | #ifdef ENABLE_RECORD_TUPLE |
11359 | bool BytecodeEmitter::emitRecordLiteral(ListNode* record) { |
11360 | if (!emitUint32Operand(JSOp::InitRecord, record->count())) { |
11361 | // [stack] RECORD |
11362 | return false; |
11363 | } |
11364 | |
11365 | for (ParseNode* propdef : record->contents()) { |
11366 | if (propdef->isKind(ParseNodeKind::Spread)) { |
11367 | if (!emitTree(propdef->as<UnaryNode>().kid())) { |
11368 | // [stack] RECORD SPREADEE |
11369 | return false; |
11370 | } |
11371 | if (!emit1(JSOp::AddRecordSpread)) { |
11372 | // [stack] RECORD |
11373 | return false; |
11374 | } |
11375 | } else { |
11376 | BinaryNode* prop = &propdef->as<BinaryNode>(); |
11377 | |
11378 | ParseNode* key = prop->left(); |
11379 | ParseNode* value = prop->right(); |
11380 | |
11381 | switch (key->getKind()) { |
11382 | case ParseNodeKind::ObjectPropertyName: |
11383 | if (!emitStringOp(JSOp::String, key->as<NameNode>().atom())) { |
11384 | return false; |
11385 | } |
11386 | break; |
11387 | case ParseNodeKind::ComputedName: |
11388 | if (!emitTree(key->as<UnaryNode>().kid())) { |
11389 | return false; |
11390 | } |
11391 | break; |
11392 | default: |
11393 | MOZ_ASSERT(key->isKind(ParseNodeKind::StringExpr) ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(key->isKind(ParseNodeKind::StringExpr) || key-> isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind ::BigIntExpr))>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(key->isKind(ParseNodeKind::StringExpr ) || key->isKind(ParseNodeKind::NumberExpr) || key->isKind (ParseNodeKind::BigIntExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11395); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr)" ")"); do { *((volatile int*)__null) = 11395; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
11394 | key->isKind(ParseNodeKind::NumberExpr) ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(key->isKind(ParseNodeKind::StringExpr) || key-> isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind ::BigIntExpr))>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(key->isKind(ParseNodeKind::StringExpr ) || key->isKind(ParseNodeKind::NumberExpr) || key->isKind (ParseNodeKind::BigIntExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11395); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr)" ")"); do { *((volatile int*)__null) = 11395; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
11395 | key->isKind(ParseNodeKind::BigIntExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(key->isKind(ParseNodeKind::StringExpr) || key-> isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind ::BigIntExpr))>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(key->isKind(ParseNodeKind::StringExpr ) || key->isKind(ParseNodeKind::NumberExpr) || key->isKind (ParseNodeKind::BigIntExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11395); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr)" ")"); do { *((volatile int*)__null) = 11395; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
11396 | if (!emitTree(key)) { |
11397 | return false; |
11398 | } |
11399 | break; |
11400 | } |
11401 | // [stack] RECORD KEY |
11402 | |
11403 | if (!emitTree(value)) { |
11404 | // [stack] RECORD KEY VALUE |
11405 | return false; |
11406 | } |
11407 | |
11408 | if (!emit1(JSOp::AddRecordProperty)) { |
11409 | // [stack] RECORD |
11410 | return false; |
11411 | } |
11412 | } |
11413 | } |
11414 | |
11415 | if (!emit1(JSOp::FinishRecord)) { |
11416 | // [stack] RECORD |
11417 | return false; |
11418 | } |
11419 | |
11420 | return true; |
11421 | } |
11422 | |
11423 | bool BytecodeEmitter::emitTupleLiteral(ListNode* tuple) { |
11424 | if (!emitUint32Operand(JSOp::InitTuple, tuple->count())) { |
11425 | // [stack] TUPLE |
11426 | return false; |
11427 | } |
11428 | |
11429 | for (ParseNode* elt : tuple->contents()) { |
11430 | if (elt->isKind(ParseNodeKind::Spread)) { |
11431 | ParseNode* expr = elt->as<UnaryNode>().kid(); |
11432 | auto selfHostedIter = getSelfHostedIterFor(expr); |
11433 | |
11434 | if (!emitIterable(expr, selfHostedIter)) { |
11435 | // [stack] TUPLE ITERABLE |
11436 | return false; |
11437 | } |
11438 | if (!emitIterator(selfHostedIter)) { |
11439 | // [stack] TUPLE NEXT ITER |
11440 | return false; |
11441 | } |
11442 | if (!emit2(JSOp::Pick, 2)) { |
11443 | // [stack] NEXT ITER TUPLE |
11444 | return false; |
11445 | } |
11446 | if (!emitSpread(selfHostedIter, /* spreadeeStackItems = */ 1, |
11447 | JSOp::AddTupleElement)) { |
11448 | // [stack] TUPLE |
11449 | return false; |
11450 | } |
11451 | } else { |
11452 | // Update location to throw errors about non-primitive elements |
11453 | // in the correct position. |
11454 | if (!updateSourceCoordNotesIfNonLiteral(elt)) { |
11455 | return false; |
11456 | } |
11457 | |
11458 | if (!emitTree(elt)) { |
11459 | // [stack] TUPLE VALUE |
11460 | return false; |
11461 | } |
11462 | |
11463 | if (!emit1(JSOp::AddTupleElement)) { |
11464 | // [stack] TUPLE |
11465 | return false; |
11466 | } |
11467 | } |
11468 | } |
11469 | |
11470 | if (!emit1(JSOp::FinishTuple)) { |
11471 | // [stack] TUPLE |
11472 | return false; |
11473 | } |
11474 | |
11475 | return true; |
11476 | } |
11477 | #endif |
11478 | |
11479 | static inline JSOp UnaryOpParseNodeKindToJSOp(ParseNodeKind pnk) { |
11480 | switch (pnk) { |
11481 | case ParseNodeKind::ThrowStmt: |
11482 | return JSOp::Throw; |
11483 | case ParseNodeKind::VoidExpr: |
11484 | return JSOp::Void; |
11485 | case ParseNodeKind::NotExpr: |
11486 | return JSOp::Not; |
11487 | case ParseNodeKind::BitNotExpr: |
11488 | return JSOp::BitNot; |
11489 | case ParseNodeKind::PosExpr: |
11490 | return JSOp::Pos; |
11491 | case ParseNodeKind::NegExpr: |
11492 | return JSOp::Neg; |
11493 | default: |
11494 | MOZ_CRASH("unexpected unary op")do { do { } while (false); MOZ_ReportCrash("" "unexpected unary op" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11494); AnnotateMozCrashReason("MOZ_CRASH(" "unexpected unary op" ")"); do { *((volatile int*)__null) = 11494; __attribute__(( nomerge)) ::abort(); } while (false); } while (false); |
11495 | } |
11496 | } |
11497 | |
11498 | bool BytecodeEmitter::emitUnary(UnaryNode* unaryNode) { |
11499 | if (!updateSourceCoordNotes(unaryNode->pn_pos.begin)) { |
11500 | return false; |
11501 | } |
11502 | |
11503 | JSOp op = UnaryOpParseNodeKindToJSOp(unaryNode->getKind()); |
11504 | ValueUsage valueUsage = |
11505 | op == JSOp::Void ? ValueUsage::IgnoreValue : ValueUsage::WantValue; |
11506 | if (!emitTree(unaryNode->kid(), valueUsage)) { |
11507 | return false; |
11508 | } |
11509 | return emit1(op); |
11510 | } |
11511 | |
11512 | bool BytecodeEmitter::emitTypeof(UnaryNode* typeofNode, JSOp op) { |
11513 | MOZ_ASSERT(op == JSOp::Typeof || op == JSOp::TypeofExpr)do { static_assert( mozilla::detail::AssertionConditionType< decltype(op == JSOp::Typeof || op == JSOp::TypeofExpr)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(op == JSOp::Typeof || op == JSOp::TypeofExpr))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("op == JSOp::Typeof || op == JSOp::TypeofExpr" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11513); AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::Typeof || op == JSOp::TypeofExpr" ")"); do { *((volatile int*)__null) = 11513; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
11514 | |
11515 | if (!updateSourceCoordNotes(typeofNode->pn_pos.begin)) { |
11516 | return false; |
11517 | } |
11518 | |
11519 | if (!emitTree(typeofNode->kid())) { |
11520 | return false; |
11521 | } |
11522 | |
11523 | return emit1(op); |
11524 | } |
11525 | |
11526 | bool BytecodeEmitter::tryEmitTypeofEq(ListNode* node, bool* emitted) { |
11527 | // Emit specialized opcode for `typeof val == "type` or `typeof val != "type` |
11528 | // if possible. |
11529 | // |
11530 | // NOTE: Given the comparison is done for string, `==` and `===` have |
11531 | // no difference. Same for `!=` and `!==`. |
11532 | MOZ_ASSERT(node->isKind(ParseNodeKind::StrictEqExpr) ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(node->isKind(ParseNodeKind::StrictEqExpr) || node ->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind ::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr))> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(node->isKind(ParseNodeKind::StrictEqExpr) || node ->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind ::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("node->isKind(ParseNodeKind::StrictEqExpr) || node->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11535); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::StrictEqExpr) || node->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)" ")"); do { *((volatile int*)__null) = 11535; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
11533 | node->isKind(ParseNodeKind::EqExpr) ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(node->isKind(ParseNodeKind::StrictEqExpr) || node ->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind ::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr))> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(node->isKind(ParseNodeKind::StrictEqExpr) || node ->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind ::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("node->isKind(ParseNodeKind::StrictEqExpr) || node->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11535); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::StrictEqExpr) || node->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)" ")"); do { *((volatile int*)__null) = 11535; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
11534 | node->isKind(ParseNodeKind::StrictNeExpr) ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(node->isKind(ParseNodeKind::StrictEqExpr) || node ->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind ::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr))> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(node->isKind(ParseNodeKind::StrictEqExpr) || node ->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind ::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("node->isKind(ParseNodeKind::StrictEqExpr) || node->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11535); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::StrictEqExpr) || node->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)" ")"); do { *((volatile int*)__null) = 11535; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
11535 | node->isKind(ParseNodeKind::NeExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(node->isKind(ParseNodeKind::StrictEqExpr) || node ->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind ::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr))> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(node->isKind(ParseNodeKind::StrictEqExpr) || node ->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind ::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("node->isKind(ParseNodeKind::StrictEqExpr) || node->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11535); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::StrictEqExpr) || node->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)" ")"); do { *((volatile int*)__null) = 11535; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
11536 | |
11537 | if (node->count() != 2) { |
11538 | *emitted = false; |
11539 | return true; |
11540 | } |
11541 | |
11542 | ParseNode* left = node->head(); |
11543 | ParseNode* right = left->pn_next; |
11544 | MOZ_ASSERT(right)do { static_assert( mozilla::detail::AssertionConditionType< decltype(right)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(right))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("right", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11544); AnnotateMozCrashReason("MOZ_ASSERT" "(" "right" ")" ); do { *((volatile int*)__null) = 11544; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
11545 | |
11546 | UnaryNode* typeofNode; |
11547 | NameNode* typenameNode; |
11548 | JSOp op; |
11549 | |
11550 | if (node->isKind(ParseNodeKind::StrictEqExpr) || |
11551 | node->isKind(ParseNodeKind::EqExpr)) { |
11552 | op = JSOp::Eq; |
11553 | } else { |
11554 | op = JSOp::Ne; |
11555 | } |
11556 | |
11557 | // NOTE: ParseNodeKind::TypeOfExpr cannot use JSOp::TypeofEq. |
11558 | // See JSOp::GetName document. |
11559 | if (left->isKind(ParseNodeKind::TypeOfNameExpr) && |
11560 | right->isKind(ParseNodeKind::StringExpr)) { |
11561 | typeofNode = &left->as<UnaryNode>(); |
11562 | typenameNode = &right->as<NameNode>(); |
11563 | } else if (right->isKind(ParseNodeKind::TypeOfNameExpr) && |
11564 | left->isKind(ParseNodeKind::StringExpr)) { |
11565 | typeofNode = &right->as<UnaryNode>(); |
11566 | typenameNode = &left->as<NameNode>(); |
11567 | } else { |
11568 | *emitted = false; |
11569 | return true; |
11570 | } |
11571 | |
11572 | JSType type; |
11573 | TaggedParserAtomIndex typeName = typenameNode->atom(); |
11574 | if (typeName == TaggedParserAtomIndex::WellKnown::undefined()) { |
11575 | type = JSTYPE_UNDEFINED; |
11576 | } else if (typeName == TaggedParserAtomIndex::WellKnown::object()) { |
11577 | type = JSTYPE_OBJECT; |
11578 | } else if (typeName == TaggedParserAtomIndex::WellKnown::function()) { |
11579 | type = JSTYPE_FUNCTION; |
11580 | } else if (typeName == TaggedParserAtomIndex::WellKnown::string()) { |
11581 | type = JSTYPE_STRING; |
11582 | } else if (typeName == TaggedParserAtomIndex::WellKnown::number()) { |
11583 | type = JSTYPE_NUMBER; |
11584 | } else if (typeName == TaggedParserAtomIndex::WellKnown::boolean()) { |
11585 | type = JSTYPE_BOOLEAN; |
11586 | } else if (typeName == TaggedParserAtomIndex::WellKnown::symbol()) { |
11587 | type = JSTYPE_SYMBOL; |
11588 | } else if (typeName == TaggedParserAtomIndex::WellKnown::bigint()) { |
11589 | type = JSTYPE_BIGINT; |
11590 | } |
11591 | #ifdef ENABLE_RECORD_TUPLE |
11592 | else if (typeName == TaggedParserAtomIndex::WellKnown::record()) { |
11593 | type = JSTYPE_RECORD; |
11594 | } else if (typeName == TaggedParserAtomIndex::WellKnown::tuple()) { |
11595 | type = JSTYPE_TUPLE; |
11596 | } |
11597 | #endif |
11598 | else { |
11599 | *emitted = false; |
11600 | return true; |
11601 | } |
11602 | |
11603 | if (!updateSourceCoordNotes(typeofNode->pn_pos.begin)) { |
11604 | return false; |
11605 | } |
11606 | |
11607 | if (!emitTree(typeofNode->kid())) { |
11608 | // [stack] VAL |
11609 | return false; |
11610 | } |
11611 | |
11612 | if (!emit2(JSOp::TypeofEq, TypeofEqOperand(type, op).rawValue())) { |
11613 | // [stack] CMP |
11614 | return false; |
11615 | } |
11616 | |
11617 | *emitted = true; |
11618 | return true; |
11619 | } |
11620 | |
11621 | bool BytecodeEmitter::emitFunctionFormalParameters(ParamsBodyNode* paramsBody) { |
11622 | FunctionBox* funbox = sc->asFunctionBox(); |
11623 | |
11624 | bool hasRest = funbox->hasRest(); |
11625 | |
11626 | FunctionParamsEmitter fpe(this, funbox); |
11627 | for (ParseNode* arg : paramsBody->parameters()) { |
11628 | ParseNode* bindingElement = arg; |
11629 | ParseNode* initializer = nullptr; |
11630 | if (arg->isKind(ParseNodeKind::AssignExpr)) { |
11631 | bindingElement = arg->as<BinaryNode>().left(); |
11632 | initializer = arg->as<BinaryNode>().right(); |
11633 | } |
11634 | bool hasInitializer = !!initializer; |
11635 | bool isRest = |
11636 | hasRest && arg->pn_next == *std::end(paramsBody->parameters()); |
11637 | bool isDestructuring = !bindingElement->isKind(ParseNodeKind::Name); |
11638 | |
11639 | // Left-hand sides are either simple names or destructuring patterns. |
11640 | MOZ_ASSERT(bindingElement->isKind(ParseNodeKind::Name) ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(bindingElement->isKind(ParseNodeKind::Name) || bindingElement ->isKind(ParseNodeKind::ArrayExpr) || bindingElement->isKind (ParseNodeKind::ObjectExpr))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(bindingElement->isKind(ParseNodeKind ::Name) || bindingElement->isKind(ParseNodeKind::ArrayExpr ) || bindingElement->isKind(ParseNodeKind::ObjectExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("bindingElement->isKind(ParseNodeKind::Name) || bindingElement->isKind(ParseNodeKind::ArrayExpr) || bindingElement->isKind(ParseNodeKind::ObjectExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11642); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bindingElement->isKind(ParseNodeKind::Name) || bindingElement->isKind(ParseNodeKind::ArrayExpr) || bindingElement->isKind(ParseNodeKind::ObjectExpr)" ")"); do { *((volatile int*)__null) = 11642; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
11641 | bindingElement->isKind(ParseNodeKind::ArrayExpr) ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(bindingElement->isKind(ParseNodeKind::Name) || bindingElement ->isKind(ParseNodeKind::ArrayExpr) || bindingElement->isKind (ParseNodeKind::ObjectExpr))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(bindingElement->isKind(ParseNodeKind ::Name) || bindingElement->isKind(ParseNodeKind::ArrayExpr ) || bindingElement->isKind(ParseNodeKind::ObjectExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("bindingElement->isKind(ParseNodeKind::Name) || bindingElement->isKind(ParseNodeKind::ArrayExpr) || bindingElement->isKind(ParseNodeKind::ObjectExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11642); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bindingElement->isKind(ParseNodeKind::Name) || bindingElement->isKind(ParseNodeKind::ArrayExpr) || bindingElement->isKind(ParseNodeKind::ObjectExpr)" ")"); do { *((volatile int*)__null) = 11642; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
11642 | bindingElement->isKind(ParseNodeKind::ObjectExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(bindingElement->isKind(ParseNodeKind::Name) || bindingElement ->isKind(ParseNodeKind::ArrayExpr) || bindingElement->isKind (ParseNodeKind::ObjectExpr))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(bindingElement->isKind(ParseNodeKind ::Name) || bindingElement->isKind(ParseNodeKind::ArrayExpr ) || bindingElement->isKind(ParseNodeKind::ObjectExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("bindingElement->isKind(ParseNodeKind::Name) || bindingElement->isKind(ParseNodeKind::ArrayExpr) || bindingElement->isKind(ParseNodeKind::ObjectExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11642); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bindingElement->isKind(ParseNodeKind::Name) || bindingElement->isKind(ParseNodeKind::ArrayExpr) || bindingElement->isKind(ParseNodeKind::ObjectExpr)" ")"); do { *((volatile int*)__null) = 11642; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
11643 | |
11644 | auto emitDefaultInitializer = [this, &initializer, &bindingElement]() { |
11645 | // [stack] |
11646 | |
11647 | if (!this->emitInitializer(initializer, bindingElement)) { |
11648 | // [stack] DEFAULT |
11649 | return false; |
11650 | } |
11651 | return true; |
11652 | }; |
11653 | |
11654 | auto emitDestructuring = [this, &bindingElement]() { |
11655 | // [stack] ARG |
11656 | |
11657 | if (!this->emitDestructuringOps(&bindingElement->as<ListNode>(), |
11658 | DestructuringFlavor::Declaration)) { |
11659 | // [stack] ARG |
11660 | return false; |
11661 | } |
11662 | |
11663 | return true; |
11664 | }; |
11665 | |
11666 | if (isRest) { |
11667 | if (isDestructuring) { |
11668 | if (!fpe.prepareForDestructuringRest()) { |
11669 | // [stack] |
11670 | return false; |
11671 | } |
11672 | if (!emitDestructuring()) { |
11673 | // [stack] |
11674 | return false; |
11675 | } |
11676 | if (!fpe.emitDestructuringRestEnd()) { |
11677 | // [stack] |
11678 | return false; |
11679 | } |
11680 | } else { |
11681 | auto paramName = bindingElement->as<NameNode>().name(); |
11682 | if (!fpe.emitRest(paramName)) { |
11683 | // [stack] |
11684 | return false; |
11685 | } |
11686 | } |
11687 | |
11688 | continue; |
11689 | } |
11690 | |
11691 | if (isDestructuring) { |
11692 | if (hasInitializer) { |
11693 | if (!fpe.prepareForDestructuringDefaultInitializer()) { |
11694 | // [stack] |
11695 | return false; |
11696 | } |
11697 | if (!emitDefaultInitializer()) { |
11698 | // [stack] |
11699 | return false; |
11700 | } |
11701 | if (!fpe.prepareForDestructuringDefault()) { |
11702 | // [stack] |
11703 | return false; |
11704 | } |
11705 | if (!emitDestructuring()) { |
11706 | // [stack] |
11707 | return false; |
11708 | } |
11709 | if (!fpe.emitDestructuringDefaultEnd()) { |
11710 | // [stack] |
11711 | return false; |
11712 | } |
11713 | } else { |
11714 | if (!fpe.prepareForDestructuring()) { |
11715 | // [stack] |
11716 | return false; |
11717 | } |
11718 | if (!emitDestructuring()) { |
11719 | // [stack] |
11720 | return false; |
11721 | } |
11722 | if (!fpe.emitDestructuringEnd()) { |
11723 | // [stack] |
11724 | return false; |
11725 | } |
11726 | } |
11727 | |
11728 | continue; |
11729 | } |
11730 | |
11731 | if (hasInitializer) { |
11732 | if (!fpe.prepareForDefault()) { |
11733 | // [stack] |
11734 | return false; |
11735 | } |
11736 | if (!emitDefaultInitializer()) { |
11737 | // [stack] |
11738 | return false; |
11739 | } |
11740 | auto paramName = bindingElement->as<NameNode>().name(); |
11741 | if (!fpe.emitDefaultEnd(paramName)) { |
11742 | // [stack] |
11743 | return false; |
11744 | } |
11745 | |
11746 | continue; |
11747 | } |
11748 | |
11749 | auto paramName = bindingElement->as<NameNode>().name(); |
11750 | if (!fpe.emitSimple(paramName)) { |
11751 | // [stack] |
11752 | return false; |
11753 | } |
11754 | } |
11755 | |
11756 | return true; |
11757 | } |
11758 | |
11759 | bool BytecodeEmitter::emitInitializeFunctionSpecialNames() { |
11760 | FunctionBox* funbox = sc->asFunctionBox(); |
11761 | |
11762 | // [stack] |
11763 | |
11764 | auto emitInitializeFunctionSpecialName = |
11765 | [](BytecodeEmitter* bce, TaggedParserAtomIndex name, JSOp op) { |
11766 | // A special name must be slotful, either on the frame or on the |
11767 | // call environment. |
11768 | MOZ_ASSERT(bce->lookupName(name).hasKnownSlot())do { static_assert( mozilla::detail::AssertionConditionType< decltype(bce->lookupName(name).hasKnownSlot())>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(bce->lookupName(name).hasKnownSlot()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("bce->lookupName(name).hasKnownSlot()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11768); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bce->lookupName(name).hasKnownSlot()" ")"); do { *((volatile int*)__null) = 11768; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
11769 | |
11770 | NameOpEmitter noe(bce, name, NameOpEmitter::Kind::Initialize); |
11771 | if (!noe.prepareForRhs()) { |
11772 | // [stack] |
11773 | return false; |
11774 | } |
11775 | if (!bce->emit1(op)) { |
11776 | // [stack] THIS/ARGUMENTS/NEW.TARGET |
11777 | return false; |
11778 | } |
11779 | if (!noe.emitAssignment()) { |
11780 | // [stack] THIS/ARGUMENTS/NEW.TARGET |
11781 | return false; |
11782 | } |
11783 | if (!bce->emit1(JSOp::Pop)) { |
11784 | // [stack] |
11785 | return false; |
11786 | } |
11787 | |
11788 | return true; |
11789 | }; |
11790 | |
11791 | // Do nothing if the function doesn't have an arguments binding. |
11792 | if (funbox->needsArgsObj()) { |
11793 | // Self-hosted code should use the more efficient ArgumentsLength and |
11794 | // GetArgument intrinsics instead of `arguments`. |
11795 | MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting)do { static_assert( mozilla::detail::AssertionConditionType< decltype(emitterMode != BytecodeEmitter::SelfHosting)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(emitterMode != BytecodeEmitter::SelfHosting))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("emitterMode != BytecodeEmitter::SelfHosting" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11795); AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode != BytecodeEmitter::SelfHosting" ")"); do { *((volatile int*)__null) = 11795; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
11796 | if (!emitInitializeFunctionSpecialName( |
11797 | this, TaggedParserAtomIndex::WellKnown::arguments(), |
11798 | JSOp::Arguments)) { |
11799 | // [stack] |
11800 | return false; |
11801 | } |
11802 | } |
11803 | |
11804 | // Do nothing if the function doesn't have a this-binding (this |
11805 | // happens for instance if it doesn't use this/eval or if it's an |
11806 | // arrow function). |
11807 | if (funbox->functionHasThisBinding()) { |
11808 | if (!emitInitializeFunctionSpecialName( |
11809 | this, TaggedParserAtomIndex::WellKnown::dot_this_(), |
11810 | JSOp::FunctionThis)) { |
11811 | return false; |
11812 | } |
11813 | } |
11814 | |
11815 | // Do nothing if the function doesn't have a new.target-binding (this happens |
11816 | // for instance if it doesn't use new.target/eval or if it's an arrow |
11817 | // function). |
11818 | if (funbox->functionHasNewTargetBinding()) { |
11819 | if (!emitInitializeFunctionSpecialName( |
11820 | this, TaggedParserAtomIndex::WellKnown::dot_newTarget_(), |
11821 | JSOp::NewTarget)) { |
11822 | return false; |
11823 | } |
11824 | } |
11825 | |
11826 | // Do nothing if the function doesn't implicitly return a promise result. |
11827 | if (funbox->needsPromiseResult()) { |
11828 | if (!emitInitializeFunctionSpecialName( |
11829 | this, TaggedParserAtomIndex::WellKnown::dot_generator_(), |
11830 | JSOp::Generator)) { |
11831 | // [stack] |
11832 | return false; |
11833 | } |
11834 | } |
11835 | return true; |
11836 | } |
11837 | |
11838 | bool BytecodeEmitter::emitLexicalInitialization(NameNode* name) { |
11839 | return emitLexicalInitialization(name->name()); |
11840 | } |
11841 | |
11842 | bool BytecodeEmitter::emitLexicalInitialization(TaggedParserAtomIndex name) { |
11843 | NameOpEmitter noe(this, name, NameOpEmitter::Kind::Initialize); |
11844 | if (!noe.prepareForRhs()) { |
11845 | return false; |
11846 | } |
11847 | |
11848 | // The caller has pushed the RHS to the top of the stack. Assert that the |
11849 | // binding can be initialized without a binding object on the stack, and that |
11850 | // no JSOp::BindUnqualifiedName or JSOp::BindUnqualifiedGName ops were |
11851 | // emitted. |
11852 | MOZ_ASSERT(noe.loc().isLexical() || noe.loc().isSynthetic() ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(noe.loc().isLexical() || noe.loc().isSynthetic() || noe .loc().isPrivateMethod())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(noe.loc().isLexical() || noe .loc().isSynthetic() || noe.loc().isPrivateMethod()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("noe.loc().isLexical() || noe.loc().isSynthetic() || noe.loc().isPrivateMethod()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11853); AnnotateMozCrashReason("MOZ_ASSERT" "(" "noe.loc().isLexical() || noe.loc().isSynthetic() || noe.loc().isPrivateMethod()" ")"); do { *((volatile int*)__null) = 11853; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
11853 | noe.loc().isPrivateMethod())do { static_assert( mozilla::detail::AssertionConditionType< decltype(noe.loc().isLexical() || noe.loc().isSynthetic() || noe .loc().isPrivateMethod())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(noe.loc().isLexical() || noe .loc().isSynthetic() || noe.loc().isPrivateMethod()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("noe.loc().isLexical() || noe.loc().isSynthetic() || noe.loc().isPrivateMethod()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11853); AnnotateMozCrashReason("MOZ_ASSERT" "(" "noe.loc().isLexical() || noe.loc().isSynthetic() || noe.loc().isPrivateMethod()" ")"); do { *((volatile int*)__null) = 11853; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
11854 | MOZ_ASSERT(!noe.emittedBindOp())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!noe.emittedBindOp())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!noe.emittedBindOp()))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("!noe.emittedBindOp()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11854); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!noe.emittedBindOp()" ")"); do { *((volatile int*)__null) = 11854; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
11855 | |
11856 | if (!noe.emitAssignment()) { |
11857 | return false; |
11858 | } |
11859 | |
11860 | return true; |
11861 | } |
11862 | |
11863 | static MOZ_ALWAYS_INLINEinline ParseNode* FindConstructor(ListNode* classMethods) { |
11864 | for (ParseNode* classElement : classMethods->contents()) { |
11865 | ParseNode* unwrappedElement = classElement; |
11866 | if (unwrappedElement->is<LexicalScopeNode>()) { |
11867 | unwrappedElement = unwrappedElement->as<LexicalScopeNode>().scopeBody(); |
11868 | } |
11869 | if (unwrappedElement->is<ClassMethod>()) { |
11870 | ClassMethod& method = unwrappedElement->as<ClassMethod>(); |
11871 | ParseNode& methodName = method.name(); |
11872 | if (!method.isStatic() && |
11873 | (methodName.isKind(ParseNodeKind::ObjectPropertyName) || |
11874 | methodName.isKind(ParseNodeKind::StringExpr)) && |
11875 | methodName.as<NameNode>().atom() == |
11876 | TaggedParserAtomIndex::WellKnown::constructor()) { |
11877 | return classElement; |
11878 | } |
11879 | } |
11880 | } |
11881 | return nullptr; |
11882 | } |
11883 | |
11884 | bool BytecodeEmitter::emitNewPrivateName(TaggedParserAtomIndex bindingName, |
11885 | TaggedParserAtomIndex symbolName) { |
11886 | if (!emitAtomOp(JSOp::NewPrivateName, symbolName)) { |
11887 | // [stack] HERITAGE PRIVATENAME |
11888 | return false; |
11889 | } |
11890 | |
11891 | // Add a binding for #name => privatename |
11892 | if (!emitLexicalInitialization(bindingName)) { |
11893 | // [stack] HERITAGE PRIVATENAME |
11894 | return false; |
11895 | } |
11896 | |
11897 | // Pop Private name off the stack. |
11898 | if (!emit1(JSOp::Pop)) { |
11899 | // [stack] HERITAGE |
11900 | return false; |
11901 | } |
11902 | |
11903 | return true; |
11904 | } |
11905 | |
11906 | bool BytecodeEmitter::emitNewPrivateNames( |
11907 | TaggedParserAtomIndex privateBrandName, ListNode* classMembers) { |
11908 | bool hasPrivateBrand = false; |
11909 | |
11910 | for (ParseNode* classElement : classMembers->contents()) { |
11911 | ParseNode* elementName; |
11912 | if (classElement->is<ClassMethod>()) { |
11913 | elementName = &classElement->as<ClassMethod>().name(); |
11914 | } else if (classElement->is<ClassField>()) { |
11915 | elementName = &classElement->as<ClassField>().name(); |
11916 | } else { |
11917 | continue; |
11918 | } |
11919 | |
11920 | if (!elementName->isKind(ParseNodeKind::PrivateName)) { |
11921 | continue; |
11922 | } |
11923 | |
11924 | // Non-static private methods' private names are optimized away. |
11925 | bool isOptimized = false; |
11926 | if (classElement->is<ClassMethod>() && |
11927 | !classElement->as<ClassMethod>().isStatic()) { |
11928 | hasPrivateBrand = true; |
11929 | if (classElement->as<ClassMethod>().accessorType() == |
11930 | AccessorType::None) { |
11931 | isOptimized = true; |
11932 | } |
11933 | } |
11934 | |
11935 | if (!isOptimized) { |
11936 | auto privateName = elementName->as<NameNode>().name(); |
11937 | if (!emitNewPrivateName(privateName, privateName)) { |
11938 | return false; |
11939 | } |
11940 | } |
11941 | } |
11942 | |
11943 | if (hasPrivateBrand) { |
11944 | // We don't make a private name for every optimized method, but we need one |
11945 | // private name per class, the `.privateBrand`. |
11946 | if (!emitNewPrivateName( |
11947 | TaggedParserAtomIndex::WellKnown::dot_privateBrand_(), |
11948 | privateBrandName)) { |
11949 | return false; |
11950 | } |
11951 | } |
11952 | return true; |
11953 | } |
11954 | |
11955 | // This follows ES6 14.5.14 (ClassDefinitionEvaluation) and ES6 14.5.15 |
11956 | // (BindingClassDeclarationEvaluation). |
11957 | bool BytecodeEmitter::emitClass( |
11958 | ClassNode* classNode, |
11959 | ClassNameKind nameKind /* = ClassNameKind::BindingName */, |
11960 | TaggedParserAtomIndex |
11961 | nameForAnonymousClass /* = TaggedParserAtomIndex::null() */) { |
11962 | MOZ_ASSERT((nameKind == ClassNameKind::InferredName) ==do { static_assert( mozilla::detail::AssertionConditionType< decltype((nameKind == ClassNameKind::InferredName) == bool(nameForAnonymousClass ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!((nameKind == ClassNameKind::InferredName) == bool(nameForAnonymousClass )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("(nameKind == ClassNameKind::InferredName) == bool(nameForAnonymousClass)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11963); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(nameKind == ClassNameKind::InferredName) == bool(nameForAnonymousClass)" ")"); do { *((volatile int*)__null) = 11963; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
11963 | bool(nameForAnonymousClass))do { static_assert( mozilla::detail::AssertionConditionType< decltype((nameKind == ClassNameKind::InferredName) == bool(nameForAnonymousClass ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!((nameKind == ClassNameKind::InferredName) == bool(nameForAnonymousClass )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("(nameKind == ClassNameKind::InferredName) == bool(nameForAnonymousClass)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11963); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(nameKind == ClassNameKind::InferredName) == bool(nameForAnonymousClass)" ")"); do { *((volatile int*)__null) = 11963; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
11964 | |
11965 | ParseNode* heritageExpression = classNode->heritage(); |
11966 | ListNode* classMembers = classNode->memberList(); |
11967 | ParseNode* constructor = FindConstructor(classMembers); |
11968 | |
11969 | // If |nameKind != ClassNameKind::ComputedName| |
11970 | // [stack] |
11971 | // Else |
11972 | // [stack] NAME |
11973 | |
11974 | ClassEmitter ce(this); |
11975 | TaggedParserAtomIndex innerName; |
11976 | ClassEmitter::Kind kind = ClassEmitter::Kind::Expression; |
11977 | if (ClassNames* names = classNode->names()) { |
11978 | MOZ_ASSERT(nameKind == ClassNameKind::BindingName)do { static_assert( mozilla::detail::AssertionConditionType< decltype(nameKind == ClassNameKind::BindingName)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(nameKind == ClassNameKind::BindingName))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("nameKind == ClassNameKind::BindingName" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11978); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nameKind == ClassNameKind::BindingName" ")"); do { *((volatile int*)__null) = 11978; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
11979 | innerName = names->innerBinding()->name(); |
11980 | MOZ_ASSERT(innerName)do { static_assert( mozilla::detail::AssertionConditionType< decltype(innerName)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(innerName))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("innerName", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11980); AnnotateMozCrashReason("MOZ_ASSERT" "(" "innerName" ")"); do { *((volatile int*)__null) = 11980; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
11981 | |
11982 | if (names->outerBinding()) { |
11983 | MOZ_ASSERT(names->outerBinding()->name())do { static_assert( mozilla::detail::AssertionConditionType< decltype(names->outerBinding()->name())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(names->outerBinding()-> name()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("names->outerBinding()->name()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11983); AnnotateMozCrashReason("MOZ_ASSERT" "(" "names->outerBinding()->name()" ")"); do { *((volatile int*)__null) = 11983; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
11984 | MOZ_ASSERT(names->outerBinding()->name() == innerName)do { static_assert( mozilla::detail::AssertionConditionType< decltype(names->outerBinding()->name() == innerName)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(names->outerBinding()->name() == innerName))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("names->outerBinding()->name() == innerName" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11984); AnnotateMozCrashReason("MOZ_ASSERT" "(" "names->outerBinding()->name() == innerName" ")"); do { *((volatile int*)__null) = 11984; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
11985 | kind = ClassEmitter::Kind::Declaration; |
11986 | } |
11987 | } |
11988 | |
11989 | if (LexicalScopeNode* scopeBindings = classNode->scopeBindings()) { |
11990 | if (!ce.emitScope(scopeBindings->scopeBindings())) { |
11991 | // [stack] |
11992 | return false; |
11993 | } |
11994 | } |
11995 | |
11996 | bool isDerived = !!heritageExpression; |
11997 | if (isDerived) { |
11998 | if (!updateSourceCoordNotes(classNode->pn_pos.begin)) { |
11999 | return false; |
12000 | } |
12001 | if (!markStepBreakpoint()) { |
12002 | return false; |
12003 | } |
12004 | if (!emitTree(heritageExpression)) { |
12005 | // [stack] HERITAGE |
12006 | return false; |
12007 | } |
12008 | } |
12009 | |
12010 | // The class body scope holds any private names. Those mustn't be visible in |
12011 | // the heritage expression and hence the scope must be emitted after the |
12012 | // heritage expression. |
12013 | if (ClassBodyScopeNode* bodyScopeBindings = classNode->bodyScopeBindings()) { |
12014 | if (!ce.emitBodyScope(bodyScopeBindings->scopeBindings())) { |
12015 | // [stack] HERITAGE |
12016 | return false; |
12017 | } |
12018 | |
12019 | // The spec does not say anything about private brands being symbols. It's |
12020 | // an implementation detail. So we can give the special private brand |
12021 | // symbol any description we want and users won't normally see it. For |
12022 | // debugging, use the class name. |
12023 | auto privateBrandName = innerName; |
12024 | if (!innerName) { |
12025 | privateBrandName = nameForAnonymousClass |
12026 | ? nameForAnonymousClass |
12027 | : TaggedParserAtomIndex::WellKnown::anonymous(); |
12028 | } |
12029 | if (!emitNewPrivateNames(privateBrandName, classMembers)) { |
12030 | return false; |
12031 | } |
12032 | } |
12033 | |
12034 | bool hasNameOnStack = nameKind == ClassNameKind::ComputedName; |
12035 | if (isDerived) { |
12036 | if (!ce.emitDerivedClass(innerName, nameForAnonymousClass, |
12037 | hasNameOnStack)) { |
12038 | // [stack] HOMEOBJ HERITAGE |
12039 | return false; |
12040 | } |
12041 | } else { |
12042 | if (!ce.emitClass(innerName, nameForAnonymousClass, hasNameOnStack)) { |
12043 | // [stack] HOMEOBJ |
12044 | return false; |
12045 | } |
12046 | } |
12047 | |
12048 | // Stack currently has HOMEOBJ followed by optional HERITAGE. When HERITAGE |
12049 | // is not used, an implicit value of %FunctionPrototype% is implied. |
12050 | |
12051 | // See |Parser::classMember(...)| for the reason why |.initializers| is |
12052 | // created within its own scope. |
12053 | Maybe<LexicalScopeEmitter> lse; |
12054 | FunctionNode* ctor; |
12055 | #ifdef ENABLE_DECORATORS |
12056 | bool extraInitializersPresent = false; |
12057 | #endif |
12058 | if (constructor->is<LexicalScopeNode>()) { |
12059 | LexicalScopeNode* constructorScope = &constructor->as<LexicalScopeNode>(); |
12060 | |
12061 | MOZ_ASSERT(!constructorScope->isEmptyScope())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!constructorScope->isEmptyScope())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!constructorScope->isEmptyScope ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!constructorScope->isEmptyScope()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12061); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!constructorScope->isEmptyScope()" ")"); do { *((volatile int*)__null) = 12061; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12062 | #ifdef ENABLE_DECORATORS |
12063 | // With decorators enabled we expect to see |.initializers|, |
12064 | // and |.instanceExtraInitializers| in this scope. |
12065 | MOZ_ASSERT(constructorScope->scopeBindings()->length == 2)do { static_assert( mozilla::detail::AssertionConditionType< decltype(constructorScope->scopeBindings()->length == 2 )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(constructorScope->scopeBindings()->length == 2 ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "constructorScope->scopeBindings()->length == 2", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12065); AnnotateMozCrashReason("MOZ_ASSERT" "(" "constructorScope->scopeBindings()->length == 2" ")"); do { *((volatile int*)__null) = 12065; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12066 | MOZ_ASSERT(GetScopeDataTrailingNames(constructorScope->scopeBindings())[0]do { static_assert( mozilla::detail::AssertionConditionType< decltype(GetScopeDataTrailingNames(constructorScope->scopeBindings ())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_ ())>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(GetScopeDataTrailingNames(constructorScope->scopeBindings ())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_ ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12068); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()" ")"); do { *((volatile int*)__null) = 12068; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
12067 | .name() ==do { static_assert( mozilla::detail::AssertionConditionType< decltype(GetScopeDataTrailingNames(constructorScope->scopeBindings ())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_ ())>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(GetScopeDataTrailingNames(constructorScope->scopeBindings ())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_ ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12068); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()" ")"); do { *((volatile int*)__null) = 12068; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
12068 | TaggedParserAtomIndex::WellKnown::dot_initializers_())do { static_assert( mozilla::detail::AssertionConditionType< decltype(GetScopeDataTrailingNames(constructorScope->scopeBindings ())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_ ())>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(GetScopeDataTrailingNames(constructorScope->scopeBindings ())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_ ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12068); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()" ")"); do { *((volatile int*)__null) = 12068; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12069 | MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType< decltype(GetScopeDataTrailingNames(constructorScope->scopeBindings ())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_ ())>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(GetScopeDataTrailingNames(constructorScope->scopeBindings ())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_ ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("GetScopeDataTrailingNames(constructorScope->scopeBindings())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12072); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_()" ")"); do { *((volatile int*)__null) = 12072; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
12070 | GetScopeDataTrailingNames(constructorScope->scopeBindings())[1]do { static_assert( mozilla::detail::AssertionConditionType< decltype(GetScopeDataTrailingNames(constructorScope->scopeBindings ())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_ ())>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(GetScopeDataTrailingNames(constructorScope->scopeBindings ())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_ ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("GetScopeDataTrailingNames(constructorScope->scopeBindings())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12072); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_()" ")"); do { *((volatile int*)__null) = 12072; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
12071 | .name() ==do { static_assert( mozilla::detail::AssertionConditionType< decltype(GetScopeDataTrailingNames(constructorScope->scopeBindings ())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_ ())>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(GetScopeDataTrailingNames(constructorScope->scopeBindings ())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_ ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("GetScopeDataTrailingNames(constructorScope->scopeBindings())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12072); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_()" ")"); do { *((volatile int*)__null) = 12072; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
12072 | TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_())do { static_assert( mozilla::detail::AssertionConditionType< decltype(GetScopeDataTrailingNames(constructorScope->scopeBindings ())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_ ())>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(GetScopeDataTrailingNames(constructorScope->scopeBindings ())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_ ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("GetScopeDataTrailingNames(constructorScope->scopeBindings())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12072); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_()" ")"); do { *((volatile int*)__null) = 12072; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12073 | |
12074 | // We should only call this code if we know decorators are present, see bug |
12075 | // 1871147. |
12076 | lse.emplace(this); |
12077 | if (!lse->emitScope(ScopeKind::Lexical, |
12078 | constructorScope->scopeBindings())) { |
12079 | return false; |
12080 | } |
12081 | |
12082 | // TODO: See bug 1868220 for support for static extra initializers. |
12083 | if (!ce.prepareForExtraInitializers(TaggedParserAtomIndex::WellKnown:: |
12084 | dot_instanceExtraInitializers_())) { |
12085 | return false; |
12086 | } |
12087 | |
12088 | if (classNode->addInitializerFunction()) { |
12089 | DecoratorEmitter de(this); |
12090 | if (!de.emitCreateAddInitializerFunction( |
12091 | classNode->addInitializerFunction(), |
12092 | TaggedParserAtomIndex::WellKnown:: |
12093 | dot_instanceExtraInitializers_())) { |
12094 | // [stack] HOMEOBJ HERITAGE? ADDINIT |
12095 | return false; |
12096 | } |
12097 | |
12098 | if (!emitUnpickN(isDerived ? 2 : 1)) { |
12099 | // [stack] ADDINIT HOMEOBJ HERITAGE? |
12100 | return false; |
12101 | } |
12102 | |
12103 | extraInitializersPresent = true; |
12104 | } |
12105 | #else |
12106 | // The constructor scope should only contain the |.initializers| binding. |
12107 | MOZ_ASSERT(constructorScope->scopeBindings()->length == 1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(constructorScope->scopeBindings()->length == 1 )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(constructorScope->scopeBindings()->length == 1 ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "constructorScope->scopeBindings()->length == 1", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12107); AnnotateMozCrashReason("MOZ_ASSERT" "(" "constructorScope->scopeBindings()->length == 1" ")"); do { *((volatile int*)__null) = 12107; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12108 | MOZ_ASSERT(GetScopeDataTrailingNames(constructorScope->scopeBindings())[0]do { static_assert( mozilla::detail::AssertionConditionType< decltype(GetScopeDataTrailingNames(constructorScope->scopeBindings ())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_ ())>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(GetScopeDataTrailingNames(constructorScope->scopeBindings ())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_ ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12110); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()" ")"); do { *((volatile int*)__null) = 12110; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
12109 | .name() ==do { static_assert( mozilla::detail::AssertionConditionType< decltype(GetScopeDataTrailingNames(constructorScope->scopeBindings ())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_ ())>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(GetScopeDataTrailingNames(constructorScope->scopeBindings ())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_ ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12110); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()" ")"); do { *((volatile int*)__null) = 12110; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
12110 | TaggedParserAtomIndex::WellKnown::dot_initializers_())do { static_assert( mozilla::detail::AssertionConditionType< decltype(GetScopeDataTrailingNames(constructorScope->scopeBindings ())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_ ())>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(GetScopeDataTrailingNames(constructorScope->scopeBindings ())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_ ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12110); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()" ")"); do { *((volatile int*)__null) = 12110; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12111 | #endif |
12112 | |
12113 | auto needsInitializer = [](ParseNode* propdef) { |
12114 | return NeedsFieldInitializer(propdef, false) || |
12115 | NeedsAccessorInitializer(propdef, false); |
12116 | }; |
12117 | |
12118 | // As an optimization omit the |.initializers| binding when no instance |
12119 | // fields or private methods are present. |
12120 | bool needsInitializers = |
12121 | std::any_of(classMembers->contents().begin(), |
12122 | classMembers->contents().end(), needsInitializer); |
12123 | if (needsInitializers) { |
12124 | #ifndef ENABLE_DECORATORS |
12125 | lse.emplace(this); |
12126 | if (!lse->emitScope(ScopeKind::Lexical, |
12127 | constructorScope->scopeBindings())) { |
12128 | return false; |
12129 | } |
12130 | #endif |
12131 | // Any class with field initializers will have a constructor |
12132 | if (!emitCreateMemberInitializers(ce, classMembers, |
12133 | FieldPlacement::Instance |
12134 | #ifdef ENABLE_DECORATORS |
12135 | , |
12136 | isDerived |
12137 | #endif |
12138 | )) { |
12139 | return false; |
12140 | } |
12141 | } |
12142 | |
12143 | ctor = &constructorScope->scopeBody()->as<ClassMethod>().method(); |
12144 | } else { |
12145 | // The |.initializers| binding is never emitted when in self-hosting mode. |
12146 | MOZ_ASSERT(emitterMode == BytecodeEmitter::SelfHosting)do { static_assert( mozilla::detail::AssertionConditionType< decltype(emitterMode == BytecodeEmitter::SelfHosting)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(emitterMode == BytecodeEmitter::SelfHosting))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("emitterMode == BytecodeEmitter::SelfHosting" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12146); AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode == BytecodeEmitter::SelfHosting" ")"); do { *((volatile int*)__null) = 12146; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12147 | ctor = &constructor->as<ClassMethod>().method(); |
12148 | } |
12149 | |
12150 | bool needsHomeObject = ctor->funbox()->needsHomeObject(); |
12151 | // HERITAGE is consumed inside emitFunction. |
12152 | if (nameKind == ClassNameKind::InferredName) { |
12153 | setFunName(ctor->funbox(), nameForAnonymousClass); |
12154 | } |
12155 | if (!emitFunction(ctor, isDerived)) { |
12156 | // [stack] HOMEOBJ CTOR |
12157 | return false; |
12158 | } |
12159 | if (lse.isSome()) { |
12160 | if (!lse->emitEnd()) { |
12161 | return false; |
12162 | } |
12163 | lse.reset(); |
12164 | } |
12165 | if (!ce.emitInitConstructor(needsHomeObject)) { |
12166 | // [stack] CTOR HOMEOBJ |
12167 | return false; |
12168 | } |
12169 | |
12170 | if (!emitCreateFieldKeys(classMembers, FieldPlacement::Instance)) { |
12171 | return false; |
12172 | } |
12173 | |
12174 | #ifdef ENABLE_DECORATORS |
12175 | // TODO: See Bug 1868220 for support for static extra initializers. |
12176 | if (!emit1(JSOp::Undefined)) { |
12177 | // [stack] ADDINIT? CTOR HOMEOBJ UNDEFINED |
12178 | return false; |
12179 | } |
12180 | if (!emitUnpickN(2)) { |
12181 | // [stack] ADDINIT? UNDEFINED CTOR HOMEOBJ |
12182 | } |
12183 | #endif |
12184 | |
12185 | if (!emitCreateMemberInitializers(ce, classMembers, FieldPlacement::Static |
12186 | #ifdef ENABLE_DECORATORS |
12187 | , |
12188 | false |
12189 | #endif |
12190 | )) { |
12191 | return false; |
12192 | } |
12193 | |
12194 | #ifdef ENABLE_DECORATORS |
12195 | if (!emitPickN(2)) { |
12196 | // [stack] ADDINIT? CTOR HOMEOBJ UNDEFINED |
12197 | return false; |
12198 | } |
12199 | if (!emitPopN(1)) { |
12200 | // [stack] ADDINIT? CTOR HOMEOBJ |
12201 | return false; |
12202 | } |
12203 | #endif |
12204 | |
12205 | if (!emitCreateFieldKeys(classMembers, FieldPlacement::Static)) { |
12206 | return false; |
12207 | } |
12208 | |
12209 | if (!emitPropertyList(classMembers, ce, ClassBody)) { |
12210 | // [stack] CTOR HOMEOBJ |
12211 | return false; |
12212 | } |
12213 | |
12214 | #ifdef ENABLE_DECORATORS |
12215 | if (extraInitializersPresent) { |
12216 | if (!emitPickN(2)) { |
12217 | // [stack] CTOR HOMEOBJ ADDINIT |
12218 | return false; |
12219 | } |
12220 | if (!emitPopN(1)) { |
12221 | // [stack] CTOR HOMEOBJ |
12222 | return false; |
12223 | } |
12224 | } |
12225 | #endif |
12226 | |
12227 | if (!ce.emitBinding()) { |
12228 | // [stack] CTOR |
12229 | return false; |
12230 | } |
12231 | |
12232 | if (!emitInitializeStaticFields(classMembers)) { |
12233 | // [stack] CTOR |
12234 | return false; |
12235 | } |
12236 | |
12237 | #if ENABLE_DECORATORS |
12238 | if (!ce.prepareForDecorators()) { |
12239 | // [stack] CTOR |
12240 | return false; |
12241 | } |
12242 | if (classNode->decorators() != nullptr) { |
12243 | DecoratorEmitter de(this); |
12244 | NameNode* className = |
12245 | classNode->names() ? classNode->names()->innerBinding() : nullptr; |
12246 | if (!de.emitApplyDecoratorsToClassDefinition(className, |
12247 | classNode->decorators())) { |
12248 | // [stack] CTOR |
12249 | return false; |
12250 | } |
12251 | } |
12252 | #endif |
12253 | |
12254 | if (!ce.emitEnd(kind)) { |
12255 | // [stack] # class declaration |
12256 | // [stack] |
12257 | // [stack] # class expression |
12258 | // [stack] CTOR |
12259 | return false; |
12260 | } |
12261 | |
12262 | return true; |
12263 | } |
12264 | |
12265 | bool BytecodeEmitter::emitExportDefault(BinaryNode* exportNode) { |
12266 | MOZ_ASSERT(exportNode->isKind(ParseNodeKind::ExportDefaultStmt))do { static_assert( mozilla::detail::AssertionConditionType< decltype(exportNode->isKind(ParseNodeKind::ExportDefaultStmt ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(exportNode->isKind(ParseNodeKind::ExportDefaultStmt )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("exportNode->isKind(ParseNodeKind::ExportDefaultStmt)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12266); AnnotateMozCrashReason("MOZ_ASSERT" "(" "exportNode->isKind(ParseNodeKind::ExportDefaultStmt)" ")"); do { *((volatile int*)__null) = 12266; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12267 | |
12268 | ParseNode* valueNode = exportNode->left(); |
12269 | if (valueNode->isDirectRHSAnonFunction()) { |
12270 | MOZ_ASSERT(exportNode->right())do { static_assert( mozilla::detail::AssertionConditionType< decltype(exportNode->right())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(exportNode->right()))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("exportNode->right()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12270); AnnotateMozCrashReason("MOZ_ASSERT" "(" "exportNode->right()" ")"); do { *((volatile int*)__null) = 12270; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12271 | |
12272 | if (!emitAnonymousFunctionWithName( |
12273 | valueNode, TaggedParserAtomIndex::WellKnown::default_())) { |
12274 | return false; |
12275 | } |
12276 | } else { |
12277 | if (!emitTree(valueNode)) { |
12278 | return false; |
12279 | } |
12280 | } |
12281 | |
12282 | if (ParseNode* binding = exportNode->right()) { |
12283 | if (!emitLexicalInitialization(&binding->as<NameNode>())) { |
12284 | return false; |
12285 | } |
12286 | |
12287 | if (!emit1(JSOp::Pop)) { |
12288 | return false; |
12289 | } |
12290 | } |
12291 | |
12292 | return true; |
12293 | } |
12294 | |
12295 | bool BytecodeEmitter::emitTree( |
12296 | ParseNode* pn, ValueUsage valueUsage /* = ValueUsage::WantValue */, |
12297 | EmitLineNumberNote emitLineNote /* = EMIT_LINENOTE */) { |
12298 | AutoCheckRecursionLimit recursion(fc); |
12299 | if (!recursion.check(fc)) { |
12300 | return false; |
12301 | } |
12302 | |
12303 | /* Emit notes to tell the current bytecode's source line number. |
12304 | However, a couple trees require special treatment; see the |
12305 | relevant emitter functions for details. */ |
12306 | if (emitLineNote == EMIT_LINENOTE && |
12307 | !ParseNodeRequiresSpecialLineNumberNotes(pn)) { |
12308 | if (!updateLineNumberNotes(pn->pn_pos.begin)) { |
12309 | return false; |
12310 | } |
12311 | } |
12312 | |
12313 | switch (pn->getKind()) { |
12314 | case ParseNodeKind::Function: |
12315 | if (!emitFunction(&pn->as<FunctionNode>())) { |
12316 | return false; |
12317 | } |
12318 | break; |
12319 | |
12320 | case ParseNodeKind::ParamsBody: |
12321 | MOZ_ASSERT_UNREACHABLE(do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "ParamsBody should be handled in emitFunctionScript." ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12322); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "ParamsBody should be handled in emitFunctionScript." ")"); do { *((volatile int*)__null) = 12322; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
12322 | "ParamsBody should be handled in emitFunctionScript.")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "ParamsBody should be handled in emitFunctionScript." ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12322); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "ParamsBody should be handled in emitFunctionScript." ")"); do { *((volatile int*)__null) = 12322; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12323 | break; |
12324 | |
12325 | case ParseNodeKind::IfStmt: |
12326 | if (!emitIf(&pn->as<TernaryNode>())) { |
12327 | return false; |
12328 | } |
12329 | break; |
12330 | |
12331 | case ParseNodeKind::SwitchStmt: |
12332 | if (!emitSwitch(&pn->as<SwitchStatement>())) { |
12333 | return false; |
12334 | } |
12335 | break; |
12336 | |
12337 | case ParseNodeKind::WhileStmt: |
12338 | if (!emitWhile(&pn->as<BinaryNode>())) { |
12339 | return false; |
12340 | } |
12341 | break; |
12342 | |
12343 | case ParseNodeKind::DoWhileStmt: |
12344 | if (!emitDo(&pn->as<BinaryNode>())) { |
12345 | return false; |
12346 | } |
12347 | break; |
12348 | |
12349 | case ParseNodeKind::ForStmt: |
12350 | if (!emitFor(&pn->as<ForNode>())) { |
12351 | return false; |
12352 | } |
12353 | break; |
12354 | |
12355 | case ParseNodeKind::BreakStmt: |
12356 | // Ensure that the column of the 'break' is set properly. |
12357 | if (!updateSourceCoordNotes(pn->pn_pos.begin)) { |
12358 | return false; |
12359 | } |
12360 | if (!markStepBreakpoint()) { |
12361 | return false; |
12362 | } |
12363 | |
12364 | if (!emitBreak(pn->as<BreakStatement>().label())) { |
12365 | return false; |
12366 | } |
12367 | break; |
12368 | |
12369 | case ParseNodeKind::ContinueStmt: |
12370 | // Ensure that the column of the 'continue' is set properly. |
12371 | if (!updateSourceCoordNotes(pn->pn_pos.begin)) { |
12372 | return false; |
12373 | } |
12374 | if (!markStepBreakpoint()) { |
12375 | return false; |
12376 | } |
12377 | |
12378 | if (!emitContinue(pn->as<ContinueStatement>().label())) { |
12379 | return false; |
12380 | } |
12381 | break; |
12382 | |
12383 | case ParseNodeKind::WithStmt: |
12384 | if (!emitWith(&pn->as<BinaryNode>())) { |
12385 | return false; |
12386 | } |
12387 | break; |
12388 | |
12389 | case ParseNodeKind::TryStmt: |
12390 | if (!emitTry(&pn->as<TryNode>())) { |
12391 | return false; |
12392 | } |
12393 | break; |
12394 | |
12395 | case ParseNodeKind::Catch: |
12396 | if (!emitCatch(&pn->as<BinaryNode>())) { |
12397 | return false; |
12398 | } |
12399 | break; |
12400 | |
12401 | case ParseNodeKind::VarStmt: |
12402 | if (!emitDeclarationList(&pn->as<ListNode>())) { |
12403 | return false; |
12404 | } |
12405 | break; |
12406 | |
12407 | case ParseNodeKind::ReturnStmt: |
12408 | if (!emitReturn(&pn->as<UnaryNode>())) { |
12409 | return false; |
12410 | } |
12411 | break; |
12412 | |
12413 | case ParseNodeKind::YieldStarExpr: |
12414 | if (!emitYieldStar(pn->as<UnaryNode>().kid())) { |
12415 | return false; |
12416 | } |
12417 | break; |
12418 | |
12419 | case ParseNodeKind::Generator: |
12420 | if (!emit1(JSOp::Generator)) { |
12421 | return false; |
12422 | } |
12423 | break; |
12424 | |
12425 | case ParseNodeKind::InitialYield: |
12426 | if (!emitInitialYield(&pn->as<UnaryNode>())) { |
12427 | return false; |
12428 | } |
12429 | break; |
12430 | |
12431 | case ParseNodeKind::YieldExpr: |
12432 | if (!emitYield(&pn->as<UnaryNode>())) { |
12433 | return false; |
12434 | } |
12435 | break; |
12436 | |
12437 | case ParseNodeKind::AwaitExpr: |
12438 | if (!emitAwaitInInnermostScope(&pn->as<UnaryNode>())) { |
12439 | return false; |
12440 | } |
12441 | break; |
12442 | |
12443 | case ParseNodeKind::StatementList: |
12444 | if (!emitStatementList(&pn->as<ListNode>())) { |
12445 | return false; |
12446 | } |
12447 | break; |
12448 | |
12449 | case ParseNodeKind::EmptyStmt: |
12450 | break; |
12451 | |
12452 | case ParseNodeKind::ExpressionStmt: |
12453 | if (!emitExpressionStatement(&pn->as<UnaryNode>())) { |
12454 | return false; |
12455 | } |
12456 | break; |
12457 | |
12458 | case ParseNodeKind::LabelStmt: |
12459 | if (!emitLabeledStatement(&pn->as<LabeledStatement>())) { |
12460 | return false; |
12461 | } |
12462 | break; |
12463 | |
12464 | case ParseNodeKind::CommaExpr: |
12465 | if (!emitSequenceExpr(&pn->as<ListNode>(), valueUsage)) { |
12466 | return false; |
12467 | } |
12468 | break; |
12469 | |
12470 | case ParseNodeKind::InitExpr: |
12471 | case ParseNodeKind::AssignExpr: |
12472 | case ParseNodeKind::AddAssignExpr: |
12473 | case ParseNodeKind::SubAssignExpr: |
12474 | case ParseNodeKind::BitOrAssignExpr: |
12475 | case ParseNodeKind::BitXorAssignExpr: |
12476 | case ParseNodeKind::BitAndAssignExpr: |
12477 | case ParseNodeKind::LshAssignExpr: |
12478 | case ParseNodeKind::RshAssignExpr: |
12479 | case ParseNodeKind::UrshAssignExpr: |
12480 | case ParseNodeKind::MulAssignExpr: |
12481 | case ParseNodeKind::DivAssignExpr: |
12482 | case ParseNodeKind::ModAssignExpr: |
12483 | case ParseNodeKind::PowAssignExpr: { |
12484 | BinaryNode* assignNode = &pn->as<BinaryNode>(); |
12485 | if (!emitAssignmentOrInit(assignNode->getKind(), assignNode->left(), |
12486 | assignNode->right())) { |
12487 | return false; |
12488 | } |
12489 | break; |
12490 | } |
12491 | |
12492 | case ParseNodeKind::CoalesceAssignExpr: |
12493 | case ParseNodeKind::OrAssignExpr: |
12494 | case ParseNodeKind::AndAssignExpr: |
12495 | if (!emitShortCircuitAssignment(&pn->as<AssignmentNode>())) { |
12496 | return false; |
12497 | } |
12498 | break; |
12499 | |
12500 | case ParseNodeKind::ConditionalExpr: |
12501 | if (!emitConditionalExpression(pn->as<ConditionalExpression>(), |
12502 | valueUsage)) { |
12503 | return false; |
12504 | } |
12505 | break; |
12506 | |
12507 | case ParseNodeKind::OrExpr: |
12508 | case ParseNodeKind::CoalesceExpr: |
12509 | case ParseNodeKind::AndExpr: |
12510 | if (!emitShortCircuit(&pn->as<ListNode>(), valueUsage)) { |
12511 | return false; |
12512 | } |
12513 | break; |
12514 | |
12515 | case ParseNodeKind::StrictEqExpr: |
12516 | case ParseNodeKind::EqExpr: |
12517 | case ParseNodeKind::StrictNeExpr: |
12518 | case ParseNodeKind::NeExpr: { |
12519 | bool emitted; |
12520 | if (!tryEmitTypeofEq(&pn->as<ListNode>(), &emitted)) { |
12521 | return false; |
12522 | } |
12523 | if (emitted) { |
12524 | return true; |
12525 | } |
12526 | } |
12527 | [[fallthrough]]; |
12528 | |
12529 | case ParseNodeKind::AddExpr: |
12530 | case ParseNodeKind::SubExpr: |
12531 | case ParseNodeKind::BitOrExpr: |
12532 | case ParseNodeKind::BitXorExpr: |
12533 | case ParseNodeKind::BitAndExpr: |
12534 | case ParseNodeKind::LtExpr: |
12535 | case ParseNodeKind::LeExpr: |
12536 | case ParseNodeKind::GtExpr: |
12537 | case ParseNodeKind::GeExpr: |
12538 | case ParseNodeKind::InExpr: |
12539 | case ParseNodeKind::InstanceOfExpr: |
12540 | case ParseNodeKind::LshExpr: |
12541 | case ParseNodeKind::RshExpr: |
12542 | case ParseNodeKind::UrshExpr: |
12543 | case ParseNodeKind::MulExpr: |
12544 | case ParseNodeKind::DivExpr: |
12545 | case ParseNodeKind::ModExpr: |
12546 | if (!emitLeftAssociative(&pn->as<ListNode>())) { |
12547 | return false; |
12548 | } |
12549 | break; |
12550 | |
12551 | case ParseNodeKind::PrivateInExpr: |
12552 | if (!emitPrivateInExpr(&pn->as<ListNode>())) { |
12553 | return false; |
12554 | } |
12555 | break; |
12556 | |
12557 | case ParseNodeKind::PowExpr: |
12558 | if (!emitRightAssociative(&pn->as<ListNode>())) { |
12559 | return false; |
12560 | } |
12561 | break; |
12562 | |
12563 | case ParseNodeKind::TypeOfNameExpr: |
12564 | if (!emitTypeof(&pn->as<UnaryNode>(), JSOp::Typeof)) { |
12565 | return false; |
12566 | } |
12567 | break; |
12568 | |
12569 | case ParseNodeKind::TypeOfExpr: |
12570 | if (!emitTypeof(&pn->as<UnaryNode>(), JSOp::TypeofExpr)) { |
12571 | return false; |
12572 | } |
12573 | break; |
12574 | |
12575 | case ParseNodeKind::ThrowStmt: |
12576 | if (!updateSourceCoordNotes(pn->pn_pos.begin)) { |
12577 | return false; |
12578 | } |
12579 | if (!markStepBreakpoint()) { |
12580 | return false; |
12581 | } |
12582 | [[fallthrough]]; |
12583 | case ParseNodeKind::VoidExpr: |
12584 | case ParseNodeKind::NotExpr: |
12585 | case ParseNodeKind::BitNotExpr: |
12586 | case ParseNodeKind::PosExpr: |
12587 | case ParseNodeKind::NegExpr: |
12588 | if (!emitUnary(&pn->as<UnaryNode>())) { |
12589 | return false; |
12590 | } |
12591 | break; |
12592 | |
12593 | case ParseNodeKind::PreIncrementExpr: |
12594 | case ParseNodeKind::PreDecrementExpr: |
12595 | case ParseNodeKind::PostIncrementExpr: |
12596 | case ParseNodeKind::PostDecrementExpr: |
12597 | if (!emitIncOrDec(&pn->as<UnaryNode>(), valueUsage)) { |
12598 | return false; |
12599 | } |
12600 | break; |
12601 | |
12602 | case ParseNodeKind::DeleteNameExpr: |
12603 | if (!emitDeleteName(&pn->as<UnaryNode>())) { |
12604 | return false; |
12605 | } |
12606 | break; |
12607 | |
12608 | case ParseNodeKind::DeletePropExpr: |
12609 | if (!emitDeleteProperty(&pn->as<UnaryNode>())) { |
12610 | return false; |
12611 | } |
12612 | break; |
12613 | |
12614 | case ParseNodeKind::DeleteElemExpr: |
12615 | if (!emitDeleteElement(&pn->as<UnaryNode>())) { |
12616 | return false; |
12617 | } |
12618 | break; |
12619 | |
12620 | case ParseNodeKind::DeleteExpr: |
12621 | if (!emitDeleteExpression(&pn->as<UnaryNode>())) { |
12622 | return false; |
12623 | } |
12624 | break; |
12625 | |
12626 | case ParseNodeKind::DeleteOptionalChainExpr: |
12627 | if (!emitDeleteOptionalChain(&pn->as<UnaryNode>())) { |
12628 | return false; |
12629 | } |
12630 | break; |
12631 | |
12632 | case ParseNodeKind::OptionalChain: |
12633 | if (!emitOptionalChain(&pn->as<UnaryNode>(), valueUsage)) { |
12634 | return false; |
12635 | } |
12636 | break; |
12637 | |
12638 | case ParseNodeKind::DotExpr: { |
12639 | PropertyAccess* prop = &pn->as<PropertyAccess>(); |
12640 | bool isSuper = prop->isSuper(); |
12641 | PropOpEmitter poe(this, PropOpEmitter::Kind::Get, |
12642 | isSuper ? PropOpEmitter::ObjKind::Super |
12643 | : PropOpEmitter::ObjKind::Other); |
12644 | if (!poe.prepareForObj()) { |
12645 | return false; |
12646 | } |
12647 | if (isSuper) { |
12648 | UnaryNode* base = &prop->expression().as<UnaryNode>(); |
12649 | if (!emitGetThisForSuperBase(base)) { |
12650 | // [stack] THIS |
12651 | return false; |
12652 | } |
12653 | } else { |
12654 | if (!emitPropLHS(prop)) { |
12655 | // [stack] OBJ |
12656 | return false; |
12657 | } |
12658 | } |
12659 | if (!poe.emitGet(prop->key().atom())) { |
12660 | // [stack] PROP |
12661 | return false; |
12662 | } |
12663 | break; |
12664 | } |
12665 | |
12666 | case ParseNodeKind::ArgumentsLength: { |
12667 | if (sc->isFunctionBox() && |
12668 | sc->asFunctionBox()->isEligibleForArgumentsLength() && |
12669 | !sc->asFunctionBox()->needsArgsObj()) { |
12670 | if (!emit1(JSOp::ArgumentsLength)) { |
12671 | return false; |
12672 | } |
12673 | } else { |
12674 | PropOpEmitter poe(this, PropOpEmitter::Kind::Get, |
12675 | PropOpEmitter::ObjKind::Other); |
12676 | if (!poe.prepareForObj()) { |
12677 | return false; |
12678 | } |
12679 | |
12680 | NameOpEmitter noe(this, TaggedParserAtomIndex::WellKnown::arguments(), |
12681 | NameOpEmitter::Kind::Get); |
12682 | if (!noe.emitGet()) { |
12683 | return false; |
12684 | } |
12685 | if (!poe.emitGet(TaggedParserAtomIndex::WellKnown::length())) { |
12686 | return false; |
12687 | } |
12688 | } |
12689 | break; |
12690 | } |
12691 | |
12692 | case ParseNodeKind::ElemExpr: { |
12693 | PropertyByValue* elem = &pn->as<PropertyByValue>(); |
12694 | bool isSuper = elem->isSuper(); |
12695 | MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!elem->key().isKind(ParseNodeKind::PrivateName))> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!elem->key().isKind(ParseNodeKind::PrivateName))) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!elem->key().isKind(ParseNodeKind::PrivateName)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12695); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)" ")"); do { *((volatile int*)__null) = 12695; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12696 | ElemOpEmitter eoe(this, ElemOpEmitter::Kind::Get, |
12697 | isSuper ? ElemOpEmitter::ObjKind::Super |
12698 | : ElemOpEmitter::ObjKind::Other); |
12699 | if (!emitElemObjAndKey(elem, eoe)) { |
12700 | // [stack] # if Super |
12701 | // [stack] THIS KEY |
12702 | // [stack] # otherwise |
12703 | // [stack] OBJ KEY |
12704 | return false; |
12705 | } |
12706 | if (!eoe.emitGet()) { |
12707 | // [stack] ELEM |
12708 | return false; |
12709 | } |
12710 | |
12711 | break; |
12712 | } |
12713 | |
12714 | case ParseNodeKind::PrivateMemberExpr: { |
12715 | PrivateMemberAccess* privateExpr = &pn->as<PrivateMemberAccess>(); |
12716 | PrivateOpEmitter xoe(this, PrivateOpEmitter::Kind::Get, |
12717 | privateExpr->privateName().name()); |
12718 | if (!emitTree(&privateExpr->expression())) { |
12719 | // [stack] OBJ |
12720 | return false; |
12721 | } |
12722 | if (!xoe.emitReference()) { |
12723 | // [stack] OBJ NAME |
12724 | return false; |
12725 | } |
12726 | if (!xoe.emitGet()) { |
12727 | // [stack] VALUE |
12728 | return false; |
12729 | } |
12730 | |
12731 | break; |
12732 | } |
12733 | |
12734 | case ParseNodeKind::NewExpr: |
12735 | case ParseNodeKind::TaggedTemplateExpr: |
12736 | case ParseNodeKind::CallExpr: |
12737 | case ParseNodeKind::SuperCallExpr: |
12738 | if (!emitCallOrNew(&pn->as<CallNode>(), valueUsage)) { |
12739 | return false; |
12740 | } |
12741 | break; |
12742 | |
12743 | case ParseNodeKind::LexicalScope: |
12744 | if (!emitLexicalScope(&pn->as<LexicalScopeNode>())) { |
12745 | return false; |
12746 | } |
12747 | break; |
12748 | |
12749 | case ParseNodeKind::ConstDecl: |
12750 | case ParseNodeKind::LetDecl: |
12751 | if (!emitDeclarationList(&pn->as<ListNode>())) { |
12752 | return false; |
12753 | } |
12754 | break; |
12755 | #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT |
12756 | case ParseNodeKind::AwaitUsingDecl: |
12757 | case ParseNodeKind::UsingDecl: |
12758 | if (!emitDeclarationList(&pn->as<ListNode>())) { |
12759 | return false; |
12760 | } |
12761 | break; |
12762 | #endif |
12763 | |
12764 | case ParseNodeKind::ImportDecl: |
12765 | MOZ_ASSERT(sc->isModuleContext())do { static_assert( mozilla::detail::AssertionConditionType< decltype(sc->isModuleContext())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(sc->isModuleContext()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("sc->isModuleContext()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12765); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isModuleContext()" ")"); do { *((volatile int*)__null) = 12765; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12766 | break; |
12767 | |
12768 | case ParseNodeKind::ExportStmt: { |
12769 | MOZ_ASSERT(sc->isModuleContext())do { static_assert( mozilla::detail::AssertionConditionType< decltype(sc->isModuleContext())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(sc->isModuleContext()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("sc->isModuleContext()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12769); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isModuleContext()" ")"); do { *((volatile int*)__null) = 12769; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12770 | UnaryNode* node = &pn->as<UnaryNode>(); |
12771 | ParseNode* decl = node->kid(); |
12772 | if (decl->getKind() != ParseNodeKind::ExportSpecList) { |
12773 | if (!emitTree(decl)) { |
12774 | return false; |
12775 | } |
12776 | } |
12777 | break; |
12778 | } |
12779 | |
12780 | case ParseNodeKind::ExportDefaultStmt: |
12781 | MOZ_ASSERT(sc->isModuleContext())do { static_assert( mozilla::detail::AssertionConditionType< decltype(sc->isModuleContext())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(sc->isModuleContext()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("sc->isModuleContext()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12781); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isModuleContext()" ")"); do { *((volatile int*)__null) = 12781; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12782 | if (!emitExportDefault(&pn->as<BinaryNode>())) { |
12783 | return false; |
12784 | } |
12785 | break; |
12786 | |
12787 | case ParseNodeKind::ExportFromStmt: |
12788 | MOZ_ASSERT(sc->isModuleContext())do { static_assert( mozilla::detail::AssertionConditionType< decltype(sc->isModuleContext())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(sc->isModuleContext()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("sc->isModuleContext()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12788); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isModuleContext()" ")"); do { *((volatile int*)__null) = 12788; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12789 | break; |
12790 | |
12791 | case ParseNodeKind::CallSiteObj: |
12792 | if (!emitCallSiteObject(&pn->as<CallSiteNode>())) { |
12793 | return false; |
12794 | } |
12795 | break; |
12796 | |
12797 | case ParseNodeKind::ArrayExpr: |
12798 | if (!emitArrayLiteral(&pn->as<ListNode>())) { |
12799 | return false; |
12800 | } |
12801 | break; |
12802 | |
12803 | case ParseNodeKind::ObjectExpr: |
12804 | if (!emitObject(&pn->as<ListNode>())) { |
12805 | return false; |
12806 | } |
12807 | break; |
12808 | |
12809 | case ParseNodeKind::Name: |
12810 | if (!emitGetName(&pn->as<NameNode>())) { |
12811 | return false; |
12812 | } |
12813 | break; |
12814 | |
12815 | case ParseNodeKind::PrivateName: |
12816 | if (!emitGetPrivateName(&pn->as<NameNode>())) { |
12817 | return false; |
12818 | } |
12819 | break; |
12820 | |
12821 | case ParseNodeKind::TemplateStringListExpr: |
12822 | if (!emitTemplateString(&pn->as<ListNode>())) { |
12823 | return false; |
12824 | } |
12825 | break; |
12826 | |
12827 | case ParseNodeKind::TemplateStringExpr: |
12828 | case ParseNodeKind::StringExpr: |
12829 | if (!emitStringOp(JSOp::String, pn->as<NameNode>().atom())) { |
12830 | return false; |
12831 | } |
12832 | break; |
12833 | |
12834 | case ParseNodeKind::NumberExpr: |
12835 | if (!emitNumberOp(pn->as<NumericLiteral>().value())) { |
12836 | return false; |
12837 | } |
12838 | break; |
12839 | |
12840 | case ParseNodeKind::BigIntExpr: |
12841 | if (!emitBigIntOp(&pn->as<BigIntLiteral>())) { |
12842 | return false; |
12843 | } |
12844 | break; |
12845 | |
12846 | case ParseNodeKind::RegExpExpr: { |
12847 | GCThingIndex index; |
12848 | if (!perScriptData().gcThingList().append(&pn->as<RegExpLiteral>(), |
12849 | &index)) { |
12850 | return false; |
12851 | } |
12852 | if (!emitRegExp(index)) { |
12853 | return false; |
12854 | } |
12855 | break; |
12856 | } |
12857 | |
12858 | case ParseNodeKind::TrueExpr: |
12859 | if (!emit1(JSOp::True)) { |
12860 | return false; |
12861 | } |
12862 | break; |
12863 | case ParseNodeKind::FalseExpr: |
12864 | if (!emit1(JSOp::False)) { |
12865 | return false; |
12866 | } |
12867 | break; |
12868 | case ParseNodeKind::NullExpr: |
12869 | if (!emit1(JSOp::Null)) { |
12870 | return false; |
12871 | } |
12872 | break; |
12873 | case ParseNodeKind::RawUndefinedExpr: |
12874 | if (!emit1(JSOp::Undefined)) { |
12875 | return false; |
12876 | } |
12877 | break; |
12878 | |
12879 | case ParseNodeKind::ThisExpr: |
12880 | if (!emitThisLiteral(&pn->as<ThisLiteral>())) { |
12881 | return false; |
12882 | } |
12883 | break; |
12884 | |
12885 | case ParseNodeKind::DebuggerStmt: |
12886 | if (!updateSourceCoordNotes(pn->pn_pos.begin)) { |
12887 | return false; |
12888 | } |
12889 | if (!markStepBreakpoint()) { |
12890 | return false; |
12891 | } |
12892 | if (!emit1(JSOp::Debugger)) { |
12893 | return false; |
12894 | } |
12895 | break; |
12896 | |
12897 | case ParseNodeKind::ClassDecl: |
12898 | if (!emitClass(&pn->as<ClassNode>())) { |
12899 | return false; |
12900 | } |
12901 | break; |
12902 | |
12903 | case ParseNodeKind::NewTargetExpr: |
12904 | if (!emitNewTarget(&pn->as<NewTargetNode>())) { |
12905 | return false; |
12906 | } |
12907 | break; |
12908 | |
12909 | case ParseNodeKind::ImportMetaExpr: |
12910 | if (!emit1(JSOp::ImportMeta)) { |
12911 | return false; |
12912 | } |
12913 | break; |
12914 | |
12915 | case ParseNodeKind::CallImportExpr: { |
12916 | BinaryNode* spec = &pn->as<BinaryNode>().right()->as<BinaryNode>(); |
12917 | |
12918 | if (!emitTree(spec->left())) { |
12919 | // [stack] specifier |
12920 | return false; |
12921 | } |
12922 | |
12923 | if (!spec->right()->isKind(ParseNodeKind::PosHolder)) { |
12924 | // [stack] specifier options |
12925 | if (!emitTree(spec->right())) { |
12926 | return false; |
12927 | } |
12928 | } else { |
12929 | // [stack] specifier undefined |
12930 | if (!emit1(JSOp::Undefined)) { |
12931 | return false; |
12932 | } |
12933 | } |
12934 | |
12935 | if (!emit1(JSOp::DynamicImport)) { |
12936 | return false; |
12937 | } |
12938 | |
12939 | break; |
12940 | } |
12941 | |
12942 | case ParseNodeKind::SetThis: |
12943 | if (!emitSetThis(&pn->as<BinaryNode>())) { |
12944 | return false; |
12945 | } |
12946 | break; |
12947 | |
12948 | #ifdef ENABLE_RECORD_TUPLE |
12949 | case ParseNodeKind::RecordExpr: |
12950 | if (!emitRecordLiteral(&pn->as<ListNode>())) { |
12951 | return false; |
12952 | } |
12953 | break; |
12954 | |
12955 | case ParseNodeKind::TupleExpr: |
12956 | if (!emitTupleLiteral(&pn->as<ListNode>())) { |
12957 | return false; |
12958 | } |
12959 | break; |
12960 | #endif |
12961 | |
12962 | case ParseNodeKind::PropertyNameExpr: |
12963 | case ParseNodeKind::PosHolder: |
12964 | MOZ_FALLTHROUGH_ASSERT(do { do { } while (false); MOZ_ReportCrash("" "MOZ_FALLTHROUGH_ASSERT: " "Should never try to emit ParseNodeKind::PosHolder or ::Property" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12965); AnnotateMozCrashReason("MOZ_CRASH(" "MOZ_FALLTHROUGH_ASSERT: " "Should never try to emit ParseNodeKind::PosHolder or ::Property" ")"); do { *((volatile int*)__null) = 12965; __attribute__(( nomerge)) ::abort(); } while (false); } while (false) |
12965 | "Should never try to emit ParseNodeKind::PosHolder or ::Property")do { do { } while (false); MOZ_ReportCrash("" "MOZ_FALLTHROUGH_ASSERT: " "Should never try to emit ParseNodeKind::PosHolder or ::Property" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12965); AnnotateMozCrashReason("MOZ_CRASH(" "MOZ_FALLTHROUGH_ASSERT: " "Should never try to emit ParseNodeKind::PosHolder or ::Property" ")"); do { *((volatile int*)__null) = 12965; __attribute__(( nomerge)) ::abort(); } while (false); } while (false); |
12966 | |
12967 | default: |
12968 | MOZ_ASSERT(0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(0)>::isValid, "invalid assertion condition"); if ( (__builtin_expect(!!(!(!!(0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("0", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12968); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0" ")"); do { *((volatile int*)__null) = 12968; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
12969 | } |
12970 | |
12971 | return true; |
12972 | } |
12973 | |
12974 | static bool AllocSrcNote(FrontendContext* fc, SrcNotesVector& notes, |
12975 | unsigned size, unsigned* index) { |
12976 | size_t oldLength = notes.length(); |
12977 | |
12978 | if (MOZ_UNLIKELY(oldLength + size > MaxSrcNotesLength)(__builtin_expect(!!(oldLength + size > MaxSrcNotesLength) , 0))) { |
12979 | ReportAllocationOverflow(fc); |
12980 | return false; |
12981 | } |
12982 | |
12983 | if (!notes.growByUninitialized(size)) { |
12984 | return false; |
12985 | } |
12986 | |
12987 | *index = oldLength; |
12988 | return true; |
12989 | } |
12990 | |
12991 | bool BytecodeEmitter::addTryNote(TryNoteKind kind, uint32_t stackDepth, |
12992 | BytecodeOffset start, BytecodeOffset end) { |
12993 | MOZ_ASSERT(!inPrologue())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!inPrologue())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!inPrologue()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!inPrologue()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12993); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inPrologue()" ")"); do { *((volatile int*)__null) = 12993; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12994 | return bytecodeSection().tryNoteList().append(kind, stackDepth, start, end); |
12995 | } |
12996 | |
12997 | bool BytecodeEmitter::newSrcNote(SrcNoteType type, unsigned* indexp) { |
12998 | SrcNotesVector& notes = bytecodeSection().notes(); |
12999 | unsigned index; |
13000 | |
13001 | /* |
13002 | * Compute delta from the last annotated bytecode's offset. If it's too |
13003 | * big to fit in sn, allocate one or more xdelta notes and reset sn. |
13004 | */ |
13005 | BytecodeOffset offset = bytecodeSection().offset(); |
13006 | ptrdiff_t delta = (offset - bytecodeSection().lastNoteOffset()).value(); |
13007 | bytecodeSection().setLastNoteOffset(offset); |
13008 | |
13009 | auto allocator = [&](unsigned size) -> SrcNote* { |
13010 | if (!AllocSrcNote(fc, notes, size, &index)) { |
13011 | return nullptr; |
13012 | } |
13013 | return ¬es[index]; |
13014 | }; |
13015 | |
13016 | if (!SrcNoteWriter::writeNote(type, delta, allocator)) { |
13017 | return false; |
13018 | } |
13019 | |
13020 | if (indexp) { |
13021 | *indexp = index; |
13022 | } |
13023 | |
13024 | if (type == SrcNoteType::NewLine || type == SrcNoteType::SetLine) { |
13025 | lastLineOnlySrcNoteIndex = index; |
13026 | } else { |
13027 | lastLineOnlySrcNoteIndex = LastSrcNoteIsNotLineOnly; |
13028 | } |
13029 | |
13030 | return true; |
13031 | } |
13032 | |
13033 | bool BytecodeEmitter::newSrcNote2(SrcNoteType type, ptrdiff_t offset, |
13034 | unsigned* indexp) { |
13035 | unsigned index; |
13036 | if (!newSrcNote(type, &index)) { |
13037 | return false; |
13038 | } |
13039 | if (!newSrcNoteOperand(offset)) { |
13040 | return false; |
13041 | } |
13042 | if (indexp) { |
13043 | *indexp = index; |
13044 | } |
13045 | return true; |
13046 | } |
13047 | |
13048 | bool BytecodeEmitter::convertLastNewLineToNewLineColumn( |
13049 | JS::LimitedColumnNumberOneOrigin column) { |
13050 | SrcNotesVector& notes = bytecodeSection().notes(); |
13051 | MOZ_ASSERT(lastLineOnlySrcNoteIndex == notes.length() - 1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(lastLineOnlySrcNoteIndex == notes.length() - 1)>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(lastLineOnlySrcNoteIndex == notes.length() - 1))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("lastLineOnlySrcNoteIndex == notes.length() - 1" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 13051); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lastLineOnlySrcNoteIndex == notes.length() - 1" ")"); do { *((volatile int*)__null) = 13051; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
13052 | SrcNote* sn = ¬es[lastLineOnlySrcNoteIndex]; |
13053 | MOZ_ASSERT(sn->type() == SrcNoteType::NewLine)do { static_assert( mozilla::detail::AssertionConditionType< decltype(sn->type() == SrcNoteType::NewLine)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(! !(sn->type() == SrcNoteType::NewLine))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("sn->type() == SrcNoteType::NewLine" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 13053); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sn->type() == SrcNoteType::NewLine" ")"); do { *((volatile int*)__null) = 13053; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
13054 | |
13055 | SrcNoteWriter::convertNote(sn, SrcNoteType::NewLineColumn); |
13056 | if (!newSrcNoteOperand(SrcNote::NewLineColumn::toOperand(column))) { |
13057 | return false; |
13058 | } |
13059 | |
13060 | lastLineOnlySrcNoteIndex = LastSrcNoteIsNotLineOnly; |
13061 | return true; |
13062 | } |
13063 | |
13064 | bool BytecodeEmitter::convertLastSetLineToSetLineColumn( |
13065 | JS::LimitedColumnNumberOneOrigin column) { |
13066 | SrcNotesVector& notes = bytecodeSection().notes(); |
13067 | // The Line operand is either 1 byte or 4 bytes. |
13068 | MOZ_ASSERT(lastLineOnlySrcNoteIndex == notes.length() - 1 - 1 ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(lastLineOnlySrcNoteIndex == notes.length() - 1 - 1 || lastLineOnlySrcNoteIndex == notes.length() - 1 - 4)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(lastLineOnlySrcNoteIndex == notes.length() - 1 - 1 || lastLineOnlySrcNoteIndex == notes.length() - 1 - 4))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("lastLineOnlySrcNoteIndex == notes.length() - 1 - 1 || lastLineOnlySrcNoteIndex == notes.length() - 1 - 4" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 13069); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lastLineOnlySrcNoteIndex == notes.length() - 1 - 1 || lastLineOnlySrcNoteIndex == notes.length() - 1 - 4" ")"); do { *((volatile int*)__null) = 13069; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
13069 | lastLineOnlySrcNoteIndex == notes.length() - 1 - 4)do { static_assert( mozilla::detail::AssertionConditionType< decltype(lastLineOnlySrcNoteIndex == notes.length() - 1 - 1 || lastLineOnlySrcNoteIndex == notes.length() - 1 - 4)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(lastLineOnlySrcNoteIndex == notes.length() - 1 - 1 || lastLineOnlySrcNoteIndex == notes.length() - 1 - 4))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("lastLineOnlySrcNoteIndex == notes.length() - 1 - 1 || lastLineOnlySrcNoteIndex == notes.length() - 1 - 4" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 13069); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lastLineOnlySrcNoteIndex == notes.length() - 1 - 1 || lastLineOnlySrcNoteIndex == notes.length() - 1 - 4" ")"); do { *((volatile int*)__null) = 13069; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
13070 | SrcNote* sn = ¬es[lastLineOnlySrcNoteIndex]; |
13071 | MOZ_ASSERT(sn->type() == SrcNoteType::SetLine)do { static_assert( mozilla::detail::AssertionConditionType< decltype(sn->type() == SrcNoteType::SetLine)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(! !(sn->type() == SrcNoteType::SetLine))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("sn->type() == SrcNoteType::SetLine" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 13071); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sn->type() == SrcNoteType::SetLine" ")"); do { *((volatile int*)__null) = 13071; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
13072 | |
13073 | SrcNoteWriter::convertNote(sn, SrcNoteType::SetLineColumn); |
13074 | if (!newSrcNoteOperand(SrcNote::SetLineColumn::columnToOperand(column))) { |
13075 | return false; |
13076 | } |
13077 | |
13078 | lastLineOnlySrcNoteIndex = LastSrcNoteIsNotLineOnly; |
13079 | return true; |
13080 | } |
13081 | |
13082 | bool BytecodeEmitter::newSrcNoteOperand(ptrdiff_t operand) { |
13083 | if (!SrcNote::isRepresentableOperand(operand)) { |
13084 | reportError(nullptr, JSMSG_NEED_DIET, "script"); |
13085 | return false; |
13086 | } |
13087 | |
13088 | SrcNotesVector& notes = bytecodeSection().notes(); |
13089 | |
13090 | auto allocator = [&](unsigned size) -> SrcNote* { |
13091 | unsigned index; |
13092 | if (!AllocSrcNote(fc, notes, size, &index)) { |
13093 | return nullptr; |
13094 | } |
13095 | return ¬es[index]; |
13096 | }; |
13097 | |
13098 | return SrcNoteWriter::writeOperand(operand, allocator); |
13099 | } |
13100 | |
13101 | bool BytecodeEmitter::intoScriptStencil(ScriptIndex scriptIndex) { |
13102 | js::UniquePtr<ImmutableScriptData> immutableScriptData = |
13103 | createImmutableScriptData(); |
13104 | if (!immutableScriptData) { |
13105 | return false; |
13106 | } |
13107 | |
13108 | MOZ_ASSERT(outermostScope().hasNonSyntacticScopeOnChain() ==do { static_assert( mozilla::detail::AssertionConditionType< decltype(outermostScope().hasNonSyntacticScopeOnChain() == sc ->hasNonSyntacticScope())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(outermostScope().hasNonSyntacticScopeOnChain () == sc->hasNonSyntacticScope()))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("outermostScope().hasNonSyntacticScopeOnChain() == sc->hasNonSyntacticScope()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 13109); AnnotateMozCrashReason("MOZ_ASSERT" "(" "outermostScope().hasNonSyntacticScopeOnChain() == sc->hasNonSyntacticScope()" ")"); do { *((volatile int*)__null) = 13109; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
13109 | sc->hasNonSyntacticScope())do { static_assert( mozilla::detail::AssertionConditionType< decltype(outermostScope().hasNonSyntacticScopeOnChain() == sc ->hasNonSyntacticScope())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(outermostScope().hasNonSyntacticScopeOnChain () == sc->hasNonSyntacticScope()))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("outermostScope().hasNonSyntacticScopeOnChain() == sc->hasNonSyntacticScope()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 13109); AnnotateMozCrashReason("MOZ_ASSERT" "(" "outermostScope().hasNonSyntacticScopeOnChain() == sc->hasNonSyntacticScope()" ")"); do { *((volatile int*)__null) = 13109; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
13110 | |
13111 | auto& things = perScriptData().gcThingList().objects(); |
13112 | if (!compilationState.appendGCThings(fc, scriptIndex, things)) { |
13113 | return false; |
13114 | } |
13115 | |
13116 | // Hand over the ImmutableScriptData instance generated by BCE. |
13117 | auto* sharedData = |
13118 | SharedImmutableScriptData::createWith(fc, std::move(immutableScriptData)); |
13119 | if (!sharedData) { |
13120 | return false; |
13121 | } |
13122 | |
13123 | // De-duplicate the bytecode within the runtime. |
13124 | if (!compilationState.sharedData.addAndShare(fc, scriptIndex, sharedData)) { |
13125 | return false; |
13126 | } |
13127 | |
13128 | ScriptStencil& script = compilationState.scriptData[scriptIndex]; |
13129 | script.setHasSharedData(); |
13130 | |
13131 | // Update flags specific to functions. |
13132 | if (sc->isFunctionBox()) { |
13133 | FunctionBox* funbox = sc->asFunctionBox(); |
13134 | MOZ_ASSERT(&script == &funbox->functionStencil())do { static_assert( mozilla::detail::AssertionConditionType< decltype(&script == &funbox->functionStencil())> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(&script == &funbox->functionStencil()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("&script == &funbox->functionStencil()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 13134); AnnotateMozCrashReason("MOZ_ASSERT" "(" "&script == &funbox->functionStencil()" ")"); do { *((volatile int*)__null) = 13134; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
13135 | funbox->copyUpdatedImmutableFlags(); |
13136 | MOZ_ASSERT(script.isFunction())do { static_assert( mozilla::detail::AssertionConditionType< decltype(script.isFunction())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(script.isFunction()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("script.isFunction()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 13136); AnnotateMozCrashReason("MOZ_ASSERT" "(" "script.isFunction()" ")"); do { *((volatile int*)__null) = 13136; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
13137 | } else { |
13138 | ScriptStencilExtra& scriptExtra = compilationState.scriptExtra[scriptIndex]; |
13139 | sc->copyScriptExtraFields(scriptExtra); |
13140 | } |
13141 | |
13142 | return true; |
13143 | } |
13144 | |
13145 | SelfHostedIter BytecodeEmitter::getSelfHostedIterFor( |
13146 | ParseNode* parseNode) const { |
13147 | if (emitterMode == BytecodeEmitter::SelfHosting && |
13148 | parseNode->isKind(ParseNodeKind::CallExpr)) { |
13149 | auto* callee = parseNode->as<CallNode>().callee(); |
13150 | if (callee->isName(TaggedParserAtomIndex::WellKnown::allowContentIter())) { |
13151 | return SelfHostedIter::AllowContent; |
13152 | } |
13153 | if (callee->isName( |
13154 | TaggedParserAtomIndex::WellKnown::allowContentIterWith())) { |
13155 | return SelfHostedIter::AllowContentWith; |
13156 | } |
13157 | if (callee->isName( |
13158 | TaggedParserAtomIndex::WellKnown::allowContentIterWithNext())) { |
13159 | return SelfHostedIter::AllowContentWithNext; |
13160 | } |
13161 | } |
13162 | |
13163 | return SelfHostedIter::Deny; |
13164 | } |
13165 | |
13166 | #if defined(DEBUG1) || defined(JS_JITSPEW1) |
13167 | void BytecodeEmitter::dumpAtom(TaggedParserAtomIndex index) const { |
13168 | parserAtoms().dump(index); |
13169 | } |
13170 | #endif |