File: | var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp |
Warning: | line 823, column 3 Value stored to 'pc' is never read |
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/PodOperations.h" // mozilla::PodCopy |
19 | #include "mozilla/Saturate.h" |
20 | #include "mozilla/Variant.h" // mozilla::AsVariant |
21 | |
22 | #include <algorithm> |
23 | #include <iterator> |
24 | #include <string.h> |
25 | |
26 | #include "jstypes.h" // JS_BIT |
27 | |
28 | #include "frontend/AbstractScopePtr.h" // ScopeIndex |
29 | #include "frontend/BytecodeControlStructures.h" // NestableControl, BreakableControl, LabelControl, LoopControl, TryFinallyControl |
30 | #include "frontend/CallOrNewEmitter.h" // CallOrNewEmitter |
31 | #include "frontend/CForEmitter.h" // CForEmitter |
32 | #include "frontend/DecoratorEmitter.h" // DecoratorEmitter |
33 | #include "frontend/DefaultEmitter.h" // DefaultEmitter |
34 | #include "frontend/DoWhileEmitter.h" // DoWhileEmitter |
35 | #include "frontend/ElemOpEmitter.h" // ElemOpEmitter |
36 | #include "frontend/EmitterScope.h" // EmitterScope |
37 | #include "frontend/ExpressionStatementEmitter.h" // ExpressionStatementEmitter |
38 | #include "frontend/ForInEmitter.h" // ForInEmitter |
39 | #include "frontend/ForOfEmitter.h" // ForOfEmitter |
40 | #include "frontend/FunctionEmitter.h" // FunctionEmitter, FunctionScriptEmitter, FunctionParamsEmitter |
41 | #include "frontend/IfEmitter.h" // IfEmitter, InternalIfEmitter, CondEmitter |
42 | #include "frontend/LabelEmitter.h" // LabelEmitter |
43 | #include "frontend/LexicalScopeEmitter.h" // LexicalScopeEmitter |
44 | #include "frontend/ModuleSharedContext.h" // ModuleSharedContext |
45 | #include "frontend/NameAnalysisTypes.h" // PrivateNameKind |
46 | #include "frontend/NameFunctions.h" // NameFunctions |
47 | #include "frontend/NameOpEmitter.h" // NameOpEmitter |
48 | #include "frontend/ObjectEmitter.h" // PropertyEmitter, ObjectEmitter, ClassEmitter |
49 | #include "frontend/OptionalEmitter.h" // OptionalEmitter |
50 | #include "frontend/ParseContext.h" // ParseContext::Scope |
51 | #include "frontend/ParseNode.h" // ParseNodeKind, ParseNode and subclasses |
52 | #include "frontend/Parser.h" // Parser |
53 | #include "frontend/ParserAtom.h" // ParserAtomsTable, ParserAtom |
54 | #include "frontend/PrivateOpEmitter.h" // PrivateOpEmitter |
55 | #include "frontend/PropOpEmitter.h" // PropOpEmitter |
56 | #include "frontend/SourceNotes.h" // SrcNote, SrcNoteType, SrcNoteWriter |
57 | #include "frontend/SwitchEmitter.h" // SwitchEmitter |
58 | #include "frontend/TaggedParserAtomIndexHasher.h" // TaggedParserAtomIndexHasher |
59 | #include "frontend/TDZCheckCache.h" // TDZCheckCache |
60 | #include "frontend/TryEmitter.h" // TryEmitter |
61 | #include "frontend/UsingEmitter.h" // UsingEmitter |
62 | #include "frontend/WhileEmitter.h" // WhileEmitter |
63 | #include "js/ColumnNumber.h" // JS::LimitedColumnNumberOneOrigin, JS::ColumnNumberOffset |
64 | #include "js/friend/ErrorMessages.h" // JSMSG_* |
65 | #include "js/friend/StackLimits.h" // AutoCheckRecursionLimit |
66 | #include "util/StringBuffer.h" // StringBuffer |
67 | #include "vm/BytecodeUtil.h" // JOF_*, IsArgOp, IsLocalOp, SET_UINT24, SET_ICINDEX, BytecodeFallsThrough, BytecodeIsJumpTarget |
68 | #include "vm/CompletionKind.h" // CompletionKind |
69 | #include "vm/FunctionPrefixKind.h" // FunctionPrefixKind |
70 | #include "vm/GeneratorObject.h" // AbstractGeneratorObject |
71 | #include "vm/Opcodes.h" // JSOp, JSOpLength_* |
72 | #include "vm/PropMap.h" // SharedPropMap::MaxPropsForNonDictionary |
73 | #include "vm/Scope.h" // GetScopeDataTrailingNames |
74 | #include "vm/SharedStencil.h" // ScopeNote |
75 | #include "vm/ThrowMsgKind.h" // ThrowMsgKind |
76 | #include "vm/TypeofEqOperand.h" // TypeofEqOperand |
77 | |
78 | using namespace js; |
79 | using namespace js::frontend; |
80 | |
81 | using mozilla::AssertedCast; |
82 | using mozilla::AsVariant; |
83 | using mozilla::DebugOnly; |
84 | using mozilla::Maybe; |
85 | using mozilla::Nothing; |
86 | using mozilla::NumberEqualsInt32; |
87 | using mozilla::NumberIsInt32; |
88 | using mozilla::PodCopy; |
89 | using mozilla::Some; |
90 | |
91 | static bool ParseNodeRequiresSpecialLineNumberNotes(ParseNode* pn) { |
92 | // The few node types listed below are exceptions to the usual |
93 | // location-source-note-emitting code in BytecodeEmitter::emitTree(). |
94 | // Single-line `while` loops and C-style `for` loops require careful |
95 | // handling to avoid strange stepping behavior. |
96 | // Functions usually shouldn't have location information (bug 1431202). |
97 | |
98 | ParseNodeKind kind = pn->getKind(); |
99 | return kind == ParseNodeKind::WhileStmt || kind == ParseNodeKind::ForStmt || |
100 | kind == ParseNodeKind::Function; |
101 | } |
102 | |
103 | static bool NeedsFieldInitializer(ParseNode* member, bool inStaticContext) { |
104 | // For the purposes of bytecode emission, StaticClassBlocks are treated as if |
105 | // they were static initializers. |
106 | return (member->is<StaticClassBlock>() && inStaticContext) || |
107 | (member->is<ClassField>() && |
108 | member->as<ClassField>().isStatic() == inStaticContext); |
109 | } |
110 | |
111 | static bool NeedsAccessorInitializer(ParseNode* member, bool isStatic) { |
112 | if (isStatic) { |
113 | return false; |
114 | } |
115 | return member->is<ClassMethod>() && |
116 | member->as<ClassMethod>().name().isKind(ParseNodeKind::PrivateName) && |
117 | !member->as<ClassMethod>().isStatic() && |
118 | member->as<ClassMethod>().accessorType() != AccessorType::None; |
119 | } |
120 | |
121 | static bool ShouldSuppressBreakpointsAndSourceNotes( |
122 | SharedContext* sc, BytecodeEmitter::EmitterMode emitterMode) { |
123 | // Suppress for all self-hosting code. |
124 | if (emitterMode == BytecodeEmitter::EmitterMode::SelfHosting) { |
125 | return true; |
126 | } |
127 | |
128 | // Suppress for synthesized class constructors. |
129 | if (sc->isFunctionBox()) { |
130 | FunctionBox* funbox = sc->asFunctionBox(); |
131 | return funbox->isSyntheticFunction() && funbox->isClassConstructor(); |
132 | } |
133 | |
134 | return false; |
135 | } |
136 | |
137 | BytecodeEmitter::BytecodeEmitter(BytecodeEmitter* parent, FrontendContext* fc, |
138 | SharedContext* sc, |
139 | const ErrorReporter& errorReporter, |
140 | CompilationState& compilationState, |
141 | EmitterMode emitterMode) |
142 | : sc(sc), |
143 | fc(fc), |
144 | parent(parent), |
145 | bytecodeSection_(fc, sc->extent().lineno, |
146 | JS::LimitedColumnNumberOneOrigin(sc->extent().column)), |
147 | perScriptData_(fc, compilationState), |
148 | errorReporter_(errorReporter), |
149 | compilationState(compilationState), |
150 | suppressBreakpointsAndSourceNotes( |
151 | ShouldSuppressBreakpointsAndSourceNotes(sc, emitterMode)), |
152 | emitterMode(emitterMode) { |
153 | MOZ_ASSERT_IF(parent, fc == parent->fc)do { if (parent) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(fc == parent->fc)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(fc == parent->fc))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("fc == parent->fc" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 153); AnnotateMozCrashReason("MOZ_ASSERT" "(" "fc == parent->fc" ")"); do { *((volatile int*)__null) = 153; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
154 | } |
155 | |
156 | BytecodeEmitter::BytecodeEmitter(BytecodeEmitter* parent, SharedContext* sc) |
157 | : BytecodeEmitter(parent, parent->fc, sc, parent->errorReporter_, |
158 | parent->compilationState, parent->emitterMode) {} |
159 | |
160 | BytecodeEmitter::BytecodeEmitter(FrontendContext* fc, |
161 | const EitherParser& parser, SharedContext* sc, |
162 | CompilationState& compilationState, |
163 | EmitterMode emitterMode) |
164 | : BytecodeEmitter(nullptr, fc, sc, parser.errorReporter(), compilationState, |
165 | emitterMode) { |
166 | ep_.emplace(parser); |
167 | } |
168 | |
169 | void BytecodeEmitter::initFromBodyPosition(TokenPos bodyPosition) { |
170 | setScriptStartOffsetIfUnset(bodyPosition.begin); |
171 | setFunctionBodyEndPos(bodyPosition.end); |
172 | } |
173 | |
174 | bool BytecodeEmitter::init() { |
175 | if (!parent) { |
176 | if (!compilationState.prepareSharedDataStorage(fc)) { |
177 | return false; |
178 | } |
179 | } |
180 | return perScriptData_.init(fc); |
181 | } |
182 | |
183 | bool BytecodeEmitter::init(TokenPos bodyPosition) { |
184 | initFromBodyPosition(bodyPosition); |
185 | return init(); |
186 | } |
187 | |
188 | template <typename T> |
189 | T* BytecodeEmitter::findInnermostNestableControl() const { |
190 | return NestableControl::findNearest<T>(innermostNestableControl); |
191 | } |
192 | |
193 | template <typename T, typename Predicate /* (T*) -> bool */> |
194 | T* BytecodeEmitter::findInnermostNestableControl(Predicate predicate) const { |
195 | return NestableControl::findNearest<T>(innermostNestableControl, predicate); |
196 | } |
197 | |
198 | NameLocation BytecodeEmitter::lookupName(TaggedParserAtomIndex name) { |
199 | return innermostEmitterScope()->lookup(this, name); |
200 | } |
201 | |
202 | void BytecodeEmitter::lookupPrivate(TaggedParserAtomIndex name, |
203 | NameLocation& loc, |
204 | Maybe<NameLocation>& brandLoc) { |
205 | innermostEmitterScope()->lookupPrivate(this, name, loc, brandLoc); |
206 | } |
207 | |
208 | Maybe<NameLocation> BytecodeEmitter::locationOfNameBoundInScope( |
209 | TaggedParserAtomIndex name, EmitterScope* target) { |
210 | return innermostEmitterScope()->locationBoundInScope(name, target); |
211 | } |
212 | |
213 | template <typename T> |
214 | Maybe<NameLocation> BytecodeEmitter::locationOfNameBoundInScopeType( |
215 | TaggedParserAtomIndex name, EmitterScope* source) { |
216 | EmitterScope* aScope = source; |
217 | while (!aScope->scope(this).is<T>()) { |
218 | aScope = aScope->enclosingInFrame(); |
219 | } |
220 | return source->locationBoundInScope(name, aScope); |
221 | } |
222 | |
223 | bool BytecodeEmitter::markStepBreakpoint() { |
224 | if (skipBreakpointSrcNotes()) { |
225 | return true; |
226 | } |
227 | |
228 | if (!newSrcNote(SrcNoteType::BreakpointStepSep)) { |
229 | return false; |
230 | } |
231 | |
232 | // We track the location of the most recent separator for use in |
233 | // markSimpleBreakpoint. Note that this means that the position must already |
234 | // be set before markStepBreakpoint is called. |
235 | bytecodeSection().updateSeparatorPosition(); |
236 | |
237 | return true; |
238 | } |
239 | |
240 | bool BytecodeEmitter::markSimpleBreakpoint() { |
241 | if (skipBreakpointSrcNotes()) { |
242 | return true; |
243 | } |
244 | |
245 | // If a breakable call ends up being the same location as the most recent |
246 | // expression start, we need to skip marking it breakable in order to avoid |
247 | // having two breakpoints with the same line/column position. |
248 | // Note: This assumes that the position for the call has already been set. |
249 | if (!bytecodeSection().isDuplicateLocation()) { |
250 | if (!newSrcNote(SrcNoteType::Breakpoint)) { |
251 | return false; |
252 | } |
253 | } |
254 | |
255 | return true; |
256 | } |
257 | |
258 | bool BytecodeEmitter::emitCheck(JSOp op, ptrdiff_t delta, |
259 | BytecodeOffset* offset) { |
260 | size_t oldLength = bytecodeSection().code().length(); |
261 | *offset = BytecodeOffset(oldLength); |
262 | |
263 | size_t newLength = oldLength + size_t(delta); |
264 | if (MOZ_UNLIKELY(newLength > MaxBytecodeLength)(__builtin_expect(!!(newLength > MaxBytecodeLength), 0))) { |
265 | ReportAllocationOverflow(fc); |
266 | return false; |
267 | } |
268 | |
269 | if (!bytecodeSection().code().growByUninitialized(delta)) { |
270 | return false; |
271 | } |
272 | |
273 | if (BytecodeOpHasIC(op)) { |
274 | // Even if every bytecode op is a JOF_IC op and the function has ARGC_LIMIT |
275 | // arguments, numICEntries cannot overflow. |
276 | static_assert(MaxBytecodeLength + 1 /* this */ + ARGC_LIMIT <= UINT32_MAX(4294967295U), |
277 | "numICEntries must not overflow"); |
278 | bytecodeSection().incrementNumICEntries(); |
279 | } |
280 | |
281 | return true; |
282 | } |
283 | |
284 | #ifdef DEBUG1 |
285 | bool BytecodeEmitter::checkStrictOrSloppy(JSOp op) { |
286 | if (IsCheckStrictOp(op) && !sc->strict()) { |
287 | return false; |
288 | } |
289 | if (IsCheckSloppyOp(op) && sc->strict()) { |
290 | return false; |
291 | } |
292 | return true; |
293 | } |
294 | #endif |
295 | |
296 | bool BytecodeEmitter::emit1(JSOp op) { |
297 | MOZ_ASSERT(checkStrictOrSloppy(op))do { static_assert( mozilla::detail::AssertionConditionType< decltype(checkStrictOrSloppy(op))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(checkStrictOrSloppy(op)))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("checkStrictOrSloppy(op)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 297); AnnotateMozCrashReason("MOZ_ASSERT" "(" "checkStrictOrSloppy(op)" ")"); do { *((volatile int*)__null) = 297; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
298 | |
299 | BytecodeOffset offset; |
300 | if (!emitCheck(op, 1, &offset)) { |
301 | return false; |
302 | } |
303 | |
304 | jsbytecode* code = bytecodeSection().code(offset); |
305 | code[0] = jsbytecode(op); |
306 | bytecodeSection().updateDepth(op, offset); |
307 | return true; |
308 | } |
309 | |
310 | bool BytecodeEmitter::emit2(JSOp op, uint8_t op1) { |
311 | MOZ_ASSERT(checkStrictOrSloppy(op))do { static_assert( mozilla::detail::AssertionConditionType< decltype(checkStrictOrSloppy(op))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(checkStrictOrSloppy(op)))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("checkStrictOrSloppy(op)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 311); AnnotateMozCrashReason("MOZ_ASSERT" "(" "checkStrictOrSloppy(op)" ")"); do { *((volatile int*)__null) = 311; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
312 | |
313 | BytecodeOffset offset; |
314 | if (!emitCheck(op, 2, &offset)) { |
315 | return false; |
316 | } |
317 | |
318 | jsbytecode* code = bytecodeSection().code(offset); |
319 | code[0] = jsbytecode(op); |
320 | code[1] = jsbytecode(op1); |
321 | bytecodeSection().updateDepth(op, offset); |
322 | return true; |
323 | } |
324 | |
325 | bool BytecodeEmitter::emit3(JSOp op, jsbytecode op1, jsbytecode op2) { |
326 | MOZ_ASSERT(checkStrictOrSloppy(op))do { static_assert( mozilla::detail::AssertionConditionType< decltype(checkStrictOrSloppy(op))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(checkStrictOrSloppy(op)))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("checkStrictOrSloppy(op)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 326); AnnotateMozCrashReason("MOZ_ASSERT" "(" "checkStrictOrSloppy(op)" ")"); do { *((volatile int*)__null) = 326; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
327 | |
328 | /* These should filter through emitVarOp. */ |
329 | MOZ_ASSERT(!IsArgOp(op))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!IsArgOp(op))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!IsArgOp(op)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!IsArgOp(op)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 329); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsArgOp(op)" ")"); do { *((volatile int*)__null) = 329; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
330 | MOZ_ASSERT(!IsLocalOp(op))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!IsLocalOp(op))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!IsLocalOp(op)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!IsLocalOp(op)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 330); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsLocalOp(op)" ")"); do { *((volatile int*)__null) = 330; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
331 | |
332 | BytecodeOffset offset; |
333 | if (!emitCheck(op, 3, &offset)) { |
334 | return false; |
335 | } |
336 | |
337 | jsbytecode* code = bytecodeSection().code(offset); |
338 | code[0] = jsbytecode(op); |
339 | code[1] = op1; |
340 | code[2] = op2; |
341 | bytecodeSection().updateDepth(op, offset); |
342 | return true; |
343 | } |
344 | |
345 | bool BytecodeEmitter::emitN(JSOp op, size_t extra, BytecodeOffset* offset) { |
346 | MOZ_ASSERT(checkStrictOrSloppy(op))do { static_assert( mozilla::detail::AssertionConditionType< decltype(checkStrictOrSloppy(op))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(checkStrictOrSloppy(op)))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("checkStrictOrSloppy(op)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 346); AnnotateMozCrashReason("MOZ_ASSERT" "(" "checkStrictOrSloppy(op)" ")"); do { *((volatile int*)__null) = 346; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
347 | ptrdiff_t length = 1 + ptrdiff_t(extra); |
348 | |
349 | BytecodeOffset off; |
350 | if (!emitCheck(op, length, &off)) { |
351 | return false; |
352 | } |
353 | |
354 | jsbytecode* code = bytecodeSection().code(off); |
355 | code[0] = jsbytecode(op); |
356 | /* The remaining |extra| bytes are set by the caller */ |
357 | |
358 | /* |
359 | * Don't updateDepth if op's use-count comes from the immediate |
360 | * operand yet to be stored in the extra bytes after op. |
361 | */ |
362 | if (CodeSpec(op).nuses >= 0) { |
363 | bytecodeSection().updateDepth(op, off); |
364 | } |
365 | |
366 | if (offset) { |
367 | *offset = off; |
368 | } |
369 | return true; |
370 | } |
371 | |
372 | bool BytecodeEmitter::emitJumpTargetOp(JSOp op, BytecodeOffset* off) { |
373 | MOZ_ASSERT(BytecodeIsJumpTarget(op))do { static_assert( mozilla::detail::AssertionConditionType< decltype(BytecodeIsJumpTarget(op))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(BytecodeIsJumpTarget(op)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("BytecodeIsJumpTarget(op)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 373); AnnotateMozCrashReason("MOZ_ASSERT" "(" "BytecodeIsJumpTarget(op)" ")"); do { *((volatile int*)__null) = 373; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
374 | |
375 | // Record the current IC-entry index at start of this op. |
376 | uint32_t numEntries = bytecodeSection().numICEntries(); |
377 | |
378 | size_t n = GetOpLength(op) - 1; |
379 | MOZ_ASSERT(GetOpLength(op) >= 1 + ICINDEX_LEN)do { static_assert( mozilla::detail::AssertionConditionType< decltype(GetOpLength(op) >= 1 + ICINDEX_LEN)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(! !(GetOpLength(op) >= 1 + ICINDEX_LEN))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("GetOpLength(op) >= 1 + ICINDEX_LEN" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 379); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetOpLength(op) >= 1 + ICINDEX_LEN" ")"); do { *((volatile int*)__null) = 379; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
380 | |
381 | if (!emitN(op, n, off)) { |
382 | return false; |
383 | } |
384 | |
385 | SET_ICINDEX(bytecodeSection().code(*off), numEntries); |
386 | return true; |
387 | } |
388 | |
389 | bool BytecodeEmitter::emitJumpTarget(JumpTarget* target) { |
390 | BytecodeOffset off = bytecodeSection().offset(); |
391 | |
392 | // Alias consecutive jump targets. |
393 | if (bytecodeSection().lastTargetOffset().valid() && |
394 | off == bytecodeSection().lastTargetOffset() + |
395 | BytecodeOffsetDiff(JSOpLength_JumpTarget)) { |
396 | target->offset = bytecodeSection().lastTargetOffset(); |
397 | return true; |
398 | } |
399 | |
400 | target->offset = off; |
401 | bytecodeSection().setLastTargetOffset(off); |
402 | |
403 | BytecodeOffset opOff; |
404 | return emitJumpTargetOp(JSOp::JumpTarget, &opOff); |
405 | } |
406 | |
407 | bool BytecodeEmitter::emitJumpNoFallthrough(JSOp op, JumpList* jump) { |
408 | BytecodeOffset offset; |
409 | if (!emitCheck(op, 5, &offset)) { |
410 | return false; |
411 | } |
412 | |
413 | jsbytecode* code = bytecodeSection().code(offset); |
414 | code[0] = jsbytecode(op); |
415 | MOZ_ASSERT(!jump->offset.valid() ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(!jump->offset.valid() || (0 <= jump->offset .value() && jump->offset < offset))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(!jump->offset.valid() || (0 <= jump->offset.value () && jump->offset < offset)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!jump->offset.valid() || (0 <= jump->offset.value() && jump->offset < offset)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 416); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!jump->offset.valid() || (0 <= jump->offset.value() && jump->offset < offset)" ")"); do { *((volatile int*)__null) = 416; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
416 | (0 <= jump->offset.value() && jump->offset < offset))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!jump->offset.valid() || (0 <= jump->offset .value() && jump->offset < offset))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(!jump->offset.valid() || (0 <= jump->offset.value () && jump->offset < offset)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!jump->offset.valid() || (0 <= jump->offset.value() && jump->offset < offset)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 416); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!jump->offset.valid() || (0 <= jump->offset.value() && jump->offset < offset)" ")"); do { *((volatile int*)__null) = 416; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
417 | jump->push(bytecodeSection().code(BytecodeOffset(0)), offset); |
418 | bytecodeSection().updateDepth(op, offset); |
419 | return true; |
420 | } |
421 | |
422 | bool BytecodeEmitter::emitJump(JSOp op, JumpList* jump) { |
423 | if (!emitJumpNoFallthrough(op, jump)) { |
424 | return false; |
425 | } |
426 | if (BytecodeFallsThrough(op)) { |
427 | JumpTarget fallthrough; |
428 | if (!emitJumpTarget(&fallthrough)) { |
429 | return false; |
430 | } |
431 | } |
432 | return true; |
433 | } |
434 | |
435 | void BytecodeEmitter::patchJumpsToTarget(JumpList jump, JumpTarget target) { |
436 | MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType< decltype(!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset()))> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset())))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset())" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 438); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset())" ")"); do { *((volatile int*)__null) = 438; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
437 | !jump.offset.valid() ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset()))> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset())))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset())" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 438); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset())" ")"); do { *((volatile int*)__null) = 438; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
438 | (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset()))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset()))> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset())))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset())" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 438); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!jump.offset.valid() || (0 <= jump.offset.value() && jump.offset <= bytecodeSection().offset())" ")"); do { *((volatile int*)__null) = 438; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
439 | MOZ_ASSERT(0 <= target.offset.value() &&do { static_assert( mozilla::detail::AssertionConditionType< decltype(0 <= target.offset.value() && target.offset <= bytecodeSection().offset())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(0 <= target.offset.value( ) && target.offset <= bytecodeSection().offset())) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("0 <= target.offset.value() && target.offset <= bytecodeSection().offset()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 440); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0 <= target.offset.value() && target.offset <= bytecodeSection().offset()" ")"); do { *((volatile int*)__null) = 440; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
440 | target.offset <= bytecodeSection().offset())do { static_assert( mozilla::detail::AssertionConditionType< decltype(0 <= target.offset.value() && target.offset <= bytecodeSection().offset())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(0 <= target.offset.value( ) && target.offset <= bytecodeSection().offset())) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("0 <= target.offset.value() && target.offset <= bytecodeSection().offset()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 440); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0 <= target.offset.value() && target.offset <= bytecodeSection().offset()" ")"); do { *((volatile int*)__null) = 440; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
441 | MOZ_ASSERT_IF(do { if (jump.offset.valid() && target.offset + BytecodeOffsetDiff (4) <= bytecodeSection().offset()) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(BytecodeIsJumpTarget (JSOp(*bytecodeSection().code(target.offset))))>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(! !(BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset )))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 444); AnnotateMozCrashReason("MOZ_ASSERT" "(" "BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))" ")"); do { *((volatile int*)__null) = 444; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
442 | jump.offset.valid() &&do { if (jump.offset.valid() && target.offset + BytecodeOffsetDiff (4) <= bytecodeSection().offset()) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(BytecodeIsJumpTarget (JSOp(*bytecodeSection().code(target.offset))))>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(! !(BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset )))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 444); AnnotateMozCrashReason("MOZ_ASSERT" "(" "BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))" ")"); do { *((volatile int*)__null) = 444; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
443 | target.offset + BytecodeOffsetDiff(4) <= bytecodeSection().offset(),do { if (jump.offset.valid() && target.offset + BytecodeOffsetDiff (4) <= bytecodeSection().offset()) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(BytecodeIsJumpTarget (JSOp(*bytecodeSection().code(target.offset))))>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(! !(BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset )))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 444); AnnotateMozCrashReason("MOZ_ASSERT" "(" "BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))" ")"); do { *((volatile int*)__null) = 444; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
444 | BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset))))do { if (jump.offset.valid() && target.offset + BytecodeOffsetDiff (4) <= bytecodeSection().offset()) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(BytecodeIsJumpTarget (JSOp(*bytecodeSection().code(target.offset))))>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(! !(BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset )))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 444); AnnotateMozCrashReason("MOZ_ASSERT" "(" "BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset)))" ")"); do { *((volatile int*)__null) = 444; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
445 | jump.patchAll(bytecodeSection().code(BytecodeOffset(0)), target); |
446 | } |
447 | |
448 | bool BytecodeEmitter::emitJumpTargetAndPatch(JumpList jump) { |
449 | if (!jump.offset.valid()) { |
450 | return true; |
451 | } |
452 | JumpTarget target; |
453 | if (!emitJumpTarget(&target)) { |
454 | return false; |
455 | } |
456 | patchJumpsToTarget(jump, target); |
457 | return true; |
458 | } |
459 | |
460 | bool BytecodeEmitter::emitCall(JSOp op, uint16_t argc, |
461 | const Maybe<uint32_t>& sourceCoordOffset) { |
462 | if (sourceCoordOffset.isSome()) { |
463 | if (!updateSourceCoordNotes(*sourceCoordOffset)) { |
464 | return false; |
465 | } |
466 | } |
467 | return emit3(op, ARGC_LO(argc), ARGC_HI(argc)); |
468 | } |
469 | |
470 | bool BytecodeEmitter::emitCall(JSOp op, uint16_t argc, ParseNode* pn) { |
471 | return emitCall(op, argc, pn ? Some(pn->pn_pos.begin) : Nothing()); |
472 | } |
473 | |
474 | bool BytecodeEmitter::emitDupAt(unsigned slotFromTop, unsigned count) { |
475 | MOZ_ASSERT(slotFromTop < unsigned(bytecodeSection().stackDepth()))do { static_assert( mozilla::detail::AssertionConditionType< decltype(slotFromTop < unsigned(bytecodeSection().stackDepth ()))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(slotFromTop < unsigned(bytecodeSection().stackDepth ())))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("slotFromTop < unsigned(bytecodeSection().stackDepth())", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 475); AnnotateMozCrashReason("MOZ_ASSERT" "(" "slotFromTop < unsigned(bytecodeSection().stackDepth())" ")"); do { *((volatile int*)__null) = 475; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
476 | MOZ_ASSERT(slotFromTop + 1 >= count)do { static_assert( mozilla::detail::AssertionConditionType< decltype(slotFromTop + 1 >= count)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(slotFromTop + 1 >= count) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("slotFromTop + 1 >= count" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 476); AnnotateMozCrashReason("MOZ_ASSERT" "(" "slotFromTop + 1 >= count" ")"); do { *((volatile int*)__null) = 476; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
477 | |
478 | if (slotFromTop == 0 && count == 1) { |
479 | return emit1(JSOp::Dup); |
480 | } |
481 | |
482 | if (slotFromTop == 1 && count == 2) { |
483 | return emit1(JSOp::Dup2); |
484 | } |
485 | |
486 | if (slotFromTop >= Bit(24)) { |
487 | reportError(nullptr, JSMSG_TOO_MANY_LOCALS); |
488 | return false; |
489 | } |
490 | |
491 | for (unsigned i = 0; i < count; i++) { |
492 | BytecodeOffset off; |
493 | if (!emitN(JSOp::DupAt, 3, &off)) { |
494 | return false; |
495 | } |
496 | |
497 | jsbytecode* pc = bytecodeSection().code(off); |
498 | SET_UINT24(pc, slotFromTop); |
499 | } |
500 | |
501 | return true; |
502 | } |
503 | |
504 | bool BytecodeEmitter::emitPopN(unsigned n) { |
505 | MOZ_ASSERT(n != 0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(n != 0)>::isValid, "invalid assertion condition") ; if ((__builtin_expect(!!(!(!!(n != 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("n != 0", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 505); AnnotateMozCrashReason("MOZ_ASSERT" "(" "n != 0" ")") ; do { *((volatile int*)__null) = 505; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
506 | |
507 | if (n == 1) { |
508 | return emit1(JSOp::Pop); |
509 | } |
510 | |
511 | // 2 JSOp::Pop instructions (2 bytes) are shorter than JSOp::PopN (3 bytes). |
512 | if (n == 2) { |
513 | return emit1(JSOp::Pop) && emit1(JSOp::Pop); |
514 | } |
515 | |
516 | return emitUint16Operand(JSOp::PopN, n); |
517 | } |
518 | |
519 | bool BytecodeEmitter::emitPickN(uint8_t n) { |
520 | MOZ_ASSERT(n != 0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(n != 0)>::isValid, "invalid assertion condition") ; if ((__builtin_expect(!!(!(!!(n != 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("n != 0", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 520); AnnotateMozCrashReason("MOZ_ASSERT" "(" "n != 0" ")") ; do { *((volatile int*)__null) = 520; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
521 | |
522 | if (n == 1) { |
523 | return emit1(JSOp::Swap); |
524 | } |
525 | |
526 | return emit2(JSOp::Pick, n); |
527 | } |
528 | |
529 | bool BytecodeEmitter::emitUnpickN(uint8_t n) { |
530 | MOZ_ASSERT(n != 0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(n != 0)>::isValid, "invalid assertion condition") ; if ((__builtin_expect(!!(!(!!(n != 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("n != 0", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 530); AnnotateMozCrashReason("MOZ_ASSERT" "(" "n != 0" ")") ; do { *((volatile int*)__null) = 530; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
531 | |
532 | if (n == 1) { |
533 | return emit1(JSOp::Swap); |
534 | } |
535 | |
536 | return emit2(JSOp::Unpick, n); |
537 | } |
538 | |
539 | bool BytecodeEmitter::emitCheckIsObj(CheckIsObjectKind kind) { |
540 | return emit2(JSOp::CheckIsObj, uint8_t(kind)); |
541 | } |
542 | |
543 | bool BytecodeEmitter::emitBuiltinObject(BuiltinObjectKind kind) { |
544 | return emit2(JSOp::BuiltinObject, uint8_t(kind)); |
545 | } |
546 | |
547 | /* Updates line number notes, not column notes. */ |
548 | bool BytecodeEmitter::updateLineNumberNotes(uint32_t offset) { |
549 | if (skipLocationSrcNotes()) { |
550 | return true; |
551 | } |
552 | |
553 | const ErrorReporter& er = errorReporter(); |
554 | std::optional<bool> onThisLineStatus = |
555 | er.isOnThisLine(offset, bytecodeSection().currentLine()); |
556 | if (!onThisLineStatus.has_value()) { |
557 | er.errorNoOffset(JSMSG_OUT_OF_MEMORY); |
558 | return false; |
559 | } |
560 | |
561 | bool onThisLine = *onThisLineStatus; |
562 | |
563 | if (!onThisLine) { |
564 | unsigned line = er.lineAt(offset); |
565 | unsigned delta = line - bytecodeSection().currentLine(); |
566 | |
567 | // If we use a `SetLine` note below, we want it to be relative to the |
568 | // scripts initial line number for better chance of sharing. |
569 | unsigned initialLine = sc->extent().lineno; |
570 | MOZ_ASSERT(line >= initialLine)do { static_assert( mozilla::detail::AssertionConditionType< decltype(line >= initialLine)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(line >= initialLine))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("line >= initialLine" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 570); AnnotateMozCrashReason("MOZ_ASSERT" "(" "line >= initialLine" ")"); do { *((volatile int*)__null) = 570; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
571 | |
572 | /* |
573 | * Encode any change in the current source line number by using |
574 | * either several SrcNoteType::NewLine notes or just one |
575 | * SrcNoteType::SetLine note, whichever consumes less space. |
576 | * |
577 | * NB: We handle backward line number deltas (possible with for |
578 | * loops where the update part is emitted after the body, but its |
579 | * line number is <= any line number in the body) here by letting |
580 | * unsigned delta_ wrap to a very large number, which triggers a |
581 | * SrcNoteType::SetLine. |
582 | */ |
583 | bytecodeSection().setCurrentLine(line, offset); |
584 | if (delta >= SrcNote::SetLine::lengthFor(line, initialLine)) { |
585 | if (!newSrcNote2(SrcNoteType::SetLine, |
586 | SrcNote::SetLine::toOperand(line, initialLine))) { |
587 | return false; |
588 | } |
589 | } else { |
590 | do { |
591 | if (!newSrcNote(SrcNoteType::NewLine)) { |
592 | return false; |
593 | } |
594 | } while (--delta != 0); |
595 | } |
596 | |
597 | bytecodeSection().updateSeparatorPositionIfPresent(); |
598 | } |
599 | return true; |
600 | } |
601 | |
602 | /* Updates the line number and column number information in the source notes. */ |
603 | bool BytecodeEmitter::updateSourceCoordNotes(uint32_t offset) { |
604 | if (skipLocationSrcNotes()) { |
605 | return true; |
606 | } |
607 | |
608 | if (!updateLineNumberNotes(offset)) { |
609 | return false; |
610 | } |
611 | |
612 | JS::LimitedColumnNumberOneOrigin columnIndex = |
613 | errorReporter().columnAt(offset); |
614 | |
615 | // Assert colspan is always representable. |
616 | static_assert((0 - ptrdiff_t(JS::LimitedColumnNumberOneOrigin::Limit)) >= |
617 | SrcNote::ColSpan::MinColSpan); |
618 | static_assert((ptrdiff_t(JS::LimitedColumnNumberOneOrigin::Limit) - 0) <= |
619 | SrcNote::ColSpan::MaxColSpan); |
620 | |
621 | JS::ColumnNumberOffset colspan = columnIndex - bytecodeSection().lastColumn(); |
622 | |
623 | if (colspan != JS::ColumnNumberOffset::zero()) { |
624 | if (lastLineOnlySrcNoteIndex != LastSrcNoteIsNotLineOnly) { |
625 | MOZ_ASSERT(bytecodeSection().lastColumn() ==do { static_assert( mozilla::detail::AssertionConditionType< decltype(bytecodeSection().lastColumn() == JS::LimitedColumnNumberOneOrigin ())>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(bytecodeSection().lastColumn() == JS::LimitedColumnNumberOneOrigin ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("bytecodeSection().lastColumn() == JS::LimitedColumnNumberOneOrigin()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 626); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().lastColumn() == JS::LimitedColumnNumberOneOrigin()" ")"); do { *((volatile int*)__null) = 626; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
626 | JS::LimitedColumnNumberOneOrigin())do { static_assert( mozilla::detail::AssertionConditionType< decltype(bytecodeSection().lastColumn() == JS::LimitedColumnNumberOneOrigin ())>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(bytecodeSection().lastColumn() == JS::LimitedColumnNumberOneOrigin ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("bytecodeSection().lastColumn() == JS::LimitedColumnNumberOneOrigin()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 626); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().lastColumn() == JS::LimitedColumnNumberOneOrigin()" ")"); do { *((volatile int*)__null) = 626; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
627 | |
628 | const SrcNotesVector& notes = bytecodeSection().notes(); |
629 | SrcNoteType type = notes[lastLineOnlySrcNoteIndex].type(); |
630 | if (type == SrcNoteType::NewLine) { |
631 | if (!convertLastNewLineToNewLineColumn(columnIndex)) { |
632 | return false; |
633 | } |
634 | } else { |
635 | MOZ_ASSERT(type == SrcNoteType::SetLine)do { static_assert( mozilla::detail::AssertionConditionType< decltype(type == SrcNoteType::SetLine)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(type == SrcNoteType::SetLine ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "type == SrcNoteType::SetLine", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 635); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == SrcNoteType::SetLine" ")"); do { *((volatile int*)__null) = 635; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
636 | if (!convertLastSetLineToSetLineColumn(columnIndex)) { |
637 | return false; |
638 | } |
639 | } |
640 | } else { |
641 | if (!newSrcNote2(SrcNoteType::ColSpan, |
642 | SrcNote::ColSpan::toOperand(colspan))) { |
643 | return false; |
644 | } |
645 | } |
646 | bytecodeSection().setLastColumn(columnIndex, offset); |
647 | bytecodeSection().updateSeparatorPositionIfPresent(); |
648 | } |
649 | return true; |
650 | } |
651 | |
652 | bool BytecodeEmitter::updateSourceCoordNotesIfNonLiteral(ParseNode* node) { |
653 | if (node->isLiteral()) { |
654 | return true; |
655 | } |
656 | return updateSourceCoordNotes(node->pn_pos.begin); |
657 | } |
658 | |
659 | uint32_t BytecodeEmitter::getOffsetForLoop(ParseNode* nextpn) { |
660 | // Try to give the JSOp::LoopHead the same line number as the next |
661 | // instruction. nextpn is often a block, in which case the next instruction |
662 | // typically comes from the first statement inside. |
663 | if (nextpn->is<LexicalScopeNode>()) { |
664 | nextpn = nextpn->as<LexicalScopeNode>().scopeBody(); |
665 | } |
666 | if (nextpn->isKind(ParseNodeKind::StatementList)) { |
667 | if (ParseNode* firstStatement = nextpn->as<ListNode>().head()) { |
668 | nextpn = firstStatement; |
669 | } |
670 | } |
671 | |
672 | return nextpn->pn_pos.begin; |
673 | } |
674 | |
675 | bool BytecodeEmitter::emitUint16Operand(JSOp op, uint32_t operand) { |
676 | MOZ_ASSERT(operand <= UINT16_MAX)do { static_assert( mozilla::detail::AssertionConditionType< decltype(operand <= (65535))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(operand <= (65535)))), 0) )) { do { } while (false); MOZ_ReportAssertionFailure("operand <= (65535)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 676); AnnotateMozCrashReason("MOZ_ASSERT" "(" "operand <= (65535)" ")"); do { *((volatile int*)__null) = 676; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
677 | if (!emit3(op, UINT16_LO(operand), UINT16_HI(operand))) { |
678 | return false; |
679 | } |
680 | return true; |
681 | } |
682 | |
683 | bool BytecodeEmitter::emitUint32Operand(JSOp op, uint32_t operand) { |
684 | BytecodeOffset off; |
685 | if (!emitN(op, 4, &off)) { |
686 | return false; |
687 | } |
688 | SET_UINT32(bytecodeSection().code(off), operand); |
689 | return true; |
690 | } |
691 | |
692 | bool BytecodeEmitter::emitGoto(NestableControl* target, GotoKind kind) { |
693 | NonLocalExitControl nle(this, kind == GotoKind::Continue |
694 | ? NonLocalExitKind::Continue |
695 | : NonLocalExitKind::Break); |
696 | return nle.emitNonLocalJump(target); |
697 | } |
698 | |
699 | AbstractScopePtr BytecodeEmitter::innermostScope() const { |
700 | return innermostEmitterScope()->scope(this); |
701 | } |
702 | |
703 | ScopeIndex BytecodeEmitter::innermostScopeIndex() const { |
704 | return *innermostEmitterScope()->scopeIndex(this); |
705 | } |
706 | |
707 | bool BytecodeEmitter::emitGCIndexOp(JSOp op, GCThingIndex index) { |
708 | MOZ_ASSERT(checkStrictOrSloppy(op))do { static_assert( mozilla::detail::AssertionConditionType< decltype(checkStrictOrSloppy(op))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(checkStrictOrSloppy(op)))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("checkStrictOrSloppy(op)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 708); AnnotateMozCrashReason("MOZ_ASSERT" "(" "checkStrictOrSloppy(op)" ")"); do { *((volatile int*)__null) = 708; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
709 | |
710 | constexpr size_t OpLength = 1 + GCTHING_INDEX_LEN; |
711 | MOZ_ASSERT(GetOpLength(op) == OpLength)do { static_assert( mozilla::detail::AssertionConditionType< decltype(GetOpLength(op) == OpLength)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(GetOpLength(op) == OpLength) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("GetOpLength(op) == OpLength" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 711); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetOpLength(op) == OpLength" ")"); do { *((volatile int*)__null) = 711; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
712 | |
713 | BytecodeOffset offset; |
714 | if (!emitCheck(op, OpLength, &offset)) { |
715 | return false; |
716 | } |
717 | |
718 | jsbytecode* code = bytecodeSection().code(offset); |
719 | code[0] = jsbytecode(op); |
720 | SET_GCTHING_INDEX(code, index); |
721 | bytecodeSection().updateDepth(op, offset); |
722 | return true; |
723 | } |
724 | |
725 | bool BytecodeEmitter::emitAtomOp(JSOp op, TaggedParserAtomIndex atom) { |
726 | MOZ_ASSERT(atom)do { static_assert( mozilla::detail::AssertionConditionType< decltype(atom)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(atom))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("atom", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 726); AnnotateMozCrashReason("MOZ_ASSERT" "(" "atom" ")"); do { *((volatile int*)__null) = 726; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); |
727 | |
728 | // .generator lookups should be emitted as JSOp::GetAliasedVar instead of |
729 | // JSOp::GetName etc, to bypass |with| objects on the scope chain. |
730 | // It's safe to emit .this lookups though because |with| objects skip |
731 | // those. |
732 | MOZ_ASSERT_IF(op == JSOp::GetName || op == JSOp::GetGName,do { if (op == JSOp::GetName || op == JSOp::GetGName) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(atom != TaggedParserAtomIndex::WellKnown::dot_generator_())>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(atom != TaggedParserAtomIndex::WellKnown::dot_generator_() ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "atom != TaggedParserAtomIndex::WellKnown::dot_generator_()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 733); AnnotateMozCrashReason("MOZ_ASSERT" "(" "atom != TaggedParserAtomIndex::WellKnown::dot_generator_()" ")"); do { *((volatile int*)__null) = 733; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
733 | atom != TaggedParserAtomIndex::WellKnown::dot_generator_())do { if (op == JSOp::GetName || op == JSOp::GetGName) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(atom != TaggedParserAtomIndex::WellKnown::dot_generator_())>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(atom != TaggedParserAtomIndex::WellKnown::dot_generator_() ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "atom != TaggedParserAtomIndex::WellKnown::dot_generator_()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 733); AnnotateMozCrashReason("MOZ_ASSERT" "(" "atom != TaggedParserAtomIndex::WellKnown::dot_generator_()" ")"); do { *((volatile int*)__null) = 733; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
734 | |
735 | GCThingIndex index; |
736 | if (!makeAtomIndex(atom, ParserAtom::Atomize::Yes, &index)) { |
737 | return false; |
738 | } |
739 | |
740 | return emitAtomOp(op, index); |
741 | } |
742 | |
743 | bool BytecodeEmitter::emitAtomOp(JSOp op, GCThingIndex atomIndex) { |
744 | MOZ_ASSERT(JOF_OPTYPE(op) == JOF_ATOM)do { static_assert( mozilla::detail::AssertionConditionType< decltype(JOF_OPTYPE(op) == JOF_ATOM)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(JOF_OPTYPE(op) == JOF_ATOM)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("JOF_OPTYPE(op) == JOF_ATOM" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 744); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JOF_OPTYPE(op) == JOF_ATOM" ")"); do { *((volatile int*)__null) = 744; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
745 | #ifdef DEBUG1 |
746 | auto atom = perScriptData().gcThingList().getAtom(atomIndex); |
747 | MOZ_ASSERT(compilationState.parserAtoms.isInstantiatedAsJSAtom(atom))do { static_assert( mozilla::detail::AssertionConditionType< decltype(compilationState.parserAtoms.isInstantiatedAsJSAtom( atom))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(compilationState.parserAtoms.isInstantiatedAsJSAtom( atom)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("compilationState.parserAtoms.isInstantiatedAsJSAtom(atom)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 747); AnnotateMozCrashReason("MOZ_ASSERT" "(" "compilationState.parserAtoms.isInstantiatedAsJSAtom(atom)" ")"); do { *((volatile int*)__null) = 747; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
748 | #endif |
749 | return emitGCIndexOp(op, atomIndex); |
750 | } |
751 | |
752 | bool BytecodeEmitter::emitStringOp(JSOp op, TaggedParserAtomIndex atom) { |
753 | MOZ_ASSERT(atom)do { static_assert( mozilla::detail::AssertionConditionType< decltype(atom)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(atom))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("atom", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 753); AnnotateMozCrashReason("MOZ_ASSERT" "(" "atom" ")"); do { *((volatile int*)__null) = 753; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); |
754 | GCThingIndex index; |
755 | if (!makeAtomIndex(atom, ParserAtom::Atomize::No, &index)) { |
756 | return false; |
757 | } |
758 | |
759 | return emitStringOp(op, index); |
760 | } |
761 | |
762 | bool BytecodeEmitter::emitStringOp(JSOp op, GCThingIndex atomIndex) { |
763 | MOZ_ASSERT(JOF_OPTYPE(op) == JOF_STRING)do { static_assert( mozilla::detail::AssertionConditionType< decltype(JOF_OPTYPE(op) == JOF_STRING)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(JOF_OPTYPE(op) == JOF_STRING ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "JOF_OPTYPE(op) == JOF_STRING", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 763); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JOF_OPTYPE(op) == JOF_STRING" ")"); do { *((volatile int*)__null) = 763; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
764 | return emitGCIndexOp(op, atomIndex); |
765 | } |
766 | |
767 | bool BytecodeEmitter::emitInternedScopeOp(GCThingIndex index, JSOp op) { |
768 | MOZ_ASSERT(JOF_OPTYPE(op) == JOF_SCOPE)do { static_assert( mozilla::detail::AssertionConditionType< decltype(JOF_OPTYPE(op) == JOF_SCOPE)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(JOF_OPTYPE(op) == JOF_SCOPE) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("JOF_OPTYPE(op) == JOF_SCOPE" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 768); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JOF_OPTYPE(op) == JOF_SCOPE" ")"); do { *((volatile int*)__null) = 768; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
769 | MOZ_ASSERT(index < perScriptData().gcThingList().length())do { static_assert( mozilla::detail::AssertionConditionType< decltype(index < perScriptData().gcThingList().length())> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(index < perScriptData().gcThingList().length()))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("index < perScriptData().gcThingList().length()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 769); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index < perScriptData().gcThingList().length()" ")"); do { *((volatile int*)__null) = 769; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
770 | return emitGCIndexOp(op, index); |
771 | } |
772 | |
773 | bool BytecodeEmitter::emitInternedObjectOp(GCThingIndex index, JSOp op) { |
774 | MOZ_ASSERT(JOF_OPTYPE(op) == JOF_OBJECT)do { static_assert( mozilla::detail::AssertionConditionType< decltype(JOF_OPTYPE(op) == JOF_OBJECT)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(JOF_OPTYPE(op) == JOF_OBJECT ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "JOF_OPTYPE(op) == JOF_OBJECT", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 774); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JOF_OPTYPE(op) == JOF_OBJECT" ")"); do { *((volatile int*)__null) = 774; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
775 | MOZ_ASSERT(index < perScriptData().gcThingList().length())do { static_assert( mozilla::detail::AssertionConditionType< decltype(index < perScriptData().gcThingList().length())> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(index < perScriptData().gcThingList().length()))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("index < perScriptData().gcThingList().length()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 775); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index < perScriptData().gcThingList().length()" ")"); do { *((volatile int*)__null) = 775; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
776 | return emitGCIndexOp(op, index); |
777 | } |
778 | |
779 | bool BytecodeEmitter::emitRegExp(GCThingIndex index) { |
780 | return emitGCIndexOp(JSOp::RegExp, index); |
781 | } |
782 | |
783 | bool BytecodeEmitter::emitLocalOp(JSOp op, uint32_t slot) { |
784 | MOZ_ASSERT(JOF_OPTYPE(op) != JOF_ENVCOORD)do { static_assert( mozilla::detail::AssertionConditionType< decltype(JOF_OPTYPE(op) != JOF_ENVCOORD)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(JOF_OPTYPE(op) != JOF_ENVCOORD ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "JOF_OPTYPE(op) != JOF_ENVCOORD", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 784); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JOF_OPTYPE(op) != JOF_ENVCOORD" ")"); do { *((volatile int*)__null) = 784; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
785 | MOZ_ASSERT(IsLocalOp(op))do { static_assert( mozilla::detail::AssertionConditionType< decltype(IsLocalOp(op))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsLocalOp(op)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsLocalOp(op)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 785); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsLocalOp(op)" ")"); do { *((volatile int*)__null) = 785; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
786 | |
787 | BytecodeOffset off; |
788 | if (!emitN(op, LOCALNO_LEN, &off)) { |
789 | return false; |
790 | } |
791 | |
792 | SET_LOCALNO(bytecodeSection().code(off), slot); |
793 | return true; |
794 | } |
795 | |
796 | bool BytecodeEmitter::emitArgOp(JSOp op, uint16_t slot) { |
797 | MOZ_ASSERT(IsArgOp(op))do { static_assert( mozilla::detail::AssertionConditionType< decltype(IsArgOp(op))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsArgOp(op)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsArgOp(op)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 797); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsArgOp(op)" ")"); do { *((volatile int*)__null) = 797; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
798 | BytecodeOffset off; |
799 | if (!emitN(op, ARGNO_LEN, &off)) { |
800 | return false; |
801 | } |
802 | |
803 | SET_ARGNO(bytecodeSection().code(off), slot); |
804 | return true; |
805 | } |
806 | |
807 | bool BytecodeEmitter::emitEnvCoordOp(JSOp op, EnvironmentCoordinate ec) { |
808 | MOZ_ASSERT(JOF_OPTYPE(op) == JOF_ENVCOORD ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(JOF_OPTYPE(op) == JOF_ENVCOORD || JOF_OPTYPE(op) == JOF_DEBUGCOORD )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(JOF_OPTYPE(op) == JOF_ENVCOORD || JOF_OPTYPE(op) == JOF_DEBUGCOORD ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "JOF_OPTYPE(op) == JOF_ENVCOORD || JOF_OPTYPE(op) == JOF_DEBUGCOORD" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 809); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JOF_OPTYPE(op) == JOF_ENVCOORD || JOF_OPTYPE(op) == JOF_DEBUGCOORD" ")"); do { *((volatile int*)__null) = 809; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
809 | JOF_OPTYPE(op) == JOF_DEBUGCOORD)do { static_assert( mozilla::detail::AssertionConditionType< decltype(JOF_OPTYPE(op) == JOF_ENVCOORD || JOF_OPTYPE(op) == JOF_DEBUGCOORD )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(JOF_OPTYPE(op) == JOF_ENVCOORD || JOF_OPTYPE(op) == JOF_DEBUGCOORD ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "JOF_OPTYPE(op) == JOF_ENVCOORD || JOF_OPTYPE(op) == JOF_DEBUGCOORD" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 809); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JOF_OPTYPE(op) == JOF_ENVCOORD || JOF_OPTYPE(op) == JOF_DEBUGCOORD" ")"); do { *((volatile int*)__null) = 809; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
810 | |
811 | constexpr size_t N = ENVCOORD_HOPS_LEN + ENVCOORD_SLOT_LEN; |
812 | MOZ_ASSERT(GetOpLength(op) == 1 + N)do { static_assert( mozilla::detail::AssertionConditionType< decltype(GetOpLength(op) == 1 + N)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(GetOpLength(op) == 1 + N))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("GetOpLength(op) == 1 + N" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 812); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetOpLength(op) == 1 + N" ")"); do { *((volatile int*)__null) = 812; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
813 | |
814 | BytecodeOffset off; |
815 | if (!emitN(op, N, &off)) { |
816 | return false; |
817 | } |
818 | |
819 | jsbytecode* pc = bytecodeSection().code(off); |
820 | SET_ENVCOORD_HOPS(pc, ec.hops()); |
821 | pc += ENVCOORD_HOPS_LEN; |
822 | SET_ENVCOORD_SLOT(pc, ec.slot()); |
823 | pc += ENVCOORD_SLOT_LEN; |
Value stored to 'pc' is never read | |
824 | return true; |
825 | } |
826 | |
827 | JSOp BytecodeEmitter::strictifySetNameOp(JSOp op) { |
828 | switch (op) { |
829 | case JSOp::SetName: |
830 | if (sc->strict()) { |
831 | op = JSOp::StrictSetName; |
832 | } |
833 | break; |
834 | case JSOp::SetGName: |
835 | if (sc->strict()) { |
836 | op = JSOp::StrictSetGName; |
837 | } |
838 | break; |
839 | default:; |
840 | } |
841 | return op; |
842 | } |
843 | |
844 | bool BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer) { |
845 | AutoCheckRecursionLimit recursion(fc); |
846 | if (!recursion.check(fc)) { |
847 | return false; |
848 | } |
849 | |
850 | restart: |
851 | |
852 | switch (pn->getKind()) { |
853 | // Trivial cases with no side effects. |
854 | case ParseNodeKind::EmptyStmt: |
855 | case ParseNodeKind::TrueExpr: |
856 | case ParseNodeKind::FalseExpr: |
857 | case ParseNodeKind::NullExpr: |
858 | case ParseNodeKind::RawUndefinedExpr: |
859 | case ParseNodeKind::Elision: |
860 | case ParseNodeKind::Generator: |
861 | MOZ_ASSERT(pn->is<NullaryNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<NullaryNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<NullaryNode> ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("pn->is<NullaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 861); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<NullaryNode>()" ")"); do { *((volatile int*)__null) = 861; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
862 | *answer = false; |
863 | return true; |
864 | |
865 | case ParseNodeKind::ObjectPropertyName: |
866 | case ParseNodeKind::PrivateName: // no side effects, unlike |
867 | // ParseNodeKind::Name |
868 | case ParseNodeKind::StringExpr: |
869 | case ParseNodeKind::TemplateStringExpr: |
870 | MOZ_ASSERT(pn->is<NameNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<NameNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<NameNode>()) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("pn->is<NameNode>()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 870); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<NameNode>()" ")"); do { *((volatile int*)__null) = 870; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
871 | *answer = false; |
872 | return true; |
873 | |
874 | case ParseNodeKind::RegExpExpr: |
875 | MOZ_ASSERT(pn->is<RegExpLiteral>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<RegExpLiteral>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<RegExpLiteral> ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("pn->is<RegExpLiteral>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 875); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<RegExpLiteral>()" ")"); do { *((volatile int*)__null) = 875; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
876 | *answer = false; |
877 | return true; |
878 | |
879 | case ParseNodeKind::NumberExpr: |
880 | MOZ_ASSERT(pn->is<NumericLiteral>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<NumericLiteral>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<NumericLiteral> ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("pn->is<NumericLiteral>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 880); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<NumericLiteral>()" ")"); do { *((volatile int*)__null) = 880; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
881 | *answer = false; |
882 | return true; |
883 | |
884 | case ParseNodeKind::BigIntExpr: |
885 | MOZ_ASSERT(pn->is<BigIntLiteral>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<BigIntLiteral>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<BigIntLiteral> ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("pn->is<BigIntLiteral>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 885); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BigIntLiteral>()" ")"); do { *((volatile int*)__null) = 885; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
886 | *answer = false; |
887 | return true; |
888 | |
889 | // |this| can throw in derived class constructors, including nested arrow |
890 | // functions or eval. |
891 | case ParseNodeKind::ThisExpr: |
892 | MOZ_ASSERT(pn->is<UnaryNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<UnaryNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<UnaryNode>() ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "pn->is<UnaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 892); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()" ")"); do { *((volatile int*)__null) = 892; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
893 | *answer = sc->needsThisTDZChecks(); |
894 | return true; |
895 | |
896 | // |new.target| doesn't have any side-effects. |
897 | case ParseNodeKind::NewTargetExpr: { |
898 | MOZ_ASSERT(pn->is<NewTargetNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<NewTargetNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<NewTargetNode> ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("pn->is<NewTargetNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 898); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<NewTargetNode>()" ")"); do { *((volatile int*)__null) = 898; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
899 | *answer = false; |
900 | return true; |
901 | } |
902 | |
903 | // Trivial binary nodes with more token pos holders. |
904 | case ParseNodeKind::ImportMetaExpr: { |
905 | MOZ_ASSERT(pn->as<BinaryNode>().left()->isKind(ParseNodeKind::PosHolder))do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->as<BinaryNode>().left()->isKind(ParseNodeKind ::PosHolder))>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(pn->as<BinaryNode>().left ()->isKind(ParseNodeKind::PosHolder)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("pn->as<BinaryNode>().left()->isKind(ParseNodeKind::PosHolder)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 905); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->as<BinaryNode>().left()->isKind(ParseNodeKind::PosHolder)" ")"); do { *((volatile int*)__null) = 905; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
906 | MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->as<BinaryNode>().right()->isKind(ParseNodeKind ::PosHolder))>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(pn->as<BinaryNode>().right ()->isKind(ParseNodeKind::PosHolder)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("pn->as<BinaryNode>().right()->isKind(ParseNodeKind::PosHolder)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 907); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->as<BinaryNode>().right()->isKind(ParseNodeKind::PosHolder)" ")"); do { *((volatile int*)__null) = 907; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
907 | pn->as<BinaryNode>().right()->isKind(ParseNodeKind::PosHolder))do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->as<BinaryNode>().right()->isKind(ParseNodeKind ::PosHolder))>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(pn->as<BinaryNode>().right ()->isKind(ParseNodeKind::PosHolder)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("pn->as<BinaryNode>().right()->isKind(ParseNodeKind::PosHolder)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 907); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->as<BinaryNode>().right()->isKind(ParseNodeKind::PosHolder)" ")"); do { *((volatile int*)__null) = 907; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
908 | *answer = false; |
909 | return true; |
910 | } |
911 | |
912 | case ParseNodeKind::BreakStmt: |
913 | MOZ_ASSERT(pn->is<BreakStatement>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<BreakStatement>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<BreakStatement> ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("pn->is<BreakStatement>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 913); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BreakStatement>()" ")"); do { *((volatile int*)__null) = 913; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
914 | *answer = true; |
915 | return true; |
916 | |
917 | case ParseNodeKind::ContinueStmt: |
918 | MOZ_ASSERT(pn->is<ContinueStatement>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<ContinueStatement>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<ContinueStatement >()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("pn->is<ContinueStatement>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 918); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<ContinueStatement>()" ")"); do { *((volatile int*)__null) = 918; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
919 | *answer = true; |
920 | return true; |
921 | |
922 | case ParseNodeKind::DebuggerStmt: |
923 | MOZ_ASSERT(pn->is<DebuggerStatement>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<DebuggerStatement>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<DebuggerStatement >()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("pn->is<DebuggerStatement>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 923); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<DebuggerStatement>()" ")"); do { *((volatile int*)__null) = 923; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
924 | *answer = true; |
925 | return true; |
926 | |
927 | // Watch out for getters! |
928 | case ParseNodeKind::OptionalDotExpr: |
929 | case ParseNodeKind::DotExpr: |
930 | case ParseNodeKind::ArgumentsLength: |
931 | MOZ_ASSERT(pn->is<BinaryNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<BinaryNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<BinaryNode>( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("pn->is<BinaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 931); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()" ")"); do { *((volatile int*)__null) = 931; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
932 | *answer = true; |
933 | return true; |
934 | |
935 | // Unary cases with side effects only if the child has them. |
936 | case ParseNodeKind::TypeOfExpr: |
937 | case ParseNodeKind::VoidExpr: |
938 | case ParseNodeKind::NotExpr: |
939 | return checkSideEffects(pn->as<UnaryNode>().kid(), answer); |
940 | |
941 | // Even if the name expression is effect-free, performing ToPropertyKey on |
942 | // it might not be effect-free: |
943 | // |
944 | // RegExp.prototype.toString = () => { throw 42; }; |
945 | // ({ [/regex/]: 0 }); // ToPropertyKey(/regex/) throws 42 |
946 | // |
947 | // function Q() { |
948 | // ({ [new.target]: 0 }); |
949 | // } |
950 | // Q.toString = () => { throw 17; }; |
951 | // new Q; // new.target will be Q, ToPropertyKey(Q) throws 17 |
952 | case ParseNodeKind::ComputedName: |
953 | MOZ_ASSERT(pn->is<UnaryNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<UnaryNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<UnaryNode>() ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "pn->is<UnaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 953); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()" ")"); do { *((volatile int*)__null) = 953; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
954 | *answer = true; |
955 | return true; |
956 | |
957 | // Looking up or evaluating the associated name could throw. |
958 | case ParseNodeKind::TypeOfNameExpr: |
959 | MOZ_ASSERT(pn->is<UnaryNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<UnaryNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<UnaryNode>() ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "pn->is<UnaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 959); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()" ")"); do { *((volatile int*)__null) = 959; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
960 | *answer = true; |
961 | return true; |
962 | |
963 | // This unary case has side effects on the enclosing object, sure. But |
964 | // that's not the question this function answers: it's whether the |
965 | // operation may have a side effect on something *other* than the result |
966 | // of the overall operation in which it's embedded. The answer to that |
967 | // is no, because an object literal having a mutated prototype only |
968 | // produces a value, without affecting anything else. |
969 | case ParseNodeKind::MutateProto: |
970 | return checkSideEffects(pn->as<UnaryNode>().kid(), answer); |
971 | |
972 | // Unary cases with obvious side effects. |
973 | case ParseNodeKind::PreIncrementExpr: |
974 | case ParseNodeKind::PostIncrementExpr: |
975 | case ParseNodeKind::PreDecrementExpr: |
976 | case ParseNodeKind::PostDecrementExpr: |
977 | case ParseNodeKind::ThrowStmt: |
978 | MOZ_ASSERT(pn->is<UnaryNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<UnaryNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<UnaryNode>() ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "pn->is<UnaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 978); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()" ")"); do { *((volatile int*)__null) = 978; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
979 | *answer = true; |
980 | return true; |
981 | |
982 | // These might invoke valueOf/toString, even with a subexpression without |
983 | // side effects! Consider |+{ valueOf: null, toString: null }|. |
984 | case ParseNodeKind::BitNotExpr: |
985 | case ParseNodeKind::PosExpr: |
986 | case ParseNodeKind::NegExpr: |
987 | MOZ_ASSERT(pn->is<UnaryNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<UnaryNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<UnaryNode>() ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "pn->is<UnaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 987); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()" ")"); do { *((volatile int*)__null) = 987; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
988 | *answer = true; |
989 | return true; |
990 | |
991 | // This invokes the (user-controllable) iterator protocol. |
992 | case ParseNodeKind::Spread: |
993 | MOZ_ASSERT(pn->is<UnaryNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<UnaryNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<UnaryNode>() ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "pn->is<UnaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 993); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()" ")"); do { *((volatile int*)__null) = 993; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
994 | *answer = true; |
995 | return true; |
996 | |
997 | case ParseNodeKind::InitialYield: |
998 | case ParseNodeKind::YieldStarExpr: |
999 | case ParseNodeKind::YieldExpr: |
1000 | case ParseNodeKind::AwaitExpr: |
1001 | MOZ_ASSERT(pn->is<UnaryNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<UnaryNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<UnaryNode>() ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "pn->is<UnaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1001); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()" ")"); do { *((volatile int*)__null) = 1001; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1002 | *answer = true; |
1003 | return true; |
1004 | |
1005 | // Deletion generally has side effects, even if isolated cases have none. |
1006 | case ParseNodeKind::DeleteNameExpr: |
1007 | case ParseNodeKind::DeletePropExpr: |
1008 | case ParseNodeKind::DeleteElemExpr: |
1009 | case ParseNodeKind::DeleteOptionalChainExpr: |
1010 | MOZ_ASSERT(pn->is<UnaryNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<UnaryNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<UnaryNode>() ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "pn->is<UnaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1010); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()" ")"); do { *((volatile int*)__null) = 1010; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1011 | *answer = true; |
1012 | return true; |
1013 | |
1014 | // Deletion of a non-Reference expression has side effects only through |
1015 | // evaluating the expression. |
1016 | case ParseNodeKind::DeleteExpr: { |
1017 | ParseNode* expr = pn->as<UnaryNode>().kid(); |
1018 | return checkSideEffects(expr, answer); |
1019 | } |
1020 | |
1021 | case ParseNodeKind::ExpressionStmt: |
1022 | return checkSideEffects(pn->as<UnaryNode>().kid(), answer); |
1023 | |
1024 | // Binary cases with obvious side effects. |
1025 | case ParseNodeKind::InitExpr: |
1026 | *answer = true; |
1027 | return true; |
1028 | |
1029 | case ParseNodeKind::AssignExpr: |
1030 | case ParseNodeKind::AddAssignExpr: |
1031 | case ParseNodeKind::SubAssignExpr: |
1032 | case ParseNodeKind::CoalesceAssignExpr: |
1033 | case ParseNodeKind::OrAssignExpr: |
1034 | case ParseNodeKind::AndAssignExpr: |
1035 | case ParseNodeKind::BitOrAssignExpr: |
1036 | case ParseNodeKind::BitXorAssignExpr: |
1037 | case ParseNodeKind::BitAndAssignExpr: |
1038 | case ParseNodeKind::LshAssignExpr: |
1039 | case ParseNodeKind::RshAssignExpr: |
1040 | case ParseNodeKind::UrshAssignExpr: |
1041 | case ParseNodeKind::MulAssignExpr: |
1042 | case ParseNodeKind::DivAssignExpr: |
1043 | case ParseNodeKind::ModAssignExpr: |
1044 | case ParseNodeKind::PowAssignExpr: |
1045 | MOZ_ASSERT(pn->is<AssignmentNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<AssignmentNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<AssignmentNode> ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("pn->is<AssignmentNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1045); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<AssignmentNode>()" ")"); do { *((volatile int*)__null) = 1045; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1046 | *answer = true; |
1047 | return true; |
1048 | |
1049 | case ParseNodeKind::SetThis: |
1050 | MOZ_ASSERT(pn->is<BinaryNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<BinaryNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<BinaryNode>( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("pn->is<BinaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1050); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()" ")"); do { *((volatile int*)__null) = 1050; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1051 | *answer = true; |
1052 | return true; |
1053 | |
1054 | case ParseNodeKind::StatementList: |
1055 | // Strict equality operations and short circuit operators are well-behaved |
1056 | // and perform no conversions. |
1057 | case ParseNodeKind::CoalesceExpr: |
1058 | case ParseNodeKind::OrExpr: |
1059 | case ParseNodeKind::AndExpr: |
1060 | case ParseNodeKind::StrictEqExpr: |
1061 | case ParseNodeKind::StrictNeExpr: |
1062 | // Any subexpression of a comma expression could be effectful. |
1063 | case ParseNodeKind::CommaExpr: |
1064 | MOZ_ASSERT(!pn->as<ListNode>().empty())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!pn->as<ListNode>().empty())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!pn->as<ListNode>() .empty()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!pn->as<ListNode>().empty()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1064); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!pn->as<ListNode>().empty()" ")"); do { *((volatile int*)__null) = 1064; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1065 | [[fallthrough]]; |
1066 | // Subcomponents of a literal may be effectful. |
1067 | case ParseNodeKind::ArrayExpr: |
1068 | case ParseNodeKind::ObjectExpr: |
1069 | for (ParseNode* item : pn->as<ListNode>().contents()) { |
1070 | if (!checkSideEffects(item, answer)) { |
1071 | return false; |
1072 | } |
1073 | if (*answer) { |
1074 | return true; |
1075 | } |
1076 | } |
1077 | return true; |
1078 | |
1079 | #ifdef ENABLE_RECORD_TUPLE |
1080 | case ParseNodeKind::RecordExpr: |
1081 | case ParseNodeKind::TupleExpr: |
1082 | MOZ_CRASH("Record and Tuple are not supported yet")do { do { } while (false); MOZ_ReportCrash("" "Record and Tuple are not supported yet" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1082); AnnotateMozCrashReason("MOZ_CRASH(" "Record and Tuple are not supported yet" ")"); do { *((volatile int*)__null) = 1082; __attribute__((nomerge )) ::abort(); } while (false); } while (false); |
1083 | #endif |
1084 | |
1085 | #ifdef ENABLE_DECORATORS |
1086 | case ParseNodeKind::DecoratorList: |
1087 | MOZ_CRASH("Decorators are not supported yet")do { do { } while (false); MOZ_ReportCrash("" "Decorators are not supported yet" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1087); AnnotateMozCrashReason("MOZ_CRASH(" "Decorators are not supported yet" ")"); do { *((volatile int*)__null) = 1087; __attribute__((nomerge )) ::abort(); } while (false); } while (false); |
1088 | #endif |
1089 | |
1090 | #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT |
1091 | case ParseNodeKind::UsingDecl: |
1092 | case ParseNodeKind::AwaitUsingDecl: |
1093 | MOZ_CRASH("Using declarations are not supported yet")do { do { } while (false); MOZ_ReportCrash("" "Using declarations are not supported yet" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1093); AnnotateMozCrashReason("MOZ_CRASH(" "Using declarations are not supported yet" ")"); do { *((volatile int*)__null) = 1093; __attribute__((nomerge )) ::abort(); } while (false); } while (false); |
1094 | #endif |
1095 | |
1096 | // Most other binary operations (parsed as lists in SpiderMonkey) may |
1097 | // perform conversions triggering side effects. Math operations perform |
1098 | // ToNumber and may fail invoking invalid user-defined toString/valueOf: |
1099 | // |5 < { toString: null }|. |instanceof| throws if provided a |
1100 | // non-object constructor: |null instanceof null|. |in| throws if given |
1101 | // a non-object RHS: |5 in null|. |
1102 | case ParseNodeKind::BitOrExpr: |
1103 | case ParseNodeKind::BitXorExpr: |
1104 | case ParseNodeKind::BitAndExpr: |
1105 | case ParseNodeKind::EqExpr: |
1106 | case ParseNodeKind::NeExpr: |
1107 | case ParseNodeKind::LtExpr: |
1108 | case ParseNodeKind::LeExpr: |
1109 | case ParseNodeKind::GtExpr: |
1110 | case ParseNodeKind::GeExpr: |
1111 | case ParseNodeKind::InstanceOfExpr: |
1112 | case ParseNodeKind::InExpr: |
1113 | case ParseNodeKind::PrivateInExpr: |
1114 | case ParseNodeKind::LshExpr: |
1115 | case ParseNodeKind::RshExpr: |
1116 | case ParseNodeKind::UrshExpr: |
1117 | case ParseNodeKind::AddExpr: |
1118 | case ParseNodeKind::SubExpr: |
1119 | case ParseNodeKind::MulExpr: |
1120 | case ParseNodeKind::DivExpr: |
1121 | case ParseNodeKind::ModExpr: |
1122 | case ParseNodeKind::PowExpr: |
1123 | MOZ_ASSERT(pn->as<ListNode>().count() >= 2)do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->as<ListNode>().count() >= 2)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(pn->as<ListNode>().count() >= 2))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("pn->as<ListNode>().count() >= 2" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1123); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->as<ListNode>().count() >= 2" ")"); do { *((volatile int*)__null) = 1123; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1124 | *answer = true; |
1125 | return true; |
1126 | |
1127 | case ParseNodeKind::PropertyDefinition: |
1128 | case ParseNodeKind::Case: { |
1129 | BinaryNode* node = &pn->as<BinaryNode>(); |
1130 | if (!checkSideEffects(node->left(), answer)) { |
1131 | return false; |
1132 | } |
1133 | if (*answer) { |
1134 | return true; |
1135 | } |
1136 | return checkSideEffects(node->right(), answer); |
1137 | } |
1138 | |
1139 | // More getters. |
1140 | case ParseNodeKind::ElemExpr: |
1141 | case ParseNodeKind::OptionalElemExpr: |
1142 | MOZ_ASSERT(pn->is<BinaryNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<BinaryNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<BinaryNode>( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("pn->is<BinaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1142); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()" ")"); do { *((volatile int*)__null) = 1142; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1143 | *answer = true; |
1144 | return true; |
1145 | |
1146 | // Throws if the operand is not of the right class. Can also call a private |
1147 | // getter. |
1148 | case ParseNodeKind::PrivateMemberExpr: |
1149 | case ParseNodeKind::OptionalPrivateMemberExpr: |
1150 | *answer = true; |
1151 | return true; |
1152 | |
1153 | // These affect visible names in this code, or in other code. |
1154 | case ParseNodeKind::ImportDecl: |
1155 | case ParseNodeKind::ExportFromStmt: |
1156 | case ParseNodeKind::ExportDefaultStmt: |
1157 | MOZ_ASSERT(pn->is<BinaryNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<BinaryNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<BinaryNode>( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("pn->is<BinaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1157); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()" ")"); do { *((volatile int*)__null) = 1157; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1158 | *answer = true; |
1159 | return true; |
1160 | |
1161 | // Likewise. |
1162 | case ParseNodeKind::ExportStmt: |
1163 | MOZ_ASSERT(pn->is<UnaryNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<UnaryNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<UnaryNode>() ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "pn->is<UnaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1163); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()" ")"); do { *((volatile int*)__null) = 1163; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1164 | *answer = true; |
1165 | return true; |
1166 | |
1167 | case ParseNodeKind::CallImportExpr: |
1168 | case ParseNodeKind::CallImportSpec: |
1169 | MOZ_ASSERT(pn->is<BinaryNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<BinaryNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<BinaryNode>( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("pn->is<BinaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1169); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()" ")"); do { *((volatile int*)__null) = 1169; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1170 | *answer = true; |
1171 | return true; |
1172 | |
1173 | // Every part of a loop might be effect-free, but looping infinitely *is* |
1174 | // an effect. (Language lawyer trivia: C++ says threads can be assumed |
1175 | // to exit or have side effects, C++14 [intro.multithread]p27, so a C++ |
1176 | // implementation's equivalent of the below could set |*answer = false;| |
1177 | // if all loop sub-nodes set |*answer = false|!) |
1178 | case ParseNodeKind::DoWhileStmt: |
1179 | case ParseNodeKind::WhileStmt: |
1180 | case ParseNodeKind::ForStmt: |
1181 | MOZ_ASSERT(pn->is<BinaryNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<BinaryNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<BinaryNode>( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("pn->is<BinaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1181); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()" ")"); do { *((volatile int*)__null) = 1181; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1182 | *answer = true; |
1183 | return true; |
1184 | |
1185 | // Declarations affect the name set of the relevant scope. |
1186 | case ParseNodeKind::VarStmt: |
1187 | case ParseNodeKind::ConstDecl: |
1188 | case ParseNodeKind::LetDecl: |
1189 | MOZ_ASSERT(pn->is<ListNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<ListNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<ListNode>()) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("pn->is<ListNode>()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1189); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<ListNode>()" ")"); do { *((volatile int*)__null) = 1189; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1190 | *answer = true; |
1191 | return true; |
1192 | |
1193 | case ParseNodeKind::IfStmt: |
1194 | case ParseNodeKind::ConditionalExpr: { |
1195 | TernaryNode* node = &pn->as<TernaryNode>(); |
1196 | if (!checkSideEffects(node->kid1(), answer)) { |
1197 | return false; |
1198 | } |
1199 | if (*answer) { |
1200 | return true; |
1201 | } |
1202 | if (!checkSideEffects(node->kid2(), answer)) { |
1203 | return false; |
1204 | } |
1205 | if (*answer) { |
1206 | return true; |
1207 | } |
1208 | if ((pn = node->kid3())) { |
1209 | goto restart; |
1210 | } |
1211 | return true; |
1212 | } |
1213 | |
1214 | // Function calls can invoke non-local code. |
1215 | case ParseNodeKind::NewExpr: |
1216 | case ParseNodeKind::CallExpr: |
1217 | case ParseNodeKind::OptionalCallExpr: |
1218 | case ParseNodeKind::TaggedTemplateExpr: |
1219 | case ParseNodeKind::SuperCallExpr: |
1220 | MOZ_ASSERT(pn->is<BinaryNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<BinaryNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<BinaryNode>( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("pn->is<BinaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1220); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()" ")"); do { *((volatile int*)__null) = 1220; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1221 | *answer = true; |
1222 | return true; |
1223 | |
1224 | // Function arg lists can contain arbitrary expressions. Technically |
1225 | // this only causes side-effects if one of the arguments does, but since |
1226 | // the call being made will always trigger side-effects, it isn't needed. |
1227 | case ParseNodeKind::Arguments: |
1228 | MOZ_ASSERT(pn->is<ListNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<ListNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<ListNode>()) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("pn->is<ListNode>()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1228); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<ListNode>()" ")"); do { *((volatile int*)__null) = 1228; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1229 | *answer = true; |
1230 | return true; |
1231 | |
1232 | case ParseNodeKind::OptionalChain: |
1233 | MOZ_ASSERT(pn->is<UnaryNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<UnaryNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<UnaryNode>() ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "pn->is<UnaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1233); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<UnaryNode>()" ")"); do { *((volatile int*)__null) = 1233; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1234 | *answer = true; |
1235 | return true; |
1236 | |
1237 | // Classes typically introduce names. Even if no name is introduced, |
1238 | // the heritage and/or class body (through computed property names) |
1239 | // usually have effects. |
1240 | case ParseNodeKind::ClassDecl: |
1241 | MOZ_ASSERT(pn->is<ClassNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<ClassNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<ClassNode>() ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "pn->is<ClassNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1241); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<ClassNode>()" ")"); do { *((volatile int*)__null) = 1241; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1242 | *answer = true; |
1243 | return true; |
1244 | |
1245 | // |with| calls |ToObject| on its expression and so throws if that value |
1246 | // is null/undefined. |
1247 | case ParseNodeKind::WithStmt: |
1248 | MOZ_ASSERT(pn->is<BinaryNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<BinaryNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<BinaryNode>( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("pn->is<BinaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1248); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()" ")"); do { *((volatile int*)__null) = 1248; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1249 | *answer = true; |
1250 | return true; |
1251 | |
1252 | case ParseNodeKind::ReturnStmt: |
1253 | MOZ_ASSERT(pn->is<BinaryNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<BinaryNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<BinaryNode>( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("pn->is<BinaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1253); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()" ")"); do { *((volatile int*)__null) = 1253; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1254 | *answer = true; |
1255 | return true; |
1256 | |
1257 | case ParseNodeKind::Name: |
1258 | MOZ_ASSERT(pn->is<NameNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<NameNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<NameNode>()) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("pn->is<NameNode>()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1258); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<NameNode>()" ")"); do { *((volatile int*)__null) = 1258; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1259 | *answer = true; |
1260 | return true; |
1261 | |
1262 | // Shorthands could trigger getters: the |x| in the object literal in |
1263 | // |with ({ get x() { throw 42; } }) ({ x });|, for example, triggers |
1264 | // one. (Of course, it isn't necessary to use |with| for a shorthand to |
1265 | // trigger a getter.) |
1266 | case ParseNodeKind::Shorthand: |
1267 | MOZ_ASSERT(pn->is<BinaryNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<BinaryNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<BinaryNode>( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("pn->is<BinaryNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1267); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<BinaryNode>()" ")"); do { *((volatile int*)__null) = 1267; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1268 | *answer = true; |
1269 | return true; |
1270 | |
1271 | case ParseNodeKind::Function: |
1272 | MOZ_ASSERT(pn->is<FunctionNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->is<FunctionNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->is<FunctionNode> ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("pn->is<FunctionNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1272); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->is<FunctionNode>()" ")"); do { *((volatile int*)__null) = 1272; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1273 | /* |
1274 | * A named function, contrary to ES3, is no longer effectful, because |
1275 | * we bind its name lexically (using JSOp::Callee) instead of creating |
1276 | * an Object instance and binding a readonly, permanent property in it |
1277 | * (the object and binding can be detected and hijacked or captured). |
1278 | * This is a bug fix to ES3; it is fixed in ES3.1 drafts. |
1279 | */ |
1280 | *answer = false; |
1281 | return true; |
1282 | |
1283 | case ParseNodeKind::Module: |
1284 | *answer = false; |
1285 | return true; |
1286 | |
1287 | case ParseNodeKind::TryStmt: { |
1288 | TryNode* tryNode = &pn->as<TryNode>(); |
1289 | if (!checkSideEffects(tryNode->body(), answer)) { |
1290 | return false; |
1291 | } |
1292 | if (*answer) { |
1293 | return true; |
1294 | } |
1295 | if (LexicalScopeNode* catchScope = tryNode->catchScope()) { |
1296 | if (!checkSideEffects(catchScope, answer)) { |
1297 | return false; |
1298 | } |
1299 | if (*answer) { |
1300 | return true; |
1301 | } |
1302 | } |
1303 | if (ParseNode* finallyBlock = tryNode->finallyBlock()) { |
1304 | if (!checkSideEffects(finallyBlock, answer)) { |
1305 | return false; |
1306 | } |
1307 | } |
1308 | return true; |
1309 | } |
1310 | |
1311 | case ParseNodeKind::Catch: { |
1312 | BinaryNode* catchClause = &pn->as<BinaryNode>(); |
1313 | if (ParseNode* name = catchClause->left()) { |
1314 | if (!checkSideEffects(name, answer)) { |
1315 | return false; |
1316 | } |
1317 | if (*answer) { |
1318 | return true; |
1319 | } |
1320 | } |
1321 | return checkSideEffects(catchClause->right(), answer); |
1322 | } |
1323 | |
1324 | case ParseNodeKind::SwitchStmt: { |
1325 | SwitchStatement* switchStmt = &pn->as<SwitchStatement>(); |
1326 | if (!checkSideEffects(&switchStmt->discriminant(), answer)) { |
1327 | return false; |
1328 | } |
1329 | return *answer || |
1330 | checkSideEffects(&switchStmt->lexicalForCaseList(), answer); |
1331 | } |
1332 | |
1333 | case ParseNodeKind::LabelStmt: |
1334 | return checkSideEffects(pn->as<LabeledStatement>().statement(), answer); |
1335 | |
1336 | case ParseNodeKind::LexicalScope: |
1337 | return checkSideEffects(pn->as<LexicalScopeNode>().scopeBody(), answer); |
1338 | |
1339 | // We could methodically check every interpolated expression, but it's |
1340 | // probably not worth the trouble. Treat template strings as effect-free |
1341 | // only if they don't contain any substitutions. |
1342 | case ParseNodeKind::TemplateStringListExpr: { |
1343 | ListNode* list = &pn->as<ListNode>(); |
1344 | MOZ_ASSERT(!list->empty())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!list->empty())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!list->empty()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!list->empty()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1344); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!list->empty()" ")"); do { *((volatile int*)__null) = 1344; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1345 | MOZ_ASSERT((list->count() % 2) == 1,do { static_assert( mozilla::detail::AssertionConditionType< decltype((list->count() % 2) == 1)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!((list->count() % 2) == 1) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("(list->count() % 2) == 1" " (" "template strings must alternate template and substitution " "parts" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1347); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(list->count() % 2) == 1" ") (" "template strings must alternate template and substitution " "parts" ")"); do { *((volatile int*)__null) = 1347; __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false) |
1346 | "template strings must alternate template and substitution "do { static_assert( mozilla::detail::AssertionConditionType< decltype((list->count() % 2) == 1)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!((list->count() % 2) == 1) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("(list->count() % 2) == 1" " (" "template strings must alternate template and substitution " "parts" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1347); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(list->count() % 2) == 1" ") (" "template strings must alternate template and substitution " "parts" ")"); do { *((volatile int*)__null) = 1347; __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false) |
1347 | "parts")do { static_assert( mozilla::detail::AssertionConditionType< decltype((list->count() % 2) == 1)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!((list->count() % 2) == 1) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("(list->count() % 2) == 1" " (" "template strings must alternate template and substitution " "parts" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1347); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(list->count() % 2) == 1" ") (" "template strings must alternate template and substitution " "parts" ")"); do { *((volatile int*)__null) = 1347; __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false); |
1348 | *answer = list->count() > 1; |
1349 | return true; |
1350 | } |
1351 | |
1352 | // This should be unreachable but is left as-is for now. |
1353 | case ParseNodeKind::ParamsBody: |
1354 | *answer = true; |
1355 | return true; |
1356 | |
1357 | case ParseNodeKind::ForIn: // by ParseNodeKind::For |
1358 | case ParseNodeKind::ForOf: // by ParseNodeKind::For |
1359 | case ParseNodeKind::ForHead: // by ParseNodeKind::For |
1360 | case ParseNodeKind::DefaultConstructor: // by ParseNodeKind::ClassDecl |
1361 | case ParseNodeKind::ClassBodyScope: // by ParseNodeKind::ClassDecl |
1362 | case ParseNodeKind::ClassMethod: // by ParseNodeKind::ClassDecl |
1363 | case ParseNodeKind::ClassField: // by ParseNodeKind::ClassDecl |
1364 | case ParseNodeKind::ClassNames: // by ParseNodeKind::ClassDecl |
1365 | case ParseNodeKind::StaticClassBlock: // by ParseNodeKind::ClassDecl |
1366 | case ParseNodeKind::ClassMemberList: // by ParseNodeKind::ClassDecl |
1367 | case ParseNodeKind::ImportSpecList: // by ParseNodeKind::Import |
1368 | case ParseNodeKind::ImportSpec: // by ParseNodeKind::Import |
1369 | case ParseNodeKind::ImportNamespaceSpec: // by ParseNodeKind::Import |
1370 | case ParseNodeKind::ImportAttribute: // by ParseNodeKind::Import |
1371 | case ParseNodeKind::ImportAttributeList: // by ParseNodeKind::Import |
1372 | case ParseNodeKind::ImportModuleRequest: // by ParseNodeKind::Import |
1373 | case ParseNodeKind::ExportBatchSpecStmt: // by ParseNodeKind::Export |
1374 | case ParseNodeKind::ExportSpecList: // by ParseNodeKind::Export |
1375 | case ParseNodeKind::ExportSpec: // by ParseNodeKind::Export |
1376 | case ParseNodeKind::ExportNamespaceSpec: // by ParseNodeKind::Export |
1377 | case ParseNodeKind::CallSiteObj: // by ParseNodeKind::TaggedTemplate |
1378 | case ParseNodeKind::PosHolder: // by ParseNodeKind::NewTarget |
1379 | case ParseNodeKind::SuperBase: // by ParseNodeKind::Elem and others |
1380 | case ParseNodeKind::PropertyNameExpr: // by ParseNodeKind::Dot |
1381 | MOZ_CRASH("handled by parent nodes")do { do { } while (false); MOZ_ReportCrash("" "handled by parent nodes" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1381); AnnotateMozCrashReason("MOZ_CRASH(" "handled by parent nodes" ")"); do { *((volatile int*)__null) = 1381; __attribute__((nomerge )) ::abort(); } while (false); } while (false); |
1382 | |
1383 | case ParseNodeKind::LastUnused: |
1384 | case ParseNodeKind::Limit: |
1385 | MOZ_CRASH("invalid node kind")do { do { } while (false); MOZ_ReportCrash("" "invalid node kind" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1385); AnnotateMozCrashReason("MOZ_CRASH(" "invalid node kind" ")"); do { *((volatile int*)__null) = 1385; __attribute__((nomerge )) ::abort(); } while (false); } while (false); |
1386 | } |
1387 | |
1388 | MOZ_CRASH(do { do { } while (false); MOZ_ReportCrash("" "invalid, unenumerated ParseNodeKind value encountered in " "BytecodeEmitter::checkSideEffects", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1390); AnnotateMozCrashReason("MOZ_CRASH(" "invalid, unenumerated ParseNodeKind value encountered in " "BytecodeEmitter::checkSideEffects" ")"); do { *((volatile int *)__null) = 1390; __attribute__((nomerge)) ::abort(); } while (false); } while (false) |
1389 | "invalid, unenumerated ParseNodeKind value encountered in "do { do { } while (false); MOZ_ReportCrash("" "invalid, unenumerated ParseNodeKind value encountered in " "BytecodeEmitter::checkSideEffects", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1390); AnnotateMozCrashReason("MOZ_CRASH(" "invalid, unenumerated ParseNodeKind value encountered in " "BytecodeEmitter::checkSideEffects" ")"); do { *((volatile int *)__null) = 1390; __attribute__((nomerge)) ::abort(); } while (false); } while (false) |
1390 | "BytecodeEmitter::checkSideEffects")do { do { } while (false); MOZ_ReportCrash("" "invalid, unenumerated ParseNodeKind value encountered in " "BytecodeEmitter::checkSideEffects", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1390); AnnotateMozCrashReason("MOZ_CRASH(" "invalid, unenumerated ParseNodeKind value encountered in " "BytecodeEmitter::checkSideEffects" ")"); do { *((volatile int *)__null) = 1390; __attribute__((nomerge)) ::abort(); } while (false); } while (false); |
1391 | } |
1392 | |
1393 | bool BytecodeEmitter::isInLoop() { |
1394 | return findInnermostNestableControl<LoopControl>(); |
1395 | } |
1396 | |
1397 | bool BytecodeEmitter::checkSingletonContext() { |
1398 | MOZ_ASSERT_IF(sc->treatAsRunOnce(), sc->isTopLevelContext())do { if (sc->treatAsRunOnce()) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(sc->isTopLevelContext ())>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(sc->isTopLevelContext()))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("sc->isTopLevelContext()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1398); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isTopLevelContext()" ")"); do { *((volatile int*)__null) = 1398; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
1399 | return sc->treatAsRunOnce() && !isInLoop(); |
1400 | } |
1401 | |
1402 | bool BytecodeEmitter::needsImplicitThis() { |
1403 | // Short-circuit if there is an enclosing 'with' scope. |
1404 | if (sc->inWith()) { |
1405 | return true; |
1406 | } |
1407 | |
1408 | // Otherwise see if the current point is under a 'with'. |
1409 | for (EmitterScope* es = innermostEmitterScope(); es; |
1410 | es = es->enclosingInFrame()) { |
1411 | if (es->scope(this).kind() == ScopeKind::With) { |
1412 | return true; |
1413 | } |
1414 | } |
1415 | |
1416 | return false; |
1417 | } |
1418 | |
1419 | size_t BytecodeEmitter::countThisEnvironmentHops() { |
1420 | unsigned numHops = 0; |
1421 | |
1422 | for (BytecodeEmitter* current = this; current; current = current->parent) { |
1423 | for (EmitterScope* es = current->innermostEmitterScope(); es; |
1424 | es = es->enclosingInFrame()) { |
1425 | if (es->scope(current).is<FunctionScope>()) { |
1426 | if (!es->scope(current).isArrow()) { |
1427 | // The Parser is responsible for marking the environment as either |
1428 | // closed-over or used-by-eval which ensure that is must exist. |
1429 | MOZ_ASSERT(es->scope(current).hasEnvironment())do { static_assert( mozilla::detail::AssertionConditionType< decltype(es->scope(current).hasEnvironment())>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(es->scope(current).hasEnvironment()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("es->scope(current).hasEnvironment()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1429); AnnotateMozCrashReason("MOZ_ASSERT" "(" "es->scope(current).hasEnvironment()" ")"); do { *((volatile int*)__null) = 1429; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1430 | return numHops; |
1431 | } |
1432 | } |
1433 | if (es->scope(current).hasEnvironment()) { |
1434 | numHops++; |
1435 | } |
1436 | } |
1437 | } |
1438 | |
1439 | // The "this" environment exists outside of the compilation, but the |
1440 | // `ScopeContext` recorded the number of additional hops needed, so add |
1441 | // those in now. |
1442 | MOZ_ASSERT(sc->allowSuperProperty())do { static_assert( mozilla::detail::AssertionConditionType< decltype(sc->allowSuperProperty())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(sc->allowSuperProperty()) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("sc->allowSuperProperty()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1442); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->allowSuperProperty()" ")"); do { *((volatile int*)__null) = 1442; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1443 | numHops += compilationState.scopeContext.enclosingThisEnvironmentHops; |
1444 | return numHops; |
1445 | } |
1446 | |
1447 | bool BytecodeEmitter::emitThisEnvironmentCallee() { |
1448 | // Get the innermost enclosing function that has a |this| binding. |
1449 | |
1450 | // Directly load callee from the frame if possible. |
1451 | if (sc->isFunctionBox() && !sc->asFunctionBox()->isArrow()) { |
1452 | return emit1(JSOp::Callee); |
1453 | } |
1454 | |
1455 | // We have to load the callee from the environment chain. |
1456 | size_t numHops = countThisEnvironmentHops(); |
1457 | |
1458 | static_assert( |
1459 | ENVCOORD_HOPS_LIMIT - 1 <= UINT8_MAX(255), |
1460 | "JSOp::EnvCallee operand size should match ENVCOORD_HOPS_LIMIT"); |
1461 | |
1462 | MOZ_ASSERT(numHops < ENVCOORD_HOPS_LIMIT - 1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(numHops < ENVCOORD_HOPS_LIMIT - 1)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(numHops < ENVCOORD_HOPS_LIMIT - 1))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("numHops < ENVCOORD_HOPS_LIMIT - 1", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1462); AnnotateMozCrashReason("MOZ_ASSERT" "(" "numHops < ENVCOORD_HOPS_LIMIT - 1" ")"); do { *((volatile int*)__null) = 1462; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1463 | |
1464 | return emit2(JSOp::EnvCallee, numHops); |
1465 | } |
1466 | |
1467 | bool BytecodeEmitter::emitSuperBase() { |
1468 | if (!emitThisEnvironmentCallee()) { |
1469 | return false; |
1470 | } |
1471 | |
1472 | return emit1(JSOp::SuperBase); |
1473 | } |
1474 | |
1475 | void BytecodeEmitter::reportError(ParseNode* pn, unsigned errorNumber, ...) { |
1476 | uint32_t offset = pn ? pn->pn_pos.begin : *scriptStartOffset; |
1477 | |
1478 | va_list args; |
1479 | va_start(args, errorNumber)__builtin_va_start(args, errorNumber); |
1480 | |
1481 | errorReporter().errorWithNotesAtVA(nullptr, AsVariant(offset), errorNumber, |
1482 | &args); |
1483 | |
1484 | va_end(args)__builtin_va_end(args); |
1485 | } |
1486 | |
1487 | void BytecodeEmitter::reportError(uint32_t offset, unsigned errorNumber, ...) { |
1488 | va_list args; |
1489 | va_start(args, errorNumber)__builtin_va_start(args, errorNumber); |
1490 | |
1491 | errorReporter().errorWithNotesAtVA(nullptr, AsVariant(offset), errorNumber, |
1492 | &args); |
1493 | |
1494 | va_end(args)__builtin_va_end(args); |
1495 | } |
1496 | |
1497 | bool BytecodeEmitter::addObjLiteralData(ObjLiteralWriter& writer, |
1498 | GCThingIndex* outIndex) { |
1499 | if (!writer.checkForDuplicatedNames(fc)) { |
1500 | return false; |
1501 | } |
1502 | |
1503 | size_t len = writer.getCode().size(); |
1504 | auto* code = compilationState.alloc.newArrayUninitialized<uint8_t>(len); |
1505 | if (!code) { |
1506 | js::ReportOutOfMemory(fc); |
1507 | return false; |
1508 | } |
1509 | memcpy(code, writer.getCode().data(), len); |
1510 | |
1511 | ObjLiteralIndex objIndex(compilationState.objLiteralData.length()); |
1512 | if (uint32_t(objIndex) >= TaggedScriptThingIndex::IndexLimit) { |
1513 | ReportAllocationOverflow(fc); |
1514 | return false; |
1515 | } |
1516 | if (!compilationState.objLiteralData.emplaceBack(code, len, writer.getKind(), |
1517 | writer.getFlags(), |
1518 | writer.getPropertyCount())) { |
1519 | js::ReportOutOfMemory(fc); |
1520 | return false; |
1521 | } |
1522 | |
1523 | return perScriptData().gcThingList().append(objIndex, outIndex); |
1524 | } |
1525 | |
1526 | bool BytecodeEmitter::emitPrepareIteratorResult() { |
1527 | constexpr JSOp op = JSOp::NewObject; |
1528 | |
1529 | ObjLiteralWriter writer; |
1530 | writer.beginShape(op); |
1531 | |
1532 | writer.setPropNameNoDuplicateCheck(parserAtoms(), |
1533 | TaggedParserAtomIndex::WellKnown::value()); |
1534 | if (!writer.propWithUndefinedValue(fc)) { |
1535 | return false; |
1536 | } |
1537 | writer.setPropNameNoDuplicateCheck(parserAtoms(), |
1538 | TaggedParserAtomIndex::WellKnown::done()); |
1539 | if (!writer.propWithUndefinedValue(fc)) { |
1540 | return false; |
1541 | } |
1542 | |
1543 | GCThingIndex shape; |
1544 | if (!addObjLiteralData(writer, &shape)) { |
1545 | return false; |
1546 | } |
1547 | |
1548 | return emitGCIndexOp(op, shape); |
1549 | } |
1550 | |
1551 | bool BytecodeEmitter::emitFinishIteratorResult(bool done) { |
1552 | if (!emitAtomOp(JSOp::InitProp, TaggedParserAtomIndex::WellKnown::value())) { |
1553 | return false; |
1554 | } |
1555 | if (!emit1(done ? JSOp::True : JSOp::False)) { |
1556 | return false; |
1557 | } |
1558 | if (!emitAtomOp(JSOp::InitProp, TaggedParserAtomIndex::WellKnown::done())) { |
1559 | return false; |
1560 | } |
1561 | return true; |
1562 | } |
1563 | |
1564 | bool BytecodeEmitter::emitGetNameAtLocation(TaggedParserAtomIndex name, |
1565 | const NameLocation& loc) { |
1566 | NameOpEmitter noe(this, name, loc, NameOpEmitter::Kind::Get); |
1567 | if (!noe.emitGet()) { |
1568 | return false; |
1569 | } |
1570 | |
1571 | return true; |
1572 | } |
1573 | |
1574 | bool BytecodeEmitter::emitGetName(NameNode* name) { |
1575 | MOZ_ASSERT(name->isKind(ParseNodeKind::Name))do { static_assert( mozilla::detail::AssertionConditionType< decltype(name->isKind(ParseNodeKind::Name))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(name->isKind(ParseNodeKind ::Name)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("name->isKind(ParseNodeKind::Name)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1575); AnnotateMozCrashReason("MOZ_ASSERT" "(" "name->isKind(ParseNodeKind::Name)" ")"); do { *((volatile int*)__null) = 1575; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1576 | |
1577 | return emitGetName(name->name()); |
1578 | } |
1579 | |
1580 | bool BytecodeEmitter::emitGetPrivateName(NameNode* name) { |
1581 | MOZ_ASSERT(name->isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType< decltype(name->isKind(ParseNodeKind::PrivateName))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(name->isKind(ParseNodeKind::PrivateName)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("name->isKind(ParseNodeKind::PrivateName)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1581); AnnotateMozCrashReason("MOZ_ASSERT" "(" "name->isKind(ParseNodeKind::PrivateName)" ")"); do { *((volatile int*)__null) = 1581; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1582 | return emitGetPrivateName(name->name()); |
1583 | } |
1584 | |
1585 | bool BytecodeEmitter::emitGetPrivateName(TaggedParserAtomIndex nameAtom) { |
1586 | // The parser ensures the private name is present on the environment chain, |
1587 | // but its location can be Dynamic or Global when emitting debugger |
1588 | // eval-in-frame code. |
1589 | NameLocation location = lookupName(nameAtom); |
1590 | MOZ_ASSERT(location.kind() == NameLocation::Kind::FrameSlot ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(location.kind() == NameLocation::Kind::FrameSlot || location .kind() == NameLocation::Kind::EnvironmentCoordinate || location .kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation ::Kind::Global)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(location.kind() == NameLocation ::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate || location.kind() == NameLocation::Kind::Dynamic || location .kind() == NameLocation::Kind::Global))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("location.kind() == NameLocation::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate || location.kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation::Kind::Global" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1593); AnnotateMozCrashReason("MOZ_ASSERT" "(" "location.kind() == NameLocation::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate || location.kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation::Kind::Global" ")"); do { *((volatile int*)__null) = 1593; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
1591 | location.kind() == NameLocation::Kind::EnvironmentCoordinate ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(location.kind() == NameLocation::Kind::FrameSlot || location .kind() == NameLocation::Kind::EnvironmentCoordinate || location .kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation ::Kind::Global)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(location.kind() == NameLocation ::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate || location.kind() == NameLocation::Kind::Dynamic || location .kind() == NameLocation::Kind::Global))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("location.kind() == NameLocation::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate || location.kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation::Kind::Global" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1593); AnnotateMozCrashReason("MOZ_ASSERT" "(" "location.kind() == NameLocation::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate || location.kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation::Kind::Global" ")"); do { *((volatile int*)__null) = 1593; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
1592 | location.kind() == NameLocation::Kind::Dynamic ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(location.kind() == NameLocation::Kind::FrameSlot || location .kind() == NameLocation::Kind::EnvironmentCoordinate || location .kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation ::Kind::Global)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(location.kind() == NameLocation ::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate || location.kind() == NameLocation::Kind::Dynamic || location .kind() == NameLocation::Kind::Global))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("location.kind() == NameLocation::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate || location.kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation::Kind::Global" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1593); AnnotateMozCrashReason("MOZ_ASSERT" "(" "location.kind() == NameLocation::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate || location.kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation::Kind::Global" ")"); do { *((volatile int*)__null) = 1593; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
1593 | location.kind() == NameLocation::Kind::Global)do { static_assert( mozilla::detail::AssertionConditionType< decltype(location.kind() == NameLocation::Kind::FrameSlot || location .kind() == NameLocation::Kind::EnvironmentCoordinate || location .kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation ::Kind::Global)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(location.kind() == NameLocation ::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate || location.kind() == NameLocation::Kind::Dynamic || location .kind() == NameLocation::Kind::Global))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("location.kind() == NameLocation::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate || location.kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation::Kind::Global" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1593); AnnotateMozCrashReason("MOZ_ASSERT" "(" "location.kind() == NameLocation::Kind::FrameSlot || location.kind() == NameLocation::Kind::EnvironmentCoordinate || location.kind() == NameLocation::Kind::Dynamic || location.kind() == NameLocation::Kind::Global" ")"); do { *((volatile int*)__null) = 1593; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1594 | |
1595 | return emitGetNameAtLocation(nameAtom, location); |
1596 | } |
1597 | |
1598 | bool BytecodeEmitter::emitTDZCheckIfNeeded(TaggedParserAtomIndex name, |
1599 | const NameLocation& loc, |
1600 | ValueIsOnStack isOnStack) { |
1601 | // Dynamic accesses have TDZ checks built into their VM code and should |
1602 | // never emit explicit TDZ checks. |
1603 | MOZ_ASSERT(loc.hasKnownSlot())do { static_assert( mozilla::detail::AssertionConditionType< decltype(loc.hasKnownSlot())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(loc.hasKnownSlot()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("loc.hasKnownSlot()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1603); AnnotateMozCrashReason("MOZ_ASSERT" "(" "loc.hasKnownSlot()" ")"); do { *((volatile int*)__null) = 1603; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1604 | MOZ_ASSERT(loc.isLexical() || loc.isPrivateMethod() || loc.isSynthetic())do { static_assert( mozilla::detail::AssertionConditionType< decltype(loc.isLexical() || loc.isPrivateMethod() || loc.isSynthetic ())>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(loc.isLexical() || loc.isPrivateMethod() || loc.isSynthetic ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("loc.isLexical() || loc.isPrivateMethod() || loc.isSynthetic()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1604); AnnotateMozCrashReason("MOZ_ASSERT" "(" "loc.isLexical() || loc.isPrivateMethod() || loc.isSynthetic()" ")"); do { *((volatile int*)__null) = 1604; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1605 | |
1606 | // Private names are implemented as lexical bindings, but it's just an |
1607 | // implementation detail. Per spec there's no TDZ check when using them. |
1608 | if (parserAtoms().isPrivateName(name)) { |
1609 | return true; |
1610 | } |
1611 | |
1612 | Maybe<MaybeCheckTDZ> check = |
1613 | innermostTDZCheckCache->needsTDZCheck(this, name); |
1614 | if (!check) { |
1615 | return false; |
1616 | } |
1617 | |
1618 | // We've already emitted a check in this basic block. |
1619 | if (*check == DontCheckTDZ) { |
1620 | return true; |
1621 | } |
1622 | |
1623 | // If the value is not on the stack, we have to load it first. |
1624 | if (isOnStack == ValueIsOnStack::No) { |
1625 | if (loc.kind() == NameLocation::Kind::FrameSlot) { |
1626 | if (!emitLocalOp(JSOp::GetLocal, loc.frameSlot())) { |
1627 | return false; |
1628 | } |
1629 | } else { |
1630 | if (!emitEnvCoordOp(JSOp::GetAliasedVar, loc.environmentCoordinate())) { |
1631 | return false; |
1632 | } |
1633 | } |
1634 | } |
1635 | |
1636 | // Emit the lexical check. |
1637 | if (loc.kind() == NameLocation::Kind::FrameSlot) { |
1638 | if (!emitLocalOp(JSOp::CheckLexical, loc.frameSlot())) { |
1639 | return false; |
1640 | } |
1641 | } else { |
1642 | if (!emitEnvCoordOp(JSOp::CheckAliasedLexical, |
1643 | loc.environmentCoordinate())) { |
1644 | return false; |
1645 | } |
1646 | } |
1647 | |
1648 | // Pop the value if needed. |
1649 | if (isOnStack == ValueIsOnStack::No) { |
1650 | if (!emit1(JSOp::Pop)) { |
1651 | return false; |
1652 | } |
1653 | } |
1654 | |
1655 | return innermostTDZCheckCache->noteTDZCheck(this, name, DontCheckTDZ); |
1656 | } |
1657 | |
1658 | bool BytecodeEmitter::emitPropLHS(PropertyAccess* prop) { |
1659 | MOZ_ASSERT(!prop->isSuper())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!prop->isSuper())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!prop->isSuper()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!prop->isSuper()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1659); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!prop->isSuper()" ")"); do { *((volatile int*)__null) = 1659; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1660 | |
1661 | ParseNode* expr = &prop->expression(); |
1662 | |
1663 | if (!expr->is<PropertyAccess>() || expr->as<PropertyAccess>().isSuper()) { |
1664 | // The non-optimized case. |
1665 | return emitTree(expr); |
1666 | } |
1667 | |
1668 | // If the object operand is also a dotted property reference, reverse the |
1669 | // list linked via expression() temporarily so we can iterate over it from |
1670 | // the bottom up (reversing again as we go), to avoid excessive recursion. |
1671 | PropertyAccess* pndot = &expr->as<PropertyAccess>(); |
1672 | ParseNode* pnup = nullptr; |
1673 | ParseNode* pndown; |
1674 | for (;;) { |
1675 | // Reverse pndot->expression() to point up, not down. |
1676 | pndown = &pndot->expression(); |
1677 | pndot->setExpression(pnup); |
1678 | if (!pndown->is<PropertyAccess>() || |
1679 | pndown->as<PropertyAccess>().isSuper()) { |
1680 | break; |
1681 | } |
1682 | pnup = pndot; |
1683 | pndot = &pndown->as<PropertyAccess>(); |
1684 | } |
1685 | |
1686 | // pndown is a primary expression, not a dotted property reference. |
1687 | if (!emitTree(pndown)) { |
1688 | return false; |
1689 | } |
1690 | |
1691 | while (true) { |
1692 | // Walk back up the list, emitting annotated name ops. |
1693 | if (!emitAtomOp(JSOp::GetProp, pndot->key().atom())) { |
1694 | return false; |
1695 | } |
1696 | |
1697 | // Reverse the pndot->expression() link again. |
1698 | pnup = pndot->maybeExpression(); |
1699 | pndot->setExpression(pndown); |
1700 | pndown = pndot; |
1701 | if (!pnup) { |
1702 | break; |
1703 | } |
1704 | pndot = &pnup->as<PropertyAccess>(); |
1705 | } |
1706 | return true; |
1707 | } |
1708 | |
1709 | bool BytecodeEmitter::emitPropIncDec(UnaryNode* incDec, ValueUsage valueUsage) { |
1710 | PropertyAccess* prop = &incDec->kid()->as<PropertyAccess>(); |
1711 | bool isSuper = prop->isSuper(); |
1712 | ParseNodeKind kind = incDec->getKind(); |
1713 | PropOpEmitter poe( |
1714 | this, |
1715 | kind == ParseNodeKind::PostIncrementExpr |
1716 | ? PropOpEmitter::Kind::PostIncrement |
1717 | : kind == ParseNodeKind::PreIncrementExpr |
1718 | ? PropOpEmitter::Kind::PreIncrement |
1719 | : kind == ParseNodeKind::PostDecrementExpr |
1720 | ? PropOpEmitter::Kind::PostDecrement |
1721 | : PropOpEmitter::Kind::PreDecrement, |
1722 | isSuper ? PropOpEmitter::ObjKind::Super : PropOpEmitter::ObjKind::Other); |
1723 | if (!poe.prepareForObj()) { |
1724 | return false; |
1725 | } |
1726 | if (isSuper) { |
1727 | UnaryNode* base = &prop->expression().as<UnaryNode>(); |
1728 | if (!emitGetThisForSuperBase(base)) { |
1729 | // [stack] THIS |
1730 | return false; |
1731 | } |
1732 | } else { |
1733 | if (!emitPropLHS(prop)) { |
1734 | // [stack] OBJ |
1735 | return false; |
1736 | } |
1737 | } |
1738 | if (!poe.emitIncDec(prop->key().atom(), valueUsage)) { |
1739 | // [stack] RESULT |
1740 | return false; |
1741 | } |
1742 | |
1743 | return true; |
1744 | } |
1745 | |
1746 | bool BytecodeEmitter::emitNameIncDec(UnaryNode* incDec, ValueUsage valueUsage) { |
1747 | MOZ_ASSERT(incDec->kid()->isKind(ParseNodeKind::Name))do { static_assert( mozilla::detail::AssertionConditionType< decltype(incDec->kid()->isKind(ParseNodeKind::Name))> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(incDec->kid()->isKind(ParseNodeKind::Name)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("incDec->kid()->isKind(ParseNodeKind::Name)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1747); AnnotateMozCrashReason("MOZ_ASSERT" "(" "incDec->kid()->isKind(ParseNodeKind::Name)" ")"); do { *((volatile int*)__null) = 1747; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1748 | |
1749 | ParseNodeKind kind = incDec->getKind(); |
1750 | NameNode* name = &incDec->kid()->as<NameNode>(); |
1751 | NameOpEmitter noe(this, name->atom(), |
1752 | kind == ParseNodeKind::PostIncrementExpr |
1753 | ? NameOpEmitter::Kind::PostIncrement |
1754 | : kind == ParseNodeKind::PreIncrementExpr |
1755 | ? NameOpEmitter::Kind::PreIncrement |
1756 | : kind == ParseNodeKind::PostDecrementExpr |
1757 | ? NameOpEmitter::Kind::PostDecrement |
1758 | : NameOpEmitter::Kind::PreDecrement); |
1759 | if (!noe.emitIncDec(valueUsage)) { |
1760 | return false; |
1761 | } |
1762 | |
1763 | return true; |
1764 | } |
1765 | |
1766 | bool BytecodeEmitter::emitObjAndKey(ParseNode* exprOrSuper, ParseNode* key, |
1767 | ElemOpEmitter& eoe) { |
1768 | if (exprOrSuper->isKind(ParseNodeKind::SuperBase)) { |
1769 | if (!eoe.prepareForObj()) { |
1770 | // [stack] |
1771 | return false; |
1772 | } |
1773 | UnaryNode* base = &exprOrSuper->as<UnaryNode>(); |
1774 | if (!emitGetThisForSuperBase(base)) { |
1775 | // [stack] THIS |
1776 | return false; |
1777 | } |
1778 | if (!eoe.prepareForKey()) { |
1779 | // [stack] THIS |
1780 | return false; |
1781 | } |
1782 | if (!emitTree(key)) { |
1783 | // [stack] THIS KEY |
1784 | return false; |
1785 | } |
1786 | |
1787 | return true; |
1788 | } |
1789 | |
1790 | if (!eoe.prepareForObj()) { |
1791 | // [stack] |
1792 | return false; |
1793 | } |
1794 | if (!emitTree(exprOrSuper)) { |
1795 | // [stack] OBJ |
1796 | return false; |
1797 | } |
1798 | if (!eoe.prepareForKey()) { |
1799 | // [stack] OBJ? OBJ |
1800 | return false; |
1801 | } |
1802 | if (!emitTree(key)) { |
1803 | // [stack] OBJ? OBJ KEY |
1804 | return false; |
1805 | } |
1806 | |
1807 | return true; |
1808 | } |
1809 | |
1810 | bool BytecodeEmitter::emitElemOpBase(JSOp op) { |
1811 | if (!emit1(op)) { |
1812 | return false; |
1813 | } |
1814 | |
1815 | return true; |
1816 | } |
1817 | |
1818 | bool BytecodeEmitter::emitElemObjAndKey(PropertyByValue* elem, bool isSuper, |
1819 | ElemOpEmitter& eoe) { |
1820 | MOZ_ASSERT(isSuper == elem->expression().isKind(ParseNodeKind::SuperBase))do { static_assert( mozilla::detail::AssertionConditionType< decltype(isSuper == elem->expression().isKind(ParseNodeKind ::SuperBase))>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(isSuper == elem->expression(). isKind(ParseNodeKind::SuperBase)))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("isSuper == elem->expression().isKind(ParseNodeKind::SuperBase)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1820); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isSuper == elem->expression().isKind(ParseNodeKind::SuperBase)" ")"); do { *((volatile int*)__null) = 1820; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1821 | return emitObjAndKey(&elem->expression(), &elem->key(), eoe); |
1822 | } |
1823 | |
1824 | static ElemOpEmitter::Kind ConvertIncDecKind(ParseNodeKind kind) { |
1825 | switch (kind) { |
1826 | case ParseNodeKind::PostIncrementExpr: |
1827 | return ElemOpEmitter::Kind::PostIncrement; |
1828 | case ParseNodeKind::PreIncrementExpr: |
1829 | return ElemOpEmitter::Kind::PreIncrement; |
1830 | case ParseNodeKind::PostDecrementExpr: |
1831 | return ElemOpEmitter::Kind::PostDecrement; |
1832 | case ParseNodeKind::PreDecrementExpr: |
1833 | return ElemOpEmitter::Kind::PreDecrement; |
1834 | default: |
1835 | MOZ_CRASH("unexpected inc/dec node kind")do { do { } while (false); MOZ_ReportCrash("" "unexpected inc/dec node kind" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1835); AnnotateMozCrashReason("MOZ_CRASH(" "unexpected inc/dec node kind" ")"); do { *((volatile int*)__null) = 1835; __attribute__((nomerge )) ::abort(); } while (false); } while (false); |
1836 | } |
1837 | } |
1838 | |
1839 | static PrivateOpEmitter::Kind PrivateConvertIncDecKind(ParseNodeKind kind) { |
1840 | switch (kind) { |
1841 | case ParseNodeKind::PostIncrementExpr: |
1842 | return PrivateOpEmitter::Kind::PostIncrement; |
1843 | case ParseNodeKind::PreIncrementExpr: |
1844 | return PrivateOpEmitter::Kind::PreIncrement; |
1845 | case ParseNodeKind::PostDecrementExpr: |
1846 | return PrivateOpEmitter::Kind::PostDecrement; |
1847 | case ParseNodeKind::PreDecrementExpr: |
1848 | return PrivateOpEmitter::Kind::PreDecrement; |
1849 | default: |
1850 | MOZ_CRASH("unexpected inc/dec node kind")do { do { } while (false); MOZ_ReportCrash("" "unexpected inc/dec node kind" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1850); AnnotateMozCrashReason("MOZ_CRASH(" "unexpected inc/dec node kind" ")"); do { *((volatile int*)__null) = 1850; __attribute__((nomerge )) ::abort(); } while (false); } while (false); |
1851 | } |
1852 | } |
1853 | |
1854 | bool BytecodeEmitter::emitElemIncDec(UnaryNode* incDec, ValueUsage valueUsage) { |
1855 | PropertyByValue* elemExpr = &incDec->kid()->as<PropertyByValue>(); |
1856 | bool isSuper = elemExpr->isSuper(); |
1857 | MOZ_ASSERT(!elemExpr->key().isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!elemExpr->key().isKind(ParseNodeKind::PrivateName ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!elemExpr->key().isKind(ParseNodeKind::PrivateName )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!elemExpr->key().isKind(ParseNodeKind::PrivateName)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1857); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elemExpr->key().isKind(ParseNodeKind::PrivateName)" ")"); do { *((volatile int*)__null) = 1857; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1858 | ParseNodeKind kind = incDec->getKind(); |
1859 | ElemOpEmitter eoe( |
1860 | this, ConvertIncDecKind(kind), |
1861 | isSuper ? ElemOpEmitter::ObjKind::Super : ElemOpEmitter::ObjKind::Other); |
1862 | if (!emitElemObjAndKey(elemExpr, isSuper, eoe)) { |
1863 | // [stack] # if Super |
1864 | // [stack] THIS KEY |
1865 | // [stack] # otherwise |
1866 | // [stack] OBJ KEY |
1867 | return false; |
1868 | } |
1869 | if (!eoe.emitIncDec(valueUsage)) { |
1870 | // [stack] RESULT |
1871 | return false; |
1872 | } |
1873 | |
1874 | return true; |
1875 | } |
1876 | |
1877 | bool BytecodeEmitter::emitCallIncDec(UnaryNode* incDec) { |
1878 | MOZ_ASSERT(incDec->isKind(ParseNodeKind::PreIncrementExpr) ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec ->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind (ParseNodeKind::PostDecrementExpr))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(incDec->isKind(ParseNodeKind ::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr ) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec ->isKind(ParseNodeKind::PostDecrementExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind(ParseNodeKind::PostDecrementExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1881); AnnotateMozCrashReason("MOZ_ASSERT" "(" "incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind(ParseNodeKind::PostDecrementExpr)" ")"); do { *((volatile int*)__null) = 1881; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
1879 | incDec->isKind(ParseNodeKind::PostIncrementExpr) ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec ->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind (ParseNodeKind::PostDecrementExpr))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(incDec->isKind(ParseNodeKind ::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr ) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec ->isKind(ParseNodeKind::PostDecrementExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind(ParseNodeKind::PostDecrementExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1881); AnnotateMozCrashReason("MOZ_ASSERT" "(" "incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind(ParseNodeKind::PostDecrementExpr)" ")"); do { *((volatile int*)__null) = 1881; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
1880 | incDec->isKind(ParseNodeKind::PreDecrementExpr) ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec ->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind (ParseNodeKind::PostDecrementExpr))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(incDec->isKind(ParseNodeKind ::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr ) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec ->isKind(ParseNodeKind::PostDecrementExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind(ParseNodeKind::PostDecrementExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1881); AnnotateMozCrashReason("MOZ_ASSERT" "(" "incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind(ParseNodeKind::PostDecrementExpr)" ")"); do { *((volatile int*)__null) = 1881; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
1881 | incDec->isKind(ParseNodeKind::PostDecrementExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec ->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind (ParseNodeKind::PostDecrementExpr))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(incDec->isKind(ParseNodeKind ::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr ) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec ->isKind(ParseNodeKind::PostDecrementExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind(ParseNodeKind::PostDecrementExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1881); AnnotateMozCrashReason("MOZ_ASSERT" "(" "incDec->isKind(ParseNodeKind::PreIncrementExpr) || incDec->isKind(ParseNodeKind::PostIncrementExpr) || incDec->isKind(ParseNodeKind::PreDecrementExpr) || incDec->isKind(ParseNodeKind::PostDecrementExpr)" ")"); do { *((volatile int*)__null) = 1881; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1882 | |
1883 | ParseNode* call = incDec->kid(); |
1884 | MOZ_ASSERT(call->isKind(ParseNodeKind::CallExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(call->isKind(ParseNodeKind::CallExpr))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(call->isKind(ParseNodeKind::CallExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("call->isKind(ParseNodeKind::CallExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1884); AnnotateMozCrashReason("MOZ_ASSERT" "(" "call->isKind(ParseNodeKind::CallExpr)" ")"); do { *((volatile int*)__null) = 1884; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1885 | if (!emitTree(call)) { |
1886 | // [stack] CALLRESULT |
1887 | return false; |
1888 | } |
1889 | if (!emit1(JSOp::ToNumeric)) { |
1890 | // [stack] N |
1891 | return false; |
1892 | } |
1893 | |
1894 | // The increment/decrement has no side effects, so proceed to throw for |
1895 | // invalid assignment target. |
1896 | return emit2(JSOp::ThrowMsg, uint8_t(ThrowMsgKind::AssignToCall)); |
1897 | } |
1898 | |
1899 | bool BytecodeEmitter::emitPrivateIncDec(UnaryNode* incDec, |
1900 | ValueUsage valueUsage) { |
1901 | PrivateMemberAccess* privateExpr = &incDec->kid()->as<PrivateMemberAccess>(); |
1902 | ParseNodeKind kind = incDec->getKind(); |
1903 | PrivateOpEmitter xoe(this, PrivateConvertIncDecKind(kind), |
1904 | privateExpr->privateName().name()); |
1905 | if (!emitTree(&privateExpr->expression())) { |
1906 | // [stack] OBJ |
1907 | return false; |
1908 | } |
1909 | if (!xoe.emitReference()) { |
1910 | // [stack] OBJ NAME |
1911 | return false; |
1912 | } |
1913 | if (!xoe.emitIncDec(valueUsage)) { |
1914 | // [stack] RESULT |
1915 | return false; |
1916 | } |
1917 | |
1918 | return true; |
1919 | } |
1920 | |
1921 | bool BytecodeEmitter::emitDouble(double d) { |
1922 | BytecodeOffset offset; |
1923 | if (!emitCheck(JSOp::Double, 9, &offset)) { |
1924 | return false; |
1925 | } |
1926 | |
1927 | jsbytecode* code = bytecodeSection().code(offset); |
1928 | code[0] = jsbytecode(JSOp::Double); |
1929 | SET_INLINE_VALUE(code, DoubleValue(d)); |
1930 | bytecodeSection().updateDepth(JSOp::Double, offset); |
1931 | return true; |
1932 | } |
1933 | |
1934 | bool BytecodeEmitter::emitNumberOp(double dval) { |
1935 | int32_t ival; |
1936 | if (NumberIsInt32(dval, &ival)) { |
1937 | if (ival == 0) { |
1938 | return emit1(JSOp::Zero); |
1939 | } |
1940 | if (ival == 1) { |
1941 | return emit1(JSOp::One); |
1942 | } |
1943 | if ((int)(int8_t)ival == ival) { |
1944 | return emit2(JSOp::Int8, uint8_t(int8_t(ival))); |
1945 | } |
1946 | |
1947 | uint32_t u = uint32_t(ival); |
1948 | if (u < Bit(16)) { |
1949 | if (!emitUint16Operand(JSOp::Uint16, u)) { |
1950 | return false; |
1951 | } |
1952 | } else if (u < Bit(24)) { |
1953 | BytecodeOffset off; |
1954 | if (!emitN(JSOp::Uint24, 3, &off)) { |
1955 | return false; |
1956 | } |
1957 | SET_UINT24(bytecodeSection().code(off), u); |
1958 | } else { |
1959 | BytecodeOffset off; |
1960 | if (!emitN(JSOp::Int32, 4, &off)) { |
1961 | return false; |
1962 | } |
1963 | SET_INT32(bytecodeSection().code(off), ival); |
1964 | } |
1965 | return true; |
1966 | } |
1967 | |
1968 | return emitDouble(dval); |
1969 | } |
1970 | |
1971 | /* |
1972 | * Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. |
1973 | * LLVM is deciding to inline this function which uses a lot of stack space |
1974 | * into emitTree which is recursive and uses relatively little stack space. |
1975 | */ |
1976 | MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitSwitch(SwitchStatement* switchStmt) { |
1977 | LexicalScopeNode& lexical = switchStmt->lexicalForCaseList(); |
1978 | MOZ_ASSERT(lexical.isKind(ParseNodeKind::LexicalScope))do { static_assert( mozilla::detail::AssertionConditionType< decltype(lexical.isKind(ParseNodeKind::LexicalScope))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(lexical.isKind(ParseNodeKind::LexicalScope)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("lexical.isKind(ParseNodeKind::LexicalScope)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1978); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lexical.isKind(ParseNodeKind::LexicalScope)" ")"); do { *((volatile int*)__null) = 1978; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1979 | ListNode* cases = &lexical.scopeBody()->as<ListNode>(); |
1980 | MOZ_ASSERT(cases->isKind(ParseNodeKind::StatementList))do { static_assert( mozilla::detail::AssertionConditionType< decltype(cases->isKind(ParseNodeKind::StatementList))>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(cases->isKind(ParseNodeKind::StatementList)))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("cases->isKind(ParseNodeKind::StatementList)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 1980); AnnotateMozCrashReason("MOZ_ASSERT" "(" "cases->isKind(ParseNodeKind::StatementList)" ")"); do { *((volatile int*)__null) = 1980; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1981 | |
1982 | SwitchEmitter se(this); |
1983 | if (!se.emitDiscriminant(switchStmt->discriminant().pn_pos.begin)) { |
1984 | return false; |
1985 | } |
1986 | |
1987 | if (!markStepBreakpoint()) { |
1988 | return false; |
1989 | } |
1990 | if (!emitTree(&switchStmt->discriminant())) { |
1991 | return false; |
1992 | } |
1993 | |
1994 | // Enter the scope before pushing the switch BreakableControl since all |
1995 | // breaks are under this scope. |
1996 | |
1997 | if (!lexical.isEmptyScope()) { |
1998 | if (!se.emitLexical(lexical.scopeBindings())) { |
1999 | return false; |
2000 | } |
2001 | |
2002 | // A switch statement may contain hoisted functions inside its |
2003 | // cases. The hasTopLevelFunctionDeclarations flag is propagated from the |
2004 | // StatementList bodies of the cases to the case list. |
2005 | if (cases->hasTopLevelFunctionDeclarations()) { |
2006 | for (ParseNode* item : cases->contents()) { |
2007 | CaseClause* caseClause = &item->as<CaseClause>(); |
2008 | ListNode* statements = caseClause->statementList(); |
2009 | if (statements->hasTopLevelFunctionDeclarations()) { |
2010 | if (!emitHoistedFunctionsInList(statements)) { |
2011 | return false; |
2012 | } |
2013 | } |
2014 | } |
2015 | } |
2016 | } else { |
2017 | MOZ_ASSERT(!cases->hasTopLevelFunctionDeclarations())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!cases->hasTopLevelFunctionDeclarations())>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(!cases->hasTopLevelFunctionDeclarations()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!cases->hasTopLevelFunctionDeclarations()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2017); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!cases->hasTopLevelFunctionDeclarations()" ")"); do { *((volatile int*)__null) = 2017; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2018 | } |
2019 | |
2020 | SwitchEmitter::TableGenerator tableGen(this); |
2021 | uint32_t caseCount = cases->count() - (switchStmt->hasDefault() ? 1 : 0); |
2022 | if (caseCount == 0) { |
2023 | tableGen.finish(0); |
2024 | } else { |
2025 | for (ParseNode* item : cases->contents()) { |
2026 | CaseClause* caseClause = &item->as<CaseClause>(); |
2027 | if (caseClause->isDefault()) { |
2028 | continue; |
2029 | } |
2030 | |
2031 | ParseNode* caseValue = caseClause->caseExpression(); |
2032 | |
2033 | if (caseValue->getKind() != ParseNodeKind::NumberExpr) { |
2034 | tableGen.setInvalid(); |
2035 | break; |
2036 | } |
2037 | |
2038 | int32_t i; |
2039 | if (!NumberEqualsInt32(caseValue->as<NumericLiteral>().value(), &i)) { |
2040 | tableGen.setInvalid(); |
2041 | break; |
2042 | } |
2043 | |
2044 | if (!tableGen.addNumber(i)) { |
2045 | return false; |
2046 | } |
2047 | } |
2048 | |
2049 | tableGen.finish(caseCount); |
2050 | } |
2051 | |
2052 | if (!se.validateCaseCount(caseCount)) { |
2053 | return false; |
2054 | } |
2055 | |
2056 | bool isTableSwitch = tableGen.isValid(); |
2057 | if (isTableSwitch) { |
2058 | if (!se.emitTable(tableGen)) { |
2059 | return false; |
2060 | } |
2061 | } else { |
2062 | if (!se.emitCond()) { |
2063 | return false; |
2064 | } |
2065 | |
2066 | // Emit code for evaluating cases and jumping to case statements. |
2067 | for (ParseNode* item : cases->contents()) { |
2068 | CaseClause* caseClause = &item->as<CaseClause>(); |
2069 | if (caseClause->isDefault()) { |
2070 | continue; |
2071 | } |
2072 | |
2073 | if (!se.prepareForCaseValue()) { |
2074 | return false; |
2075 | } |
2076 | |
2077 | ParseNode* caseValue = caseClause->caseExpression(); |
2078 | // If the expression is a literal, suppress line number emission so |
2079 | // that debugging works more naturally. |
2080 | if (!emitTree( |
2081 | caseValue, ValueUsage::WantValue, |
2082 | caseValue->isLiteral() ? SUPPRESS_LINENOTE : EMIT_LINENOTE)) { |
2083 | return false; |
2084 | } |
2085 | |
2086 | if (!se.emitCaseJump()) { |
2087 | return false; |
2088 | } |
2089 | } |
2090 | } |
2091 | |
2092 | // Emit code for each case's statements. |
2093 | for (ParseNode* item : cases->contents()) { |
2094 | CaseClause* caseClause = &item->as<CaseClause>(); |
2095 | if (caseClause->isDefault()) { |
2096 | if (!se.emitDefaultBody()) { |
2097 | return false; |
2098 | } |
2099 | } else { |
2100 | if (isTableSwitch) { |
2101 | ParseNode* caseValue = caseClause->caseExpression(); |
2102 | MOZ_ASSERT(caseValue->isKind(ParseNodeKind::NumberExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(caseValue->isKind(ParseNodeKind::NumberExpr))> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(caseValue->isKind(ParseNodeKind::NumberExpr)))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("caseValue->isKind(ParseNodeKind::NumberExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2102); AnnotateMozCrashReason("MOZ_ASSERT" "(" "caseValue->isKind(ParseNodeKind::NumberExpr)" ")"); do { *((volatile int*)__null) = 2102; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2103 | |
2104 | NumericLiteral* literal = &caseValue->as<NumericLiteral>(); |
2105 | #ifdef DEBUG1 |
2106 | // Use NumberEqualsInt32 here because switches compare using |
2107 | // strict equality, which will equate -0 and +0. In contrast |
2108 | // NumberIsInt32 would return false for -0. |
2109 | int32_t v; |
2110 | MOZ_ASSERT(mozilla::NumberEqualsInt32(literal->value(), &v))do { static_assert( mozilla::detail::AssertionConditionType< decltype(mozilla::NumberEqualsInt32(literal->value(), & v))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(mozilla::NumberEqualsInt32(literal->value(), & v)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mozilla::NumberEqualsInt32(literal->value(), &v)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2110); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mozilla::NumberEqualsInt32(literal->value(), &v)" ")"); do { *((volatile int*)__null) = 2110; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2111 | #endif |
2112 | int32_t i = int32_t(literal->value()); |
2113 | |
2114 | if (!se.emitCaseBody(i, tableGen)) { |
2115 | return false; |
2116 | } |
2117 | } else { |
2118 | if (!se.emitCaseBody()) { |
2119 | return false; |
2120 | } |
2121 | } |
2122 | } |
2123 | |
2124 | if (!emitTree(caseClause->statementList())) { |
2125 | return false; |
2126 | } |
2127 | } |
2128 | |
2129 | if (!se.emitEnd()) { |
2130 | return false; |
2131 | } |
2132 | |
2133 | return true; |
2134 | } |
2135 | |
2136 | bool BytecodeEmitter::allocateResumeIndex(BytecodeOffset offset, |
2137 | uint32_t* resumeIndex) { |
2138 | static constexpr uint32_t MaxResumeIndex = BitMask(24); |
2139 | |
2140 | static_assert( |
2141 | MaxResumeIndex < uint32_t(AbstractGeneratorObject::RESUME_INDEX_RUNNING), |
2142 | "resumeIndex should not include magic AbstractGeneratorObject " |
2143 | "resumeIndex values"); |
2144 | static_assert( |
2145 | MaxResumeIndex <= INT32_MAX(2147483647) / sizeof(uintptr_t), |
2146 | "resumeIndex * sizeof(uintptr_t) must fit in an int32. JIT code relies " |
2147 | "on this when loading resume entries from BaselineScript"); |
2148 | |
2149 | *resumeIndex = bytecodeSection().resumeOffsetList().length(); |
2150 | if (*resumeIndex > MaxResumeIndex) { |
2151 | reportError(nullptr, JSMSG_TOO_MANY_RESUME_INDEXES); |
2152 | return false; |
2153 | } |
2154 | |
2155 | return bytecodeSection().resumeOffsetList().append(offset.value()); |
2156 | } |
2157 | |
2158 | bool BytecodeEmitter::allocateResumeIndexRange( |
2159 | mozilla::Span<BytecodeOffset> offsets, uint32_t* firstResumeIndex) { |
2160 | *firstResumeIndex = 0; |
2161 | |
2162 | for (size_t i = 0, len = offsets.size(); i < len; i++) { |
2163 | uint32_t resumeIndex; |
2164 | if (!allocateResumeIndex(offsets[i], &resumeIndex)) { |
2165 | return false; |
2166 | } |
2167 | if (i == 0) { |
2168 | *firstResumeIndex = resumeIndex; |
2169 | } |
2170 | } |
2171 | |
2172 | return true; |
2173 | } |
2174 | |
2175 | bool BytecodeEmitter::emitYieldOp(JSOp op) { |
2176 | // ParseContext::Scope::setOwnStackSlotCount should check the fixed slot |
2177 | // for the following, and it should prevent using fixed slot if there are |
2178 | // too many bindings: |
2179 | // * generator or asyn function |
2180 | // * module code after top-level await |
2181 | MOZ_ASSERT(innermostEmitterScopeNoCheck()->frameSlotEnd() <=do { static_assert( mozilla::detail::AssertionConditionType< decltype(innermostEmitterScopeNoCheck()->frameSlotEnd() <= ParseContext::Scope::FixedSlotLimit)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(innermostEmitterScopeNoCheck ()->frameSlotEnd() <= ParseContext::Scope::FixedSlotLimit ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "innermostEmitterScopeNoCheck()->frameSlotEnd() <= ParseContext::Scope::FixedSlotLimit" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2182); AnnotateMozCrashReason("MOZ_ASSERT" "(" "innermostEmitterScopeNoCheck()->frameSlotEnd() <= ParseContext::Scope::FixedSlotLimit" ")"); do { *((volatile int*)__null) = 2182; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2182 | ParseContext::Scope::FixedSlotLimit)do { static_assert( mozilla::detail::AssertionConditionType< decltype(innermostEmitterScopeNoCheck()->frameSlotEnd() <= ParseContext::Scope::FixedSlotLimit)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(innermostEmitterScopeNoCheck ()->frameSlotEnd() <= ParseContext::Scope::FixedSlotLimit ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "innermostEmitterScopeNoCheck()->frameSlotEnd() <= ParseContext::Scope::FixedSlotLimit" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2182); AnnotateMozCrashReason("MOZ_ASSERT" "(" "innermostEmitterScopeNoCheck()->frameSlotEnd() <= ParseContext::Scope::FixedSlotLimit" ")"); do { *((volatile int*)__null) = 2182; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2183 | |
2184 | if (op == JSOp::FinalYieldRval) { |
2185 | return emit1(JSOp::FinalYieldRval); |
2186 | } |
2187 | |
2188 | MOZ_ASSERT(op == JSOp::InitialYield || op == JSOp::Yield ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(op == JSOp::InitialYield || op == JSOp::Yield || op == JSOp::Await)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(op == JSOp::InitialYield || op == JSOp::Yield || op == JSOp::Await))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("op == JSOp::InitialYield || op == JSOp::Yield || op == JSOp::Await" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2189); AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::InitialYield || op == JSOp::Yield || op == JSOp::Await" ")"); do { *((volatile int*)__null) = 2189; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2189 | op == JSOp::Await)do { static_assert( mozilla::detail::AssertionConditionType< decltype(op == JSOp::InitialYield || op == JSOp::Yield || op == JSOp::Await)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(op == JSOp::InitialYield || op == JSOp::Yield || op == JSOp::Await))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("op == JSOp::InitialYield || op == JSOp::Yield || op == JSOp::Await" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2189); AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::InitialYield || op == JSOp::Yield || op == JSOp::Await" ")"); do { *((volatile int*)__null) = 2189; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2190 | |
2191 | BytecodeOffset off; |
2192 | if (!emitN(op, 3, &off)) { |
2193 | return false; |
2194 | } |
2195 | |
2196 | if (op == JSOp::InitialYield || op == JSOp::Yield) { |
2197 | bytecodeSection().addNumYields(); |
2198 | } |
2199 | |
2200 | uint32_t resumeIndex; |
2201 | if (!allocateResumeIndex(bytecodeSection().offset(), &resumeIndex)) { |
2202 | return false; |
2203 | } |
2204 | |
2205 | SET_RESUMEINDEX(bytecodeSection().code(off), resumeIndex); |
2206 | |
2207 | BytecodeOffset unusedOffset; |
2208 | return emitJumpTargetOp(JSOp::AfterYield, &unusedOffset); |
2209 | } |
2210 | |
2211 | bool BytecodeEmitter::emitPushResumeKind(GeneratorResumeKind kind) { |
2212 | return emit2(JSOp::ResumeKind, uint8_t(kind)); |
2213 | } |
2214 | |
2215 | bool BytecodeEmitter::emitSetThis(BinaryNode* setThisNode) { |
2216 | // ParseNodeKind::SetThis is used to update |this| after a super() call |
2217 | // in a derived class constructor. |
2218 | |
2219 | MOZ_ASSERT(setThisNode->isKind(ParseNodeKind::SetThis))do { static_assert( mozilla::detail::AssertionConditionType< decltype(setThisNode->isKind(ParseNodeKind::SetThis))>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(setThisNode->isKind(ParseNodeKind::SetThis)))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("setThisNode->isKind(ParseNodeKind::SetThis)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2219); AnnotateMozCrashReason("MOZ_ASSERT" "(" "setThisNode->isKind(ParseNodeKind::SetThis)" ")"); do { *((volatile int*)__null) = 2219; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2220 | MOZ_ASSERT(setThisNode->left()->isKind(ParseNodeKind::Name))do { static_assert( mozilla::detail::AssertionConditionType< decltype(setThisNode->left()->isKind(ParseNodeKind::Name ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(setThisNode->left()->isKind(ParseNodeKind::Name )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("setThisNode->left()->isKind(ParseNodeKind::Name)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2220); AnnotateMozCrashReason("MOZ_ASSERT" "(" "setThisNode->left()->isKind(ParseNodeKind::Name)" ")"); do { *((volatile int*)__null) = 2220; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2221 | |
2222 | auto name = setThisNode->left()->as<NameNode>().name(); |
2223 | |
2224 | // The 'this' binding is not lexical, but due to super() semantics this |
2225 | // initialization needs to be treated as a lexical one. |
2226 | NameLocation loc = lookupName(name); |
2227 | NameLocation lexicalLoc; |
2228 | if (loc.kind() == NameLocation::Kind::FrameSlot) { |
2229 | lexicalLoc = NameLocation::FrameSlot(BindingKind::Let, loc.frameSlot()); |
2230 | } else if (loc.kind() == NameLocation::Kind::EnvironmentCoordinate) { |
2231 | EnvironmentCoordinate coord = loc.environmentCoordinate(); |
2232 | uint8_t hops = AssertedCast<uint8_t>(coord.hops()); |
2233 | lexicalLoc = NameLocation::EnvironmentCoordinate(BindingKind::Let, hops, |
2234 | coord.slot()); |
2235 | } else { |
2236 | MOZ_ASSERT(loc.kind() == NameLocation::Kind::Dynamic)do { static_assert( mozilla::detail::AssertionConditionType< decltype(loc.kind() == NameLocation::Kind::Dynamic)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(loc.kind() == NameLocation::Kind::Dynamic))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("loc.kind() == NameLocation::Kind::Dynamic" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2236); AnnotateMozCrashReason("MOZ_ASSERT" "(" "loc.kind() == NameLocation::Kind::Dynamic" ")"); do { *((volatile int*)__null) = 2236; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2237 | lexicalLoc = loc; |
2238 | } |
2239 | |
2240 | NameOpEmitter noe(this, name, lexicalLoc, NameOpEmitter::Kind::Initialize); |
2241 | if (!noe.prepareForRhs()) { |
2242 | // [stack] |
2243 | return false; |
2244 | } |
2245 | |
2246 | // Emit the new |this| value. |
2247 | if (!emitTree(setThisNode->right())) { |
2248 | // [stack] NEWTHIS |
2249 | return false; |
2250 | } |
2251 | |
2252 | // Get the original |this| and throw if we already initialized |
2253 | // it. Do *not* use the NameLocation argument, as that's the special |
2254 | // lexical location below to deal with super() semantics. |
2255 | if (!emitGetName(name)) { |
2256 | // [stack] NEWTHIS THIS |
2257 | return false; |
2258 | } |
2259 | if (!emit1(JSOp::CheckThisReinit)) { |
2260 | // [stack] NEWTHIS THIS |
2261 | return false; |
2262 | } |
2263 | if (!emit1(JSOp::Pop)) { |
2264 | // [stack] NEWTHIS |
2265 | return false; |
2266 | } |
2267 | if (!noe.emitAssignment()) { |
2268 | // [stack] NEWTHIS |
2269 | return false; |
2270 | } |
2271 | |
2272 | if (!emitInitializeInstanceMembers(true)) { |
2273 | return false; |
2274 | } |
2275 | |
2276 | return true; |
2277 | } |
2278 | |
2279 | bool BytecodeEmitter::defineHoistedTopLevelFunctions(ParseNode* body) { |
2280 | MOZ_ASSERT(inPrologue())do { static_assert( mozilla::detail::AssertionConditionType< decltype(inPrologue())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(inPrologue()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("inPrologue()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2280); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inPrologue()" ")"); do { *((volatile int*)__null) = 2280; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2281 | MOZ_ASSERT(sc->isGlobalContext() || (sc->isEvalContext() && !sc->strict()))do { static_assert( mozilla::detail::AssertionConditionType< decltype(sc->isGlobalContext() || (sc->isEvalContext() && !sc->strict()))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(sc->isGlobalContext() || ( sc->isEvalContext() && !sc->strict())))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("sc->isGlobalContext() || (sc->isEvalContext() && !sc->strict())" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2281); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isGlobalContext() || (sc->isEvalContext() && !sc->strict())" ")"); do { *((volatile int*)__null) = 2281; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2282 | MOZ_ASSERT(body->is<LexicalScopeNode>() || body->is<ListNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(body->is<LexicalScopeNode>() || body->is <ListNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(body->is<LexicalScopeNode >() || body->is<ListNode>()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("body->is<LexicalScopeNode>() || body->is<ListNode>()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2282); AnnotateMozCrashReason("MOZ_ASSERT" "(" "body->is<LexicalScopeNode>() || body->is<ListNode>()" ")"); do { *((volatile int*)__null) = 2282; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2283 | |
2284 | if (body->is<LexicalScopeNode>()) { |
2285 | body = body->as<LexicalScopeNode>().scopeBody(); |
2286 | MOZ_ASSERT(body->is<ListNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(body->is<ListNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(body->is<ListNode>( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("body->is<ListNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2286); AnnotateMozCrashReason("MOZ_ASSERT" "(" "body->is<ListNode>()" ")"); do { *((volatile int*)__null) = 2286; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2287 | } |
2288 | |
2289 | if (!body->as<ListNode>().hasTopLevelFunctionDeclarations()) { |
2290 | return true; |
2291 | } |
2292 | |
2293 | return emitHoistedFunctionsInList(&body->as<ListNode>()); |
2294 | } |
2295 | |
2296 | // For Global and sloppy-Eval scripts, this performs most of the steps of the |
2297 | // spec's [GlobalDeclarationInstantiation] and [EvalDeclarationInstantiation] |
2298 | // operations. |
2299 | // |
2300 | // Note that while strict-Eval is handled in the same part of the spec, it never |
2301 | // fails for global-redeclaration checks so those scripts initialize directly in |
2302 | // their bytecode. |
2303 | bool BytecodeEmitter::emitDeclarationInstantiation(ParseNode* body) { |
2304 | if (sc->isModuleContext()) { |
2305 | // ES Modules have dedicated variable and lexial environments and therefore |
2306 | // do not have to perform redeclaration checks. We initialize their bindings |
2307 | // elsewhere in bytecode. |
2308 | return true; |
2309 | } |
2310 | |
2311 | if (sc->isEvalContext() && sc->strict()) { |
2312 | // Strict Eval has a dedicated variables (and lexical) environment and |
2313 | // therefore does not have to perform redeclaration checks. We initialize |
2314 | // their bindings elsewhere in the bytecode. |
2315 | return true; |
2316 | } |
2317 | |
2318 | // If we have no variables bindings, then we are done! |
2319 | if (sc->isGlobalContext()) { |
2320 | if (!sc->asGlobalContext()->bindings) { |
2321 | return true; |
2322 | } |
2323 | } else { |
2324 | MOZ_ASSERT(sc->isEvalContext())do { static_assert( mozilla::detail::AssertionConditionType< decltype(sc->isEvalContext())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(sc->isEvalContext()))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("sc->isEvalContext()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2324); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isEvalContext()" ")"); do { *((volatile int*)__null) = 2324; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2325 | |
2326 | if (!sc->asEvalContext()->bindings) { |
2327 | return true; |
2328 | } |
2329 | } |
2330 | |
2331 | #if DEBUG1 |
2332 | // There should be no emitted functions yet. |
2333 | for (const auto& thing : perScriptData().gcThingList().objects()) { |
2334 | MOZ_ASSERT(thing.isEmptyGlobalScope() || thing.isScope())do { static_assert( mozilla::detail::AssertionConditionType< decltype(thing.isEmptyGlobalScope() || thing.isScope())>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(thing.isEmptyGlobalScope() || thing.isScope()))), 0) )) { do { } while (false); MOZ_ReportAssertionFailure("thing.isEmptyGlobalScope() || thing.isScope()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2334); AnnotateMozCrashReason("MOZ_ASSERT" "(" "thing.isEmptyGlobalScope() || thing.isScope()" ")"); do { *((volatile int*)__null) = 2334; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2335 | } |
2336 | #endif |
2337 | |
2338 | // Emit the hoisted functions to gc-things list. There is no bytecode |
2339 | // generated yet to bind them. |
2340 | if (!defineHoistedTopLevelFunctions(body)) { |
2341 | return false; |
2342 | } |
2343 | |
2344 | // Save the last GCThingIndex emitted. The hoisted functions are contained in |
2345 | // the gc-things list up until this point. This set of gc-things also contain |
2346 | // initial scopes (of which there must be at least one). |
2347 | MOZ_ASSERT(perScriptData().gcThingList().length() > 0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(perScriptData().gcThingList().length() > 0)>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(perScriptData().gcThingList().length() > 0))), 0) )) { do { } while (false); MOZ_ReportAssertionFailure("perScriptData().gcThingList().length() > 0" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2347); AnnotateMozCrashReason("MOZ_ASSERT" "(" "perScriptData().gcThingList().length() > 0" ")"); do { *((volatile int*)__null) = 2347; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2348 | GCThingIndex lastFun = |
2349 | GCThingIndex(perScriptData().gcThingList().length() - 1); |
2350 | |
2351 | #if DEBUG1 |
2352 | for (const auto& thing : perScriptData().gcThingList().objects()) { |
2353 | MOZ_ASSERT(thing.isEmptyGlobalScope() || thing.isScope() ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(thing.isEmptyGlobalScope() || thing.isScope() || thing .isFunction())>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(thing.isEmptyGlobalScope() || thing .isScope() || thing.isFunction()))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("thing.isEmptyGlobalScope() || thing.isScope() || thing.isFunction()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2354); AnnotateMozCrashReason("MOZ_ASSERT" "(" "thing.isEmptyGlobalScope() || thing.isScope() || thing.isFunction()" ")"); do { *((volatile int*)__null) = 2354; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2354 | thing.isFunction())do { static_assert( mozilla::detail::AssertionConditionType< decltype(thing.isEmptyGlobalScope() || thing.isScope() || thing .isFunction())>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(thing.isEmptyGlobalScope() || thing .isScope() || thing.isFunction()))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("thing.isEmptyGlobalScope() || thing.isScope() || thing.isFunction()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2354); AnnotateMozCrashReason("MOZ_ASSERT" "(" "thing.isEmptyGlobalScope() || thing.isScope() || thing.isFunction()" ")"); do { *((volatile int*)__null) = 2354; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2355 | } |
2356 | #endif |
2357 | |
2358 | // Check for declaration conflicts and initialize the bindings. |
2359 | // NOTE: The self-hosting top-level script should not populate the builtins |
2360 | // directly on the GlobalObject (and instead uses JSOp::GetIntrinsic for |
2361 | // lookups). |
2362 | if (emitterMode == BytecodeEmitter::EmitterMode::Normal) { |
2363 | if (!emitGCIndexOp(JSOp::GlobalOrEvalDeclInstantiation, lastFun)) { |
2364 | return false; |
2365 | } |
2366 | } |
2367 | |
2368 | return true; |
2369 | } |
2370 | |
2371 | bool BytecodeEmitter::emitScript(ParseNode* body) { |
2372 | setScriptStartOffsetIfUnset(body->pn_pos.begin); |
2373 | |
2374 | MOZ_ASSERT(inPrologue())do { static_assert( mozilla::detail::AssertionConditionType< decltype(inPrologue())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(inPrologue()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("inPrologue()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2374); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inPrologue()" ")"); do { *((volatile int*)__null) = 2374; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2375 | |
2376 | TDZCheckCache tdzCache(this); |
2377 | EmitterScope emitterScope(this); |
2378 | Maybe<AsyncEmitter> topLevelAwait; |
2379 | if (sc->isGlobalContext()) { |
2380 | if (!emitterScope.enterGlobal(this, sc->asGlobalContext())) { |
2381 | return false; |
2382 | } |
2383 | } else if (sc->isEvalContext()) { |
2384 | if (!emitterScope.enterEval(this, sc->asEvalContext())) { |
2385 | return false; |
2386 | } |
2387 | } else { |
2388 | MOZ_ASSERT(sc->isModuleContext())do { static_assert( mozilla::detail::AssertionConditionType< decltype(sc->isModuleContext())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(sc->isModuleContext()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("sc->isModuleContext()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2388); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isModuleContext()" ")"); do { *((volatile int*)__null) = 2388; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2389 | if (!emitterScope.enterModule(this, sc->asModuleContext())) { |
2390 | return false; |
2391 | } |
2392 | if (sc->asModuleContext()->isAsync()) { |
2393 | topLevelAwait.emplace(this); |
2394 | } |
2395 | } |
2396 | |
2397 | setFunctionBodyEndPos(body->pn_pos.end); |
2398 | |
2399 | bool isSloppyEval = sc->isEvalContext() && !sc->strict(); |
2400 | if (isSloppyEval && body->is<LexicalScopeNode>() && |
2401 | !body->as<LexicalScopeNode>().isEmptyScope()) { |
2402 | // Sloppy eval scripts may emit hoisted functions bindings with a |
2403 | // `JSOp::GlobalOrEvalDeclInstantiation` opcode below. If this eval needs a |
2404 | // top-level lexical environment, we must ensure that environment is created |
2405 | // before those functions are created and bound. |
2406 | // |
2407 | // This differs from the global-script case below because the global-lexical |
2408 | // environment exists outside the script itself. In the case of strict eval |
2409 | // scripts, the `emitterScope` above is already sufficient. |
2410 | EmitterScope lexicalEmitterScope(this); |
2411 | LexicalScopeNode* scope = &body->as<LexicalScopeNode>(); |
2412 | |
2413 | if (!lexicalEmitterScope.enterLexical(this, ScopeKind::Lexical, |
2414 | scope->scopeBindings())) { |
2415 | return false; |
2416 | } |
2417 | |
2418 | if (!emitDeclarationInstantiation(scope->scopeBody())) { |
2419 | return false; |
2420 | } |
2421 | |
2422 | switchToMain(); |
2423 | |
2424 | ParseNode* scopeBody = scope->scopeBody(); |
2425 | if (!emitLexicalScopeBody(scopeBody)) { |
2426 | return false; |
2427 | } |
2428 | |
2429 | if (!updateSourceCoordNotes(scopeBody->pn_pos.end)) { |
2430 | return false; |
2431 | } |
2432 | |
2433 | if (!lexicalEmitterScope.leave(this)) { |
2434 | return false; |
2435 | } |
2436 | } else { |
2437 | if (!emitDeclarationInstantiation(body)) { |
2438 | return false; |
2439 | } |
2440 | if (topLevelAwait) { |
2441 | if (!topLevelAwait->prepareForModule()) { |
2442 | return false; |
2443 | } |
2444 | } |
2445 | |
2446 | switchToMain(); |
2447 | |
2448 | #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT |
2449 | if (!emitterScope.prepareForModuleDisposableScopeBody(this)) { |
2450 | return false; |
2451 | } |
2452 | #endif |
2453 | |
2454 | if (topLevelAwait) { |
2455 | if (!topLevelAwait->prepareForBody()) { |
2456 | return false; |
2457 | } |
2458 | } |
2459 | |
2460 | if (!emitTree(body)) { |
2461 | // [stack] |
2462 | return false; |
2463 | } |
2464 | |
2465 | if (!updateSourceCoordNotes(body->pn_pos.end)) { |
2466 | return false; |
2467 | } |
2468 | } |
2469 | |
2470 | if (topLevelAwait) { |
2471 | if (!topLevelAwait->emitEndModule()) { |
2472 | return false; |
2473 | } |
2474 | } |
2475 | |
2476 | #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT |
2477 | if (!emitterScope.emitModuleDisposableScopeBodyEnd(this)) { |
2478 | return false; |
2479 | } |
2480 | #endif |
2481 | |
2482 | if (!markSimpleBreakpoint()) { |
2483 | return false; |
2484 | } |
2485 | |
2486 | if (!emitReturnRval()) { |
2487 | return false; |
2488 | } |
2489 | |
2490 | if (!emitterScope.leave(this)) { |
2491 | return false; |
2492 | } |
2493 | |
2494 | if (!NameFunctions(fc, parserAtoms(), body)) { |
2495 | return false; |
2496 | } |
2497 | |
2498 | // Create a Stencil and convert it into a JSScript. |
2499 | return intoScriptStencil(CompilationStencil::TopLevelIndex); |
2500 | } |
2501 | |
2502 | js::UniquePtr<ImmutableScriptData> |
2503 | BytecodeEmitter::createImmutableScriptData() { |
2504 | uint32_t nslots; |
2505 | if (!getNslots(&nslots)) { |
2506 | return nullptr; |
2507 | } |
2508 | |
2509 | bool isFunction = sc->isFunctionBox(); |
2510 | uint16_t funLength = isFunction ? sc->asFunctionBox()->length() : 0; |
2511 | |
2512 | mozilla::SaturateUint8 propertyCountEstimate = propertyAdditionEstimate; |
2513 | |
2514 | // Add fields to the property count estimate. |
2515 | if (isFunction && sc->asFunctionBox()->useMemberInitializers()) { |
2516 | propertyCountEstimate += |
2517 | sc->asFunctionBox()->memberInitializers().numMemberInitializers; |
2518 | } |
2519 | |
2520 | return ImmutableScriptData::new_( |
2521 | fc, mainOffset(), maxFixedSlots, nslots, bodyScopeIndex, |
2522 | bytecodeSection().numICEntries(), isFunction, funLength, |
2523 | propertyCountEstimate.value(), bytecodeSection().code(), |
2524 | bytecodeSection().notes(), bytecodeSection().resumeOffsetList().span(), |
2525 | bytecodeSection().scopeNoteList().span(), |
2526 | bytecodeSection().tryNoteList().span()); |
2527 | } |
2528 | |
2529 | #if defined(ENABLE_DECORATORS) || defined(ENABLE_EXPLICIT_RESOURCE_MANAGEMENT) |
2530 | bool BytecodeEmitter::emitCheckIsCallable() { |
2531 | // This emits code to check if the value at the top of the stack is |
2532 | // callable. The value is left on the stack. |
2533 | // [stack] VAL |
2534 | if (!emitAtomOp(JSOp::GetIntrinsic, |
2535 | TaggedParserAtomIndex::WellKnown::IsCallable())) { |
2536 | // [stack] VAL ISCALLABLE |
2537 | return false; |
2538 | } |
2539 | if (!emit1(JSOp::Undefined)) { |
2540 | // [stack] VAL ISCALLABLE UNDEFINED |
2541 | return false; |
2542 | } |
2543 | if (!emitDupAt(2)) { |
2544 | // [stack] VAL ISCALLABLE UNDEFINED VAL |
2545 | return false; |
2546 | } |
2547 | return emitCall(JSOp::Call, 1); |
2548 | // [stack] VAL ISCALLABLE_RESULT |
2549 | } |
2550 | #endif |
2551 | |
2552 | bool BytecodeEmitter::getNslots(uint32_t* nslots) { |
2553 | uint64_t nslots64 = |
2554 | maxFixedSlots + static_cast<uint64_t>(bytecodeSection().maxStackDepth()); |
2555 | if (nslots64 > UINT32_MAX(4294967295U)) { |
2556 | reportError(nullptr, JSMSG_NEED_DIET, "script"); |
2557 | return false; |
2558 | } |
2559 | *nslots = nslots64; |
2560 | return true; |
2561 | } |
2562 | |
2563 | bool BytecodeEmitter::emitFunctionScript(FunctionNode* funNode) { |
2564 | MOZ_ASSERT(inPrologue())do { static_assert( mozilla::detail::AssertionConditionType< decltype(inPrologue())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(inPrologue()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("inPrologue()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2564); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inPrologue()" ")"); do { *((volatile int*)__null) = 2564; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2565 | ParamsBodyNode* paramsBody = funNode->body(); |
2566 | FunctionBox* funbox = sc->asFunctionBox(); |
2567 | |
2568 | setScriptStartOffsetIfUnset(paramsBody->pn_pos.begin); |
2569 | |
2570 | // [stack] |
2571 | |
2572 | FunctionScriptEmitter fse(this, funbox, Some(paramsBody->pn_pos.begin), |
2573 | Some(paramsBody->pn_pos.end)); |
2574 | if (!fse.prepareForParameters()) { |
2575 | // [stack] |
2576 | return false; |
2577 | } |
2578 | |
2579 | if (!emitFunctionFormalParameters(paramsBody)) { |
2580 | // [stack] |
2581 | return false; |
2582 | } |
2583 | |
2584 | if (!fse.prepareForBody()) { |
2585 | // [stack] |
2586 | return false; |
2587 | } |
2588 | |
2589 | if (!emitTree(paramsBody->body())) { |
2590 | // [stack] |
2591 | return false; |
2592 | } |
2593 | |
2594 | if (!fse.emitEndBody()) { |
2595 | // [stack] |
2596 | return false; |
2597 | } |
2598 | |
2599 | if (funbox->index() == CompilationStencil::TopLevelIndex) { |
2600 | if (!NameFunctions(fc, parserAtoms(), funNode)) { |
2601 | return false; |
2602 | } |
2603 | } |
2604 | |
2605 | return fse.intoStencil(); |
2606 | } |
2607 | |
2608 | bool BytecodeEmitter::emitDestructuringLHSRef(ParseNode* target, |
2609 | size_t* emitted) { |
2610 | #ifdef DEBUG1 |
2611 | int depth = bytecodeSection().stackDepth(); |
2612 | #endif |
2613 | |
2614 | switch (target->getKind()) { |
2615 | case ParseNodeKind::Name: |
2616 | case ParseNodeKind::ArrayExpr: |
2617 | case ParseNodeKind::ObjectExpr: |
2618 | // No need to recurse into ParseNodeKind::Array and ParseNodeKind::Object |
2619 | // subpatterns here, since emitSetOrInitializeDestructuring does the |
2620 | // recursion when setting or initializing the value. Getting reference |
2621 | // doesn't recurse. |
2622 | *emitted = 0; |
2623 | break; |
2624 | |
2625 | case ParseNodeKind::ArgumentsLength: |
2626 | case ParseNodeKind::DotExpr: { |
2627 | PropertyAccess* prop = &target->as<PropertyAccess>(); |
2628 | bool isSuper = prop->isSuper(); |
2629 | PropOpEmitter poe(this, PropOpEmitter::Kind::SimpleAssignment, |
2630 | isSuper ? PropOpEmitter::ObjKind::Super |
2631 | : PropOpEmitter::ObjKind::Other); |
2632 | if (!poe.prepareForObj()) { |
2633 | return false; |
2634 | } |
2635 | if (isSuper) { |
2636 | UnaryNode* base = &prop->expression().as<UnaryNode>(); |
2637 | if (!emitGetThisForSuperBase(base)) { |
2638 | // [stack] THIS SUPERBASE |
2639 | return false; |
2640 | } |
2641 | } else { |
2642 | if (!emitTree(&prop->expression())) { |
2643 | // [stack] OBJ |
2644 | return false; |
2645 | } |
2646 | } |
2647 | if (!poe.prepareForRhs()) { |
2648 | // [stack] # if Super |
2649 | // [stack] THIS SUPERBASE |
2650 | // [stack] # otherwise |
2651 | // [stack] OBJ |
2652 | return false; |
2653 | } |
2654 | |
2655 | // SUPERBASE was pushed onto THIS in poe.prepareForRhs above. |
2656 | *emitted = 1 + isSuper; |
2657 | break; |
2658 | } |
2659 | |
2660 | case ParseNodeKind::ElemExpr: { |
2661 | PropertyByValue* elem = &target->as<PropertyByValue>(); |
2662 | bool isSuper = elem->isSuper(); |
2663 | MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!elem->key().isKind(ParseNodeKind::PrivateName))> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!elem->key().isKind(ParseNodeKind::PrivateName))) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!elem->key().isKind(ParseNodeKind::PrivateName)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2663); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)" ")"); do { *((volatile int*)__null) = 2663; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2664 | ElemOpEmitter eoe(this, ElemOpEmitter::Kind::SimpleAssignment, |
2665 | isSuper ? ElemOpEmitter::ObjKind::Super |
2666 | : ElemOpEmitter::ObjKind::Other); |
2667 | if (!emitElemObjAndKey(elem, isSuper, eoe)) { |
2668 | // [stack] # if Super |
2669 | // [stack] THIS KEY |
2670 | // [stack] # otherwise |
2671 | // [stack] OBJ KEY |
2672 | return false; |
2673 | } |
2674 | if (!eoe.prepareForRhs()) { |
2675 | // [stack] # if Super |
2676 | // [stack] THIS KEY SUPERBASE |
2677 | // [stack] # otherwise |
2678 | // [stack] OBJ KEY |
2679 | return false; |
2680 | } |
2681 | |
2682 | // SUPERBASE was pushed onto KEY in eoe.prepareForRhs above. |
2683 | *emitted = 2 + isSuper; |
2684 | break; |
2685 | } |
2686 | |
2687 | case ParseNodeKind::PrivateMemberExpr: { |
2688 | PrivateMemberAccess* privateExpr = &target->as<PrivateMemberAccess>(); |
2689 | PrivateOpEmitter xoe(this, PrivateOpEmitter::Kind::SimpleAssignment, |
2690 | privateExpr->privateName().name()); |
2691 | if (!emitTree(&privateExpr->expression())) { |
2692 | // [stack] OBJ |
2693 | return false; |
2694 | } |
2695 | if (!xoe.emitReference()) { |
2696 | // [stack] OBJ NAME |
2697 | return false; |
2698 | } |
2699 | *emitted = xoe.numReferenceSlots(); |
2700 | break; |
2701 | } |
2702 | |
2703 | case ParseNodeKind::CallExpr: |
2704 | MOZ_ASSERT_UNREACHABLE(do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget " "rejects function calls as assignment " "targets in destructuring assignments" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2707); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget " "rejects function calls as assignment " "targets in destructuring assignments" ")"); do { *((volatile int*)__null) = 2707; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2705 | "Parser::reportIfNotValidSimpleAssignmentTarget "do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget " "rejects function calls as assignment " "targets in destructuring assignments" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2707); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget " "rejects function calls as assignment " "targets in destructuring assignments" ")"); do { *((volatile int*)__null) = 2707; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2706 | "rejects function calls as assignment "do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget " "rejects function calls as assignment " "targets in destructuring assignments" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2707); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget " "rejects function calls as assignment " "targets in destructuring assignments" ")"); do { *((volatile int*)__null) = 2707; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2707 | "targets in destructuring assignments")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget " "rejects function calls as assignment " "targets in destructuring assignments" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2707); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget " "rejects function calls as assignment " "targets in destructuring assignments" ")"); do { *((volatile int*)__null) = 2707; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2708 | break; |
2709 | |
2710 | default: |
2711 | MOZ_CRASH("emitDestructuringLHSRef: bad lhs kind")do { do { } while (false); MOZ_ReportCrash("" "emitDestructuringLHSRef: bad lhs kind" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2711); AnnotateMozCrashReason("MOZ_CRASH(" "emitDestructuringLHSRef: bad lhs kind" ")"); do { *((volatile int*)__null) = 2711; __attribute__((nomerge )) ::abort(); } while (false); } while (false); |
2712 | } |
2713 | |
2714 | MOZ_ASSERT(bytecodeSection().stackDepth() == depth + int(*emitted))do { static_assert( mozilla::detail::AssertionConditionType< decltype(bytecodeSection().stackDepth() == depth + int(*emitted ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(bytecodeSection().stackDepth() == depth + int(*emitted )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("bytecodeSection().stackDepth() == depth + int(*emitted)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2714); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == depth + int(*emitted)" ")"); do { *((volatile int*)__null) = 2714; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2715 | |
2716 | return true; |
2717 | } |
2718 | |
2719 | bool BytecodeEmitter::emitSetOrInitializeDestructuring( |
2720 | ParseNode* target, DestructuringFlavor flav) { |
2721 | // Now emit the lvalue opcode sequence. If the lvalue is a nested |
2722 | // destructuring initialiser-form, call ourselves to handle it, then pop |
2723 | // the matched value. Otherwise emit an lvalue bytecode sequence followed |
2724 | // by an assignment op. |
2725 | |
2726 | switch (target->getKind()) { |
2727 | case ParseNodeKind::ArrayExpr: |
2728 | case ParseNodeKind::ObjectExpr: |
2729 | if (!emitDestructuringOps(&target->as<ListNode>(), flav)) { |
2730 | return false; |
2731 | } |
2732 | // emitDestructuringOps leaves the assigned (to-be-destructured) value on |
2733 | // top of the stack. |
2734 | break; |
2735 | |
2736 | case ParseNodeKind::Name: { |
2737 | auto name = target->as<NameNode>().name(); |
2738 | NameLocation loc = lookupName(name); |
2739 | NameOpEmitter::Kind kind; |
2740 | switch (flav) { |
2741 | case DestructuringFlavor::Declaration: |
2742 | kind = NameOpEmitter::Kind::Initialize; |
2743 | break; |
2744 | |
2745 | case DestructuringFlavor::Assignment: |
2746 | kind = NameOpEmitter::Kind::SimpleAssignment; |
2747 | break; |
2748 | } |
2749 | |
2750 | NameOpEmitter noe(this, name, loc, kind); |
2751 | if (!noe.prepareForRhs()) { |
2752 | // [stack] V ENV? |
2753 | return false; |
2754 | } |
2755 | if (noe.emittedBindOp()) { |
2756 | // This is like ordinary assignment, but with one difference. |
2757 | // |
2758 | // In `a = b`, we first determine a binding for `a` (using |
2759 | // JSOp::BindName or JSOp::BindGName), then we evaluate `b`, then |
2760 | // a JSOp::SetName instruction. |
2761 | // |
2762 | // In `[a] = [b]`, per spec, `b` is evaluated first, then we |
2763 | // determine a binding for `a`. Then we need to do assignment-- |
2764 | // but the operands are on the stack in the wrong order for |
2765 | // JSOp::SetProp, so we have to add a JSOp::Swap. |
2766 | // |
2767 | // In the cases where we are emitting a name op, emit a swap |
2768 | // because of this. |
2769 | if (!emit1(JSOp::Swap)) { |
2770 | // [stack] ENV V |
2771 | return false; |
2772 | } |
2773 | } else { |
2774 | // In cases of emitting a frame slot or environment slot, |
2775 | // nothing needs be done. |
2776 | } |
2777 | if (!noe.emitAssignment()) { |
2778 | // [stack] V |
2779 | return false; |
2780 | } |
2781 | |
2782 | break; |
2783 | } |
2784 | |
2785 | case ParseNodeKind::ArgumentsLength: |
2786 | case ParseNodeKind::DotExpr: { |
2787 | // The reference is already pushed by emitDestructuringLHSRef. |
2788 | // [stack] # if Super |
2789 | // [stack] THIS SUPERBASE VAL |
2790 | // [stack] # otherwise |
2791 | // [stack] OBJ VAL |
2792 | PropertyAccess* prop = &target->as<PropertyAccess>(); |
2793 | bool isSuper = prop->isSuper(); |
2794 | PropOpEmitter poe(this, PropOpEmitter::Kind::SimpleAssignment, |
2795 | isSuper ? PropOpEmitter::ObjKind::Super |
2796 | : PropOpEmitter::ObjKind::Other); |
2797 | if (!poe.skipObjAndRhs()) { |
2798 | return false; |
2799 | } |
2800 | // [stack] # VAL |
2801 | if (!poe.emitAssignment(prop->key().atom())) { |
2802 | return false; |
2803 | } |
2804 | break; |
2805 | } |
2806 | |
2807 | case ParseNodeKind::ElemExpr: { |
2808 | // The reference is already pushed by emitDestructuringLHSRef. |
2809 | // [stack] # if Super |
2810 | // [stack] THIS KEY SUPERBASE VAL |
2811 | // [stack] # otherwise |
2812 | // [stack] OBJ KEY VAL |
2813 | PropertyByValue* elem = &target->as<PropertyByValue>(); |
2814 | bool isSuper = elem->isSuper(); |
2815 | MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!elem->key().isKind(ParseNodeKind::PrivateName))> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!elem->key().isKind(ParseNodeKind::PrivateName))) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!elem->key().isKind(ParseNodeKind::PrivateName)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2815); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)" ")"); do { *((volatile int*)__null) = 2815; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2816 | ElemOpEmitter eoe(this, ElemOpEmitter::Kind::SimpleAssignment, |
2817 | isSuper ? ElemOpEmitter::ObjKind::Super |
2818 | : ElemOpEmitter::ObjKind::Other); |
2819 | if (!eoe.skipObjAndKeyAndRhs()) { |
2820 | return false; |
2821 | } |
2822 | if (!eoe.emitAssignment()) { |
2823 | // [stack] VAL |
2824 | return false; |
2825 | } |
2826 | break; |
2827 | } |
2828 | |
2829 | case ParseNodeKind::PrivateMemberExpr: { |
2830 | // The reference is already pushed by emitDestructuringLHSRef. |
2831 | // [stack] OBJ NAME VAL |
2832 | PrivateMemberAccess* privateExpr = &target->as<PrivateMemberAccess>(); |
2833 | PrivateOpEmitter xoe(this, PrivateOpEmitter::Kind::SimpleAssignment, |
2834 | privateExpr->privateName().name()); |
2835 | if (!xoe.skipReference()) { |
2836 | return false; |
2837 | } |
2838 | if (!xoe.emitAssignment()) { |
2839 | // [stack] VAL |
2840 | return false; |
2841 | } |
2842 | break; |
2843 | } |
2844 | |
2845 | case ParseNodeKind::CallExpr: |
2846 | MOZ_ASSERT_UNREACHABLE(do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget " "rejects function calls as assignment " "targets in destructuring assignments" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2849); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget " "rejects function calls as assignment " "targets in destructuring assignments" ")"); do { *((volatile int*)__null) = 2849; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2847 | "Parser::reportIfNotValidSimpleAssignmentTarget "do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget " "rejects function calls as assignment " "targets in destructuring assignments" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2849); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget " "rejects function calls as assignment " "targets in destructuring assignments" ")"); do { *((volatile int*)__null) = 2849; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2848 | "rejects function calls as assignment "do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget " "rejects function calls as assignment " "targets in destructuring assignments" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2849); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget " "rejects function calls as assignment " "targets in destructuring assignments" ")"); do { *((volatile int*)__null) = 2849; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2849 | "targets in destructuring assignments")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget " "rejects function calls as assignment " "targets in destructuring assignments" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2849); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "Parser::reportIfNotValidSimpleAssignmentTarget " "rejects function calls as assignment " "targets in destructuring assignments" ")"); do { *((volatile int*)__null) = 2849; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2850 | break; |
2851 | |
2852 | default: |
2853 | MOZ_CRASH("emitSetOrInitializeDestructuring: bad lhs kind")do { do { } while (false); MOZ_ReportCrash("" "emitSetOrInitializeDestructuring: bad lhs kind" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2853); AnnotateMozCrashReason("MOZ_CRASH(" "emitSetOrInitializeDestructuring: bad lhs kind" ")"); do { *((volatile int*)__null) = 2853; __attribute__((nomerge )) ::abort(); } while (false); } while (false); |
2854 | } |
2855 | |
2856 | // Pop the assigned value. |
2857 | if (!emit1(JSOp::Pop)) { |
2858 | // [stack] # empty |
2859 | return false; |
2860 | } |
2861 | |
2862 | return true; |
2863 | } |
2864 | |
2865 | JSOp BytecodeEmitter::getIterCallOp(JSOp callOp, |
2866 | SelfHostedIter selfHostedIter) { |
2867 | if (emitterMode == BytecodeEmitter::SelfHosting) { |
2868 | MOZ_ASSERT(selfHostedIter != SelfHostedIter::Deny)do { static_assert( mozilla::detail::AssertionConditionType< decltype(selfHostedIter != SelfHostedIter::Deny)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(selfHostedIter != SelfHostedIter::Deny))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2868); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny" ")"); do { *((volatile int*)__null) = 2868; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2869 | |
2870 | switch (callOp) { |
2871 | case JSOp::Call: |
2872 | return JSOp::CallContent; |
2873 | case JSOp::CallIter: |
2874 | return JSOp::CallContentIter; |
2875 | default: |
2876 | MOZ_CRASH("Unknown iterator call op")do { do { } while (false); MOZ_ReportCrash("" "Unknown iterator call op" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2876); AnnotateMozCrashReason("MOZ_CRASH(" "Unknown iterator call op" ")"); do { *((volatile int*)__null) = 2876; __attribute__((nomerge )) ::abort(); } while (false); } while (false); |
2877 | } |
2878 | } |
2879 | |
2880 | return callOp; |
2881 | } |
2882 | |
2883 | bool BytecodeEmitter::emitIteratorNext( |
2884 | const Maybe<uint32_t>& callSourceCoordOffset, |
2885 | IteratorKind iterKind /* = IteratorKind::Sync */, |
2886 | SelfHostedIter selfHostedIter /* = SelfHostedIter::Deny */) { |
2887 | MOZ_ASSERT(selfHostedIter != SelfHostedIter::Deny ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter ::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" " (" ".next() iteration is prohibited in self-hosted code because it" "can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2890); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" ") (" ".next() iteration is prohibited in self-hosted code because it" "can run user-modifiable iteration code" ")"); do { *((volatile int*)__null) = 2890; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
2888 | emitterMode != BytecodeEmitter::SelfHosting,do { static_assert( mozilla::detail::AssertionConditionType< decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter ::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" " (" ".next() iteration is prohibited in self-hosted code because it" "can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2890); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" ") (" ".next() iteration is prohibited in self-hosted code because it" "can run user-modifiable iteration code" ")"); do { *((volatile int*)__null) = 2890; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
2889 | ".next() iteration is prohibited in self-hosted code because it"do { static_assert( mozilla::detail::AssertionConditionType< decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter ::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" " (" ".next() iteration is prohibited in self-hosted code because it" "can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2890); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" ") (" ".next() iteration is prohibited in self-hosted code because it" "can run user-modifiable iteration code" ")"); do { *((volatile int*)__null) = 2890; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
2890 | "can run user-modifiable iteration code")do { static_assert( mozilla::detail::AssertionConditionType< decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter ::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" " (" ".next() iteration is prohibited in self-hosted code because it" "can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2890); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" ") (" ".next() iteration is prohibited in self-hosted code because it" "can run user-modifiable iteration code" ")"); do { *((volatile int*)__null) = 2890; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
2891 | |
2892 | // [stack] ... NEXT ITER |
2893 | MOZ_ASSERT(bytecodeSection().stackDepth() >= 2)do { static_assert( mozilla::detail::AssertionConditionType< decltype(bytecodeSection().stackDepth() >= 2)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(bytecodeSection().stackDepth() >= 2))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("bytecodeSection().stackDepth() >= 2" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2893); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() >= 2" ")"); do { *((volatile int*)__null) = 2893; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2894 | |
2895 | if (!emitCall(getIterCallOp(JSOp::Call, selfHostedIter), 0, |
2896 | callSourceCoordOffset)) { |
2897 | // [stack] ... RESULT |
2898 | return false; |
2899 | } |
2900 | |
2901 | if (iterKind == IteratorKind::Async) { |
2902 | if (!emitAwaitInInnermostScope()) { |
2903 | // [stack] ... RESULT |
2904 | return false; |
2905 | } |
2906 | } |
2907 | |
2908 | if (!emitCheckIsObj(CheckIsObjectKind::IteratorNext)) { |
2909 | // [stack] ... RESULT |
2910 | return false; |
2911 | } |
2912 | return true; |
2913 | } |
2914 | |
2915 | bool BytecodeEmitter::emitIteratorCloseInScope( |
2916 | EmitterScope& currentScope, |
2917 | IteratorKind iterKind /* = IteratorKind::Sync */, |
2918 | CompletionKind completionKind /* = CompletionKind::Normal */, |
2919 | SelfHostedIter selfHostedIter /* = SelfHostedIter::Deny */) { |
2920 | MOZ_ASSERT(selfHostedIter != SelfHostedIter::Deny ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter ::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" " (" ".close() on iterators is prohibited in self-hosted code because " "it can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2923); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" ") (" ".close() on iterators is prohibited in self-hosted code because " "it can run user-modifiable iteration code" ")"); do { *((volatile int*)__null) = 2923; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
2921 | emitterMode != BytecodeEmitter::SelfHosting,do { static_assert( mozilla::detail::AssertionConditionType< decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter ::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" " (" ".close() on iterators is prohibited in self-hosted code because " "it can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2923); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" ") (" ".close() on iterators is prohibited in self-hosted code because " "it can run user-modifiable iteration code" ")"); do { *((volatile int*)__null) = 2923; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
2922 | ".close() on iterators is prohibited in self-hosted code because "do { static_assert( mozilla::detail::AssertionConditionType< decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter ::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" " (" ".close() on iterators is prohibited in self-hosted code because " "it can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2923); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" ") (" ".close() on iterators is prohibited in self-hosted code because " "it can run user-modifiable iteration code" ")"); do { *((volatile int*)__null) = 2923; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
2923 | "it can run user-modifiable iteration code")do { static_assert( mozilla::detail::AssertionConditionType< decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter ::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" " (" ".close() on iterators is prohibited in self-hosted code because " "it can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 2923); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" ") (" ".close() on iterators is prohibited in self-hosted code because " "it can run user-modifiable iteration code" ")"); do { *((volatile int*)__null) = 2923; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
2924 | |
2925 | if (iterKind == IteratorKind::Sync) { |
2926 | return emit2(JSOp::CloseIter, uint8_t(completionKind)); |
2927 | } |
2928 | |
2929 | // Generate inline logic corresponding to IteratorClose (ES2021 7.4.6) and |
2930 | // AsyncIteratorClose (ES2021 7.4.7). Steps numbers apply to both operations. |
2931 | // |
2932 | // Callers need to ensure that the iterator object is at the top of the |
2933 | // stack. |
2934 | |
2935 | // For non-Throw completions, we emit the equivalent of: |
2936 | // |
2937 | // var returnMethod = GetMethod(iterator, "return"); |
2938 | // if (returnMethod !== undefined) { |
2939 | // var innerResult = [Await] Call(returnMethod, iterator); |
2940 | // CheckIsObj(innerResult); |
2941 | // } |
2942 | // |
2943 | // Whereas for Throw completions, we emit: |
2944 | // |
2945 | // try { |
2946 | // var returnMethod = GetMethod(iterator, "return"); |
2947 | // if (returnMethod !== undefined) { |
2948 | // [Await] Call(returnMethod, iterator); |
2949 | // } |
2950 | // } catch {} |
2951 | |
2952 | Maybe<TryEmitter> tryCatch; |
2953 | |
2954 | if (completionKind == CompletionKind::Throw) { |
2955 | tryCatch.emplace(this, TryEmitter::Kind::TryCatch, |
2956 | TryEmitter::ControlKind::NonSyntactic); |
2957 | |
2958 | if (!tryCatch->emitTry()) { |
2959 | // [stack] ... ITER |
2960 | return false; |
2961 | } |
2962 | } |
2963 | |
2964 | if (!emit1(JSOp::Dup)) { |
2965 | // [stack] ... ITER ITER |
2966 | return false; |
2967 | } |
2968 | |
2969 | // Steps 1-2 are assertions, step 3 is implicit. |
2970 | |
2971 | // Step 4. |
2972 | // |
2973 | // Get the "return" method. |
2974 | if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::return_())) { |
2975 | // [stack] ... ITER RET |
2976 | return false; |
2977 | } |
2978 | |
2979 | // Step 5. |
2980 | // |
2981 | // Do nothing if "return" is undefined or null. |
2982 | InternalIfEmitter ifReturnMethodIsDefined(this); |
2983 | if (!emit1(JSOp::IsNullOrUndefined)) { |
2984 | // [stack] ... ITER RET NULL-OR-UNDEF |
2985 | return false; |
2986 | } |
2987 | |
2988 | if (!ifReturnMethodIsDefined.emitThenElse( |
2989 | IfEmitter::ConditionKind::Negative)) { |
2990 | // [stack] ... ITER RET |
2991 | return false; |
2992 | } |
2993 | |
2994 | // Steps 5.c, 7. |
2995 | // |
2996 | // Call the "return" method. |
2997 | if (!emit1(JSOp::Swap)) { |
2998 | // [stack] ... RET ITER |
2999 | return false; |
3000 | } |
3001 | |
3002 | if (!emitCall(getIterCallOp(JSOp::Call, selfHostedIter), 0)) { |
3003 | // [stack] ... RESULT |
3004 | return false; |
3005 | } |
3006 | |
3007 | // 7.4.7 AsyncIteratorClose, step 5.d. |
3008 | if (iterKind == IteratorKind::Async) { |
3009 | if (completionKind != CompletionKind::Throw) { |
3010 | // Await clobbers rval, so save the current rval. |
3011 | if (!emit1(JSOp::GetRval)) { |
3012 | // [stack] ... RESULT RVAL |
3013 | return false; |
3014 | } |
3015 | if (!emit1(JSOp::Swap)) { |
3016 | // [stack] ... RVAL RESULT |
3017 | return false; |
3018 | } |
3019 | } |
3020 | |
3021 | if (!emitAwaitInScope(currentScope)) { |
3022 | // [stack] ... RVAL? RESULT |
3023 | return false; |
3024 | } |
3025 | |
3026 | if (completionKind != CompletionKind::Throw) { |
3027 | if (!emit1(JSOp::Swap)) { |
3028 | // [stack] ... RESULT RVAL |
3029 | return false; |
3030 | } |
3031 | if (!emit1(JSOp::SetRval)) { |
3032 | // [stack] ... RESULT |
3033 | return false; |
3034 | } |
3035 | } |
3036 | } |
3037 | |
3038 | // Step 6 (Handled in caller). |
3039 | |
3040 | // Step 8. |
3041 | if (completionKind != CompletionKind::Throw) { |
3042 | // Check that the "return" result is an object. |
3043 | if (!emitCheckIsObj(CheckIsObjectKind::IteratorReturn)) { |
3044 | // [stack] ... RESULT |
3045 | return false; |
3046 | } |
3047 | } |
3048 | |
3049 | if (!ifReturnMethodIsDefined.emitElse()) { |
3050 | // [stack] ... ITER RET |
3051 | return false; |
3052 | } |
3053 | |
3054 | if (!emit1(JSOp::Pop)) { |
3055 | // [stack] ... ITER |
3056 | return false; |
3057 | } |
3058 | |
3059 | if (!ifReturnMethodIsDefined.emitEnd()) { |
3060 | return false; |
3061 | } |
3062 | |
3063 | if (completionKind == CompletionKind::Throw) { |
3064 | if (!tryCatch->emitCatch()) { |
3065 | // [stack] ... ITER EXC |
3066 | return false; |
3067 | } |
3068 | |
3069 | // Just ignore the exception thrown by call and await. |
3070 | if (!emit1(JSOp::Pop)) { |
3071 | // [stack] ... ITER |
3072 | return false; |
3073 | } |
3074 | |
3075 | if (!tryCatch->emitEnd()) { |
3076 | // [stack] ... ITER |
3077 | return false; |
3078 | } |
3079 | } |
3080 | |
3081 | // Step 9 (Handled in caller). |
3082 | |
3083 | return emit1(JSOp::Pop); |
3084 | // [stack] ... |
3085 | } |
3086 | |
3087 | template <typename InnerEmitter> |
3088 | bool BytecodeEmitter::wrapWithDestructuringTryNote(int32_t iterDepth, |
3089 | InnerEmitter emitter) { |
3090 | MOZ_ASSERT(bytecodeSection().stackDepth() >= iterDepth)do { static_assert( mozilla::detail::AssertionConditionType< decltype(bytecodeSection().stackDepth() >= iterDepth)>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(bytecodeSection().stackDepth() >= iterDepth))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("bytecodeSection().stackDepth() >= iterDepth" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3090); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() >= iterDepth" ")"); do { *((volatile int*)__null) = 3090; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3091 | |
3092 | // Pad a nop at the beginning of the bytecode covered by the trynote so |
3093 | // that when unwinding environments, we may unwind to the scope |
3094 | // corresponding to the pc *before* the start, in case the first bytecode |
3095 | // emitted by |emitter| is the start of an inner scope. See comment above |
3096 | // UnwindEnvironmentToTryPc. |
3097 | if (!emit1(JSOp::TryDestructuring)) { |
3098 | return false; |
3099 | } |
3100 | |
3101 | BytecodeOffset start = bytecodeSection().offset(); |
3102 | if (!emitter(this)) { |
3103 | return false; |
3104 | } |
3105 | BytecodeOffset end = bytecodeSection().offset(); |
3106 | if (start != end) { |
3107 | return addTryNote(TryNoteKind::Destructuring, iterDepth, start, end); |
3108 | } |
3109 | return true; |
3110 | } |
3111 | |
3112 | bool BytecodeEmitter::emitDefault(ParseNode* defaultExpr, ParseNode* pattern) { |
3113 | // [stack] VALUE |
3114 | |
3115 | DefaultEmitter de(this); |
3116 | if (!de.prepareForDefault()) { |
3117 | // [stack] |
3118 | return false; |
3119 | } |
3120 | if (!emitInitializer(defaultExpr, pattern)) { |
3121 | // [stack] DEFAULTVALUE |
3122 | return false; |
3123 | } |
3124 | if (!de.emitEnd()) { |
3125 | // [stack] VALUE/DEFAULTVALUE |
3126 | return false; |
3127 | } |
3128 | return true; |
3129 | } |
3130 | |
3131 | bool BytecodeEmitter::emitAnonymousFunctionWithName( |
3132 | ParseNode* node, TaggedParserAtomIndex name) { |
3133 | MOZ_ASSERT(node->isDirectRHSAnonFunction())do { static_assert( mozilla::detail::AssertionConditionType< decltype(node->isDirectRHSAnonFunction())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(node->isDirectRHSAnonFunction ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("node->isDirectRHSAnonFunction()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3133); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isDirectRHSAnonFunction()" ")"); do { *((volatile int*)__null) = 3133; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3134 | |
3135 | if (node->is<FunctionNode>()) { |
3136 | // Function doesn't have 'name' property at this point. |
3137 | // Set function's name at compile time. |
3138 | if (!setFunName(node->as<FunctionNode>().funbox(), name)) { |
3139 | return false; |
3140 | } |
3141 | |
3142 | return emitTree(node); |
3143 | } |
3144 | |
3145 | MOZ_ASSERT(node->is<ClassNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(node->is<ClassNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(node->is<ClassNode> ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("node->is<ClassNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3145); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->is<ClassNode>()" ")"); do { *((volatile int*)__null) = 3145; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3146 | |
3147 | return emitClass(&node->as<ClassNode>(), ClassNameKind::InferredName, name); |
3148 | } |
3149 | |
3150 | bool BytecodeEmitter::emitAnonymousFunctionWithComputedName( |
3151 | ParseNode* node, FunctionPrefixKind prefixKind) { |
3152 | MOZ_ASSERT(node->isDirectRHSAnonFunction())do { static_assert( mozilla::detail::AssertionConditionType< decltype(node->isDirectRHSAnonFunction())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(node->isDirectRHSAnonFunction ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("node->isDirectRHSAnonFunction()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3152); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isDirectRHSAnonFunction()" ")"); do { *((volatile int*)__null) = 3152; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3153 | |
3154 | if (node->is<FunctionNode>()) { |
3155 | if (!emitTree(node)) { |
3156 | // [stack] NAME FUN |
3157 | return false; |
3158 | } |
3159 | if (!emitDupAt(1)) { |
3160 | // [stack] NAME FUN NAME |
3161 | return false; |
3162 | } |
3163 | if (!emit2(JSOp::SetFunName, uint8_t(prefixKind))) { |
3164 | // [stack] NAME FUN |
3165 | return false; |
3166 | } |
3167 | return true; |
3168 | } |
3169 | |
3170 | MOZ_ASSERT(node->is<ClassNode>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(node->is<ClassNode>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(node->is<ClassNode> ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("node->is<ClassNode>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3170); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->is<ClassNode>()" ")"); do { *((volatile int*)__null) = 3170; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3171 | MOZ_ASSERT(prefixKind == FunctionPrefixKind::None)do { static_assert( mozilla::detail::AssertionConditionType< decltype(prefixKind == FunctionPrefixKind::None)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(prefixKind == FunctionPrefixKind::None))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("prefixKind == FunctionPrefixKind::None" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3171); AnnotateMozCrashReason("MOZ_ASSERT" "(" "prefixKind == FunctionPrefixKind::None" ")"); do { *((volatile int*)__null) = 3171; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3172 | |
3173 | return emitClass(&node->as<ClassNode>(), ClassNameKind::ComputedName); |
3174 | } |
3175 | |
3176 | bool BytecodeEmitter::setFunName(FunctionBox* funbox, |
3177 | TaggedParserAtomIndex name) { |
3178 | // The inferred name may already be set if this function is an interpreted |
3179 | // lazy function and we OOM'ed after we set the inferred name the first |
3180 | // time. |
3181 | if (funbox->hasInferredName()) { |
3182 | MOZ_ASSERT(!funbox->emitBytecode)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!funbox->emitBytecode)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!funbox->emitBytecode))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!funbox->emitBytecode" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3182); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!funbox->emitBytecode" ")"); do { *((volatile int*)__null) = 3182; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3183 | MOZ_ASSERT(funbox->displayAtom() == name)do { static_assert( mozilla::detail::AssertionConditionType< decltype(funbox->displayAtom() == name)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(funbox->displayAtom() == name ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "funbox->displayAtom() == name", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3183); AnnotateMozCrashReason("MOZ_ASSERT" "(" "funbox->displayAtom() == name" ")"); do { *((volatile int*)__null) = 3183; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3184 | |
3185 | return true; |
3186 | } |
3187 | |
3188 | funbox->setInferredName(name); |
3189 | return true; |
3190 | } |
3191 | |
3192 | bool BytecodeEmitter::emitInitializer(ParseNode* initializer, |
3193 | ParseNode* pattern) { |
3194 | if (initializer->isDirectRHSAnonFunction()) { |
3195 | MOZ_ASSERT(!pattern->isInParens())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!pattern->isInParens())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!pattern->isInParens()))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("!pattern->isInParens()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3195); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!pattern->isInParens()" ")"); do { *((volatile int*)__null) = 3195; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3196 | auto name = pattern->as<NameNode>().name(); |
3197 | if (!emitAnonymousFunctionWithName(initializer, name)) { |
3198 | return false; |
3199 | } |
3200 | } else { |
3201 | if (!emitTree(initializer)) { |
3202 | return false; |
3203 | } |
3204 | } |
3205 | |
3206 | return true; |
3207 | } |
3208 | |
3209 | bool BytecodeEmitter::emitDestructuringOpsArray(ListNode* pattern, |
3210 | DestructuringFlavor flav) { |
3211 | MOZ_ASSERT(getSelfHostedIterFor(pattern) == SelfHostedIter::Deny,do { static_assert( mozilla::detail::AssertionConditionType< decltype(getSelfHostedIterFor(pattern) == SelfHostedIter::Deny )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(getSelfHostedIterFor(pattern) == SelfHostedIter::Deny ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "getSelfHostedIterFor(pattern) == SelfHostedIter::Deny" " (" "array destructuring is prohibited in self-hosted code because it" "can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3213); AnnotateMozCrashReason("MOZ_ASSERT" "(" "getSelfHostedIterFor(pattern) == SelfHostedIter::Deny" ") (" "array destructuring is prohibited in self-hosted code because it" "can run user-modifiable iteration code" ")"); do { *((volatile int*)__null) = 3213; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
3212 | "array destructuring is prohibited in self-hosted code because it"do { static_assert( mozilla::detail::AssertionConditionType< decltype(getSelfHostedIterFor(pattern) == SelfHostedIter::Deny )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(getSelfHostedIterFor(pattern) == SelfHostedIter::Deny ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "getSelfHostedIterFor(pattern) == SelfHostedIter::Deny" " (" "array destructuring is prohibited in self-hosted code because it" "can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3213); AnnotateMozCrashReason("MOZ_ASSERT" "(" "getSelfHostedIterFor(pattern) == SelfHostedIter::Deny" ") (" "array destructuring is prohibited in self-hosted code because it" "can run user-modifiable iteration code" ")"); do { *((volatile int*)__null) = 3213; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
3213 | "can run user-modifiable iteration code")do { static_assert( mozilla::detail::AssertionConditionType< decltype(getSelfHostedIterFor(pattern) == SelfHostedIter::Deny )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(getSelfHostedIterFor(pattern) == SelfHostedIter::Deny ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "getSelfHostedIterFor(pattern) == SelfHostedIter::Deny" " (" "array destructuring is prohibited in self-hosted code because it" "can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3213); AnnotateMozCrashReason("MOZ_ASSERT" "(" "getSelfHostedIterFor(pattern) == SelfHostedIter::Deny" ") (" "array destructuring is prohibited in self-hosted code because it" "can run user-modifiable iteration code" ")"); do { *((volatile int*)__null) = 3213; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3214 | MOZ_ASSERT(pattern->isKind(ParseNodeKind::ArrayExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(pattern->isKind(ParseNodeKind::ArrayExpr))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(pattern->isKind(ParseNodeKind::ArrayExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("pattern->isKind(ParseNodeKind::ArrayExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3214); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pattern->isKind(ParseNodeKind::ArrayExpr)" ")"); do { *((volatile int*)__null) = 3214; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3215 | MOZ_ASSERT(bytecodeSection().stackDepth() != 0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(bytecodeSection().stackDepth() != 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(bytecodeSection().stackDepth () != 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("bytecodeSection().stackDepth() != 0", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3215); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() != 0" ")"); do { *((volatile int*)__null) = 3215; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3216 | |
3217 | // Here's pseudo code for |let [a, b, , c=y, ...d] = x;| |
3218 | // |
3219 | // Lines that are annotated "covered by trynote" mean that upon throwing |
3220 | // an exception, IteratorClose is called on iter only if done is false. |
3221 | // |
3222 | // let x, y; |
3223 | // let a, b, c, d; |
3224 | // let iter, next, lref, result, done, value; // stack values |
3225 | // |
3226 | // // NOTE: the fast path for this example is not applicable, because of |
3227 | // // the spread and the assignment |c=y|, but it is documented here for a |
3228 | // // simpler example, |let [a,b] = x;| |
3229 | // // |
3230 | // // if (IsOptimizableArray(x)) { |
3231 | // // a = x[0]; |
3232 | // // b = x[1]; |
3233 | // // goto end: // (skip everything below) |
3234 | // // } |
3235 | // |
3236 | // iter = x[Symbol.iterator](); |
3237 | // next = iter.next; |
3238 | // |
3239 | // // ==== emitted by loop for a ==== |
3240 | // lref = GetReference(a); // covered by trynote |
3241 | // |
3242 | // result = Call(next, iter); |
3243 | // done = result.done; |
3244 | // |
3245 | // if (done) |
3246 | // value = undefined; |
3247 | // else |
3248 | // value = result.value; |
3249 | // |
3250 | // SetOrInitialize(lref, value); // covered by trynote |
3251 | // |
3252 | // // ==== emitted by loop for b ==== |
3253 | // lref = GetReference(b); // covered by trynote |
3254 | // |
3255 | // if (done) { |
3256 | // value = undefined; |
3257 | // } else { |
3258 | // result = Call(next, iter); |
3259 | // done = result.done; |
3260 | // if (done) |
3261 | // value = undefined; |
3262 | // else |
3263 | // value = result.value; |
3264 | // } |
3265 | // |
3266 | // SetOrInitialize(lref, value); // covered by trynote |
3267 | // |
3268 | // // ==== emitted by loop for elision ==== |
3269 | // if (done) { |
3270 | // value = undefined; |
3271 | // } else { |
3272 | // result = Call(next, iter); |
3273 | // done = result.done; |
3274 | // if (done) |
3275 | // value = undefined; |
3276 | // else |
3277 | // value = result.value; |
3278 | // } |
3279 | // |
3280 | // // ==== emitted by loop for c ==== |
3281 | // lref = GetReference(c); // covered by trynote |
3282 | // |
3283 | // if (done) { |
3284 | // value = undefined; |
3285 | // } else { |
3286 | // result = Call(next, iter); |
3287 | // done = result.done; |
3288 | // if (done) |
3289 | // value = undefined; |
3290 | // else |
3291 | // value = result.value; |
3292 | // } |
3293 | // |
3294 | // if (value === undefined) |
3295 | // value = y; // covered by trynote |
3296 | // |
3297 | // SetOrInitialize(lref, value); // covered by trynote |
3298 | // |
3299 | // // ==== emitted by loop for d ==== |
3300 | // lref = GetReference(d); // covered by trynote |
3301 | // |
3302 | // if (done) |
3303 | // value = []; |
3304 | // else |
3305 | // value = [...iter]; |
3306 | // |
3307 | // SetOrInitialize(lref, value); // covered by trynote |
3308 | // |
3309 | // // === emitted after loop === |
3310 | // if (!done) |
3311 | // IteratorClose(iter); |
3312 | // |
3313 | // end: |
3314 | |
3315 | bool isEligibleForArrayOptimizations = true; |
3316 | for (ParseNode* member : pattern->contents()) { |
3317 | switch (member->getKind()) { |
3318 | case ParseNodeKind::Elision: |
3319 | break; |
3320 | case ParseNodeKind::Name: { |
3321 | auto name = member->as<NameNode>().name(); |
3322 | NameLocation loc = lookupName(name); |
3323 | if (loc.kind() != NameLocation::Kind::ArgumentSlot && |
3324 | loc.kind() != NameLocation::Kind::FrameSlot && |
3325 | loc.kind() != NameLocation::Kind::EnvironmentCoordinate) { |
3326 | isEligibleForArrayOptimizations = false; |
3327 | } |
3328 | break; |
3329 | } |
3330 | default: |
3331 | // Unfortunately we can't handle any recursive destructuring, |
3332 | // because we can't guarantee that the recursed-into parts |
3333 | // won't run code which invalidates our constraints. We also |
3334 | // cannot handle ParseNodeKind::AssignExpr for similar reasons. |
3335 | isEligibleForArrayOptimizations = false; |
3336 | break; |
3337 | } |
3338 | if (!isEligibleForArrayOptimizations) { |
3339 | break; |
3340 | } |
3341 | } |
3342 | |
3343 | // Use an iterator to destructure the RHS, instead of index lookup. We |
3344 | // must leave the *original* value on the stack. |
3345 | if (!emit1(JSOp::Dup)) { |
3346 | // [stack] ... OBJ OBJ |
3347 | return false; |
3348 | } |
3349 | |
3350 | Maybe<InternalIfEmitter> ifArrayOptimizable; |
3351 | |
3352 | if (isEligibleForArrayOptimizations) { |
3353 | ifArrayOptimizable.emplace( |
3354 | this, BranchEmitterBase::LexicalKind::MayContainLexicalAccessInBranch); |
3355 | |
3356 | if (!emit1(JSOp::Dup)) { |
3357 | // [stack] OBJ OBJ |
3358 | return false; |
3359 | } |
3360 | |
3361 | if (!emit1(JSOp::OptimizeGetIterator)) { |
3362 | // [stack] OBJ OBJ IS_OPTIMIZABLE |
3363 | return false; |
3364 | } |
3365 | |
3366 | if (!ifArrayOptimizable->emitThenElse()) { |
3367 | // [stack] OBJ OBJ |
3368 | return false; |
3369 | } |
3370 | |
3371 | if (!emitAtomOp(JSOp::GetProp, |
3372 | TaggedParserAtomIndex::WellKnown::length())) { |
3373 | // [stack] OBJ LENGTH |
3374 | return false; |
3375 | } |
3376 | |
3377 | if (!emit1(JSOp::Swap)) { |
3378 | // [stack] LENGTH OBJ |
3379 | return false; |
3380 | } |
3381 | |
3382 | uint32_t idx = 0; |
3383 | for (ParseNode* member : pattern->contents()) { |
3384 | if (member->isKind(ParseNodeKind::Elision)) { |
3385 | idx += 1; |
3386 | continue; |
3387 | } |
3388 | |
3389 | if (!emit1(JSOp::Dup)) { |
3390 | // [stack] LENGTH OBJ OBJ |
3391 | return false; |
3392 | } |
3393 | |
3394 | if (!emitNumberOp(idx)) { |
3395 | // [stack] LENGTH OBJ OBJ IDX |
3396 | return false; |
3397 | } |
3398 | |
3399 | if (!emit1(JSOp::Dup)) { |
3400 | // [stack] LENGTH OBJ OBJ IDX IDX |
3401 | return false; |
3402 | } |
3403 | |
3404 | if (!emitDupAt(4)) { |
3405 | // [stack] LENGTH OBJ OBJ IDX IDX LENGTH |
3406 | return false; |
3407 | } |
3408 | |
3409 | if (!emit1(JSOp::Lt)) { |
3410 | // [stack] LENGTH OBJ OBJ IDX IS_IN_DENSE_BOUNDS |
3411 | return false; |
3412 | } |
3413 | |
3414 | InternalIfEmitter isInDenseBounds(this); |
3415 | if (!isInDenseBounds.emitThenElse()) { |
3416 | // [stack] LENGTH OBJ OBJ IDX |
3417 | return false; |
3418 | } |
3419 | |
3420 | if (!emit1(JSOp::GetElem)) { |
3421 | // [stack] LENGTH OBJ VALUE |
3422 | return false; |
3423 | } |
3424 | |
3425 | if (!isInDenseBounds.emitElse()) { |
3426 | // [stack] LENGTH OBJ OBJ IDX |
3427 | return false; |
3428 | } |
3429 | |
3430 | if (!emitPopN(2)) { |
3431 | // [stack] LENGTH OBJ |
3432 | return false; |
3433 | } |
3434 | |
3435 | if (!emit1(JSOp::Undefined)) { |
3436 | // [stack] LENGTH OBJ UNDEFINED |
3437 | return false; |
3438 | } |
3439 | |
3440 | if (!isInDenseBounds.emitEnd()) { |
3441 | // [stack] LENGTH OBJ VALUE|UNDEFINED |
3442 | return false; |
3443 | } |
3444 | |
3445 | if (!emitSetOrInitializeDestructuring(member, flav)) { |
3446 | // [stack] LENGTH OBJ |
3447 | return false; |
3448 | } |
3449 | |
3450 | idx += 1; |
3451 | } |
3452 | |
3453 | if (!emit1(JSOp::Swap)) { |
3454 | // [stack] OBJ LENGTH |
3455 | return false; |
3456 | } |
3457 | |
3458 | if (!emit1(JSOp::Pop)) { |
3459 | // [stack] OBJ |
3460 | return false; |
3461 | } |
3462 | |
3463 | if (!ifArrayOptimizable->emitElse()) { |
3464 | // [stack] OBJ OBJ |
3465 | return false; |
3466 | } |
3467 | } |
3468 | |
3469 | if (!emitIterator(SelfHostedIter::Deny)) { |
3470 | // [stack] ... OBJ NEXT ITER |
3471 | return false; |
3472 | } |
3473 | |
3474 | // For an empty pattern [], call IteratorClose unconditionally. Nothing |
3475 | // else needs to be done. |
3476 | if (!pattern->head()) { |
3477 | if (!emit1(JSOp::Swap)) { |
3478 | // [stack] ... OBJ ITER NEXT |
3479 | return false; |
3480 | } |
3481 | if (!emit1(JSOp::Pop)) { |
3482 | // [stack] ... OBJ ITER |
3483 | return false; |
3484 | } |
3485 | |
3486 | if (!emitIteratorCloseInInnermostScope()) { |
3487 | // [stack] ... OBJ |
3488 | return false; |
3489 | } |
3490 | |
3491 | if (ifArrayOptimizable.isSome()) { |
3492 | if (!ifArrayOptimizable->emitEnd()) { |
3493 | // [stack] OBJ |
3494 | return false; |
3495 | } |
3496 | } |
3497 | |
3498 | return true; |
3499 | } |
3500 | |
3501 | // Push an initial FALSE value for DONE. |
3502 | if (!emit1(JSOp::False)) { |
3503 | // [stack] ... OBJ NEXT ITER FALSE |
3504 | return false; |
3505 | } |
3506 | |
3507 | // TryNoteKind::Destructuring expects the iterator and the done value |
3508 | // to be the second to top and the top of the stack, respectively. |
3509 | // IteratorClose is called upon exception only if done is false. |
3510 | int32_t tryNoteDepth = bytecodeSection().stackDepth(); |
3511 | |
3512 | for (ParseNode* member : pattern->contents()) { |
3513 | bool isFirst = member == pattern->head(); |
3514 | DebugOnly<bool> hasNext = !!member->pn_next; |
3515 | |
3516 | ParseNode* subpattern; |
3517 | if (member->isKind(ParseNodeKind::Spread)) { |
3518 | subpattern = member->as<UnaryNode>().kid(); |
3519 | |
3520 | MOZ_ASSERT(!subpattern->isKind(ParseNodeKind::AssignExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!subpattern->isKind(ParseNodeKind::AssignExpr))> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!subpattern->isKind(ParseNodeKind::AssignExpr)))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("!subpattern->isKind(ParseNodeKind::AssignExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3520); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!subpattern->isKind(ParseNodeKind::AssignExpr)" ")"); do { *((volatile int*)__null) = 3520; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3521 | } else { |
3522 | subpattern = member; |
3523 | } |
3524 | |
3525 | ParseNode* lhsPattern = subpattern; |
3526 | ParseNode* pndefault = nullptr; |
3527 | if (subpattern->isKind(ParseNodeKind::AssignExpr)) { |
3528 | lhsPattern = subpattern->as<AssignmentNode>().left(); |
3529 | pndefault = subpattern->as<AssignmentNode>().right(); |
3530 | } |
3531 | |
3532 | // Number of stack slots emitted for the LHS reference. |
3533 | size_t emitted = 0; |
3534 | |
3535 | // Spec requires LHS reference to be evaluated first. |
3536 | bool isElision = lhsPattern->isKind(ParseNodeKind::Elision); |
3537 | if (!isElision) { |
3538 | auto emitLHSRef = [lhsPattern, &emitted](BytecodeEmitter* bce) { |
3539 | return bce->emitDestructuringLHSRef(lhsPattern, &emitted); |
3540 | // [stack] ... OBJ NEXT ITER DONE LREF* |
3541 | }; |
3542 | if (!wrapWithDestructuringTryNote(tryNoteDepth, emitLHSRef)) { |
3543 | return false; |
3544 | } |
3545 | } |
3546 | |
3547 | // Pick the DONE value to the top of the stack. |
3548 | if (emitted) { |
3549 | if (!emitPickN(emitted)) { |
3550 | // [stack] ... OBJ NEXT ITER LREF* DONE |
3551 | return false; |
3552 | } |
3553 | } |
3554 | |
3555 | if (isFirst) { |
3556 | // If this element is the first, DONE is always FALSE, so pop it. |
3557 | // |
3558 | // Non-first elements should emit if-else depending on the |
3559 | // member pattern, below. |
3560 | if (!emit1(JSOp::Pop)) { |
3561 | // [stack] ... OBJ NEXT ITER LREF* |
3562 | return false; |
3563 | } |
3564 | } |
3565 | |
3566 | if (member->isKind(ParseNodeKind::Spread)) { |
3567 | InternalIfEmitter ifThenElse(this); |
3568 | if (!isFirst) { |
3569 | // If spread is not the first element of the pattern, |
3570 | // iterator can already be completed. |
3571 | // [stack] ... OBJ NEXT ITER LREF* DONE |
3572 | |
3573 | if (!ifThenElse.emitThenElse()) { |
3574 | // [stack] ... OBJ NEXT ITER LREF* |
3575 | return false; |
3576 | } |
3577 | |
3578 | if (!emitUint32Operand(JSOp::NewArray, 0)) { |
3579 | // [stack] ... OBJ NEXT ITER LREF* ARRAY |
3580 | return false; |
3581 | } |
3582 | if (!ifThenElse.emitElse()) { |
3583 | // [stack] ... OBJ NEXT ITER LREF* |
3584 | return false; |
3585 | } |
3586 | } |
3587 | |
3588 | // If iterator is not completed, create a new array with the rest |
3589 | // of the iterator. |
3590 | if (!emitDupAt(emitted + 1, 2)) { |
3591 | // [stack] ... OBJ NEXT ITER LREF* NEXT ITER |
3592 | return false; |
3593 | } |
3594 | if (!emitUint32Operand(JSOp::NewArray, 0)) { |
3595 | // [stack] ... OBJ NEXT ITER LREF* NEXT ITER ARRAY |
3596 | return false; |
3597 | } |
3598 | if (!emitNumberOp(0)) { |
3599 | // [stack] ... OBJ NEXT ITER LREF* NEXT ITER ARRAY INDEX |
3600 | return false; |
3601 | } |
3602 | if (!emitSpread(SelfHostedIter::Deny)) { |
3603 | // [stack] ... OBJ NEXT ITER LREF* ARRAY INDEX |
3604 | return false; |
3605 | } |
3606 | if (!emit1(JSOp::Pop)) { |
3607 | // [stack] ... OBJ NEXT ITER LREF* ARRAY |
3608 | return false; |
3609 | } |
3610 | |
3611 | if (!isFirst) { |
3612 | if (!ifThenElse.emitEnd()) { |
3613 | return false; |
3614 | } |
3615 | MOZ_ASSERT(ifThenElse.pushed() == 1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(ifThenElse.pushed() == 1)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(ifThenElse.pushed() == 1))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("ifThenElse.pushed() == 1" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3615); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ifThenElse.pushed() == 1" ")"); do { *((volatile int*)__null) = 3615; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3616 | } |
3617 | |
3618 | // At this point the iterator is done. Unpick a TRUE value for DONE above |
3619 | // ITER. |
3620 | if (!emit1(JSOp::True)) { |
3621 | // [stack] ... OBJ NEXT ITER LREF* ARRAY TRUE |
3622 | return false; |
3623 | } |
3624 | if (!emitUnpickN(emitted + 1)) { |
3625 | // [stack] ... OBJ NEXT ITER TRUE LREF* ARRAY |
3626 | return false; |
3627 | } |
3628 | |
3629 | auto emitAssignment = [lhsPattern, flav](BytecodeEmitter* bce) { |
3630 | return bce->emitSetOrInitializeDestructuring(lhsPattern, flav); |
3631 | // [stack] ... OBJ NEXT ITER TRUE |
3632 | }; |
3633 | if (!wrapWithDestructuringTryNote(tryNoteDepth, emitAssignment)) { |
3634 | return false; |
3635 | } |
3636 | |
3637 | MOZ_ASSERT(!hasNext)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!hasNext)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!hasNext))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!hasNext", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3637); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!hasNext" ")" ); do { *((volatile int*)__null) = 3637; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3638 | break; |
3639 | } |
3640 | |
3641 | InternalIfEmitter ifAlreadyDone(this); |
3642 | if (!isFirst) { |
3643 | // [stack] ... OBJ NEXT ITER LREF* DONE |
3644 | |
3645 | if (!ifAlreadyDone.emitThenElse()) { |
3646 | // [stack] ... OBJ NEXT ITER LREF* |
3647 | return false; |
3648 | } |
3649 | |
3650 | if (!emit1(JSOp::Undefined)) { |
3651 | // [stack] ... OBJ NEXT ITER LREF* UNDEF |
3652 | return false; |
3653 | } |
3654 | if (!emit1(JSOp::NopDestructuring)) { |
3655 | // [stack] ... OBJ NEXT ITER LREF* UNDEF |
3656 | return false; |
3657 | } |
3658 | |
3659 | // The iterator is done. Unpick a TRUE value for DONE above ITER. |
3660 | if (!emit1(JSOp::True)) { |
3661 | // [stack] ... OBJ NEXT ITER LREF* UNDEF TRUE |
3662 | return false; |
3663 | } |
3664 | if (!emitUnpickN(emitted + 1)) { |
3665 | // [stack] ... OBJ NEXT ITER TRUE LREF* UNDEF |
3666 | return false; |
3667 | } |
3668 | |
3669 | if (!ifAlreadyDone.emitElse()) { |
3670 | // [stack] ... OBJ NEXT ITER LREF* |
3671 | return false; |
3672 | } |
3673 | } |
3674 | |
3675 | if (!emitDupAt(emitted + 1, 2)) { |
3676 | // [stack] ... OBJ NEXT ITER LREF* NEXT |
3677 | return false; |
3678 | } |
3679 | if (!emitIteratorNext(Some(pattern->pn_pos.begin))) { |
3680 | // [stack] ... OBJ NEXT ITER LREF* RESULT |
3681 | return false; |
3682 | } |
3683 | if (!emit1(JSOp::Dup)) { |
3684 | // [stack] ... OBJ NEXT ITER LREF* RESULT RESULT |
3685 | return false; |
3686 | } |
3687 | if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::done())) { |
3688 | // [stack] ... OBJ NEXT ITER LREF* RESULT DONE |
3689 | return false; |
3690 | } |
3691 | |
3692 | if (!emit1(JSOp::Dup)) { |
3693 | // [stack] ... OBJ NEXT ITER LREF* RESULT DONE DONE |
3694 | return false; |
3695 | } |
3696 | if (!emitUnpickN(emitted + 2)) { |
3697 | // [stack] ... OBJ NEXT ITER DONE LREF* RESULT DONE |
3698 | return false; |
3699 | } |
3700 | |
3701 | InternalIfEmitter ifDone(this); |
3702 | if (!ifDone.emitThenElse()) { |
3703 | // [stack] ... OBJ NEXT ITER DONE LREF* RESULT |
3704 | return false; |
3705 | } |
3706 | |
3707 | if (!emit1(JSOp::Pop)) { |
3708 | // [stack] ... OBJ NEXT ITER DONE LREF* |
3709 | return false; |
3710 | } |
3711 | if (!emit1(JSOp::Undefined)) { |
3712 | // [stack] ... OBJ NEXT ITER DONE LREF* UNDEF |
3713 | return false; |
3714 | } |
3715 | if (!emit1(JSOp::NopDestructuring)) { |
3716 | // [stack] ... OBJ NEXT ITER DONE LREF* UNDEF |
3717 | return false; |
3718 | } |
3719 | |
3720 | if (!ifDone.emitElse()) { |
3721 | // [stack] ... OBJ NEXT ITER DONE LREF* RESULT |
3722 | return false; |
3723 | } |
3724 | |
3725 | if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::value())) { |
3726 | // [stack] ... OBJ NEXT ITER DONE LREF* VALUE |
3727 | return false; |
3728 | } |
3729 | |
3730 | if (!ifDone.emitEnd()) { |
3731 | return false; |
3732 | } |
3733 | MOZ_ASSERT(ifDone.pushed() == 0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(ifDone.pushed() == 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(ifDone.pushed() == 0))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("ifDone.pushed() == 0" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3733); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ifDone.pushed() == 0" ")"); do { *((volatile int*)__null) = 3733; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3734 | |
3735 | if (!isFirst) { |
3736 | if (!ifAlreadyDone.emitEnd()) { |
3737 | return false; |
3738 | } |
3739 | MOZ_ASSERT(ifAlreadyDone.pushed() == 2)do { static_assert( mozilla::detail::AssertionConditionType< decltype(ifAlreadyDone.pushed() == 2)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(ifAlreadyDone.pushed() == 2) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("ifAlreadyDone.pushed() == 2" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3739); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ifAlreadyDone.pushed() == 2" ")"); do { *((volatile int*)__null) = 3739; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3740 | } |
3741 | |
3742 | if (pndefault) { |
3743 | auto emitDefault = [pndefault, lhsPattern](BytecodeEmitter* bce) { |
3744 | return bce->emitDefault(pndefault, lhsPattern); |
3745 | // [stack] ... OBJ NEXT ITER DONE LREF* VALUE |
3746 | }; |
3747 | |
3748 | if (!wrapWithDestructuringTryNote(tryNoteDepth, emitDefault)) { |
3749 | return false; |
3750 | } |
3751 | } |
3752 | |
3753 | if (!isElision) { |
3754 | auto emitAssignment = [lhsPattern, flav](BytecodeEmitter* bce) { |
3755 | return bce->emitSetOrInitializeDestructuring(lhsPattern, flav); |
3756 | // [stack] ... OBJ NEXT ITER DONE |
3757 | }; |
3758 | |
3759 | if (!wrapWithDestructuringTryNote(tryNoteDepth, emitAssignment)) { |
3760 | return false; |
3761 | } |
3762 | } else { |
3763 | if (!emit1(JSOp::Pop)) { |
3764 | // [stack] ... OBJ NEXT ITER DONE |
3765 | return false; |
3766 | } |
3767 | } |
3768 | } |
3769 | |
3770 | // The last DONE value is on top of the stack. If not DONE, call |
3771 | // IteratorClose. |
3772 | // [stack] ... OBJ NEXT ITER DONE |
3773 | |
3774 | InternalIfEmitter ifDone(this); |
3775 | if (!ifDone.emitThenElse()) { |
3776 | // [stack] ... OBJ NEXT ITER |
3777 | return false; |
3778 | } |
3779 | if (!emitPopN(2)) { |
3780 | // [stack] ... OBJ |
3781 | return false; |
3782 | } |
3783 | if (!ifDone.emitElse()) { |
3784 | // [stack] ... OBJ NEXT ITER |
3785 | return false; |
3786 | } |
3787 | if (!emit1(JSOp::Swap)) { |
3788 | // [stack] ... OBJ ITER NEXT |
3789 | return false; |
3790 | } |
3791 | if (!emit1(JSOp::Pop)) { |
3792 | // [stack] ... OBJ ITER |
3793 | return false; |
3794 | } |
3795 | if (!emitIteratorCloseInInnermostScope()) { |
3796 | // [stack] ... OBJ |
3797 | return false; |
3798 | } |
3799 | if (!ifDone.emitEnd()) { |
3800 | return false; |
3801 | } |
3802 | |
3803 | if (ifArrayOptimizable.isSome()) { |
3804 | if (!ifArrayOptimizable->emitEnd()) { |
3805 | // [stack] OBJ |
3806 | return false; |
3807 | } |
3808 | } |
3809 | |
3810 | return true; |
3811 | } |
3812 | |
3813 | bool BytecodeEmitter::emitComputedPropertyName(UnaryNode* computedPropName) { |
3814 | MOZ_ASSERT(computedPropName->isKind(ParseNodeKind::ComputedName))do { static_assert( mozilla::detail::AssertionConditionType< decltype(computedPropName->isKind(ParseNodeKind::ComputedName ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(computedPropName->isKind(ParseNodeKind::ComputedName )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("computedPropName->isKind(ParseNodeKind::ComputedName)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3814); AnnotateMozCrashReason("MOZ_ASSERT" "(" "computedPropName->isKind(ParseNodeKind::ComputedName)" ")"); do { *((volatile int*)__null) = 3814; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3815 | return emitTree(computedPropName->kid()) && emit1(JSOp::ToPropertyKey); |
3816 | } |
3817 | |
3818 | bool BytecodeEmitter::emitDestructuringOpsObject(ListNode* pattern, |
3819 | DestructuringFlavor flav) { |
3820 | MOZ_ASSERT(pattern->isKind(ParseNodeKind::ObjectExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(pattern->isKind(ParseNodeKind::ObjectExpr))>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(pattern->isKind(ParseNodeKind::ObjectExpr)))), 0) )) { do { } while (false); MOZ_ReportAssertionFailure("pattern->isKind(ParseNodeKind::ObjectExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3820); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pattern->isKind(ParseNodeKind::ObjectExpr)" ")"); do { *((volatile int*)__null) = 3820; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3821 | |
3822 | // [stack] ... RHS |
3823 | MOZ_ASSERT(bytecodeSection().stackDepth() > 0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(bytecodeSection().stackDepth() > 0)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(! !(bytecodeSection().stackDepth() > 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("bytecodeSection().stackDepth() > 0" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3823); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() > 0" ")"); do { *((volatile int*)__null) = 3823; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3824 | |
3825 | if (!emit1(JSOp::CheckObjCoercible)) { |
3826 | // [stack] ... RHS |
3827 | return false; |
3828 | } |
3829 | |
3830 | bool needsRestPropertyExcludedSet = |
3831 | pattern->count() > 1 && pattern->last()->isKind(ParseNodeKind::Spread); |
3832 | if (needsRestPropertyExcludedSet) { |
3833 | if (!emitDestructuringObjRestExclusionSet(pattern)) { |
3834 | // [stack] ... RHS SET |
3835 | return false; |
3836 | } |
3837 | |
3838 | if (!emit1(JSOp::Swap)) { |
3839 | // [stack] ... SET RHS |
3840 | return false; |
3841 | } |
3842 | } |
3843 | |
3844 | for (ParseNode* member : pattern->contents()) { |
3845 | ParseNode* subpattern; |
3846 | if (member->isKind(ParseNodeKind::MutateProto) || |
3847 | member->isKind(ParseNodeKind::Spread)) { |
3848 | subpattern = member->as<UnaryNode>().kid(); |
3849 | |
3850 | MOZ_ASSERT_IF(member->isKind(ParseNodeKind::Spread),do { if (member->isKind(ParseNodeKind::Spread)) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(!subpattern ->isKind(ParseNodeKind::AssignExpr))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!subpattern->isKind(ParseNodeKind ::AssignExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!subpattern->isKind(ParseNodeKind::AssignExpr)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3851); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!subpattern->isKind(ParseNodeKind::AssignExpr)" ")"); do { *((volatile int*)__null) = 3851; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
3851 | !subpattern->isKind(ParseNodeKind::AssignExpr))do { if (member->isKind(ParseNodeKind::Spread)) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(!subpattern ->isKind(ParseNodeKind::AssignExpr))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!subpattern->isKind(ParseNodeKind ::AssignExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!subpattern->isKind(ParseNodeKind::AssignExpr)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3851); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!subpattern->isKind(ParseNodeKind::AssignExpr)" ")"); do { *((volatile int*)__null) = 3851; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
3852 | } else { |
3853 | MOZ_ASSERT(member->isKind(ParseNodeKind::PropertyDefinition) ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(member->isKind(ParseNodeKind::PropertyDefinition) || member ->isKind(ParseNodeKind::Shorthand)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3854); AnnotateMozCrashReason("MOZ_ASSERT" "(" "member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)" ")"); do { *((volatile int*)__null) = 3854; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
3854 | member->isKind(ParseNodeKind::Shorthand))do { static_assert( mozilla::detail::AssertionConditionType< decltype(member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(member->isKind(ParseNodeKind::PropertyDefinition) || member ->isKind(ParseNodeKind::Shorthand)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3854); AnnotateMozCrashReason("MOZ_ASSERT" "(" "member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)" ")"); do { *((volatile int*)__null) = 3854; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3855 | subpattern = member->as<BinaryNode>().right(); |
3856 | } |
3857 | |
3858 | ParseNode* lhs = subpattern; |
3859 | ParseNode* pndefault = nullptr; |
3860 | if (subpattern->isKind(ParseNodeKind::AssignExpr)) { |
3861 | lhs = subpattern->as<AssignmentNode>().left(); |
3862 | pndefault = subpattern->as<AssignmentNode>().right(); |
3863 | } |
3864 | |
3865 | // Number of stack slots emitted for the LHS reference. |
3866 | size_t emitted = 0; |
3867 | |
3868 | // Spec requires LHS reference to be evaluated first. |
3869 | if (!emitDestructuringLHSRef(lhs, &emitted)) { |
3870 | // [stack] ... SET? RHS LREF* |
3871 | return false; |
3872 | } |
3873 | |
3874 | // Duplicate the value being destructured to use as a reference base. |
3875 | if (!emitDupAt(emitted)) { |
3876 | // [stack] ... SET? RHS LREF* RHS |
3877 | return false; |
3878 | } |
3879 | |
3880 | if (member->isKind(ParseNodeKind::Spread)) { |
3881 | if (!updateSourceCoordNotes(member->pn_pos.begin)) { |
3882 | return false; |
3883 | } |
3884 | |
3885 | if (!emit1(JSOp::NewInit)) { |
3886 | // [stack] ... SET? RHS LREF* RHS TARGET |
3887 | return false; |
3888 | } |
3889 | if (!emit1(JSOp::Dup)) { |
3890 | // [stack] ... SET? RHS LREF* RHS TARGET TARGET |
3891 | return false; |
3892 | } |
3893 | if (!emit2(JSOp::Pick, 2)) { |
3894 | // [stack] ... SET? RHS LREF* TARGET TARGET RHS |
3895 | return false; |
3896 | } |
3897 | |
3898 | if (needsRestPropertyExcludedSet) { |
3899 | if (!emit2(JSOp::Pick, emitted + 4)) { |
3900 | // [stack] ... RHS LREF* TARGET TARGET RHS SET |
3901 | return false; |
3902 | } |
3903 | } |
3904 | |
3905 | CopyOption option = needsRestPropertyExcludedSet ? CopyOption::Filtered |
3906 | : CopyOption::Unfiltered; |
3907 | if (!emitCopyDataProperties(option)) { |
3908 | // [stack] ... RHS LREF* TARGET |
3909 | return false; |
3910 | } |
3911 | |
3912 | // Destructure TARGET per this member's lhs. |
3913 | if (!emitSetOrInitializeDestructuring(lhs, flav)) { |
3914 | // [stack] ... RHS |
3915 | return false; |
3916 | } |
3917 | |
3918 | MOZ_ASSERT(member == pattern->last(), "Rest property is always last")do { static_assert( mozilla::detail::AssertionConditionType< decltype(member == pattern->last())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(member == pattern->last() ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "member == pattern->last()" " (" "Rest property is always last" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3918); AnnotateMozCrashReason("MOZ_ASSERT" "(" "member == pattern->last()" ") (" "Rest property is always last" ")"); do { *((volatile int *)__null) = 3918; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3919 | break; |
3920 | } |
3921 | |
3922 | // Now push the property value currently being matched, which is the value |
3923 | // of the current property name "label" on the left of a colon in the object |
3924 | // initialiser. |
3925 | if (member->isKind(ParseNodeKind::MutateProto)) { |
3926 | if (!emitAtomOp(JSOp::GetProp, |
3927 | TaggedParserAtomIndex::WellKnown::proto_())) { |
3928 | // [stack] ... SET? RHS LREF* PROP |
3929 | return false; |
3930 | } |
3931 | } else { |
3932 | MOZ_ASSERT(member->isKind(ParseNodeKind::PropertyDefinition) ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(member->isKind(ParseNodeKind::PropertyDefinition) || member ->isKind(ParseNodeKind::Shorthand)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3933); AnnotateMozCrashReason("MOZ_ASSERT" "(" "member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)" ")"); do { *((volatile int*)__null) = 3933; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
3933 | member->isKind(ParseNodeKind::Shorthand))do { static_assert( mozilla::detail::AssertionConditionType< decltype(member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(member->isKind(ParseNodeKind::PropertyDefinition) || member ->isKind(ParseNodeKind::Shorthand)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3933); AnnotateMozCrashReason("MOZ_ASSERT" "(" "member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)" ")"); do { *((volatile int*)__null) = 3933; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3934 | |
3935 | ParseNode* key = member->as<BinaryNode>().left(); |
3936 | if (key->isKind(ParseNodeKind::ObjectPropertyName) || |
3937 | key->isKind(ParseNodeKind::StringExpr)) { |
3938 | if (!emitAtomOp(JSOp::GetProp, key->as<NameNode>().atom())) { |
3939 | // [stack] ... SET? RHS LREF* PROP |
3940 | return false; |
3941 | } |
3942 | } else { |
3943 | if (key->isKind(ParseNodeKind::NumberExpr)) { |
3944 | if (!emitNumberOp(key->as<NumericLiteral>().value())) { |
3945 | // [stack]... SET? RHS LREF* RHS KEY |
3946 | return false; |
3947 | } |
3948 | } else { |
3949 | // Otherwise this is a computed property name. BigInt keys are parsed |
3950 | // as (synthetic) computed property names, too. |
3951 | MOZ_ASSERT(key->isKind(ParseNodeKind::ComputedName))do { static_assert( mozilla::detail::AssertionConditionType< decltype(key->isKind(ParseNodeKind::ComputedName))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(key->isKind(ParseNodeKind::ComputedName)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("key->isKind(ParseNodeKind::ComputedName)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 3951); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::ComputedName)" ")"); do { *((volatile int*)__null) = 3951; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3952 | |
3953 | if (!emitComputedPropertyName(&key->as<UnaryNode>())) { |
3954 | // [stack] ... SET? RHS LREF* RHS KEY |
3955 | return false; |
3956 | } |
3957 | |
3958 | // Add the computed property key to the exclusion set. |
3959 | if (needsRestPropertyExcludedSet) { |
3960 | if (!emitDupAt(emitted + 3)) { |
3961 | // [stack] ... SET RHS LREF* RHS KEY SET |
3962 | return false; |
3963 | } |
3964 | if (!emitDupAt(1)) { |
3965 | // [stack] ... SET RHS LREF* RHS KEY SET KEY |
3966 | return false; |
3967 | } |
3968 | if (!emit1(JSOp::Undefined)) { |
3969 | // [stack] ... SET RHS LREF* RHS KEY SET KEY UNDEFINED |
3970 | return false; |
3971 | } |
3972 | if (!emit1(JSOp::InitElem)) { |
3973 | // [stack] ... SET RHS LREF* RHS KEY SET |
3974 | return false; |
3975 | } |
3976 | if (!emit1(JSOp::Pop)) { |
3977 | // [stack] ... SET RHS LREF* RHS KEY |
3978 | return false; |
3979 | } |
3980 | } |
3981 | } |
3982 | |
3983 | // Get the property value. |
3984 | if (!emitElemOpBase(JSOp::GetElem)) { |
3985 | // [stack] ... SET? RHS LREF* PROP |
3986 | return false; |
3987 | } |
3988 | } |
3989 | } |
3990 | |
3991 | if (pndefault) { |
3992 | if (!emitDefault(pndefault, lhs)) { |
3993 | // [stack] ... SET? RHS LREF* VALUE |
3994 | return false; |
3995 | } |
3996 | } |
3997 | |
3998 | // Destructure PROP per this member's lhs. |
3999 | if (!emitSetOrInitializeDestructuring(lhs, flav)) { |
4000 | // [stack] ... SET? RHS |
4001 | return false; |
4002 | } |
4003 | } |
4004 | |
4005 | return true; |
4006 | } |
4007 | |
4008 | static bool IsDestructuringRestExclusionSetObjLiteralCompatible( |
4009 | ListNode* pattern) { |
4010 | uint32_t propCount = 0; |
4011 | for (ParseNode* member : pattern->contents()) { |
4012 | if (member->isKind(ParseNodeKind::Spread)) { |
4013 | MOZ_ASSERT(!member->pn_next, "unexpected trailing element after spread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!member->pn_next)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!member->pn_next))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!member->pn_next" " (" "unexpected trailing element after spread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4013); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!member->pn_next" ") (" "unexpected trailing element after spread" ")"); do { * ((volatile int*)__null) = 4013; __attribute__((nomerge)) ::abort (); } while (false); } } while (false); |
4014 | break; |
4015 | } |
4016 | |
4017 | propCount++; |
4018 | |
4019 | if (member->isKind(ParseNodeKind::MutateProto)) { |
4020 | continue; |
4021 | } |
4022 | |
4023 | ParseNode* key = member->as<BinaryNode>().left(); |
4024 | if (key->isKind(ParseNodeKind::ObjectPropertyName) || |
4025 | key->isKind(ParseNodeKind::StringExpr)) { |
4026 | continue; |
4027 | } |
4028 | |
4029 | // Number and BigInt keys aren't yet supported. Computed property names need |
4030 | // to be added dynamically. |
4031 | MOZ_ASSERT(key->isKind(ParseNodeKind::NumberExpr) ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(key->isKind(ParseNodeKind::NumberExpr) || key-> isKind(ParseNodeKind::BigIntExpr) || key->isKind(ParseNodeKind ::ComputedName))>::isValid, "invalid assertion condition") ; if ((__builtin_expect(!!(!(!!(key->isKind(ParseNodeKind:: NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr) || key ->isKind(ParseNodeKind::ComputedName)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr) || key->isKind(ParseNodeKind::ComputedName)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4033); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr) || key->isKind(ParseNodeKind::ComputedName)" ")"); do { *((volatile int*)__null) = 4033; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
4032 | key->isKind(ParseNodeKind::BigIntExpr) ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(key->isKind(ParseNodeKind::NumberExpr) || key-> isKind(ParseNodeKind::BigIntExpr) || key->isKind(ParseNodeKind ::ComputedName))>::isValid, "invalid assertion condition") ; if ((__builtin_expect(!!(!(!!(key->isKind(ParseNodeKind:: NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr) || key ->isKind(ParseNodeKind::ComputedName)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr) || key->isKind(ParseNodeKind::ComputedName)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4033); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr) || key->isKind(ParseNodeKind::ComputedName)" ")"); do { *((volatile int*)__null) = 4033; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
4033 | key->isKind(ParseNodeKind::ComputedName))do { static_assert( mozilla::detail::AssertionConditionType< decltype(key->isKind(ParseNodeKind::NumberExpr) || key-> isKind(ParseNodeKind::BigIntExpr) || key->isKind(ParseNodeKind ::ComputedName))>::isValid, "invalid assertion condition") ; if ((__builtin_expect(!!(!(!!(key->isKind(ParseNodeKind:: NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr) || key ->isKind(ParseNodeKind::ComputedName)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr) || key->isKind(ParseNodeKind::ComputedName)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4033); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr) || key->isKind(ParseNodeKind::ComputedName)" ")"); do { *((volatile int*)__null) = 4033; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4034 | return false; |
4035 | } |
4036 | |
4037 | if (propCount > SharedPropMap::MaxPropsForNonDictionary) { |
4038 | // JSOp::NewObject cannot accept dictionary-mode objects. |
4039 | return false; |
4040 | } |
4041 | |
4042 | return true; |
4043 | } |
4044 | |
4045 | bool BytecodeEmitter::emitDestructuringObjRestExclusionSet(ListNode* pattern) { |
4046 | MOZ_ASSERT(pattern->isKind(ParseNodeKind::ObjectExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(pattern->isKind(ParseNodeKind::ObjectExpr))>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(pattern->isKind(ParseNodeKind::ObjectExpr)))), 0) )) { do { } while (false); MOZ_ReportAssertionFailure("pattern->isKind(ParseNodeKind::ObjectExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4046); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pattern->isKind(ParseNodeKind::ObjectExpr)" ")"); do { *((volatile int*)__null) = 4046; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4047 | MOZ_ASSERT(pattern->last()->isKind(ParseNodeKind::Spread))do { static_assert( mozilla::detail::AssertionConditionType< decltype(pattern->last()->isKind(ParseNodeKind::Spread) )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(pattern->last()->isKind(ParseNodeKind::Spread) ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "pattern->last()->isKind(ParseNodeKind::Spread)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4047); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pattern->last()->isKind(ParseNodeKind::Spread)" ")"); do { *((volatile int*)__null) = 4047; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4048 | |
4049 | // See if we can use ObjLiteral to construct the exclusion set object. |
4050 | if (IsDestructuringRestExclusionSetObjLiteralCompatible(pattern)) { |
4051 | if (!emitDestructuringRestExclusionSetObjLiteral(pattern)) { |
4052 | // [stack] OBJ |
4053 | return false; |
4054 | } |
4055 | } else { |
4056 | // Take the slow but sure way and start off with a blank object. |
4057 | if (!emit1(JSOp::NewInit)) { |
4058 | // [stack] OBJ |
4059 | return false; |
4060 | } |
4061 | } |
4062 | |
4063 | for (ParseNode* member : pattern->contents()) { |
4064 | if (member->isKind(ParseNodeKind::Spread)) { |
4065 | MOZ_ASSERT(!member->pn_next, "unexpected trailing element after spread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!member->pn_next)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!member->pn_next))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!member->pn_next" " (" "unexpected trailing element after spread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4065); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!member->pn_next" ") (" "unexpected trailing element after spread" ")"); do { * ((volatile int*)__null) = 4065; __attribute__((nomerge)) ::abort (); } while (false); } } while (false); |
4066 | break; |
4067 | } |
4068 | |
4069 | TaggedParserAtomIndex pnatom; |
4070 | if (member->isKind(ParseNodeKind::MutateProto)) { |
4071 | pnatom = TaggedParserAtomIndex::WellKnown::proto_(); |
4072 | } else { |
4073 | ParseNode* key = member->as<BinaryNode>().left(); |
4074 | if (key->isKind(ParseNodeKind::ObjectPropertyName) || |
4075 | key->isKind(ParseNodeKind::StringExpr)) { |
4076 | pnatom = key->as<NameNode>().atom(); |
4077 | } else if (key->isKind(ParseNodeKind::NumberExpr)) { |
4078 | if (!emitNumberOp(key->as<NumericLiteral>().value())) { |
4079 | return false; |
4080 | } |
4081 | } else { |
4082 | // Otherwise this is a computed property name which needs to be added |
4083 | // dynamically. BigInt keys are parsed as (synthetic) computed property |
4084 | // names, too. |
4085 | MOZ_ASSERT(key->isKind(ParseNodeKind::ComputedName))do { static_assert( mozilla::detail::AssertionConditionType< decltype(key->isKind(ParseNodeKind::ComputedName))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(key->isKind(ParseNodeKind::ComputedName)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("key->isKind(ParseNodeKind::ComputedName)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4085); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::ComputedName)" ")"); do { *((volatile int*)__null) = 4085; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4086 | continue; |
4087 | } |
4088 | } |
4089 | |
4090 | // Initialize elements with |undefined|. |
4091 | if (!emit1(JSOp::Undefined)) { |
4092 | return false; |
4093 | } |
4094 | |
4095 | if (!pnatom) { |
4096 | if (!emit1(JSOp::InitElem)) { |
4097 | return false; |
4098 | } |
4099 | } else { |
4100 | if (!emitAtomOp(JSOp::InitProp, pnatom)) { |
4101 | return false; |
4102 | } |
4103 | } |
4104 | } |
4105 | |
4106 | return true; |
4107 | } |
4108 | |
4109 | bool BytecodeEmitter::emitDestructuringOps(ListNode* pattern, |
4110 | DestructuringFlavor flav) { |
4111 | if (pattern->isKind(ParseNodeKind::ArrayExpr)) { |
4112 | return emitDestructuringOpsArray(pattern, flav); |
4113 | } |
4114 | return emitDestructuringOpsObject(pattern, flav); |
4115 | } |
4116 | |
4117 | bool BytecodeEmitter::emitTemplateString(ListNode* templateString) { |
4118 | bool pushedString = false; |
4119 | |
4120 | for (ParseNode* item : templateString->contents()) { |
4121 | bool isString = (item->getKind() == ParseNodeKind::StringExpr || |
4122 | item->getKind() == ParseNodeKind::TemplateStringExpr); |
4123 | |
4124 | // Skip empty strings. These are very common: a template string like |
4125 | // `${a}${b}` has three empty strings and without this optimization |
4126 | // we'd emit four JSOp::Add operations instead of just one. |
4127 | if (isString && item->as<NameNode>().atom() == |
4128 | TaggedParserAtomIndex::WellKnown::empty()) { |
4129 | continue; |
4130 | } |
4131 | |
4132 | if (!isString) { |
4133 | // We update source notes before emitting the expression |
4134 | if (!updateSourceCoordNotes(item->pn_pos.begin)) { |
4135 | return false; |
4136 | } |
4137 | } |
4138 | |
4139 | if (!emitTree(item)) { |
4140 | return false; |
4141 | } |
4142 | |
4143 | if (!isString) { |
4144 | // We need to convert the expression to a string |
4145 | if (!emit1(JSOp::ToString)) { |
4146 | return false; |
4147 | } |
4148 | } |
4149 | |
4150 | if (pushedString) { |
4151 | // We've pushed two strings onto the stack. Add them together, leaving |
4152 | // just one. |
4153 | if (!emit1(JSOp::Add)) { |
4154 | return false; |
4155 | } |
4156 | } else { |
4157 | pushedString = true; |
4158 | } |
4159 | } |
4160 | |
4161 | if (!pushedString) { |
4162 | // All strings were empty, this can happen for something like `${""}`. |
4163 | // Just push an empty string. |
4164 | if (!emitStringOp(JSOp::String, |
4165 | TaggedParserAtomIndex::WellKnown::empty())) { |
4166 | return false; |
4167 | } |
4168 | } |
4169 | |
4170 | return true; |
4171 | } |
4172 | |
4173 | bool BytecodeEmitter::emitDeclarationList(ListNode* declList) { |
4174 | for (ParseNode* decl : declList->contents()) { |
4175 | ParseNode* pattern; |
4176 | ParseNode* initializer; |
4177 | if (decl->isKind(ParseNodeKind::Name)) { |
4178 | pattern = decl; |
4179 | initializer = nullptr; |
4180 | } else { |
4181 | AssignmentNode* assignNode = &decl->as<AssignmentNode>(); |
4182 | pattern = assignNode->left(); |
4183 | initializer = assignNode->right(); |
4184 | } |
4185 | |
4186 | if (pattern->isKind(ParseNodeKind::Name)) { |
4187 | // initializer can be null here. |
4188 | if (!emitSingleDeclaration(declList, &pattern->as<NameNode>(), |
4189 | initializer)) { |
4190 | return false; |
4191 | } |
4192 | } else { |
4193 | MOZ_ASSERT(pattern->isKind(ParseNodeKind::ArrayExpr) ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(pattern->isKind(ParseNodeKind::ArrayExpr) || pattern ->isKind(ParseNodeKind::ObjectExpr))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pattern->isKind(ParseNodeKind ::ArrayExpr) || pattern->isKind(ParseNodeKind::ObjectExpr) ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "pattern->isKind(ParseNodeKind::ArrayExpr) || pattern->isKind(ParseNodeKind::ObjectExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4194); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pattern->isKind(ParseNodeKind::ArrayExpr) || pattern->isKind(ParseNodeKind::ObjectExpr)" ")"); do { *((volatile int*)__null) = 4194; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
4194 | pattern->isKind(ParseNodeKind::ObjectExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(pattern->isKind(ParseNodeKind::ArrayExpr) || pattern ->isKind(ParseNodeKind::ObjectExpr))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pattern->isKind(ParseNodeKind ::ArrayExpr) || pattern->isKind(ParseNodeKind::ObjectExpr) ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "pattern->isKind(ParseNodeKind::ArrayExpr) || pattern->isKind(ParseNodeKind::ObjectExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4194); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pattern->isKind(ParseNodeKind::ArrayExpr) || pattern->isKind(ParseNodeKind::ObjectExpr)" ")"); do { *((volatile int*)__null) = 4194; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4195 | MOZ_ASSERT(initializer != nullptr)do { static_assert( mozilla::detail::AssertionConditionType< decltype(initializer != nullptr)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(initializer != nullptr))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("initializer != nullptr" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4195); AnnotateMozCrashReason("MOZ_ASSERT" "(" "initializer != nullptr" ")"); do { *((volatile int*)__null) = 4195; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4196 | |
4197 | if (!updateSourceCoordNotes(initializer->pn_pos.begin)) { |
4198 | return false; |
4199 | } |
4200 | if (!markStepBreakpoint()) { |
4201 | return false; |
4202 | } |
4203 | if (!emitTree(initializer)) { |
4204 | return false; |
4205 | } |
4206 | |
4207 | if (!emitDestructuringOps(&pattern->as<ListNode>(), |
4208 | DestructuringFlavor::Declaration)) { |
4209 | return false; |
4210 | } |
4211 | |
4212 | if (!emit1(JSOp::Pop)) { |
4213 | return false; |
4214 | } |
4215 | } |
4216 | } |
4217 | return true; |
4218 | } |
4219 | |
4220 | bool BytecodeEmitter::emitSingleDeclaration(ListNode* declList, NameNode* decl, |
4221 | ParseNode* initializer) { |
4222 | MOZ_ASSERT(decl->isKind(ParseNodeKind::Name))do { static_assert( mozilla::detail::AssertionConditionType< decltype(decl->isKind(ParseNodeKind::Name))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(decl->isKind(ParseNodeKind ::Name)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("decl->isKind(ParseNodeKind::Name)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4222); AnnotateMozCrashReason("MOZ_ASSERT" "(" "decl->isKind(ParseNodeKind::Name)" ")"); do { *((volatile int*)__null) = 4222; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4223 | |
4224 | // Nothing to do for initializer-less 'var' declarations, as there's no TDZ. |
4225 | if (!initializer && declList->isKind(ParseNodeKind::VarStmt)) { |
4226 | return true; |
4227 | } |
4228 | |
4229 | auto nameAtom = decl->name(); |
4230 | NameOpEmitter noe(this, nameAtom, NameOpEmitter::Kind::Initialize); |
4231 | if (!noe.prepareForRhs()) { |
4232 | // [stack] ENV? |
4233 | return false; |
4234 | } |
4235 | if (!initializer) { |
4236 | // Lexical declarations are initialized to undefined without an |
4237 | // initializer. |
4238 | MOZ_ASSERT(declList->isKind(ParseNodeKind::LetDecl),do { static_assert( mozilla::detail::AssertionConditionType< decltype(declList->isKind(ParseNodeKind::LetDecl))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(declList->isKind(ParseNodeKind::LetDecl)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("declList->isKind(ParseNodeKind::LetDecl)" " (" "var declarations without initializers handled above, " "and const declarations must have initializers" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4240); AnnotateMozCrashReason("MOZ_ASSERT" "(" "declList->isKind(ParseNodeKind::LetDecl)" ") (" "var declarations without initializers handled above, " "and const declarations must have initializers" ")"); do { * ((volatile int*)__null) = 4240; __attribute__((nomerge)) ::abort (); } while (false); } } while (false) |
4239 | "var declarations without initializers handled above, "do { static_assert( mozilla::detail::AssertionConditionType< decltype(declList->isKind(ParseNodeKind::LetDecl))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(declList->isKind(ParseNodeKind::LetDecl)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("declList->isKind(ParseNodeKind::LetDecl)" " (" "var declarations without initializers handled above, " "and const declarations must have initializers" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4240); AnnotateMozCrashReason("MOZ_ASSERT" "(" "declList->isKind(ParseNodeKind::LetDecl)" ") (" "var declarations without initializers handled above, " "and const declarations must have initializers" ")"); do { * ((volatile int*)__null) = 4240; __attribute__((nomerge)) ::abort (); } while (false); } } while (false) |
4240 | "and const declarations must have initializers")do { static_assert( mozilla::detail::AssertionConditionType< decltype(declList->isKind(ParseNodeKind::LetDecl))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(declList->isKind(ParseNodeKind::LetDecl)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("declList->isKind(ParseNodeKind::LetDecl)" " (" "var declarations without initializers handled above, " "and const declarations must have initializers" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4240); AnnotateMozCrashReason("MOZ_ASSERT" "(" "declList->isKind(ParseNodeKind::LetDecl)" ") (" "var declarations without initializers handled above, " "and const declarations must have initializers" ")"); do { * ((volatile int*)__null) = 4240; __attribute__((nomerge)) ::abort (); } while (false); } } while (false); |
4241 | if (!emit1(JSOp::Undefined)) { |
4242 | // [stack] ENV? UNDEF |
4243 | return false; |
4244 | } |
4245 | } else { |
4246 | MOZ_ASSERT(initializer)do { static_assert( mozilla::detail::AssertionConditionType< decltype(initializer)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(initializer))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("initializer", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4246); AnnotateMozCrashReason("MOZ_ASSERT" "(" "initializer" ")"); do { *((volatile int*)__null) = 4246; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4247 | |
4248 | if (!updateSourceCoordNotes(initializer->pn_pos.begin)) { |
4249 | return false; |
4250 | } |
4251 | if (!markStepBreakpoint()) { |
4252 | return false; |
4253 | } |
4254 | if (!emitInitializer(initializer, decl)) { |
4255 | // [stack] ENV? V |
4256 | return false; |
4257 | } |
4258 | } |
4259 | |
4260 | #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT |
4261 | if (declList->isKind(ParseNodeKind::UsingDecl)) { |
4262 | if (!innermostEmitterScope()->prepareForDisposableAssignment( |
4263 | UsingHint::Sync)) { |
4264 | // [stack] ENV? V |
4265 | return false; |
4266 | } |
4267 | } |
4268 | #endif |
4269 | |
4270 | if (!noe.emitAssignment()) { |
4271 | // [stack] V |
4272 | return false; |
4273 | } |
4274 | |
4275 | if (!emit1(JSOp::Pop)) { |
4276 | // [stack] |
4277 | return false; |
4278 | } |
4279 | |
4280 | return true; |
4281 | } |
4282 | |
4283 | bool BytecodeEmitter::emitAssignmentRhs( |
4284 | ParseNode* rhs, TaggedParserAtomIndex anonFunctionName) { |
4285 | if (rhs->isDirectRHSAnonFunction()) { |
4286 | if (anonFunctionName) { |
4287 | return emitAnonymousFunctionWithName(rhs, anonFunctionName); |
4288 | } |
4289 | return emitAnonymousFunctionWithComputedName(rhs, FunctionPrefixKind::None); |
4290 | } |
4291 | return emitTree(rhs); |
4292 | } |
4293 | |
4294 | // The RHS value to assign is already on the stack, i.e., the next enumeration |
4295 | // value in a for-in or for-of loop. Offset is the location in the stack of the |
4296 | // already-emitted rhs. If we emitted a JSOp::BindName or JSOp::BindGName, then |
4297 | // the scope is on the top of the stack and we need to dig one deeper to get |
4298 | // the right RHS value. |
4299 | bool BytecodeEmitter::emitAssignmentRhs(uint8_t offset) { |
4300 | if (offset != 1) { |
4301 | return emitPickN(offset - 1); |
4302 | } |
4303 | |
4304 | return true; |
4305 | } |
4306 | |
4307 | static inline JSOp CompoundAssignmentParseNodeKindToJSOp(ParseNodeKind pnk) { |
4308 | switch (pnk) { |
4309 | case ParseNodeKind::InitExpr: |
4310 | return JSOp::Nop; |
4311 | case ParseNodeKind::AssignExpr: |
4312 | return JSOp::Nop; |
4313 | case ParseNodeKind::AddAssignExpr: |
4314 | return JSOp::Add; |
4315 | case ParseNodeKind::SubAssignExpr: |
4316 | return JSOp::Sub; |
4317 | case ParseNodeKind::BitOrAssignExpr: |
4318 | return JSOp::BitOr; |
4319 | case ParseNodeKind::BitXorAssignExpr: |
4320 | return JSOp::BitXor; |
4321 | case ParseNodeKind::BitAndAssignExpr: |
4322 | return JSOp::BitAnd; |
4323 | case ParseNodeKind::LshAssignExpr: |
4324 | return JSOp::Lsh; |
4325 | case ParseNodeKind::RshAssignExpr: |
4326 | return JSOp::Rsh; |
4327 | case ParseNodeKind::UrshAssignExpr: |
4328 | return JSOp::Ursh; |
4329 | case ParseNodeKind::MulAssignExpr: |
4330 | return JSOp::Mul; |
4331 | case ParseNodeKind::DivAssignExpr: |
4332 | return JSOp::Div; |
4333 | case ParseNodeKind::ModAssignExpr: |
4334 | return JSOp::Mod; |
4335 | case ParseNodeKind::PowAssignExpr: |
4336 | return JSOp::Pow; |
4337 | case ParseNodeKind::CoalesceAssignExpr: |
4338 | case ParseNodeKind::OrAssignExpr: |
4339 | case ParseNodeKind::AndAssignExpr: |
4340 | // Short-circuit assignment operators are handled elsewhere. |
4341 | [[fallthrough]]; |
4342 | default: |
4343 | MOZ_CRASH("unexpected compound assignment op")do { do { } while (false); MOZ_ReportCrash("" "unexpected compound assignment op" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4343); AnnotateMozCrashReason("MOZ_CRASH(" "unexpected compound assignment op" ")"); do { *((volatile int*)__null) = 4343; __attribute__((nomerge )) ::abort(); } while (false); } while (false); |
4344 | } |
4345 | } |
4346 | |
4347 | bool BytecodeEmitter::emitAssignmentOrInit(ParseNodeKind kind, ParseNode* lhs, |
4348 | ParseNode* rhs) { |
4349 | JSOp compoundOp = CompoundAssignmentParseNodeKindToJSOp(kind); |
4350 | bool isCompound = compoundOp != JSOp::Nop; |
4351 | bool isInit = kind == ParseNodeKind::InitExpr; |
4352 | |
4353 | // We estimate the number of properties this could create |
4354 | // if used as constructor merely by counting this.foo = assignment |
4355 | // or init expressions; |
4356 | // |
4357 | // This currently doesn't handle this[x] = foo; |
4358 | if (isInit || kind == ParseNodeKind::AssignExpr) { |
4359 | if (lhs->isKind(ParseNodeKind::DotExpr)) { |
4360 | if (lhs->as<PropertyAccess>().expression().isKind( |
4361 | ParseNodeKind::ThisExpr)) { |
4362 | propertyAdditionEstimate++; |
4363 | } |
4364 | } |
4365 | } |
4366 | |
4367 | MOZ_ASSERT_IF(isInit, lhs->isKind(ParseNodeKind::DotExpr) ||do { if (isInit) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(lhs->isKind(ParseNodeKind::DotExpr) || lhs-> isKind(ParseNodeKind::ElemExpr) || lhs->isKind(ParseNodeKind ::PrivateMemberExpr))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(lhs->isKind(ParseNodeKind ::DotExpr) || lhs->isKind(ParseNodeKind::ElemExpr) || lhs-> isKind(ParseNodeKind::PrivateMemberExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("lhs->isKind(ParseNodeKind::DotExpr) || lhs->isKind(ParseNodeKind::ElemExpr) || lhs->isKind(ParseNodeKind::PrivateMemberExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4369); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lhs->isKind(ParseNodeKind::DotExpr) || lhs->isKind(ParseNodeKind::ElemExpr) || lhs->isKind(ParseNodeKind::PrivateMemberExpr)" ")"); do { *((volatile int*)__null) = 4369; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
4368 | lhs->isKind(ParseNodeKind::ElemExpr) ||do { if (isInit) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(lhs->isKind(ParseNodeKind::DotExpr) || lhs-> isKind(ParseNodeKind::ElemExpr) || lhs->isKind(ParseNodeKind ::PrivateMemberExpr))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(lhs->isKind(ParseNodeKind ::DotExpr) || lhs->isKind(ParseNodeKind::ElemExpr) || lhs-> isKind(ParseNodeKind::PrivateMemberExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("lhs->isKind(ParseNodeKind::DotExpr) || lhs->isKind(ParseNodeKind::ElemExpr) || lhs->isKind(ParseNodeKind::PrivateMemberExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4369); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lhs->isKind(ParseNodeKind::DotExpr) || lhs->isKind(ParseNodeKind::ElemExpr) || lhs->isKind(ParseNodeKind::PrivateMemberExpr)" ")"); do { *((volatile int*)__null) = 4369; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
4369 | lhs->isKind(ParseNodeKind::PrivateMemberExpr))do { if (isInit) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(lhs->isKind(ParseNodeKind::DotExpr) || lhs-> isKind(ParseNodeKind::ElemExpr) || lhs->isKind(ParseNodeKind ::PrivateMemberExpr))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(lhs->isKind(ParseNodeKind ::DotExpr) || lhs->isKind(ParseNodeKind::ElemExpr) || lhs-> isKind(ParseNodeKind::PrivateMemberExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("lhs->isKind(ParseNodeKind::DotExpr) || lhs->isKind(ParseNodeKind::ElemExpr) || lhs->isKind(ParseNodeKind::PrivateMemberExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4369); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lhs->isKind(ParseNodeKind::DotExpr) || lhs->isKind(ParseNodeKind::ElemExpr) || lhs->isKind(ParseNodeKind::PrivateMemberExpr)" ")"); do { *((volatile int*)__null) = 4369; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
4370 | |
4371 | // |name| is used within NameOpEmitter, so its lifetime must surpass |noe|. |
4372 | TaggedParserAtomIndex name; |
4373 | |
4374 | Maybe<NameOpEmitter> noe; |
4375 | Maybe<PropOpEmitter> poe; |
4376 | Maybe<ElemOpEmitter> eoe; |
4377 | Maybe<PrivateOpEmitter> xoe; |
4378 | |
4379 | // Deal with non-name assignments. |
4380 | uint8_t offset = 1; |
4381 | |
4382 | // Purpose of anonFunctionName: |
4383 | // |
4384 | // In normal name assignments (`f = function(){}`), an anonymous function gets |
4385 | // an inferred name based on the left-hand side name node. |
4386 | // |
4387 | // In normal property assignments (`obj.x = function(){}`), the anonymous |
4388 | // function does not have a computed name, and rhs->isDirectRHSAnonFunction() |
4389 | // will be false (and anonFunctionName will not be used). However, in field |
4390 | // initializers (`class C { x = function(){} }`), field initialization is |
4391 | // implemented via a property or elem assignment (where we are now), and |
4392 | // rhs->isDirectRHSAnonFunction() is set - so we'll assign the name of the |
4393 | // function. |
4394 | TaggedParserAtomIndex anonFunctionName; |
4395 | |
4396 | switch (lhs->getKind()) { |
4397 | case ParseNodeKind::Name: { |
4398 | name = lhs->as<NameNode>().name(); |
4399 | anonFunctionName = name; |
4400 | noe.emplace(this, name, |
4401 | isCompound ? NameOpEmitter::Kind::CompoundAssignment |
4402 | : NameOpEmitter::Kind::SimpleAssignment); |
4403 | break; |
4404 | } |
4405 | case ParseNodeKind::ArgumentsLength: |
4406 | case ParseNodeKind::DotExpr: { |
4407 | PropertyAccess* prop = &lhs->as<PropertyAccess>(); |
4408 | bool isSuper = prop->isSuper(); |
4409 | poe.emplace(this, |
4410 | isCompound ? PropOpEmitter::Kind::CompoundAssignment |
4411 | : isInit ? PropOpEmitter::Kind::PropInit |
4412 | : PropOpEmitter::Kind::SimpleAssignment, |
4413 | isSuper ? PropOpEmitter::ObjKind::Super |
4414 | : PropOpEmitter::ObjKind::Other); |
4415 | if (!poe->prepareForObj()) { |
4416 | return false; |
4417 | } |
4418 | anonFunctionName = prop->name(); |
4419 | if (isSuper) { |
4420 | UnaryNode* base = &prop->expression().as<UnaryNode>(); |
4421 | if (!emitGetThisForSuperBase(base)) { |
4422 | // [stack] THIS SUPERBASE |
4423 | return false; |
4424 | } |
4425 | // SUPERBASE is pushed onto THIS later in poe->emitGet below. |
4426 | offset += 2; |
4427 | } else { |
4428 | if (!emitTree(&prop->expression())) { |
4429 | // [stack] OBJ |
4430 | return false; |
4431 | } |
4432 | offset += 1; |
4433 | } |
4434 | break; |
4435 | } |
4436 | case ParseNodeKind::ElemExpr: { |
4437 | PropertyByValue* elem = &lhs->as<PropertyByValue>(); |
4438 | bool isSuper = elem->isSuper(); |
4439 | MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!elem->key().isKind(ParseNodeKind::PrivateName))> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!elem->key().isKind(ParseNodeKind::PrivateName))) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!elem->key().isKind(ParseNodeKind::PrivateName)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4439); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)" ")"); do { *((volatile int*)__null) = 4439; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4440 | eoe.emplace(this, |
4441 | isCompound ? ElemOpEmitter::Kind::CompoundAssignment |
4442 | : isInit ? ElemOpEmitter::Kind::PropInit |
4443 | : ElemOpEmitter::Kind::SimpleAssignment, |
4444 | isSuper ? ElemOpEmitter::ObjKind::Super |
4445 | : ElemOpEmitter::ObjKind::Other); |
4446 | if (!emitElemObjAndKey(elem, isSuper, *eoe)) { |
4447 | // [stack] # if Super |
4448 | // [stack] THIS KEY |
4449 | // [stack] # otherwise |
4450 | // [stack] OBJ KEY |
4451 | return false; |
4452 | } |
4453 | if (isSuper) { |
4454 | // SUPERBASE is pushed onto KEY in eoe->emitGet below. |
4455 | offset += 3; |
4456 | } else { |
4457 | offset += 2; |
4458 | } |
4459 | break; |
4460 | } |
4461 | case ParseNodeKind::PrivateMemberExpr: { |
4462 | PrivateMemberAccess* privateExpr = &lhs->as<PrivateMemberAccess>(); |
4463 | xoe.emplace(this, |
4464 | isCompound ? PrivateOpEmitter::Kind::CompoundAssignment |
4465 | : isInit ? PrivateOpEmitter::Kind::PropInit |
4466 | : PrivateOpEmitter::Kind::SimpleAssignment, |
4467 | privateExpr->privateName().name()); |
4468 | if (!emitTree(&privateExpr->expression())) { |
4469 | // [stack] OBJ |
4470 | return false; |
4471 | } |
4472 | if (!xoe->emitReference()) { |
4473 | // [stack] OBJ KEY |
4474 | return false; |
4475 | } |
4476 | offset += xoe->numReferenceSlots(); |
4477 | break; |
4478 | } |
4479 | case ParseNodeKind::ArrayExpr: |
4480 | case ParseNodeKind::ObjectExpr: |
4481 | break; |
4482 | case ParseNodeKind::CallExpr: |
4483 | if (!emitTree(lhs)) { |
4484 | return false; |
4485 | } |
4486 | |
4487 | // Assignment to function calls is forbidden, but we have to make the |
4488 | // call first. Now we can throw. |
4489 | if (!emit2(JSOp::ThrowMsg, uint8_t(ThrowMsgKind::AssignToCall))) { |
4490 | return false; |
4491 | } |
4492 | |
4493 | // Rebalance the stack to placate stack-depth assertions. |
4494 | if (!emit1(JSOp::Pop)) { |
4495 | return false; |
4496 | } |
4497 | break; |
4498 | default: |
4499 | MOZ_ASSERT(0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(0)>::isValid, "invalid assertion condition"); if ( (__builtin_expect(!!(!(!!(0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("0", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4499); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0" ")"); do { *((volatile int*)__null) = 4499; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); |
4500 | } |
4501 | |
4502 | if (isCompound) { |
4503 | MOZ_ASSERT(rhs)do { static_assert( mozilla::detail::AssertionConditionType< decltype(rhs)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(rhs))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("rhs", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4503); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rhs" ")"); do { *((volatile int*)__null) = 4503; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); |
4504 | switch (lhs->getKind()) { |
4505 | case ParseNodeKind::ArgumentsLength: |
4506 | case ParseNodeKind::DotExpr: { |
4507 | PropertyAccess* prop = &lhs->as<PropertyAccess>(); |
4508 | if (!poe->emitGet(prop->key().atom())) { |
4509 | // [stack] # if Super |
4510 | // [stack] THIS SUPERBASE PROP |
4511 | // [stack] # otherwise |
4512 | // [stack] OBJ PROP |
4513 | return false; |
4514 | } |
4515 | break; |
4516 | } |
4517 | case ParseNodeKind::ElemExpr: { |
4518 | if (!eoe->emitGet()) { |
4519 | // [stack] KEY THIS OBJ ELEM |
4520 | return false; |
4521 | } |
4522 | break; |
4523 | } |
4524 | case ParseNodeKind::PrivateMemberExpr: { |
4525 | if (!xoe->emitGet()) { |
4526 | // [stack] OBJ KEY VALUE |
4527 | return false; |
4528 | } |
4529 | break; |
4530 | } |
4531 | case ParseNodeKind::CallExpr: |
4532 | // We just emitted a JSOp::ThrowMsg and popped the call's return |
4533 | // value. Push a random value to make sure the stack depth is |
4534 | // correct. |
4535 | if (!emit1(JSOp::Null)) { |
4536 | // [stack] NULL |
4537 | return false; |
4538 | } |
4539 | break; |
4540 | default:; |
4541 | } |
4542 | } |
4543 | |
4544 | switch (lhs->getKind()) { |
4545 | case ParseNodeKind::Name: |
4546 | if (!noe->prepareForRhs()) { |
4547 | // [stack] ENV? VAL? |
4548 | return false; |
4549 | } |
4550 | offset += noe->emittedBindOp(); |
4551 | break; |
4552 | case ParseNodeKind::ArgumentsLength: |
4553 | case ParseNodeKind::DotExpr: |
4554 | if (!poe->prepareForRhs()) { |
4555 | // [stack] # if Simple Assignment with Super |
4556 | // [stack] THIS SUPERBASE |
4557 | // [stack] # if Simple Assignment with other |
4558 | // [stack] OBJ |
4559 | // [stack] # if Compound Assignment with Super |
4560 | // [stack] THIS SUPERBASE PROP |
4561 | // [stack] # if Compound Assignment with other |
4562 | // [stack] OBJ PROP |
4563 | return false; |
4564 | } |
4565 | break; |
4566 | case ParseNodeKind::ElemExpr: |
4567 | if (!eoe->prepareForRhs()) { |
4568 | // [stack] # if Simple Assignment with Super |
4569 | // [stack] THIS KEY SUPERBASE |
4570 | // [stack] # if Simple Assignment with other |
4571 | // [stack] OBJ KEY |
4572 | // [stack] # if Compound Assignment with Super |
4573 | // [stack] THIS KEY SUPERBASE ELEM |
4574 | // [stack] # if Compound Assignment with other |
4575 | // [stack] OBJ KEY ELEM |
4576 | return false; |
4577 | } |
4578 | break; |
4579 | case ParseNodeKind::PrivateMemberExpr: |
4580 | // no stack adjustment needed |
4581 | break; |
4582 | default: |
4583 | break; |
4584 | } |
4585 | |
4586 | if (rhs) { |
4587 | if (!emitAssignmentRhs(rhs, anonFunctionName)) { |
4588 | // [stack] ... VAL? RHS |
4589 | return false; |
4590 | } |
4591 | } else { |
4592 | // Assumption: Things with pre-emitted RHS values never need to be named. |
4593 | if (!emitAssignmentRhs(offset)) { |
4594 | // [stack] ... VAL? RHS |
4595 | return false; |
4596 | } |
4597 | } |
4598 | |
4599 | /* If += etc., emit the binary operator with a hint for the decompiler. */ |
4600 | if (isCompound) { |
4601 | if (!emit1(compoundOp)) { |
4602 | // [stack] ... VAL |
4603 | return false; |
4604 | } |
4605 | if (!emit1(JSOp::NopIsAssignOp)) { |
4606 | // [stack] ... VAL |
4607 | return false; |
4608 | } |
4609 | } |
4610 | |
4611 | /* Finally, emit the specialized assignment bytecode. */ |
4612 | switch (lhs->getKind()) { |
4613 | case ParseNodeKind::Name: { |
4614 | if (!noe->emitAssignment()) { |
4615 | // [stack] VAL |
4616 | return false; |
4617 | } |
4618 | break; |
4619 | } |
4620 | case ParseNodeKind::ArgumentsLength: |
4621 | case ParseNodeKind::DotExpr: { |
4622 | PropertyAccess* prop = &lhs->as<PropertyAccess>(); |
4623 | if (!poe->emitAssignment(prop->key().atom())) { |
4624 | // [stack] VAL |
4625 | return false; |
4626 | } |
4627 | break; |
4628 | } |
4629 | case ParseNodeKind::CallExpr: |
4630 | // We threw above, so nothing to do here. |
4631 | break; |
4632 | case ParseNodeKind::ElemExpr: { |
4633 | if (!eoe->emitAssignment()) { |
4634 | // [stack] VAL |
4635 | return false; |
4636 | } |
4637 | break; |
4638 | } |
4639 | case ParseNodeKind::PrivateMemberExpr: |
4640 | if (!xoe->emitAssignment()) { |
4641 | // [stack] VAL |
4642 | return false; |
4643 | } |
4644 | break; |
4645 | case ParseNodeKind::ArrayExpr: |
4646 | case ParseNodeKind::ObjectExpr: |
4647 | if (!emitDestructuringOps(&lhs->as<ListNode>(), |
4648 | DestructuringFlavor::Assignment)) { |
4649 | return false; |
4650 | } |
4651 | break; |
4652 | default: |
4653 | MOZ_ASSERT(0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(0)>::isValid, "invalid assertion condition"); if ( (__builtin_expect(!!(!(!!(0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("0", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4653); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0" ")"); do { *((volatile int*)__null) = 4653; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); |
4654 | } |
4655 | return true; |
4656 | } |
4657 | |
4658 | bool BytecodeEmitter::emitShortCircuitAssignment(AssignmentNode* node) { |
4659 | TDZCheckCache tdzCache(this); |
4660 | |
4661 | JSOp op; |
4662 | switch (node->getKind()) { |
4663 | case ParseNodeKind::CoalesceAssignExpr: |
4664 | op = JSOp::Coalesce; |
4665 | break; |
4666 | case ParseNodeKind::OrAssignExpr: |
4667 | op = JSOp::Or; |
4668 | break; |
4669 | case ParseNodeKind::AndAssignExpr: |
4670 | op = JSOp::And; |
4671 | break; |
4672 | default: |
4673 | MOZ_CRASH("Unexpected ParseNodeKind")do { do { } while (false); MOZ_ReportCrash("" "Unexpected ParseNodeKind" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4673); AnnotateMozCrashReason("MOZ_CRASH(" "Unexpected ParseNodeKind" ")"); do { *((volatile int*)__null) = 4673; __attribute__((nomerge )) ::abort(); } while (false); } while (false); |
4674 | } |
4675 | |
4676 | ParseNode* lhs = node->left(); |
4677 | ParseNode* rhs = node->right(); |
4678 | |
4679 | // |name| is used within NameOpEmitter, so its lifetime must surpass |noe|. |
4680 | TaggedParserAtomIndex name; |
4681 | |
4682 | // Select the appropriate emitter based on the left-hand side. |
4683 | Maybe<NameOpEmitter> noe; |
4684 | Maybe<PropOpEmitter> poe; |
4685 | Maybe<ElemOpEmitter> eoe; |
4686 | Maybe<PrivateOpEmitter> xoe; |
4687 | |
4688 | int32_t depth = bytecodeSection().stackDepth(); |
4689 | |
4690 | // Number of values pushed onto the stack in addition to the lhs value. |
4691 | int32_t numPushed; |
4692 | |
4693 | // Evaluate the left-hand side expression and compute any stack values needed |
4694 | // for the assignment. |
4695 | switch (lhs->getKind()) { |
4696 | case ParseNodeKind::Name: { |
4697 | name = lhs->as<NameNode>().name(); |
4698 | noe.emplace(this, name, NameOpEmitter::Kind::CompoundAssignment); |
4699 | |
4700 | if (!noe->prepareForRhs()) { |
4701 | // [stack] ENV? LHS |
4702 | return false; |
4703 | } |
4704 | |
4705 | numPushed = noe->emittedBindOp(); |
4706 | break; |
4707 | } |
4708 | case ParseNodeKind::ArgumentsLength: |
4709 | case ParseNodeKind::DotExpr: { |
4710 | PropertyAccess* prop = &lhs->as<PropertyAccess>(); |
4711 | bool isSuper = prop->isSuper(); |
4712 | |
4713 | poe.emplace(this, PropOpEmitter::Kind::CompoundAssignment, |
4714 | isSuper ? PropOpEmitter::ObjKind::Super |
4715 | : PropOpEmitter::ObjKind::Other); |
4716 | |
4717 | if (!poe->prepareForObj()) { |
4718 | return false; |
4719 | } |
4720 | |
4721 | if (isSuper) { |
4722 | UnaryNode* base = &prop->expression().as<UnaryNode>(); |
4723 | if (!emitGetThisForSuperBase(base)) { |
4724 | // [stack] THIS SUPERBASE |
4725 | return false; |
4726 | } |
4727 | } else { |
4728 | if (!emitTree(&prop->expression())) { |
4729 | // [stack] OBJ |
4730 | return false; |
4731 | } |
4732 | } |
4733 | |
4734 | if (!poe->emitGet(prop->key().atom())) { |
4735 | // [stack] # if Super |
4736 | // [stack] THIS SUPERBASE LHS |
4737 | // [stack] # otherwise |
4738 | // [stack] OBJ LHS |
4739 | return false; |
4740 | } |
4741 | |
4742 | if (!poe->prepareForRhs()) { |
4743 | // [stack] # if Super |
4744 | // [stack] THIS SUPERBASE LHS |
4745 | // [stack] # otherwise |
4746 | // [stack] OBJ LHS |
4747 | return false; |
4748 | } |
4749 | |
4750 | numPushed = 1 + isSuper; |
4751 | break; |
4752 | } |
4753 | |
4754 | case ParseNodeKind::ElemExpr: { |
4755 | PropertyByValue* elem = &lhs->as<PropertyByValue>(); |
4756 | bool isSuper = elem->isSuper(); |
4757 | MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!elem->key().isKind(ParseNodeKind::PrivateName))> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!elem->key().isKind(ParseNodeKind::PrivateName))) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!elem->key().isKind(ParseNodeKind::PrivateName)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4757); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)" ")"); do { *((volatile int*)__null) = 4757; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4758 | eoe.emplace(this, ElemOpEmitter::Kind::CompoundAssignment, |
4759 | isSuper ? ElemOpEmitter::ObjKind::Super |
4760 | : ElemOpEmitter::ObjKind::Other); |
4761 | |
4762 | if (!emitElemObjAndKey(elem, isSuper, *eoe)) { |
4763 | // [stack] # if Super |
4764 | // [stack] THIS KEY |
4765 | // [stack] # otherwise |
4766 | // [stack] OBJ KEY |
4767 | return false; |
4768 | } |
4769 | |
4770 | if (!eoe->emitGet()) { |
4771 | // [stack] # if Super |
4772 | // [stack] THIS KEY SUPERBASE LHS |
4773 | // [stack] # otherwise |
4774 | // [stack] OBJ KEY LHS |
4775 | return false; |
4776 | } |
4777 | |
4778 | if (!eoe->prepareForRhs()) { |
4779 | // [stack] # if Super |
4780 | // [stack] THIS KEY SUPERBASE LHS |
4781 | // [stack] # otherwise |
4782 | // [stack] OBJ KEY LHS |
4783 | return false; |
4784 | } |
4785 | |
4786 | numPushed = 2 + isSuper; |
4787 | break; |
4788 | } |
4789 | |
4790 | case ParseNodeKind::PrivateMemberExpr: { |
4791 | PrivateMemberAccess* privateExpr = &lhs->as<PrivateMemberAccess>(); |
4792 | xoe.emplace(this, PrivateOpEmitter::Kind::CompoundAssignment, |
4793 | privateExpr->privateName().name()); |
4794 | if (!emitTree(&privateExpr->expression())) { |
4795 | // [stack] OBJ |
4796 | return false; |
4797 | } |
4798 | if (!xoe->emitReference()) { |
4799 | // [stack] OBJ NAME |
4800 | return false; |
4801 | } |
4802 | if (!xoe->emitGet()) { |
4803 | // [stack] OBJ NAME LHS |
4804 | return false; |
4805 | } |
4806 | numPushed = xoe->numReferenceSlots(); |
4807 | break; |
4808 | } |
4809 | |
4810 | default: |
4811 | MOZ_CRASH()do { do { } while (false); MOZ_ReportCrash("" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4811); AnnotateMozCrashReason("MOZ_CRASH(" ")"); do { *((volatile int*)__null) = 4811; __attribute__((nomerge)) ::abort(); } while (false); } while (false); |
4812 | } |
4813 | |
4814 | MOZ_ASSERT(bytecodeSection().stackDepth() == depth + numPushed + 1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(bytecodeSection().stackDepth() == depth + numPushed + 1)>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(bytecodeSection().stackDepth() == depth + numPushed + 1))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("bytecodeSection().stackDepth() == depth + numPushed + 1", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4814); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == depth + numPushed + 1" ")"); do { *((volatile int*)__null) = 4814; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4815 | |
4816 | // Test for the short-circuit condition. |
4817 | JumpList jump; |
4818 | if (!emitJump(op, &jump)) { |
4819 | // [stack] ... LHS |
4820 | return false; |
4821 | } |
4822 | |
4823 | // The short-circuit condition wasn't fulfilled, pop the left-hand side value |
4824 | // which was kept on the stack. |
4825 | if (!emit1(JSOp::Pop)) { |
4826 | // [stack] ... |
4827 | return false; |
4828 | } |
4829 | |
4830 | if (!emitAssignmentRhs(rhs, name)) { |
4831 | // [stack] ... RHS |
4832 | return false; |
4833 | } |
4834 | |
4835 | // Perform the actual assignment. |
4836 | switch (lhs->getKind()) { |
4837 | case ParseNodeKind::Name: { |
4838 | if (!noe->emitAssignment()) { |
4839 | // [stack] RHS |
4840 | return false; |
4841 | } |
4842 | break; |
4843 | } |
4844 | case ParseNodeKind::ArgumentsLength: |
4845 | case ParseNodeKind::DotExpr: { |
4846 | PropertyAccess* prop = &lhs->as<PropertyAccess>(); |
4847 | |
4848 | if (!poe->emitAssignment(prop->key().atom())) { |
4849 | // [stack] RHS |
4850 | return false; |
4851 | } |
4852 | break; |
4853 | } |
4854 | |
4855 | case ParseNodeKind::ElemExpr: { |
4856 | if (!eoe->emitAssignment()) { |
4857 | // [stack] RHS |
4858 | return false; |
4859 | } |
4860 | break; |
4861 | } |
4862 | |
4863 | case ParseNodeKind::PrivateMemberExpr: |
4864 | if (!xoe->emitAssignment()) { |
4865 | // [stack] RHS |
4866 | return false; |
4867 | } |
4868 | break; |
4869 | |
4870 | default: |
4871 | MOZ_CRASH()do { do { } while (false); MOZ_ReportCrash("" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4871); AnnotateMozCrashReason("MOZ_CRASH(" ")"); do { *((volatile int*)__null) = 4871; __attribute__((nomerge)) ::abort(); } while (false); } while (false); |
4872 | } |
4873 | |
4874 | MOZ_ASSERT(bytecodeSection().stackDepth() == depth + 1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(bytecodeSection().stackDepth() == depth + 1)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(bytecodeSection().stackDepth() == depth + 1))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("bytecodeSection().stackDepth() == depth + 1" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4874); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == depth + 1" ")"); do { *((volatile int*)__null) = 4874; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4875 | |
4876 | // Join with the short-circuit jump and pop anything left on the stack. |
4877 | if (numPushed > 0) { |
4878 | JumpList jumpAroundPop; |
4879 | if (!emitJump(JSOp::Goto, &jumpAroundPop)) { |
4880 | // [stack] RHS |
4881 | return false; |
4882 | } |
4883 | |
4884 | if (!emitJumpTargetAndPatch(jump)) { |
4885 | // [stack] ... LHS |
4886 | return false; |
4887 | } |
4888 | |
4889 | // Reconstruct the stack depth after the jump. |
4890 | bytecodeSection().setStackDepth(depth + 1 + numPushed); |
4891 | |
4892 | // Move the left-hand side value to the bottom and pop the rest. |
4893 | if (!emitUnpickN(numPushed)) { |
4894 | // [stack] LHS ... |
4895 | return false; |
4896 | } |
4897 | if (!emitPopN(numPushed)) { |
4898 | // [stack] LHS |
4899 | return false; |
4900 | } |
4901 | |
4902 | if (!emitJumpTargetAndPatch(jumpAroundPop)) { |
4903 | // [stack] LHS | RHS |
4904 | return false; |
4905 | } |
4906 | } else { |
4907 | if (!emitJumpTargetAndPatch(jump)) { |
4908 | // [stack] LHS | RHS |
4909 | return false; |
4910 | } |
4911 | } |
4912 | |
4913 | MOZ_ASSERT(bytecodeSection().stackDepth() == depth + 1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(bytecodeSection().stackDepth() == depth + 1)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(bytecodeSection().stackDepth() == depth + 1))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("bytecodeSection().stackDepth() == depth + 1" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4913); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == depth + 1" ")"); do { *((volatile int*)__null) = 4913; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4914 | |
4915 | return true; |
4916 | } |
4917 | |
4918 | bool BytecodeEmitter::emitCallSiteObjectArray(ObjLiteralWriter& writer, |
4919 | ListNode* cookedOrRaw, |
4920 | ParseNode* head, uint32_t count) { |
4921 | DebugOnly<size_t> idx = 0; |
4922 | for (ParseNode* pn : cookedOrRaw->contentsFrom(head)) { |
4923 | MOZ_ASSERT(pn->isKind(ParseNodeKind::TemplateStringExpr) ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->isKind(ParseNodeKind::TemplateStringExpr) || pn ->isKind(ParseNodeKind::RawUndefinedExpr))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->isKind(ParseNodeKind:: TemplateStringExpr) || pn->isKind(ParseNodeKind::RawUndefinedExpr )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("pn->isKind(ParseNodeKind::TemplateStringExpr) || pn->isKind(ParseNodeKind::RawUndefinedExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4924); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->isKind(ParseNodeKind::TemplateStringExpr) || pn->isKind(ParseNodeKind::RawUndefinedExpr)" ")"); do { *((volatile int*)__null) = 4924; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
4924 | pn->isKind(ParseNodeKind::RawUndefinedExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->isKind(ParseNodeKind::TemplateStringExpr) || pn ->isKind(ParseNodeKind::RawUndefinedExpr))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->isKind(ParseNodeKind:: TemplateStringExpr) || pn->isKind(ParseNodeKind::RawUndefinedExpr )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("pn->isKind(ParseNodeKind::TemplateStringExpr) || pn->isKind(ParseNodeKind::RawUndefinedExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4924); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->isKind(ParseNodeKind::TemplateStringExpr) || pn->isKind(ParseNodeKind::RawUndefinedExpr)" ")"); do { *((volatile int*)__null) = 4924; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4925 | |
4926 | if (!emitObjLiteralValue(writer, pn)) { |
4927 | return false; |
4928 | } |
4929 | idx++; |
4930 | } |
4931 | MOZ_ASSERT(idx == count)do { static_assert( mozilla::detail::AssertionConditionType< decltype(idx == count)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(idx == count))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("idx == count", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4931); AnnotateMozCrashReason("MOZ_ASSERT" "(" "idx == count" ")"); do { *((volatile int*)__null) = 4931; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4932 | |
4933 | return true; |
4934 | } |
4935 | |
4936 | bool BytecodeEmitter::emitCallSiteObject(CallSiteNode* callSiteObj) { |
4937 | constexpr JSOp op = JSOp::CallSiteObj; |
4938 | |
4939 | // The first element of a call-site node is the raw-values list. Skip over it. |
4940 | ListNode* raw = callSiteObj->rawNodes(); |
4941 | MOZ_ASSERT(raw->isKind(ParseNodeKind::ArrayExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(raw->isKind(ParseNodeKind::ArrayExpr))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(raw->isKind(ParseNodeKind::ArrayExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("raw->isKind(ParseNodeKind::ArrayExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4941); AnnotateMozCrashReason("MOZ_ASSERT" "(" "raw->isKind(ParseNodeKind::ArrayExpr)" ")"); do { *((volatile int*)__null) = 4941; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4942 | ParseNode* head = callSiteObj->head()->pn_next; |
4943 | |
4944 | uint32_t count = callSiteObj->count() - 1; |
4945 | MOZ_ASSERT(count == raw->count())do { static_assert( mozilla::detail::AssertionConditionType< decltype(count == raw->count())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(count == raw->count()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("count == raw->count()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4945); AnnotateMozCrashReason("MOZ_ASSERT" "(" "count == raw->count()" ")"); do { *((volatile int*)__null) = 4945; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4946 | |
4947 | ObjLiteralWriter writer; |
4948 | writer.beginCallSiteObj(op); |
4949 | writer.beginDenseArrayElements(); |
4950 | |
4951 | // Write elements of the two arrays: the 'cooked' values followed by the |
4952 | // 'raw' values. |
4953 | MOZ_RELEASE_ASSERT(count < UINT32_MAX / 2,do { static_assert( mozilla::detail::AssertionConditionType< decltype(count < (4294967295U) / 2)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(count < (4294967295U) / 2 ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "count < (4294967295U) / 2" " (" "Number of elements for both arrays must fit in uint32_t" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4954); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "count < (4294967295U) / 2" ") (" "Number of elements for both arrays must fit in uint32_t" ")"); do { *((volatile int*)__null) = 4954; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
4954 | "Number of elements for both arrays must fit in uint32_t")do { static_assert( mozilla::detail::AssertionConditionType< decltype(count < (4294967295U) / 2)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(count < (4294967295U) / 2 ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "count < (4294967295U) / 2" " (" "Number of elements for both arrays must fit in uint32_t" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4954); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "count < (4294967295U) / 2" ") (" "Number of elements for both arrays must fit in uint32_t" ")"); do { *((volatile int*)__null) = 4954; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4955 | if (!emitCallSiteObjectArray(writer, callSiteObj, head, count)) { |
4956 | return false; |
4957 | } |
4958 | if (!emitCallSiteObjectArray(writer, raw, raw->head(), count)) { |
4959 | return false; |
4960 | } |
4961 | |
4962 | GCThingIndex cookedIndex; |
4963 | if (!addObjLiteralData(writer, &cookedIndex)) { |
4964 | return false; |
4965 | } |
4966 | |
4967 | MOZ_ASSERT(sc->hasCallSiteObj())do { static_assert( mozilla::detail::AssertionConditionType< decltype(sc->hasCallSiteObj())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(sc->hasCallSiteObj()))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("sc->hasCallSiteObj()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4967); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->hasCallSiteObj()" ")"); do { *((volatile int*)__null) = 4967; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4968 | |
4969 | return emitInternedObjectOp(cookedIndex, op); |
4970 | } |
4971 | |
4972 | bool BytecodeEmitter::emitCatch(BinaryNode* catchClause) { |
4973 | // We must be nested under a try-finally statement. |
4974 | MOZ_ASSERT(innermostNestableControl->is<TryFinallyControl>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(innermostNestableControl->is<TryFinallyControl >())>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(innermostNestableControl->is<TryFinallyControl >()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("innermostNestableControl->is<TryFinallyControl>()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 4974); AnnotateMozCrashReason("MOZ_ASSERT" "(" "innermostNestableControl->is<TryFinallyControl>()" ")"); do { *((volatile int*)__null) = 4974; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4975 | |
4976 | ParseNode* param = catchClause->left(); |
4977 | if (!param) { |
4978 | // Catch parameter was omitted; just discard the exception. |
4979 | if (!emit1(JSOp::Pop)) { |
4980 | return false; |
4981 | } |
4982 | } else { |
4983 | switch (param->getKind()) { |
4984 | case ParseNodeKind::ArrayExpr: |
4985 | case ParseNodeKind::ObjectExpr: |
4986 | if (!emitDestructuringOps(¶m->as<ListNode>(), |
4987 | DestructuringFlavor::Declaration)) { |
4988 | return false; |
4989 | } |
4990 | if (!emit1(JSOp::Pop)) { |
4991 | return false; |
4992 | } |
4993 | break; |
4994 | |
4995 | case ParseNodeKind::Name: |
4996 | if (!emitLexicalInitialization(¶m->as<NameNode>())) { |
4997 | return false; |
4998 | } |
4999 | if (!emit1(JSOp::Pop)) { |
5000 | return false; |
5001 | } |
5002 | break; |
5003 | |
5004 | default: |
5005 | MOZ_ASSERT(0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(0)>::isValid, "invalid assertion condition"); if ( (__builtin_expect(!!(!(!!(0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("0", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5005); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0" ")"); do { *((volatile int*)__null) = 5005; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); |
5006 | } |
5007 | } |
5008 | |
5009 | /* Emit the catch body. */ |
5010 | return emitTree(catchClause->right()); |
5011 | } |
5012 | |
5013 | // Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See the |
5014 | // comment on EmitSwitch. |
5015 | MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitTry(TryNode* tryNode) { |
5016 | LexicalScopeNode* catchScope = tryNode->catchScope(); |
5017 | ParseNode* finallyNode = tryNode->finallyBlock(); |
5018 | |
5019 | TryEmitter::Kind kind; |
5020 | if (catchScope) { |
5021 | if (finallyNode) { |
5022 | kind = TryEmitter::Kind::TryCatchFinally; |
5023 | } else { |
5024 | kind = TryEmitter::Kind::TryCatch; |
5025 | } |
5026 | } else { |
5027 | MOZ_ASSERT(finallyNode)do { static_assert( mozilla::detail::AssertionConditionType< decltype(finallyNode)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(finallyNode))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("finallyNode", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5027); AnnotateMozCrashReason("MOZ_ASSERT" "(" "finallyNode" ")"); do { *((volatile int*)__null) = 5027; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5028 | kind = TryEmitter::Kind::TryFinally; |
5029 | } |
5030 | TryEmitter tryCatch(this, kind, TryEmitter::ControlKind::Syntactic); |
5031 | |
5032 | if (!tryCatch.emitTry()) { |
5033 | return false; |
5034 | } |
5035 | |
5036 | if (!emitTree(tryNode->body())) { |
5037 | return false; |
5038 | } |
5039 | |
5040 | // If this try has a catch block, emit it. |
5041 | if (catchScope) { |
5042 | // The emitted code for a catch block looks like: |
5043 | // |
5044 | // [pushlexicalenv] only if any local aliased |
5045 | // exception |
5046 | // setlocal 0; pop assign or possibly destructure exception |
5047 | // < catch block contents > |
5048 | // debugleaveblock |
5049 | // [poplexicalenv] only if any local aliased |
5050 | // if there is a finally block: |
5051 | // goto <finally> |
5052 | // [jump target for returning from finally] |
5053 | // goto <after finally> |
5054 | if (!tryCatch.emitCatch()) { |
5055 | return false; |
5056 | } |
5057 | |
5058 | // Emit the lexical scope and catch body. |
5059 | if (!emitTree(catchScope)) { |
5060 | return false; |
5061 | } |
5062 | } |
5063 | |
5064 | // Emit the finally handler, if there is one. |
5065 | if (finallyNode) { |
5066 | if (!tryCatch.emitFinally(Some(finallyNode->pn_pos.begin))) { |
5067 | return false; |
5068 | } |
5069 | |
5070 | if (!emitTree(finallyNode)) { |
5071 | return false; |
5072 | } |
5073 | } |
5074 | |
5075 | if (!tryCatch.emitEnd()) { |
5076 | return false; |
5077 | } |
5078 | |
5079 | return true; |
5080 | } |
5081 | |
5082 | [[nodiscard]] bool BytecodeEmitter::emitJumpToFinally(JumpList* jump, |
5083 | uint32_t idx) { |
5084 | // Push the continuation index. |
5085 | if (!emitNumberOp(idx)) { |
5086 | return false; |
5087 | } |
5088 | |
5089 | // Push |exception_stack|. |
5090 | if (!emit1(JSOp::Null)) { |
5091 | return false; |
5092 | } |
5093 | |
5094 | // Push |throwing|. |
5095 | if (!emit1(JSOp::False)) { |
5096 | return false; |
5097 | } |
5098 | |
5099 | // Jump to the finally block. |
5100 | if (!emitJumpNoFallthrough(JSOp::Goto, jump)) { |
5101 | return false; |
5102 | } |
5103 | |
5104 | return true; |
5105 | } |
5106 | |
5107 | bool BytecodeEmitter::emitIf(TernaryNode* ifNode) { |
5108 | IfEmitter ifThenElse(this); |
5109 | |
5110 | if (!ifThenElse.emitIf(Some(ifNode->kid1()->pn_pos.begin))) { |
5111 | return false; |
5112 | } |
5113 | |
5114 | if_again: |
5115 | ParseNode* testNode = ifNode->kid1(); |
5116 | auto conditionKind = IfEmitter::ConditionKind::Positive; |
5117 | if (testNode->isKind(ParseNodeKind::NotExpr)) { |
5118 | testNode = testNode->as<UnaryNode>().kid(); |
5119 | conditionKind = IfEmitter::ConditionKind::Negative; |
5120 | } |
5121 | |
5122 | if (!markStepBreakpoint()) { |
5123 | return false; |
5124 | } |
5125 | |
5126 | // Emit code for the condition before pushing stmtInfo. |
5127 | // NOTE: NotExpr of testNode may be unwrapped, and in that case the negation |
5128 | // is handled by conditionKind. |
5129 | if (!emitTree(testNode)) { |
5130 | return false; |
5131 | } |
5132 | |
5133 | ParseNode* elseNode = ifNode->kid3(); |
5134 | if (elseNode) { |
5135 | if (!ifThenElse.emitThenElse(conditionKind)) { |
5136 | return false; |
5137 | } |
5138 | } else { |
5139 | if (!ifThenElse.emitThen(conditionKind)) { |
5140 | return false; |
5141 | } |
5142 | } |
5143 | |
5144 | /* Emit code for the then part. */ |
5145 | if (!emitTree(ifNode->kid2())) { |
5146 | return false; |
5147 | } |
5148 | |
5149 | if (elseNode) { |
5150 | if (elseNode->isKind(ParseNodeKind::IfStmt)) { |
5151 | ifNode = &elseNode->as<TernaryNode>(); |
5152 | |
5153 | if (!ifThenElse.emitElseIf(Some(ifNode->kid1()->pn_pos.begin))) { |
5154 | return false; |
5155 | } |
5156 | |
5157 | goto if_again; |
5158 | } |
5159 | |
5160 | if (!ifThenElse.emitElse()) { |
5161 | return false; |
5162 | } |
5163 | |
5164 | /* Emit code for the else part. */ |
5165 | if (!emitTree(elseNode)) { |
5166 | return false; |
5167 | } |
5168 | } |
5169 | |
5170 | if (!ifThenElse.emitEnd()) { |
5171 | return false; |
5172 | } |
5173 | |
5174 | return true; |
5175 | } |
5176 | |
5177 | bool BytecodeEmitter::emitHoistedFunctionsInList(ListNode* stmtList) { |
5178 | MOZ_ASSERT(stmtList->hasTopLevelFunctionDeclarations())do { static_assert( mozilla::detail::AssertionConditionType< decltype(stmtList->hasTopLevelFunctionDeclarations())>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(stmtList->hasTopLevelFunctionDeclarations()))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("stmtList->hasTopLevelFunctionDeclarations()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5178); AnnotateMozCrashReason("MOZ_ASSERT" "(" "stmtList->hasTopLevelFunctionDeclarations()" ")"); do { *((volatile int*)__null) = 5178; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5179 | |
5180 | // We can call this multiple times for sloppy eval scopes. |
5181 | if (stmtList->emittedTopLevelFunctionDeclarations()) { |
5182 | return true; |
5183 | } |
5184 | |
5185 | stmtList->setEmittedTopLevelFunctionDeclarations(); |
5186 | |
5187 | for (ParseNode* stmt : stmtList->contents()) { |
5188 | ParseNode* maybeFun = stmt; |
5189 | |
5190 | if (!sc->strict()) { |
5191 | while (maybeFun->isKind(ParseNodeKind::LabelStmt)) { |
5192 | maybeFun = maybeFun->as<LabeledStatement>().statement(); |
5193 | } |
5194 | } |
5195 | |
5196 | if (maybeFun->is<FunctionNode>() && |
5197 | maybeFun->as<FunctionNode>().functionIsHoisted()) { |
5198 | if (!emitTree(maybeFun)) { |
5199 | return false; |
5200 | } |
5201 | } |
5202 | } |
5203 | |
5204 | return true; |
5205 | } |
5206 | |
5207 | bool BytecodeEmitter::emitLexicalScopeBody( |
5208 | ParseNode* body, EmitLineNumberNote emitLineNote /* = EMIT_LINENOTE */) { |
5209 | if (body->isKind(ParseNodeKind::StatementList) && |
5210 | body->as<ListNode>().hasTopLevelFunctionDeclarations()) { |
5211 | // This block contains function statements whose definitions are |
5212 | // hoisted to the top of the block. Emit these as a separate pass |
5213 | // before the rest of the block. |
5214 | if (!emitHoistedFunctionsInList(&body->as<ListNode>())) { |
5215 | return false; |
5216 | } |
5217 | } |
5218 | |
5219 | // Line notes were updated by emitLexicalScope or emitScript. |
5220 | return emitTree(body, ValueUsage::WantValue, emitLineNote); |
5221 | } |
5222 | |
5223 | // Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See |
5224 | // the comment on emitSwitch. |
5225 | MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitLexicalScope( |
5226 | LexicalScopeNode* lexicalScope) { |
5227 | LexicalScopeEmitter lse(this); |
5228 | |
5229 | ParseNode* body = lexicalScope->scopeBody(); |
5230 | if (lexicalScope->isEmptyScope()) { |
5231 | if (!lse.emitEmptyScope()) { |
5232 | return false; |
5233 | } |
5234 | |
5235 | if (!emitLexicalScopeBody(body)) { |
5236 | return false; |
5237 | } |
5238 | |
5239 | if (!lse.emitEnd()) { |
5240 | return false; |
5241 | } |
5242 | |
5243 | return true; |
5244 | } |
5245 | |
5246 | // We are about to emit some bytecode for what the spec calls "declaration |
5247 | // instantiation". Assign these instructions to the opening `{` of the |
5248 | // block. (Using the location of each declaration we're instantiating is |
5249 | // too weird when stepping in the debugger.) |
5250 | if (!ParseNodeRequiresSpecialLineNumberNotes(body)) { |
5251 | if (!updateSourceCoordNotes(lexicalScope->pn_pos.begin)) { |
5252 | return false; |
5253 | } |
5254 | } |
5255 | |
5256 | ScopeKind kind; |
5257 | if (body->isKind(ParseNodeKind::Catch)) { |
5258 | BinaryNode* catchNode = &body->as<BinaryNode>(); |
5259 | kind = |
5260 | (!catchNode->left() || catchNode->left()->isKind(ParseNodeKind::Name)) |
5261 | ? ScopeKind::SimpleCatch |
5262 | : ScopeKind::Catch; |
5263 | } else { |
5264 | kind = lexicalScope->kind(); |
5265 | } |
5266 | |
5267 | if (!lse.emitScope(kind, lexicalScope->scopeBindings())) { |
5268 | return false; |
5269 | } |
5270 | |
5271 | if (body->isKind(ParseNodeKind::ForStmt)) { |
5272 | // for loops need to emit JSOp::FreshenLexicalEnv/JSOp::RecreateLexicalEnv |
5273 | // if there are lexical declarations in the head. Signal this by passing a |
5274 | // non-nullptr lexical scope. |
5275 | if (!emitFor(&body->as<ForNode>(), &lse.emitterScope())) { |
5276 | return false; |
5277 | } |
5278 | } else { |
5279 | if (!emitLexicalScopeBody(body, SUPPRESS_LINENOTE)) { |
5280 | return false; |
5281 | } |
5282 | } |
5283 | |
5284 | if (!lse.emitEnd()) { |
5285 | return false; |
5286 | } |
5287 | return true; |
5288 | } |
5289 | |
5290 | bool BytecodeEmitter::emitWith(BinaryNode* withNode) { |
5291 | // Ensure that the column of the 'with' is set properly. |
5292 | if (!updateSourceCoordNotes(withNode->left()->pn_pos.begin)) { |
5293 | return false; |
5294 | } |
5295 | |
5296 | if (!markStepBreakpoint()) { |
5297 | return false; |
5298 | } |
5299 | |
5300 | if (!emitTree(withNode->left())) { |
5301 | return false; |
5302 | } |
5303 | |
5304 | EmitterScope emitterScope(this); |
5305 | if (!emitterScope.enterWith(this)) { |
5306 | return false; |
5307 | } |
5308 | |
5309 | if (!emitTree(withNode->right())) { |
5310 | return false; |
5311 | } |
5312 | |
5313 | return emitterScope.leave(this); |
5314 | } |
5315 | |
5316 | bool BytecodeEmitter::emitCopyDataProperties(CopyOption option) { |
5317 | DebugOnly<int32_t> depth = bytecodeSection().stackDepth(); |
5318 | |
5319 | uint32_t argc; |
5320 | if (option == CopyOption::Filtered) { |
5321 | MOZ_ASSERT(depth > 2)do { static_assert( mozilla::detail::AssertionConditionType< decltype(depth > 2)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(depth > 2))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("depth > 2", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5321); AnnotateMozCrashReason("MOZ_ASSERT" "(" "depth > 2" ")"); do { *((volatile int*)__null) = 5321; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5322 | // [stack] TARGET SOURCE SET |
5323 | argc = 3; |
5324 | |
5325 | if (!emitAtomOp(JSOp::GetIntrinsic, |
5326 | TaggedParserAtomIndex::WellKnown::CopyDataProperties())) { |
5327 | // [stack] TARGET SOURCE SET COPYDATAPROPERTIES |
5328 | return false; |
5329 | } |
5330 | } else { |
5331 | MOZ_ASSERT(depth > 1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(depth > 1)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(depth > 1))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("depth > 1", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5331); AnnotateMozCrashReason("MOZ_ASSERT" "(" "depth > 1" ")"); do { *((volatile int*)__null) = 5331; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5332 | // [stack] TARGET SOURCE |
5333 | argc = 2; |
5334 | |
5335 | if (!emitAtomOp( |
5336 | JSOp::GetIntrinsic, |
5337 | TaggedParserAtomIndex::WellKnown::CopyDataPropertiesUnfiltered())) { |
5338 | // [stack] TARGET SOURCE COPYDATAPROPERTIES |
5339 | return false; |
5340 | } |
5341 | } |
5342 | |
5343 | if (!emit1(JSOp::Undefined)) { |
5344 | // [stack] TARGET SOURCE SET? COPYDATAPROPERTIES |
5345 | // UNDEFINED |
5346 | return false; |
5347 | } |
5348 | if (!emit2(JSOp::Pick, argc + 1)) { |
5349 | // [stack] SOURCE SET? COPYDATAPROPERTIES UNDEFINED |
5350 | // TARGET |
5351 | return false; |
5352 | } |
5353 | if (!emit2(JSOp::Pick, argc + 1)) { |
5354 | // [stack] SET? COPYDATAPROPERTIES UNDEFINED TARGET |
5355 | // SOURCE |
5356 | return false; |
5357 | } |
5358 | if (option == CopyOption::Filtered) { |
5359 | if (!emit2(JSOp::Pick, argc + 1)) { |
5360 | // [stack] COPYDATAPROPERTIES UNDEFINED TARGET SOURCE SET |
5361 | return false; |
5362 | } |
5363 | } |
5364 | // Callee is always self-hosted instrinsic, and cannot be content function. |
5365 | if (!emitCall(JSOp::CallIgnoresRv, argc)) { |
5366 | // [stack] IGNORED |
5367 | return false; |
5368 | } |
5369 | |
5370 | if (!emit1(JSOp::Pop)) { |
5371 | // [stack] |
5372 | return false; |
5373 | } |
5374 | |
5375 | MOZ_ASSERT(depth - int(argc) == bytecodeSection().stackDepth())do { static_assert( mozilla::detail::AssertionConditionType< decltype(depth - int(argc) == bytecodeSection().stackDepth()) >::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(depth - int(argc) == bytecodeSection().stackDepth()) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("depth - int(argc) == bytecodeSection().stackDepth()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5375); AnnotateMozCrashReason("MOZ_ASSERT" "(" "depth - int(argc) == bytecodeSection().stackDepth()" ")"); do { *((volatile int*)__null) = 5375; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5376 | return true; |
5377 | } |
5378 | |
5379 | bool BytecodeEmitter::emitBigIntOp(BigIntLiteral* bigint) { |
5380 | GCThingIndex index; |
5381 | if (!perScriptData().gcThingList().append(bigint, &index)) { |
5382 | return false; |
5383 | } |
5384 | return emitGCIndexOp(JSOp::BigInt, index); |
5385 | } |
5386 | |
5387 | bool BytecodeEmitter::emitIterable(ParseNode* value, |
5388 | SelfHostedIter selfHostedIter, |
5389 | IteratorKind iterKind) { |
5390 | MOZ_ASSERT(getSelfHostedIterFor(value) == selfHostedIter)do { static_assert( mozilla::detail::AssertionConditionType< decltype(getSelfHostedIterFor(value) == selfHostedIter)>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(getSelfHostedIterFor(value) == selfHostedIter))), 0) )) { do { } while (false); MOZ_ReportAssertionFailure("getSelfHostedIterFor(value) == selfHostedIter" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5390); AnnotateMozCrashReason("MOZ_ASSERT" "(" "getSelfHostedIterFor(value) == selfHostedIter" ")"); do { *((volatile int*)__null) = 5390; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5391 | |
5392 | if (!emitTree(value)) { |
5393 | // [stack] ITERABLE |
5394 | return false; |
5395 | } |
5396 | |
5397 | switch (selfHostedIter) { |
5398 | case SelfHostedIter::Deny: |
5399 | case SelfHostedIter::AllowContent: |
5400 | // [stack] ITERABLE |
5401 | return true; |
5402 | |
5403 | case SelfHostedIter::AllowContentWith: { |
5404 | // This is the following case: |
5405 | // |
5406 | // for (const nextValue of allowContentIterWith(items, usingIterator)) { |
5407 | // |
5408 | // `items` is emitted by `emitTree(value)` above, and the result is on the |
5409 | // stack as ITERABLE. |
5410 | // `usingIterator` is the value of `items[Symbol.iterator]`, that's |
5411 | // already retrieved. |
5412 | ListNode* argsList = value->as<CallNode>().args(); |
5413 | MOZ_ASSERT_IF(iterKind == IteratorKind::Sync, argsList->count() == 2)do { if (iterKind == IteratorKind::Sync) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(argsList ->count() == 2)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(argsList->count() == 2))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 2" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5413); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2" ")"); do { *((volatile int*)__null) = 5413; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
5414 | MOZ_ASSERT_IF(iterKind == IteratorKind::Async, argsList->count() == 3)do { if (iterKind == IteratorKind::Async) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(argsList ->count() == 3)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(argsList->count() == 3))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 3" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5414); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 3" ")"); do { *((volatile int*)__null) = 5414; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
5415 | |
5416 | if (!emitTree(argsList->head()->pn_next)) { |
5417 | // [stack] ITERABLE ITERFN |
5418 | return false; |
5419 | } |
5420 | |
5421 | // Async iterator has two possible iterators: An async iterator and a sync |
5422 | // iterator. |
5423 | if (iterKind == IteratorKind::Async) { |
5424 | if (!emitTree(argsList->head()->pn_next->pn_next)) { |
5425 | // [stack] ITERABLE ASYNC_ITERFN SYNC_ITERFN |
5426 | return false; |
5427 | } |
5428 | } |
5429 | |
5430 | // [stack] ITERABLE ASYNC_ITERFN? SYNC_ITERFN |
5431 | return true; |
5432 | } |
5433 | |
5434 | case SelfHostedIter::AllowContentWithNext: { |
5435 | // This is the following case: |
5436 | // |
5437 | // for (const nextValue of allowContentIterWithNext(iterator, next)) { |
5438 | // |
5439 | // `iterator` is emitted by `emitTree(value)` above, and the result is on |
5440 | // the stack as ITER. |
5441 | // `next` is the value of `iterator.next`, that's already retrieved. |
5442 | ListNode* argsList = value->as<CallNode>().args(); |
5443 | MOZ_ASSERT(argsList->count() == 2)do { static_assert( mozilla::detail::AssertionConditionType< decltype(argsList->count() == 2)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(argsList->count() == 2))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 2" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5443); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2" ")"); do { *((volatile int*)__null) = 5443; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5444 | |
5445 | if (!emitTree(argsList->head()->pn_next)) { |
5446 | // [stack] ITER NEXT |
5447 | return false; |
5448 | } |
5449 | |
5450 | if (!emit1(JSOp::Swap)) { |
5451 | // [stack] NEXT ITER |
5452 | return false; |
5453 | } |
5454 | |
5455 | // [stack] NEXT ITER |
5456 | return true; |
5457 | } |
5458 | } |
5459 | |
5460 | MOZ_CRASH("invalid self-hosted iteration kind")do { do { } while (false); MOZ_ReportCrash("" "invalid self-hosted iteration kind" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5460); AnnotateMozCrashReason("MOZ_CRASH(" "invalid self-hosted iteration kind" ")"); do { *((volatile int*)__null) = 5460; __attribute__((nomerge )) ::abort(); } while (false); } while (false); |
5461 | } |
5462 | |
5463 | bool BytecodeEmitter::emitIterator(SelfHostedIter selfHostedIter) { |
5464 | MOZ_ASSERT(selfHostedIter != SelfHostedIter::Deny ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter ::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" " (" "[Symbol.iterator]() call is prohibited in self-hosted code " "because it can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5467); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" ") (" "[Symbol.iterator]() call is prohibited in self-hosted code " "because it can run user-modifiable iteration code" ")"); do { *((volatile int*)__null) = 5467; __attribute__((nomerge)) :: abort(); } while (false); } } while (false) |
5465 | emitterMode != BytecodeEmitter::SelfHosting,do { static_assert( mozilla::detail::AssertionConditionType< decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter ::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" " (" "[Symbol.iterator]() call is prohibited in self-hosted code " "because it can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5467); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" ") (" "[Symbol.iterator]() call is prohibited in self-hosted code " "because it can run user-modifiable iteration code" ")"); do { *((volatile int*)__null) = 5467; __attribute__((nomerge)) :: abort(); } while (false); } } while (false) |
5466 | "[Symbol.iterator]() call is prohibited in self-hosted code "do { static_assert( mozilla::detail::AssertionConditionType< decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter ::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" " (" "[Symbol.iterator]() call is prohibited in self-hosted code " "because it can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5467); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" ") (" "[Symbol.iterator]() call is prohibited in self-hosted code " "because it can run user-modifiable iteration code" ")"); do { *((volatile int*)__null) = 5467; __attribute__((nomerge)) :: abort(); } while (false); } } while (false) |
5467 | "because it can run user-modifiable iteration code")do { static_assert( mozilla::detail::AssertionConditionType< decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter ::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" " (" "[Symbol.iterator]() call is prohibited in self-hosted code " "because it can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5467); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" ") (" "[Symbol.iterator]() call is prohibited in self-hosted code " "because it can run user-modifiable iteration code" ")"); do { *((volatile int*)__null) = 5467; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); |
5468 | |
5469 | if (selfHostedIter == SelfHostedIter::AllowContentWithNext) { |
5470 | // [stack] NEXT ITER |
5471 | |
5472 | // Nothing to do, stack already contains the iterator and its `next` method. |
5473 | return true; |
5474 | } |
5475 | |
5476 | if (selfHostedIter != SelfHostedIter::AllowContentWith) { |
5477 | // [stack] OBJ |
5478 | |
5479 | // Convert iterable to iterator. |
5480 | if (!emit1(JSOp::Dup)) { |
5481 | // [stack] OBJ OBJ |
5482 | return false; |
5483 | } |
5484 | if (!emit2(JSOp::Symbol, uint8_t(JS::SymbolCode::iterator))) { |
5485 | // [stack] OBJ OBJ @@ITERATOR |
5486 | return false; |
5487 | } |
5488 | if (!emitElemOpBase(JSOp::GetElem)) { |
5489 | // [stack] OBJ ITERFN |
5490 | return false; |
5491 | } |
5492 | } |
5493 | |
5494 | if (!emit1(JSOp::Swap)) { |
5495 | // [stack] ITERFN OBJ |
5496 | return false; |
5497 | } |
5498 | if (!emitCall(getIterCallOp(JSOp::CallIter, selfHostedIter), 0)) { |
5499 | // [stack] ITER |
5500 | return false; |
5501 | } |
5502 | if (!emitCheckIsObj(CheckIsObjectKind::GetIterator)) { |
5503 | // [stack] ITER |
5504 | return false; |
5505 | } |
5506 | if (!emit1(JSOp::Dup)) { |
5507 | // [stack] ITER ITER |
5508 | return false; |
5509 | } |
5510 | if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::next())) { |
5511 | // [stack] ITER NEXT |
5512 | return false; |
5513 | } |
5514 | if (!emit1(JSOp::Swap)) { |
5515 | // [stack] NEXT ITER |
5516 | return false; |
5517 | } |
5518 | return true; |
5519 | } |
5520 | |
5521 | bool BytecodeEmitter::emitAsyncIterator(SelfHostedIter selfHostedIter) { |
5522 | MOZ_ASSERT(selfHostedIter != SelfHostedIter::AllowContentWithNext)do { static_assert( mozilla::detail::AssertionConditionType< decltype(selfHostedIter != SelfHostedIter::AllowContentWithNext )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(selfHostedIter != SelfHostedIter::AllowContentWithNext ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "selfHostedIter != SelfHostedIter::AllowContentWithNext", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5522); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::AllowContentWithNext" ")"); do { *((volatile int*)__null) = 5522; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5523 | MOZ_ASSERT(selfHostedIter != SelfHostedIter::Deny ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter ::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" " (" "[Symbol.asyncIterator]() call is prohibited in self-hosted code " "because it can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5526); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" ") (" "[Symbol.asyncIterator]() call is prohibited in self-hosted code " "because it can run user-modifiable iteration code" ")"); do { *((volatile int*)__null) = 5526; __attribute__((nomerge)) :: abort(); } while (false); } } while (false) |
5524 | emitterMode != BytecodeEmitter::SelfHosting,do { static_assert( mozilla::detail::AssertionConditionType< decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter ::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" " (" "[Symbol.asyncIterator]() call is prohibited in self-hosted code " "because it can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5526); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" ") (" "[Symbol.asyncIterator]() call is prohibited in self-hosted code " "because it can run user-modifiable iteration code" ")"); do { *((volatile int*)__null) = 5526; __attribute__((nomerge)) :: abort(); } while (false); } } while (false) |
5525 | "[Symbol.asyncIterator]() call is prohibited in self-hosted code "do { static_assert( mozilla::detail::AssertionConditionType< decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter ::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" " (" "[Symbol.asyncIterator]() call is prohibited in self-hosted code " "because it can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5526); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" ") (" "[Symbol.asyncIterator]() call is prohibited in self-hosted code " "because it can run user-modifiable iteration code" ")"); do { *((volatile int*)__null) = 5526; __attribute__((nomerge)) :: abort(); } while (false); } } while (false) |
5526 | "because it can run user-modifiable iteration code")do { static_assert( mozilla::detail::AssertionConditionType< decltype(selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(selfHostedIter != SelfHostedIter ::Deny || emitterMode != BytecodeEmitter::SelfHosting))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" " (" "[Symbol.asyncIterator]() call is prohibited in self-hosted code " "because it can run user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5526); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter != SelfHostedIter::Deny || emitterMode != BytecodeEmitter::SelfHosting" ") (" "[Symbol.asyncIterator]() call is prohibited in self-hosted code " "because it can run user-modifiable iteration code" ")"); do { *((volatile int*)__null) = 5526; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); |
5527 | |
5528 | if (selfHostedIter != SelfHostedIter::AllowContentWith) { |
5529 | // [stack] OBJ |
5530 | |
5531 | // Convert iterable to iterator. |
5532 | if (!emit1(JSOp::Dup)) { |
5533 | // [stack] OBJ OBJ |
5534 | return false; |
5535 | } |
5536 | if (!emit2(JSOp::Symbol, uint8_t(JS::SymbolCode::asyncIterator))) { |
5537 | // [stack] OBJ OBJ @@ASYNCITERATOR |
5538 | return false; |
5539 | } |
5540 | if (!emitElemOpBase(JSOp::GetElem)) { |
5541 | // [stack] OBJ ASYNC_ITERFN |
5542 | return false; |
5543 | } |
5544 | } else { |
5545 | // [stack] OBJ ASYNC_ITERFN SYNC_ITERFN |
5546 | |
5547 | if (!emitElemOpBase(JSOp::Swap)) { |
5548 | // [stack] OBJ SYNC_ITERFN ASYNC_ITERFN |
5549 | return false; |
5550 | } |
5551 | } |
5552 | |
5553 | InternalIfEmitter ifAsyncIterIsUndefined(this); |
5554 | if (!emit1(JSOp::IsNullOrUndefined)) { |
5555 | // [stack] OBJ SYNC_ITERFN? ASYNC_ITERFN NULL-OR-UNDEF |
5556 | return false; |
5557 | } |
5558 | if (!ifAsyncIterIsUndefined.emitThenElse()) { |
5559 | // [stack] OBJ SYNC_ITERFN? ASYNC_ITERFN |
5560 | return false; |
5561 | } |
5562 | |
5563 | if (!emit1(JSOp::Pop)) { |
5564 | // [stack] OBJ SYNC_ITERFN? |
5565 | return false; |
5566 | } |
5567 | |
5568 | if (selfHostedIter != SelfHostedIter::AllowContentWith) { |
5569 | if (!emit1(JSOp::Dup)) { |
5570 | // [stack] OBJ OBJ |
5571 | return false; |
5572 | } |
5573 | if (!emit2(JSOp::Symbol, uint8_t(JS::SymbolCode::iterator))) { |
5574 | // [stack] OBJ OBJ @@ITERATOR |
5575 | return false; |
5576 | } |
5577 | if (!emitElemOpBase(JSOp::GetElem)) { |
5578 | // [stack] OBJ SYNC_ITERFN |
5579 | return false; |
5580 | } |
5581 | } else { |
5582 | // [stack] OBJ SYNC_ITERFN |
5583 | } |
5584 | |
5585 | if (!emit1(JSOp::Swap)) { |
5586 | // [stack] SYNC_ITERFN OBJ |
5587 | return false; |
5588 | } |
5589 | if (!emitCall(getIterCallOp(JSOp::CallIter, selfHostedIter), 0)) { |
5590 | // [stack] ITER |
5591 | return false; |
5592 | } |
5593 | if (!emitCheckIsObj(CheckIsObjectKind::GetIterator)) { |
5594 | // [stack] ITER |
5595 | return false; |
5596 | } |
5597 | |
5598 | if (!emit1(JSOp::Dup)) { |
5599 | // [stack] ITER ITER |
5600 | return false; |
5601 | } |
5602 | if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::next())) { |
5603 | // [stack] ITER SYNCNEXT |
5604 | return false; |
5605 | } |
5606 | |
5607 | if (!emit1(JSOp::ToAsyncIter)) { |
5608 | // [stack] ITER |
5609 | return false; |
5610 | } |
5611 | |
5612 | if (!ifAsyncIterIsUndefined.emitElse()) { |
5613 | // [stack] OBJ SYNC_ITERFN? ASYNC_ITERFN |
5614 | return false; |
5615 | } |
5616 | |
5617 | if (selfHostedIter == SelfHostedIter::AllowContentWith) { |
5618 | if (!emit1(JSOp::Swap)) { |
5619 | // [stack] OBJ ASYNC_ITERFN SYNC_ITERFN |
5620 | return false; |
5621 | } |
5622 | if (!emit1(JSOp::Pop)) { |
5623 | // [stack] OBJ ASYNC_ITERFN |
5624 | return false; |
5625 | } |
5626 | } |
5627 | |
5628 | if (!emit1(JSOp::Swap)) { |
5629 | // [stack] ASYNC_ITERFN OBJ |
5630 | return false; |
5631 | } |
5632 | if (!emitCall(getIterCallOp(JSOp::CallIter, selfHostedIter), 0)) { |
5633 | // [stack] ITER |
5634 | return false; |
5635 | } |
5636 | if (!emitCheckIsObj(CheckIsObjectKind::GetAsyncIterator)) { |
5637 | // [stack] ITER |
5638 | return false; |
5639 | } |
5640 | |
5641 | if (!ifAsyncIterIsUndefined.emitEnd()) { |
5642 | // [stack] ITER |
5643 | return false; |
5644 | } |
5645 | |
5646 | if (!emit1(JSOp::Dup)) { |
5647 | // [stack] ITER ITER |
5648 | return false; |
5649 | } |
5650 | if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::next())) { |
5651 | // [stack] ITER NEXT |
5652 | return false; |
5653 | } |
5654 | if (!emit1(JSOp::Swap)) { |
5655 | // [stack] NEXT ITER |
5656 | return false; |
5657 | } |
5658 | |
5659 | return true; |
5660 | } |
5661 | |
5662 | bool BytecodeEmitter::emitSpread(SelfHostedIter selfHostedIter) { |
5663 | // [stack] NEXT ITER ARR I |
5664 | return emitSpread(selfHostedIter, 2, JSOp::InitElemInc); |
5665 | // [stack] ARR FINAL_INDEX |
5666 | } |
5667 | |
5668 | bool BytecodeEmitter::emitSpread(SelfHostedIter selfHostedIter, |
5669 | int spreadeeStackItems, JSOp storeElementOp) { |
5670 | LoopControl loopInfo(this, StatementKind::Spread); |
5671 | // In the [stack] annotations, (spreadee) can be "ARR I" (when spreading |
5672 | // into an array or into call parameters, or "TUPLE" (when spreading into a |
5673 | // tuple) |
5674 | |
5675 | if (!loopInfo.emitLoopHead(this, Nothing())) { |
5676 | // [stack] NEXT ITER (spreadee) |
5677 | return false; |
5678 | } |
5679 | |
5680 | { |
5681 | #ifdef DEBUG1 |
5682 | auto loopDepth = bytecodeSection().stackDepth(); |
5683 | #endif |
5684 | |
5685 | // Spread operations can't contain |continue|, so don't bother setting loop |
5686 | // and enclosing "update" offsets, as we do with for-loops. |
5687 | |
5688 | if (!emitDupAt(spreadeeStackItems + 1, 2)) { |
5689 | // [stack] NEXT ITER (spreadee) NEXT ITER |
5690 | return false; |
5691 | } |
5692 | if (!emitIteratorNext(Nothing(), IteratorKind::Sync, selfHostedIter)) { |
5693 | // [stack] NEXT ITER (spreadee) RESULT |
5694 | return false; |
5695 | } |
5696 | if (!emit1(JSOp::Dup)) { |
5697 | // [stack] NEXT ITER (spreadee) RESULT RESULT |
5698 | return false; |
5699 | } |
5700 | if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::done())) { |
5701 | // [stack] NEXT ITER (spreadee) RESULT DONE |
5702 | return false; |
5703 | } |
5704 | if (!emitJump(JSOp::JumpIfTrue, &loopInfo.breaks)) { |
5705 | // [stack] NEXT ITER (spreadee) RESULT |
5706 | return false; |
5707 | } |
5708 | |
5709 | // Emit code to assign result.value to the iteration variable. |
5710 | if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::value())) { |
5711 | // [stack] NEXT ITER (spreadee) VALUE |
5712 | return false; |
5713 | } |
5714 | if (!emit1(storeElementOp)) { |
5715 | // [stack] NEXT ITER (spreadee) |
5716 | return false; |
5717 | } |
5718 | |
5719 | if (!loopInfo.emitLoopEnd(this, JSOp::Goto, TryNoteKind::ForOf)) { |
5720 | // [stack] NEXT ITER (spreadee) |
5721 | return false; |
5722 | } |
5723 | |
5724 | MOZ_ASSERT(bytecodeSection().stackDepth() == loopDepth)do { static_assert( mozilla::detail::AssertionConditionType< decltype(bytecodeSection().stackDepth() == loopDepth)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(bytecodeSection().stackDepth() == loopDepth))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("bytecodeSection().stackDepth() == loopDepth" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5724); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == loopDepth" ")"); do { *((volatile int*)__null) = 5724; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5725 | } |
5726 | |
5727 | // When we leave the loop body and jump to this point, the result value is |
5728 | // still on the stack. Account for that by updating the stack depth |
5729 | // manually. |
5730 | bytecodeSection().setStackDepth(bytecodeSection().stackDepth() + 1); |
5731 | |
5732 | // No continues should occur in spreads. |
5733 | MOZ_ASSERT(!loopInfo.continues.offset.valid())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!loopInfo.continues.offset.valid())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!loopInfo.continues.offset.valid ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!loopInfo.continues.offset.valid()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5733); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!loopInfo.continues.offset.valid()" ")"); do { *((volatile int*)__null) = 5733; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5734 | |
5735 | if (!emit2(JSOp::Pick, spreadeeStackItems + 2)) { |
5736 | // [stack] ITER (spreadee) RESULT NEXT |
5737 | return false; |
5738 | } |
5739 | if (!emit2(JSOp::Pick, spreadeeStackItems + 2)) { |
5740 | // [stack] (spreadee) RESULT NEXT ITER |
5741 | return false; |
5742 | } |
5743 | |
5744 | return emitPopN(3); |
5745 | // [stack] (spreadee) |
5746 | } |
5747 | |
5748 | bool BytecodeEmitter::emitInitializeForInOrOfTarget(TernaryNode* forHead) { |
5749 | MOZ_ASSERT(forHead->isKind(ParseNodeKind::ForIn) ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(forHead->isKind(ParseNodeKind::ForIn) || forHead-> isKind(ParseNodeKind::ForOf))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(forHead->isKind(ParseNodeKind ::ForIn) || forHead->isKind(ParseNodeKind::ForOf)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("forHead->isKind(ParseNodeKind::ForIn) || forHead->isKind(ParseNodeKind::ForOf)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5750); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forHead->isKind(ParseNodeKind::ForIn) || forHead->isKind(ParseNodeKind::ForOf)" ")"); do { *((volatile int*)__null) = 5750; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
5750 | forHead->isKind(ParseNodeKind::ForOf))do { static_assert( mozilla::detail::AssertionConditionType< decltype(forHead->isKind(ParseNodeKind::ForIn) || forHead-> isKind(ParseNodeKind::ForOf))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(forHead->isKind(ParseNodeKind ::ForIn) || forHead->isKind(ParseNodeKind::ForOf)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("forHead->isKind(ParseNodeKind::ForIn) || forHead->isKind(ParseNodeKind::ForOf)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5750); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forHead->isKind(ParseNodeKind::ForIn) || forHead->isKind(ParseNodeKind::ForOf)" ")"); do { *((volatile int*)__null) = 5750; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5751 | |
5752 | MOZ_ASSERT(bytecodeSection().stackDepth() >= 1,do { static_assert( mozilla::detail::AssertionConditionType< decltype(bytecodeSection().stackDepth() >= 1)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(bytecodeSection().stackDepth() >= 1))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("bytecodeSection().stackDepth() >= 1" " (" "must have a per-iteration value for initializing" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5753); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() >= 1" ") (" "must have a per-iteration value for initializing" ")" ); do { *((volatile int*)__null) = 5753; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
5753 | "must have a per-iteration value for initializing")do { static_assert( mozilla::detail::AssertionConditionType< decltype(bytecodeSection().stackDepth() >= 1)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(bytecodeSection().stackDepth() >= 1))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("bytecodeSection().stackDepth() >= 1" " (" "must have a per-iteration value for initializing" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5753); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() >= 1" ") (" "must have a per-iteration value for initializing" ")" ); do { *((volatile int*)__null) = 5753; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5754 | |
5755 | ParseNode* target = forHead->kid1(); |
5756 | MOZ_ASSERT(!forHead->kid2())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!forHead->kid2())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!forHead->kid2()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!forHead->kid2()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5756); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!forHead->kid2()" ")"); do { *((volatile int*)__null) = 5756; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5757 | |
5758 | // If the for-in/of loop didn't have a variable declaration, per-loop |
5759 | // initialization is just assigning the iteration value to a target |
5760 | // expression. |
5761 | if (!target->is<DeclarationListNode>()) { |
5762 | return emitAssignmentOrInit(ParseNodeKind::AssignExpr, target, nullptr); |
5763 | // [stack] ... ITERVAL |
5764 | } |
5765 | |
5766 | // Otherwise, per-loop initialization is (possibly) declaration |
5767 | // initialization. If the declaration is a lexical declaration, it must be |
5768 | // initialized. If the declaration is a variable declaration, an |
5769 | // assignment to that name (which does *not* necessarily assign to the |
5770 | // variable!) must be generated. |
5771 | |
5772 | auto* declarationList = &target->as<DeclarationListNode>(); |
5773 | if (!updateSourceCoordNotes(declarationList->pn_pos.begin)) { |
5774 | return false; |
5775 | } |
5776 | |
5777 | target = declarationList->singleBinding(); |
5778 | |
5779 | NameNode* nameNode = nullptr; |
5780 | if (target->isKind(ParseNodeKind::Name)) { |
5781 | nameNode = &target->as<NameNode>(); |
5782 | } else if (target->isKind(ParseNodeKind::AssignExpr)) { |
5783 | BinaryNode* assignNode = &target->as<BinaryNode>(); |
5784 | if (assignNode->left()->is<NameNode>()) { |
5785 | nameNode = &assignNode->left()->as<NameNode>(); |
5786 | } |
5787 | } |
5788 | |
5789 | if (nameNode) { |
5790 | auto nameAtom = nameNode->name(); |
5791 | NameOpEmitter noe(this, nameAtom, NameOpEmitter::Kind::Initialize); |
5792 | if (!noe.prepareForRhs()) { |
5793 | return false; |
5794 | } |
5795 | if (noe.emittedBindOp()) { |
5796 | // Per-iteration initialization in for-in/of loops computes the |
5797 | // iteration value *before* initializing. Thus the initializing |
5798 | // value may be buried under a bind-specific value on the stack. |
5799 | // Swap it to the top of the stack. |
5800 | MOZ_ASSERT(bytecodeSection().stackDepth() >= 2)do { static_assert( mozilla::detail::AssertionConditionType< decltype(bytecodeSection().stackDepth() >= 2)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(bytecodeSection().stackDepth() >= 2))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("bytecodeSection().stackDepth() >= 2" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5800); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() >= 2" ")"); do { *((volatile int*)__null) = 5800; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5801 | if (!emit1(JSOp::Swap)) { |
5802 | return false; |
5803 | } |
5804 | } else { |
5805 | // In cases of emitting a frame slot or environment slot, |
5806 | // nothing needs be done. |
5807 | MOZ_ASSERT(bytecodeSection().stackDepth() >= 1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(bytecodeSection().stackDepth() >= 1)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(bytecodeSection().stackDepth() >= 1))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("bytecodeSection().stackDepth() >= 1" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5807); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() >= 1" ")"); do { *((volatile int*)__null) = 5807; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5808 | } |
5809 | |
5810 | #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT |
5811 | if (declarationList->isKind(ParseNodeKind::UsingDecl)) { |
5812 | if (!innermostEmitterScope()->prepareForDisposableAssignment( |
5813 | UsingHint::Sync)) { |
5814 | // [stack] ENV? V |
5815 | return false; |
5816 | } |
5817 | } |
5818 | #endif |
5819 | |
5820 | if (!noe.emitAssignment()) { |
5821 | return false; |
5822 | } |
5823 | |
5824 | // The caller handles removing the iteration value from the stack. |
5825 | return true; |
5826 | } |
5827 | |
5828 | MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType< decltype(!target->isKind(ParseNodeKind::AssignExpr))>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!target->isKind(ParseNodeKind::AssignExpr)))), 0) )) { do { } while (false); MOZ_ReportAssertionFailure("!target->isKind(ParseNodeKind::AssignExpr)" " (" "for-in/of loop destructuring declarations can't have initializers" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5830); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!target->isKind(ParseNodeKind::AssignExpr)" ") (" "for-in/of loop destructuring declarations can't have initializers" ")"); do { *((volatile int*)__null) = 5830; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
5829 | !target->isKind(ParseNodeKind::AssignExpr),do { static_assert( mozilla::detail::AssertionConditionType< decltype(!target->isKind(ParseNodeKind::AssignExpr))>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!target->isKind(ParseNodeKind::AssignExpr)))), 0) )) { do { } while (false); MOZ_ReportAssertionFailure("!target->isKind(ParseNodeKind::AssignExpr)" " (" "for-in/of loop destructuring declarations can't have initializers" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5830); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!target->isKind(ParseNodeKind::AssignExpr)" ") (" "for-in/of loop destructuring declarations can't have initializers" ")"); do { *((volatile int*)__null) = 5830; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
5830 | "for-in/of loop destructuring declarations can't have initializers")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!target->isKind(ParseNodeKind::AssignExpr))>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!target->isKind(ParseNodeKind::AssignExpr)))), 0) )) { do { } while (false); MOZ_ReportAssertionFailure("!target->isKind(ParseNodeKind::AssignExpr)" " (" "for-in/of loop destructuring declarations can't have initializers" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5830); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!target->isKind(ParseNodeKind::AssignExpr)" ") (" "for-in/of loop destructuring declarations can't have initializers" ")"); do { *((volatile int*)__null) = 5830; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5831 | |
5832 | MOZ_ASSERT(target->isKind(ParseNodeKind::ArrayExpr) ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(target->isKind(ParseNodeKind::ArrayExpr) || target ->isKind(ParseNodeKind::ObjectExpr))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(target->isKind(ParseNodeKind ::ArrayExpr) || target->isKind(ParseNodeKind::ObjectExpr)) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("target->isKind(ParseNodeKind::ArrayExpr) || target->isKind(ParseNodeKind::ObjectExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5833); AnnotateMozCrashReason("MOZ_ASSERT" "(" "target->isKind(ParseNodeKind::ArrayExpr) || target->isKind(ParseNodeKind::ObjectExpr)" ")"); do { *((volatile int*)__null) = 5833; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
5833 | target->isKind(ParseNodeKind::ObjectExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(target->isKind(ParseNodeKind::ArrayExpr) || target ->isKind(ParseNodeKind::ObjectExpr))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(target->isKind(ParseNodeKind ::ArrayExpr) || target->isKind(ParseNodeKind::ObjectExpr)) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("target->isKind(ParseNodeKind::ArrayExpr) || target->isKind(ParseNodeKind::ObjectExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5833); AnnotateMozCrashReason("MOZ_ASSERT" "(" "target->isKind(ParseNodeKind::ArrayExpr) || target->isKind(ParseNodeKind::ObjectExpr)" ")"); do { *((volatile int*)__null) = 5833; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5834 | return emitDestructuringOps(&target->as<ListNode>(), |
5835 | DestructuringFlavor::Declaration); |
5836 | } |
5837 | |
5838 | bool BytecodeEmitter::emitForOf(ForNode* forOfLoop, |
5839 | const EmitterScope* headLexicalEmitterScope) { |
5840 | MOZ_ASSERT(forOfLoop->isKind(ParseNodeKind::ForStmt))do { static_assert( mozilla::detail::AssertionConditionType< decltype(forOfLoop->isKind(ParseNodeKind::ForStmt))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(forOfLoop->isKind(ParseNodeKind::ForStmt)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("forOfLoop->isKind(ParseNodeKind::ForStmt)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5840); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfLoop->isKind(ParseNodeKind::ForStmt)" ")"); do { *((volatile int*)__null) = 5840; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5841 | |
5842 | TernaryNode* forOfHead = forOfLoop->head(); |
5843 | MOZ_ASSERT(forOfHead->isKind(ParseNodeKind::ForOf))do { static_assert( mozilla::detail::AssertionConditionType< decltype(forOfHead->isKind(ParseNodeKind::ForOf))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(forOfHead->isKind(ParseNodeKind::ForOf)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("forOfHead->isKind(ParseNodeKind::ForOf)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5843); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfHead->isKind(ParseNodeKind::ForOf)" ")"); do { *((volatile int*)__null) = 5843; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5844 | |
5845 | unsigned iflags = forOfLoop->iflags(); |
5846 | IteratorKind iterKind = |
5847 | (iflags & JSITER_FORAWAITOF0x80) ? IteratorKind::Async : IteratorKind::Sync; |
5848 | MOZ_ASSERT_IF(iterKind == IteratorKind::Async, sc->isSuspendableContext())do { if (iterKind == IteratorKind::Async) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(sc-> isSuspendableContext())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(sc->isSuspendableContext( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("sc->isSuspendableContext()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5848); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isSuspendableContext()" ")"); do { *((volatile int*)__null) = 5848; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
5849 | MOZ_ASSERT_IF(iterKind == IteratorKind::Async,do { if (iterKind == IteratorKind::Async) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(sc-> asSuspendableContext()->isAsync())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(sc->asSuspendableContext( )->isAsync()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("sc->asSuspendableContext()->isAsync()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5850); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->asSuspendableContext()->isAsync()" ")"); do { *((volatile int*)__null) = 5850; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
5850 | sc->asSuspendableContext()->isAsync())do { if (iterKind == IteratorKind::Async) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(sc-> asSuspendableContext()->isAsync())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(sc->asSuspendableContext( )->isAsync()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("sc->asSuspendableContext()->isAsync()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5850); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->asSuspendableContext()->isAsync()" ")"); do { *((volatile int*)__null) = 5850; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
5851 | |
5852 | ParseNode* forHeadExpr = forOfHead->kid3(); |
5853 | |
5854 | // Certain builtins (e.g. Array.from) are implemented in self-hosting |
5855 | // as for-of loops. |
5856 | auto selfHostedIter = getSelfHostedIterFor(forHeadExpr); |
5857 | ForOfEmitter forOf(this, headLexicalEmitterScope, selfHostedIter, iterKind |
5858 | #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT |
5859 | , |
5860 | forOfHead->kid1()->isKind(ParseNodeKind::UsingDecl) |
5861 | ? ForOfEmitter::HasUsingDeclarationInHead::Yes |
5862 | : ForOfEmitter::HasUsingDeclarationInHead::No |
5863 | #endif |
5864 | ); |
5865 | |
5866 | if (!forOf.emitIterated()) { |
5867 | // [stack] |
5868 | return false; |
5869 | } |
5870 | |
5871 | if (!updateSourceCoordNotes(forHeadExpr->pn_pos.begin)) { |
5872 | return false; |
5873 | } |
5874 | if (!markStepBreakpoint()) { |
5875 | return false; |
5876 | } |
5877 | if (!emitIterable(forHeadExpr, selfHostedIter, iterKind)) { |
5878 | // [stack] ITERABLE |
5879 | return false; |
5880 | } |
5881 | |
5882 | if (headLexicalEmitterScope) { |
5883 | DebugOnly<ParseNode*> forOfTarget = forOfHead->kid1(); |
5884 | MOZ_ASSERT(forOfTarget->isKind(ParseNodeKind::LetDecl) ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget ->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl)endif)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget ->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl)endif))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl)endif" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5889); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl)endif" ")"); do { *((volatile int*)__null) = 5889; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
5885 | forOfTarget->isKind(ParseNodeKind::ConstDecl)do { static_assert( mozilla::detail::AssertionConditionType< decltype(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget ->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl)endif)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget ->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl)endif))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl)endif" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5889); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl)endif" ")"); do { *((volatile int*)__null) = 5889; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
5886 | #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENTdo { static_assert( mozilla::detail::AssertionConditionType< decltype(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget ->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl)endif)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget ->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl)endif))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl)endif" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5889); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl)endif" ")"); do { *((volatile int*)__null) = 5889; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
5887 | || forOfTarget->isKind(ParseNodeKind::UsingDecl)do { static_assert( mozilla::detail::AssertionConditionType< decltype(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget ->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl)endif)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget ->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl)endif))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl)endif" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5889); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl)endif" ")"); do { *((volatile int*)__null) = 5889; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
5888 | #endifdo { static_assert( mozilla::detail::AssertionConditionType< decltype(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget ->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl)endif)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget ->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl)endif))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl)endif" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5889); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl)endif" ")"); do { *((volatile int*)__null) = 5889; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
5889 | )do { static_assert( mozilla::detail::AssertionConditionType< decltype(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget ->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl)endif)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget ->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl)endif))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl)endif" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5889); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl)ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT || forOfTarget->isKind(ParseNodeKind::UsingDecl)endif" ")"); do { *((volatile int*)__null) = 5889; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5890 | } |
5891 | |
5892 | if (!forOf.emitInitialize(forOfHead->pn_pos.begin)) { |
5893 | // [stack] NEXT ITER VALUE |
5894 | return false; |
5895 | } |
5896 | |
5897 | if (!emitInitializeForInOrOfTarget(forOfHead)) { |
5898 | // [stack] NEXT ITER VALUE |
5899 | return false; |
5900 | } |
5901 | |
5902 | if (!forOf.emitBody()) { |
5903 | // [stack] NEXT ITER UNDEF |
5904 | return false; |
5905 | } |
5906 | |
5907 | // Perform the loop body. |
5908 | ParseNode* forBody = forOfLoop->body(); |
5909 | if (!emitTree(forBody)) { |
5910 | // [stack] NEXT ITER UNDEF |
5911 | return false; |
5912 | } |
5913 | |
5914 | if (!forOf.emitEnd(forHeadExpr->pn_pos.begin)) { |
5915 | // [stack] |
5916 | return false; |
5917 | } |
5918 | |
5919 | return true; |
5920 | } |
5921 | |
5922 | bool BytecodeEmitter::emitForIn(ForNode* forInLoop, |
5923 | const EmitterScope* headLexicalEmitterScope) { |
5924 | TernaryNode* forInHead = forInLoop->head(); |
5925 | MOZ_ASSERT(forInHead->isKind(ParseNodeKind::ForIn))do { static_assert( mozilla::detail::AssertionConditionType< decltype(forInHead->isKind(ParseNodeKind::ForIn))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(forInHead->isKind(ParseNodeKind::ForIn)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("forInHead->isKind(ParseNodeKind::ForIn)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5925); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInHead->isKind(ParseNodeKind::ForIn)" ")"); do { *((volatile int*)__null) = 5925; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5926 | |
5927 | ForInEmitter forIn(this, headLexicalEmitterScope); |
5928 | |
5929 | // Annex B: Evaluate the var-initializer expression if present. |
5930 | // |for (var i = initializer in expr) { ... }| |
5931 | ParseNode* forInTarget = forInHead->kid1(); |
5932 | if (forInTarget->is<DeclarationListNode>()) { |
5933 | auto* declarationList = &forInTarget->as<DeclarationListNode>(); |
5934 | |
5935 | ParseNode* decl = declarationList->singleBinding(); |
5936 | if (decl->isKind(ParseNodeKind::AssignExpr)) { |
5937 | BinaryNode* assignNode = &decl->as<BinaryNode>(); |
5938 | if (assignNode->left()->is<NameNode>()) { |
5939 | NameNode* nameNode = &assignNode->left()->as<NameNode>(); |
5940 | ParseNode* initializer = assignNode->right(); |
5941 | MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType< decltype(forInTarget->isKind(ParseNodeKind::VarStmt))>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(forInTarget->isKind(ParseNodeKind::VarStmt)))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("forInTarget->isKind(ParseNodeKind::VarStmt)" " (" "for-in initializers are only permitted for |var| declarations" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5943); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInTarget->isKind(ParseNodeKind::VarStmt)" ") (" "for-in initializers are only permitted for |var| declarations" ")"); do { *((volatile int*)__null) = 5943; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
5942 | forInTarget->isKind(ParseNodeKind::VarStmt),do { static_assert( mozilla::detail::AssertionConditionType< decltype(forInTarget->isKind(ParseNodeKind::VarStmt))>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(forInTarget->isKind(ParseNodeKind::VarStmt)))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("forInTarget->isKind(ParseNodeKind::VarStmt)" " (" "for-in initializers are only permitted for |var| declarations" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5943); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInTarget->isKind(ParseNodeKind::VarStmt)" ") (" "for-in initializers are only permitted for |var| declarations" ")"); do { *((volatile int*)__null) = 5943; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
5943 | "for-in initializers are only permitted for |var| declarations")do { static_assert( mozilla::detail::AssertionConditionType< decltype(forInTarget->isKind(ParseNodeKind::VarStmt))>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(forInTarget->isKind(ParseNodeKind::VarStmt)))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("forInTarget->isKind(ParseNodeKind::VarStmt)" " (" "for-in initializers are only permitted for |var| declarations" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5943); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInTarget->isKind(ParseNodeKind::VarStmt)" ") (" "for-in initializers are only permitted for |var| declarations" ")"); do { *((volatile int*)__null) = 5943; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5944 | |
5945 | if (!updateSourceCoordNotes(decl->pn_pos.begin)) { |
5946 | return false; |
5947 | } |
5948 | |
5949 | auto nameAtom = nameNode->name(); |
5950 | NameOpEmitter noe(this, nameAtom, NameOpEmitter::Kind::Initialize); |
5951 | if (!noe.prepareForRhs()) { |
5952 | return false; |
5953 | } |
5954 | if (!emitInitializer(initializer, nameNode)) { |
5955 | return false; |
5956 | } |
5957 | if (!noe.emitAssignment()) { |
5958 | return false; |
5959 | } |
5960 | |
5961 | // Pop the initializer. |
5962 | if (!emit1(JSOp::Pop)) { |
5963 | return false; |
5964 | } |
5965 | } |
5966 | } |
5967 | } |
5968 | |
5969 | if (!forIn.emitIterated()) { |
5970 | // [stack] |
5971 | return false; |
5972 | } |
5973 | |
5974 | // Evaluate the expression being iterated. |
5975 | ParseNode* expr = forInHead->kid3(); |
5976 | |
5977 | if (!updateSourceCoordNotes(expr->pn_pos.begin)) { |
5978 | return false; |
5979 | } |
5980 | if (!markStepBreakpoint()) { |
5981 | return false; |
5982 | } |
5983 | if (!emitTree(expr)) { |
5984 | // [stack] EXPR |
5985 | return false; |
5986 | } |
5987 | |
5988 | MOZ_ASSERT(forInLoop->iflags() == 0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(forInLoop->iflags() == 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(forInLoop->iflags() == 0) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("forInLoop->iflags() == 0" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5988); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInLoop->iflags() == 0" ")"); do { *((volatile int*)__null) = 5988; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
5989 | |
5990 | MOZ_ASSERT_IF(headLexicalEmitterScope,do { if (headLexicalEmitterScope) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(forInTarget-> isKind(ParseNodeKind::LetDecl) || forInTarget->isKind(ParseNodeKind ::ConstDecl))>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(forInTarget->isKind(ParseNodeKind ::LetDecl) || forInTarget->isKind(ParseNodeKind::ConstDecl )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("forInTarget->isKind(ParseNodeKind::LetDecl) || forInTarget->isKind(ParseNodeKind::ConstDecl)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5992); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInTarget->isKind(ParseNodeKind::LetDecl) || forInTarget->isKind(ParseNodeKind::ConstDecl)" ")"); do { *((volatile int*)__null) = 5992; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
5991 | forInTarget->isKind(ParseNodeKind::LetDecl) ||do { if (headLexicalEmitterScope) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(forInTarget-> isKind(ParseNodeKind::LetDecl) || forInTarget->isKind(ParseNodeKind ::ConstDecl))>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(forInTarget->isKind(ParseNodeKind ::LetDecl) || forInTarget->isKind(ParseNodeKind::ConstDecl )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("forInTarget->isKind(ParseNodeKind::LetDecl) || forInTarget->isKind(ParseNodeKind::ConstDecl)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5992); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInTarget->isKind(ParseNodeKind::LetDecl) || forInTarget->isKind(ParseNodeKind::ConstDecl)" ")"); do { *((volatile int*)__null) = 5992; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
5992 | forInTarget->isKind(ParseNodeKind::ConstDecl))do { if (headLexicalEmitterScope) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(forInTarget-> isKind(ParseNodeKind::LetDecl) || forInTarget->isKind(ParseNodeKind ::ConstDecl))>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(forInTarget->isKind(ParseNodeKind ::LetDecl) || forInTarget->isKind(ParseNodeKind::ConstDecl )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("forInTarget->isKind(ParseNodeKind::LetDecl) || forInTarget->isKind(ParseNodeKind::ConstDecl)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 5992); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forInTarget->isKind(ParseNodeKind::LetDecl) || forInTarget->isKind(ParseNodeKind::ConstDecl)" ")"); do { *((volatile int*)__null) = 5992; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
5993 | |
5994 | if (!forIn.emitInitialize()) { |
5995 | // [stack] ITER ITERVAL |
5996 | return false; |
5997 | } |
5998 | |
5999 | if (!emitInitializeForInOrOfTarget(forInHead)) { |
6000 | // [stack] ITER ITERVAL |
6001 | return false; |
6002 | } |
6003 | |
6004 | if (!forIn.emitBody()) { |
6005 | // [stack] ITER ITERVAL |
6006 | return false; |
6007 | } |
6008 | |
6009 | // Perform the loop body. |
6010 | ParseNode* forBody = forInLoop->body(); |
6011 | if (!emitTree(forBody)) { |
6012 | // [stack] ITER ITERVAL |
6013 | return false; |
6014 | } |
6015 | |
6016 | if (!forIn.emitEnd(forInHead->pn_pos.begin)) { |
6017 | // [stack] |
6018 | return false; |
6019 | } |
6020 | |
6021 | return true; |
6022 | } |
6023 | |
6024 | /* C-style `for (init; cond; update) ...` loop. */ |
6025 | bool BytecodeEmitter::emitCStyleFor( |
6026 | ForNode* forNode, const EmitterScope* headLexicalEmitterScope) { |
6027 | TernaryNode* forHead = forNode->head(); |
6028 | ParseNode* forBody = forNode->body(); |
6029 | ParseNode* init = forHead->kid1(); |
6030 | ParseNode* cond = forHead->kid2(); |
6031 | ParseNode* update = forHead->kid3(); |
6032 | bool isLet = init && init->isKind(ParseNodeKind::LetDecl); |
6033 | |
6034 | CForEmitter cfor(this, isLet ? headLexicalEmitterScope : nullptr); |
6035 | |
6036 | if (!cfor.emitInit(init ? Some(init->pn_pos.begin) : Nothing())) { |
6037 | // [stack] |
6038 | return false; |
6039 | } |
6040 | |
6041 | // If the head of this for-loop declared any lexical variables, the parser |
6042 | // wrapped this ParseNodeKind::For node in a ParseNodeKind::LexicalScope |
6043 | // representing the implicit scope of those variables. By the time we get |
6044 | // here, we have already entered that scope. So far, so good. |
6045 | if (init) { |
6046 | // Emit the `init` clause, whether it's an expression or a variable |
6047 | // declaration. (The loop variables were hoisted into an enclosing |
6048 | // scope, but we still need to emit code for the initializers.) |
6049 | if (init->is<DeclarationListNode>()) { |
6050 | MOZ_ASSERT(!init->as<DeclarationListNode>().empty())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!init->as<DeclarationListNode>().empty())> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!init->as<DeclarationListNode>().empty()))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("!init->as<DeclarationListNode>().empty()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6050); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!init->as<DeclarationListNode>().empty()" ")"); do { *((volatile int*)__null) = 6050; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6051 | |
6052 | if (!emitTree(init)) { |
6053 | // [stack] |
6054 | return false; |
6055 | } |
6056 | } else { |
6057 | if (!updateSourceCoordNotes(init->pn_pos.begin)) { |
6058 | return false; |
6059 | } |
6060 | if (!markStepBreakpoint()) { |
6061 | return false; |
6062 | } |
6063 | |
6064 | // 'init' is an expression, not a declaration. emitTree left its |
6065 | // value on the stack. |
6066 | if (!emitTree(init, ValueUsage::IgnoreValue)) { |
6067 | // [stack] VAL |
6068 | return false; |
6069 | } |
6070 | if (!emit1(JSOp::Pop)) { |
6071 | // [stack] |
6072 | return false; |
6073 | } |
6074 | } |
6075 | } |
6076 | |
6077 | if (!cfor.emitCond(cond ? Some(cond->pn_pos.begin) : Nothing())) { |
6078 | // [stack] |
6079 | return false; |
6080 | } |
6081 | |
6082 | if (cond) { |
6083 | if (!updateSourceCoordNotes(cond->pn_pos.begin)) { |
6084 | return false; |
6085 | } |
6086 | if (!markStepBreakpoint()) { |
6087 | return false; |
6088 | } |
6089 | if (!emitTree(cond)) { |
6090 | // [stack] VAL |
6091 | return false; |
6092 | } |
6093 | } |
6094 | |
6095 | if (!cfor.emitBody(cond ? CForEmitter::Cond::Present |
6096 | : CForEmitter::Cond::Missing)) { |
6097 | // [stack] |
6098 | return false; |
6099 | } |
6100 | |
6101 | if (!emitTree(forBody)) { |
6102 | // [stack] |
6103 | return false; |
6104 | } |
6105 | |
6106 | if (!cfor.emitUpdate( |
6107 | update ? CForEmitter::Update::Present : CForEmitter::Update::Missing, |
6108 | update ? Some(update->pn_pos.begin) : Nothing())) { |
6109 | // [stack] |
6110 | return false; |
6111 | } |
6112 | |
6113 | // Check for update code to do before the condition (if any). |
6114 | if (update) { |
6115 | if (!updateSourceCoordNotes(update->pn_pos.begin)) { |
6116 | return false; |
6117 | } |
6118 | if (!markStepBreakpoint()) { |
6119 | return false; |
6120 | } |
6121 | if (!emitTree(update, ValueUsage::IgnoreValue)) { |
6122 | // [stack] VAL |
6123 | return false; |
6124 | } |
6125 | } |
6126 | |
6127 | if (!cfor.emitEnd(forNode->pn_pos.begin)) { |
6128 | // [stack] |
6129 | return false; |
6130 | } |
6131 | |
6132 | return true; |
6133 | } |
6134 | |
6135 | bool BytecodeEmitter::emitFor(ForNode* forNode, |
6136 | const EmitterScope* headLexicalEmitterScope) { |
6137 | if (forNode->head()->isKind(ParseNodeKind::ForHead)) { |
6138 | return emitCStyleFor(forNode, headLexicalEmitterScope); |
6139 | } |
6140 | |
6141 | if (!updateLineNumberNotes(forNode->pn_pos.begin)) { |
6142 | return false; |
6143 | } |
6144 | |
6145 | if (forNode->head()->isKind(ParseNodeKind::ForIn)) { |
6146 | return emitForIn(forNode, headLexicalEmitterScope); |
6147 | } |
6148 | |
6149 | MOZ_ASSERT(forNode->head()->isKind(ParseNodeKind::ForOf))do { static_assert( mozilla::detail::AssertionConditionType< decltype(forNode->head()->isKind(ParseNodeKind::ForOf)) >::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(forNode->head()->isKind(ParseNodeKind::ForOf)) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("forNode->head()->isKind(ParseNodeKind::ForOf)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6149); AnnotateMozCrashReason("MOZ_ASSERT" "(" "forNode->head()->isKind(ParseNodeKind::ForOf)" ")"); do { *((volatile int*)__null) = 6149; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6150 | return emitForOf(forNode, headLexicalEmitterScope); |
6151 | } |
6152 | |
6153 | MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitFunction( |
6154 | FunctionNode* funNode, bool needsProto /* = false */) { |
6155 | FunctionBox* funbox = funNode->funbox(); |
6156 | |
6157 | // [stack] |
6158 | |
6159 | FunctionEmitter fe(this, funbox, funNode->syntaxKind(), |
6160 | funNode->functionIsHoisted() |
6161 | ? FunctionEmitter::IsHoisted::Yes |
6162 | : FunctionEmitter::IsHoisted::No); |
6163 | |
6164 | // |wasEmittedByEnclosingScript| flag is set to true once the function has |
6165 | // been emitted. Function definitions that need hoisting to the top of the |
6166 | // function will be seen by emitFunction in two places. |
6167 | if (funbox->wasEmittedByEnclosingScript()) { |
6168 | if (!fe.emitAgain()) { |
6169 | // [stack] |
6170 | return false; |
6171 | } |
6172 | MOZ_ASSERT(funNode->functionIsHoisted())do { static_assert( mozilla::detail::AssertionConditionType< decltype(funNode->functionIsHoisted())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(funNode->functionIsHoisted ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("funNode->functionIsHoisted()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6172); AnnotateMozCrashReason("MOZ_ASSERT" "(" "funNode->functionIsHoisted()" ")"); do { *((volatile int*)__null) = 6172; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6173 | } else if (funbox->isInterpreted()) { |
6174 | if (!funbox->emitBytecode) { |
6175 | return fe.emitLazy(); |
6176 | // [stack] FUN? |
6177 | } |
6178 | |
6179 | if (!fe.prepareForNonLazy()) { |
6180 | // [stack] |
6181 | return false; |
6182 | } |
6183 | |
6184 | BytecodeEmitter bce2(this, funbox); |
6185 | if (!bce2.init(funNode->pn_pos)) { |
6186 | return false; |
6187 | } |
6188 | |
6189 | /* We measured the max scope depth when we parsed the function. */ |
6190 | if (!bce2.emitFunctionScript(funNode)) { |
6191 | return false; |
6192 | } |
6193 | |
6194 | if (!fe.emitNonLazyEnd()) { |
6195 | // [stack] FUN? |
6196 | return false; |
6197 | } |
6198 | } else { |
6199 | if (!fe.emitAsmJSModule()) { |
6200 | // [stack] |
6201 | return false; |
6202 | } |
6203 | } |
6204 | |
6205 | // Track the last emitted top-level self-hosted function, so that intrinsics |
6206 | // can adjust attributes at parse time. |
6207 | // |
6208 | // NOTE: We also disallow lambda functions in the top-level body. This is done |
6209 | // to simplify handling of the self-hosted stencil. Within normal function |
6210 | // declarations there are no such restrictions. |
6211 | if (emitterMode == EmitterMode::SelfHosting) { |
6212 | if (sc->isTopLevelContext()) { |
6213 | MOZ_ASSERT(!funbox->isLambda())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!funbox->isLambda())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!funbox->isLambda()))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("!funbox->isLambda()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6213); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!funbox->isLambda()" ")"); do { *((volatile int*)__null) = 6213; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6214 | MOZ_ASSERT(funbox->explicitName())do { static_assert( mozilla::detail::AssertionConditionType< decltype(funbox->explicitName())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(funbox->explicitName()))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("funbox->explicitName()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6214); AnnotateMozCrashReason("MOZ_ASSERT" "(" "funbox->explicitName()" ")"); do { *((volatile int*)__null) = 6214; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6215 | prevSelfHostedTopLevelFunction = funbox; |
6216 | } |
6217 | } |
6218 | |
6219 | return true; |
6220 | } |
6221 | |
6222 | bool BytecodeEmitter::emitDo(BinaryNode* doNode) { |
6223 | ParseNode* bodyNode = doNode->left(); |
6224 | |
6225 | DoWhileEmitter doWhile(this); |
6226 | if (!doWhile.emitBody(doNode->pn_pos.begin, getOffsetForLoop(bodyNode))) { |
6227 | return false; |
6228 | } |
6229 | |
6230 | if (!emitTree(bodyNode)) { |
6231 | return false; |
6232 | } |
6233 | |
6234 | if (!doWhile.emitCond()) { |
6235 | return false; |
6236 | } |
6237 | |
6238 | ParseNode* condNode = doNode->right(); |
6239 | if (!updateSourceCoordNotes(condNode->pn_pos.begin)) { |
6240 | return false; |
6241 | } |
6242 | if (!markStepBreakpoint()) { |
6243 | return false; |
6244 | } |
6245 | if (!emitTree(condNode)) { |
6246 | return false; |
6247 | } |
6248 | |
6249 | if (!doWhile.emitEnd()) { |
6250 | return false; |
6251 | } |
6252 | |
6253 | return true; |
6254 | } |
6255 | |
6256 | bool BytecodeEmitter::emitWhile(BinaryNode* whileNode) { |
6257 | ParseNode* bodyNode = whileNode->right(); |
6258 | |
6259 | WhileEmitter wh(this); |
6260 | |
6261 | ParseNode* condNode = whileNode->left(); |
6262 | if (!wh.emitCond(whileNode->pn_pos.begin, getOffsetForLoop(condNode), |
6263 | whileNode->pn_pos.end)) { |
6264 | return false; |
6265 | } |
6266 | |
6267 | if (!updateSourceCoordNotes(condNode->pn_pos.begin)) { |
6268 | return false; |
6269 | } |
6270 | if (!markStepBreakpoint()) { |
6271 | return false; |
6272 | } |
6273 | if (!emitTree(condNode)) { |
6274 | return false; |
6275 | } |
6276 | |
6277 | if (!wh.emitBody()) { |
6278 | return false; |
6279 | } |
6280 | if (!emitTree(bodyNode)) { |
6281 | return false; |
6282 | } |
6283 | |
6284 | if (!wh.emitEnd()) { |
6285 | return false; |
6286 | } |
6287 | |
6288 | return true; |
6289 | } |
6290 | |
6291 | bool BytecodeEmitter::emitBreak(TaggedParserAtomIndex label) { |
6292 | BreakableControl* target; |
6293 | if (label) { |
6294 | // Any statement with the matching label may be the break target. |
6295 | auto hasSameLabel = [label](LabelControl* labelControl) { |
6296 | return labelControl->label() == label; |
6297 | }; |
6298 | target = findInnermostNestableControl<LabelControl>(hasSameLabel); |
6299 | } else { |
6300 | auto isNotLabel = [](BreakableControl* control) { |
6301 | return !control->is<LabelControl>(); |
6302 | }; |
6303 | target = findInnermostNestableControl<BreakableControl>(isNotLabel); |
6304 | } |
6305 | |
6306 | return emitGoto(target, GotoKind::Break); |
6307 | } |
6308 | |
6309 | bool BytecodeEmitter::emitContinue(TaggedParserAtomIndex label) { |
6310 | LoopControl* target = nullptr; |
6311 | if (label) { |
6312 | // Find the loop statement enclosed by the matching label. |
6313 | NestableControl* control = innermostNestableControl; |
6314 | while (!control->is<LabelControl>() || |
6315 | control->as<LabelControl>().label() != label) { |
6316 | if (control->is<LoopControl>()) { |
6317 | target = &control->as<LoopControl>(); |
6318 | } |
6319 | control = control->enclosing(); |
6320 | } |
6321 | } else { |
6322 | target = findInnermostNestableControl<LoopControl>(); |
6323 | } |
6324 | return emitGoto(target, GotoKind::Continue); |
6325 | } |
6326 | |
6327 | bool BytecodeEmitter::emitGetFunctionThis(NameNode* thisName) { |
6328 | MOZ_ASSERT(sc->hasFunctionThisBinding())do { static_assert( mozilla::detail::AssertionConditionType< decltype(sc->hasFunctionThisBinding())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(sc->hasFunctionThisBinding ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("sc->hasFunctionThisBinding()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6328); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->hasFunctionThisBinding()" ")"); do { *((volatile int*)__null) = 6328; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6329 | MOZ_ASSERT(thisName->isName(TaggedParserAtomIndex::WellKnown::dot_this_()))do { static_assert( mozilla::detail::AssertionConditionType< decltype(thisName->isName(TaggedParserAtomIndex::WellKnown ::dot_this_()))>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(thisName->isName(TaggedParserAtomIndex ::WellKnown::dot_this_())))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("thisName->isName(TaggedParserAtomIndex::WellKnown::dot_this_())" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6329); AnnotateMozCrashReason("MOZ_ASSERT" "(" "thisName->isName(TaggedParserAtomIndex::WellKnown::dot_this_())" ")"); do { *((volatile int*)__null) = 6329; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6330 | |
6331 | if (!updateLineNumberNotes(thisName->pn_pos.begin)) { |
6332 | return false; |
6333 | } |
6334 | |
6335 | if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_this_())) { |
6336 | // [stack] THIS |
6337 | return false; |
6338 | } |
6339 | if (sc->needsThisTDZChecks()) { |
6340 | if (!emit1(JSOp::CheckThis)) { |
6341 | // [stack] THIS |
6342 | return false; |
6343 | } |
6344 | } |
6345 | |
6346 | return true; |
6347 | } |
6348 | |
6349 | bool BytecodeEmitter::emitGetThisForSuperBase(UnaryNode* superBase) { |
6350 | MOZ_ASSERT(superBase->isKind(ParseNodeKind::SuperBase))do { static_assert( mozilla::detail::AssertionConditionType< decltype(superBase->isKind(ParseNodeKind::SuperBase))>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(superBase->isKind(ParseNodeKind::SuperBase)))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("superBase->isKind(ParseNodeKind::SuperBase)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6350); AnnotateMozCrashReason("MOZ_ASSERT" "(" "superBase->isKind(ParseNodeKind::SuperBase)" ")"); do { *((volatile int*)__null) = 6350; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6351 | NameNode* nameNode = &superBase->kid()->as<NameNode>(); |
6352 | return emitGetFunctionThis(nameNode); |
6353 | // [stack] THIS |
6354 | } |
6355 | |
6356 | bool BytecodeEmitter::emitThisLiteral(ThisLiteral* pn) { |
6357 | if (ParseNode* kid = pn->kid()) { |
6358 | NameNode* thisName = &kid->as<NameNode>(); |
6359 | return emitGetFunctionThis(thisName); |
6360 | // [stack] THIS |
6361 | } |
6362 | |
6363 | if (sc->thisBinding() == ThisBinding::Module) { |
6364 | return emit1(JSOp::Undefined); |
6365 | // [stack] UNDEF |
6366 | } |
6367 | |
6368 | MOZ_ASSERT(sc->thisBinding() == ThisBinding::Global)do { static_assert( mozilla::detail::AssertionConditionType< decltype(sc->thisBinding() == ThisBinding::Global)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(sc->thisBinding() == ThisBinding::Global))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("sc->thisBinding() == ThisBinding::Global" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6368); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->thisBinding() == ThisBinding::Global" ")"); do { *((volatile int*)__null) = 6368; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6369 | |
6370 | MOZ_ASSERT(outermostScope().hasNonSyntacticScopeOnChain() ==do { static_assert( mozilla::detail::AssertionConditionType< decltype(outermostScope().hasNonSyntacticScopeOnChain() == sc ->hasNonSyntacticScope())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(outermostScope().hasNonSyntacticScopeOnChain () == sc->hasNonSyntacticScope()))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("outermostScope().hasNonSyntacticScopeOnChain() == sc->hasNonSyntacticScope()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6371); AnnotateMozCrashReason("MOZ_ASSERT" "(" "outermostScope().hasNonSyntacticScopeOnChain() == sc->hasNonSyntacticScope()" ")"); do { *((volatile int*)__null) = 6371; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
6371 | sc->hasNonSyntacticScope())do { static_assert( mozilla::detail::AssertionConditionType< decltype(outermostScope().hasNonSyntacticScopeOnChain() == sc ->hasNonSyntacticScope())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(outermostScope().hasNonSyntacticScopeOnChain () == sc->hasNonSyntacticScope()))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("outermostScope().hasNonSyntacticScopeOnChain() == sc->hasNonSyntacticScope()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6371); AnnotateMozCrashReason("MOZ_ASSERT" "(" "outermostScope().hasNonSyntacticScopeOnChain() == sc->hasNonSyntacticScope()" ")"); do { *((volatile int*)__null) = 6371; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6372 | if (sc->hasNonSyntacticScope()) { |
6373 | return emit1(JSOp::NonSyntacticGlobalThis); |
6374 | // [stack] THIS |
6375 | } |
6376 | |
6377 | return emit1(JSOp::GlobalThis); |
6378 | // [stack] THIS |
6379 | } |
6380 | |
6381 | bool BytecodeEmitter::emitCheckDerivedClassConstructorReturn() { |
6382 | MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType< decltype(lookupName(TaggedParserAtomIndex::WellKnown::dot_this_ ()).hasKnownSlot())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(lookupName(TaggedParserAtomIndex ::WellKnown::dot_this_()).hasKnownSlot()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("lookupName(TaggedParserAtomIndex::WellKnown::dot_this_()).hasKnownSlot()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6383); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lookupName(TaggedParserAtomIndex::WellKnown::dot_this_()).hasKnownSlot()" ")"); do { *((volatile int*)__null) = 6383; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
6383 | lookupName(TaggedParserAtomIndex::WellKnown::dot_this_()).hasKnownSlot())do { static_assert( mozilla::detail::AssertionConditionType< decltype(lookupName(TaggedParserAtomIndex::WellKnown::dot_this_ ()).hasKnownSlot())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(lookupName(TaggedParserAtomIndex ::WellKnown::dot_this_()).hasKnownSlot()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("lookupName(TaggedParserAtomIndex::WellKnown::dot_this_()).hasKnownSlot()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6383); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lookupName(TaggedParserAtomIndex::WellKnown::dot_this_()).hasKnownSlot()" ")"); do { *((volatile int*)__null) = 6383; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6384 | if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_this_())) { |
6385 | return false; |
6386 | } |
6387 | if (!emit1(JSOp::CheckReturn)) { |
6388 | return false; |
6389 | } |
6390 | if (!emit1(JSOp::SetRval)) { |
6391 | return false; |
6392 | } |
6393 | return true; |
6394 | } |
6395 | |
6396 | bool BytecodeEmitter::emitNewTarget() { |
6397 | MOZ_ASSERT(sc->allowNewTarget())do { static_assert( mozilla::detail::AssertionConditionType< decltype(sc->allowNewTarget())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(sc->allowNewTarget()))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("sc->allowNewTarget()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6397); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->allowNewTarget()" ")"); do { *((volatile int*)__null) = 6397; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6398 | |
6399 | if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_newTarget_())) { |
6400 | // [stack] NEW.TARGET |
6401 | return false; |
6402 | } |
6403 | return true; |
6404 | } |
6405 | |
6406 | bool BytecodeEmitter::emitNewTarget(NewTargetNode* pn) { |
6407 | MOZ_ASSERT(pn->newTargetName()->isName(do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->newTargetName()->isName( TaggedParserAtomIndex ::WellKnown::dot_newTarget_()))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->newTargetName()->isName ( TaggedParserAtomIndex::WellKnown::dot_newTarget_())))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("pn->newTargetName()->isName( TaggedParserAtomIndex::WellKnown::dot_newTarget_())" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6408); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->newTargetName()->isName( TaggedParserAtomIndex::WellKnown::dot_newTarget_())" ")"); do { *((volatile int*)__null) = 6408; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
6408 | TaggedParserAtomIndex::WellKnown::dot_newTarget_()))do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->newTargetName()->isName( TaggedParserAtomIndex ::WellKnown::dot_newTarget_()))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->newTargetName()->isName ( TaggedParserAtomIndex::WellKnown::dot_newTarget_())))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("pn->newTargetName()->isName( TaggedParserAtomIndex::WellKnown::dot_newTarget_())" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6408); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->newTargetName()->isName( TaggedParserAtomIndex::WellKnown::dot_newTarget_())" ")"); do { *((volatile int*)__null) = 6408; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6409 | |
6410 | return emitNewTarget(); |
6411 | } |
6412 | |
6413 | bool BytecodeEmitter::emitNewTarget(CallNode* pn) { |
6414 | MOZ_ASSERT(pn->callOp() == JSOp::SuperCall ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->callOp() == JSOp::SuperCall || pn->callOp( ) == JSOp::SpreadSuperCall)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->callOp() == JSOp::SuperCall || pn->callOp() == JSOp::SpreadSuperCall))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("pn->callOp() == JSOp::SuperCall || pn->callOp() == JSOp::SpreadSuperCall" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6415); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->callOp() == JSOp::SuperCall || pn->callOp() == JSOp::SpreadSuperCall" ")"); do { *((volatile int*)__null) = 6415; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
6415 | pn->callOp() == JSOp::SpreadSuperCall)do { static_assert( mozilla::detail::AssertionConditionType< decltype(pn->callOp() == JSOp::SuperCall || pn->callOp( ) == JSOp::SpreadSuperCall)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pn->callOp() == JSOp::SuperCall || pn->callOp() == JSOp::SpreadSuperCall))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("pn->callOp() == JSOp::SuperCall || pn->callOp() == JSOp::SpreadSuperCall" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6415); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pn->callOp() == JSOp::SuperCall || pn->callOp() == JSOp::SpreadSuperCall" ")"); do { *((volatile int*)__null) = 6415; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6416 | |
6417 | // The parser is responsible for marking the "new.target" binding as being |
6418 | // implicitly used in super() calls. |
6419 | return emitNewTarget(); |
6420 | } |
6421 | |
6422 | bool BytecodeEmitter::emitReturn(UnaryNode* returnNode) { |
6423 | if (!updateSourceCoordNotes(returnNode->pn_pos.begin)) { |
6424 | return false; |
6425 | } |
6426 | |
6427 | if (!markStepBreakpoint()) { |
6428 | return false; |
6429 | } |
6430 | |
6431 | /* Push a return value */ |
6432 | if (ParseNode* expr = returnNode->kid()) { |
6433 | if (!emitTree(expr)) { |
6434 | return false; |
6435 | } |
6436 | |
6437 | if (sc->asSuspendableContext()->isAsync() && |
6438 | sc->asSuspendableContext()->isGenerator()) { |
6439 | if (!emitAwaitInInnermostScope()) { |
6440 | return false; |
6441 | } |
6442 | } |
6443 | } else { |
6444 | /* No explicit return value provided */ |
6445 | if (!emit1(JSOp::Undefined)) { |
6446 | return false; |
6447 | } |
6448 | } |
6449 | |
6450 | // We know functionBodyEndPos is set because "return" is only |
6451 | // valid in a function, and so we've passed through |
6452 | // emitFunctionScript. |
6453 | if (!updateSourceCoordNotes(*functionBodyEndPos)) { |
6454 | return false; |
6455 | } |
6456 | |
6457 | /* |
6458 | * The return value is currently on the stack. We would like to |
6459 | * generate JSOp::Return, but if we have work to do before returning, |
6460 | * we will instead generate JSOp::SetRval / JSOp::RetRval. |
6461 | * |
6462 | * We don't know whether we will need fixup code until after calling |
6463 | * prepareForNonLocalJumpToOutermost, so we start by generating |
6464 | * JSOp::SetRval, then mutate it to JSOp::Return in finishReturn if it |
6465 | * wasn't needed. |
6466 | */ |
6467 | BytecodeOffset setRvalOffset = bytecodeSection().offset(); |
6468 | if (!emit1(JSOp::SetRval)) { |
6469 | return false; |
6470 | } |
6471 | |
6472 | NonLocalExitControl nle(this, NonLocalExitKind::Return); |
6473 | return nle.emitReturn(setRvalOffset); |
6474 | } |
6475 | |
6476 | bool BytecodeEmitter::finishReturn(BytecodeOffset setRvalOffset) { |
6477 | // The return value is currently in rval. Depending on the current function, |
6478 | // we may have to do additional work before returning: |
6479 | // - Derived class constructors must check if the return value is an object. |
6480 | // - Generators and async functions must do a final yield. |
6481 | // - Non-async generators must return the value as an iterator result: |
6482 | // { value: <rval>, done: true } |
6483 | // - Non-generator async functions must resolve the function's result promise |
6484 | // with the value. |
6485 | // |
6486 | // If we have not generated any code since the SetRval that stored the return |
6487 | // value, we can also optimize the bytecode by rewriting that SetRval as a |
6488 | // JSOp::Return. See |emitReturn| above. |
6489 | |
6490 | bool isDerivedClassConstructor = |
6491 | sc->isFunctionBox() && sc->asFunctionBox()->isDerivedClassConstructor(); |
6492 | bool needsFinalYield = |
6493 | sc->isFunctionBox() && sc->asFunctionBox()->needsFinalYield(); |
6494 | bool isSimpleReturn = |
6495 | setRvalOffset.valid() && |
6496 | setRvalOffset + BytecodeOffsetDiff(JSOpLength_SetRval) == |
6497 | bytecodeSection().offset(); |
6498 | |
6499 | if (isDerivedClassConstructor) { |
6500 | MOZ_ASSERT(!needsFinalYield)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!needsFinalYield)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!needsFinalYield))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!needsFinalYield" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6500); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!needsFinalYield" ")"); do { *((volatile int*)__null) = 6500; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6501 | if (!emitJump(JSOp::Goto, &endOfDerivedClassConstructorBody)) { |
6502 | return false; |
6503 | } |
6504 | return true; |
6505 | } |
6506 | |
6507 | if (needsFinalYield) { |
6508 | if (!emitJump(JSOp::Goto, &finalYields)) { |
6509 | return false; |
6510 | } |
6511 | return true; |
6512 | } |
6513 | |
6514 | if (isSimpleReturn) { |
6515 | MOZ_ASSERT(JSOp(bytecodeSection().code()[setRvalOffset.value()]) ==do { static_assert( mozilla::detail::AssertionConditionType< decltype(JSOp(bytecodeSection().code()[setRvalOffset.value()] ) == JSOp::SetRval)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(JSOp(bytecodeSection().code( )[setRvalOffset.value()]) == JSOp::SetRval))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("JSOp(bytecodeSection().code()[setRvalOffset.value()]) == JSOp::SetRval" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6516); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JSOp(bytecodeSection().code()[setRvalOffset.value()]) == JSOp::SetRval" ")"); do { *((volatile int*)__null) = 6516; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
6516 | JSOp::SetRval)do { static_assert( mozilla::detail::AssertionConditionType< decltype(JSOp(bytecodeSection().code()[setRvalOffset.value()] ) == JSOp::SetRval)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(JSOp(bytecodeSection().code( )[setRvalOffset.value()]) == JSOp::SetRval))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("JSOp(bytecodeSection().code()[setRvalOffset.value()]) == JSOp::SetRval" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6516); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JSOp(bytecodeSection().code()[setRvalOffset.value()]) == JSOp::SetRval" ")"); do { *((volatile int*)__null) = 6516; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6517 | bytecodeSection().code()[setRvalOffset.value()] = jsbytecode(JSOp::Return); |
6518 | return true; |
6519 | } |
6520 | |
6521 | // Nothing special needs to be done. |
6522 | return emitReturnRval(); |
6523 | } |
6524 | |
6525 | bool BytecodeEmitter::emitGetDotGeneratorInScope(EmitterScope& currentScope) { |
6526 | if (!sc->isFunction() && sc->isModuleContext() && |
6527 | sc->asModuleContext()->isAsync()) { |
6528 | NameLocation loc = *locationOfNameBoundInScopeType<ModuleScope>( |
6529 | TaggedParserAtomIndex::WellKnown::dot_generator_(), ¤tScope); |
6530 | return emitGetNameAtLocation( |
6531 | TaggedParserAtomIndex::WellKnown::dot_generator_(), loc); |
6532 | } |
6533 | NameLocation loc = *locationOfNameBoundInScopeType<FunctionScope>( |
6534 | TaggedParserAtomIndex::WellKnown::dot_generator_(), ¤tScope); |
6535 | return emitGetNameAtLocation( |
6536 | TaggedParserAtomIndex::WellKnown::dot_generator_(), loc); |
6537 | } |
6538 | |
6539 | bool BytecodeEmitter::emitInitialYield(UnaryNode* yieldNode) { |
6540 | if (!emitTree(yieldNode->kid())) { |
6541 | return false; |
6542 | } |
6543 | |
6544 | if (!emitYieldOp(JSOp::InitialYield)) { |
6545 | // [stack] RVAL GENERATOR RESUMEKIND |
6546 | return false; |
6547 | } |
6548 | if (!emit1(JSOp::CheckResumeKind)) { |
6549 | // [stack] RVAL |
6550 | return false; |
6551 | } |
6552 | if (!emit1(JSOp::Pop)) { |
6553 | // [stack] |
6554 | return false; |
6555 | } |
6556 | |
6557 | return true; |
6558 | } |
6559 | |
6560 | bool BytecodeEmitter::emitYield(UnaryNode* yieldNode) { |
6561 | MOZ_ASSERT(sc->isFunctionBox())do { static_assert( mozilla::detail::AssertionConditionType< decltype(sc->isFunctionBox())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(sc->isFunctionBox()))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("sc->isFunctionBox()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6561); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isFunctionBox()" ")"); do { *((volatile int*)__null) = 6561; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6562 | MOZ_ASSERT(sc->asFunctionBox()->isGenerator())do { static_assert( mozilla::detail::AssertionConditionType< decltype(sc->asFunctionBox()->isGenerator())>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(sc->asFunctionBox()->isGenerator()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("sc->asFunctionBox()->isGenerator()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6562); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->asFunctionBox()->isGenerator()" ")"); do { *((volatile int*)__null) = 6562; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6563 | MOZ_ASSERT(yieldNode->isKind(ParseNodeKind::YieldExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(yieldNode->isKind(ParseNodeKind::YieldExpr))>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(yieldNode->isKind(ParseNodeKind::YieldExpr)))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("yieldNode->isKind(ParseNodeKind::YieldExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6563); AnnotateMozCrashReason("MOZ_ASSERT" "(" "yieldNode->isKind(ParseNodeKind::YieldExpr)" ")"); do { *((volatile int*)__null) = 6563; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6564 | |
6565 | bool needsIteratorResult = sc->asFunctionBox()->needsIteratorResult(); |
6566 | if (needsIteratorResult) { |
6567 | if (!emitPrepareIteratorResult()) { |
6568 | // [stack] ITEROBJ |
6569 | return false; |
6570 | } |
6571 | } |
6572 | if (ParseNode* expr = yieldNode->kid()) { |
6573 | if (!emitTree(expr)) { |
6574 | // [stack] ITEROBJ? VAL |
6575 | return false; |
6576 | } |
6577 | } else { |
6578 | if (!emit1(JSOp::Undefined)) { |
6579 | // [stack] ITEROBJ? UNDEFINED |
6580 | return false; |
6581 | } |
6582 | } |
6583 | |
6584 | if (sc->asSuspendableContext()->isAsync()) { |
6585 | MOZ_ASSERT(!needsIteratorResult)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!needsIteratorResult)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!needsIteratorResult))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("!needsIteratorResult" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6585); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!needsIteratorResult" ")"); do { *((volatile int*)__null) = 6585; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6586 | if (!emitAwaitInInnermostScope()) { |
6587 | // [stack] RESULT |
6588 | return false; |
6589 | } |
6590 | } |
6591 | |
6592 | if (needsIteratorResult) { |
6593 | if (!emitFinishIteratorResult(false)) { |
6594 | // [stack] ITEROBJ |
6595 | return false; |
6596 | } |
6597 | } |
6598 | |
6599 | if (!emitGetDotGeneratorInInnermostScope()) { |
6600 | // [stack] # if needsIteratorResult |
6601 | // [stack] ITEROBJ .GENERATOR |
6602 | // [stack] # else |
6603 | // [stack] RESULT .GENERATOR |
6604 | return false; |
6605 | } |
6606 | |
6607 | if (!emitYieldOp(JSOp::Yield)) { |
6608 | // [stack] YIELDRESULT GENERATOR RESUMEKIND |
6609 | return false; |
6610 | } |
6611 | |
6612 | if (!emit1(JSOp::CheckResumeKind)) { |
6613 | // [stack] YIELDRESULT |
6614 | return false; |
6615 | } |
6616 | |
6617 | return true; |
6618 | } |
6619 | |
6620 | bool BytecodeEmitter::emitAwaitInInnermostScope(UnaryNode* awaitNode) { |
6621 | MOZ_ASSERT(sc->isSuspendableContext())do { static_assert( mozilla::detail::AssertionConditionType< decltype(sc->isSuspendableContext())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(sc->isSuspendableContext( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("sc->isSuspendableContext()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6621); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isSuspendableContext()" ")"); do { *((volatile int*)__null) = 6621; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6622 | MOZ_ASSERT(awaitNode->isKind(ParseNodeKind::AwaitExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(awaitNode->isKind(ParseNodeKind::AwaitExpr))>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(awaitNode->isKind(ParseNodeKind::AwaitExpr)))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("awaitNode->isKind(ParseNodeKind::AwaitExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6622); AnnotateMozCrashReason("MOZ_ASSERT" "(" "awaitNode->isKind(ParseNodeKind::AwaitExpr)" ")"); do { *((volatile int*)__null) = 6622; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6623 | |
6624 | if (!emitTree(awaitNode->kid())) { |
6625 | return false; |
6626 | } |
6627 | return emitAwaitInInnermostScope(); |
6628 | } |
6629 | |
6630 | bool BytecodeEmitter::emitAwaitInScope(EmitterScope& currentScope) { |
6631 | if (!emit1(JSOp::CanSkipAwait)) { |
6632 | // [stack] VALUE CANSKIP |
6633 | return false; |
6634 | } |
6635 | |
6636 | if (!emit1(JSOp::MaybeExtractAwaitValue)) { |
6637 | // [stack] VALUE_OR_RESOLVED CANSKIP |
6638 | return false; |
6639 | } |
6640 | |
6641 | InternalIfEmitter ifCanSkip(this); |
6642 | if (!ifCanSkip.emitThen(IfEmitter::ConditionKind::Negative)) { |
6643 | // [stack] VALUE_OR_RESOLVED |
6644 | return false; |
6645 | } |
6646 | |
6647 | if (sc->asSuspendableContext()->needsPromiseResult()) { |
6648 | if (!emitGetDotGeneratorInScope(currentScope)) { |
6649 | // [stack] VALUE GENERATOR |
6650 | return false; |
6651 | } |
6652 | if (!emit1(JSOp::AsyncAwait)) { |
6653 | // [stack] PROMISE |
6654 | return false; |
6655 | } |
6656 | } |
6657 | |
6658 | if (!emitGetDotGeneratorInScope(currentScope)) { |
6659 | // [stack] VALUE|PROMISE GENERATOR |
6660 | return false; |
6661 | } |
6662 | if (!emitYieldOp(JSOp::Await)) { |
6663 | // [stack] RESOLVED GENERATOR RESUMEKIND |
6664 | return false; |
6665 | } |
6666 | if (!emit1(JSOp::CheckResumeKind)) { |
6667 | // [stack] RESOLVED |
6668 | return false; |
6669 | } |
6670 | |
6671 | if (!ifCanSkip.emitEnd()) { |
6672 | return false; |
6673 | } |
6674 | |
6675 | MOZ_ASSERT(ifCanSkip.popped() == 0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(ifCanSkip.popped() == 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(ifCanSkip.popped() == 0))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("ifCanSkip.popped() == 0" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6675); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ifCanSkip.popped() == 0" ")"); do { *((volatile int*)__null) = 6675; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6676 | |
6677 | return true; |
6678 | } |
6679 | |
6680 | // ES2019 draft rev 49b781ec80117b60f73327ef3054703a3111e40c |
6681 | // 14.4.14 Runtime Semantics: Evaluation |
6682 | // YieldExpression : yield* AssignmentExpression |
6683 | bool BytecodeEmitter::emitYieldStar(ParseNode* iter) { |
6684 | MOZ_ASSERT(getSelfHostedIterFor(iter) == SelfHostedIter::Deny,do { static_assert( mozilla::detail::AssertionConditionType< decltype(getSelfHostedIterFor(iter) == SelfHostedIter::Deny)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(getSelfHostedIterFor(iter) == SelfHostedIter::Deny)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("getSelfHostedIterFor(iter) == SelfHostedIter::Deny" " (" "yield* is prohibited in self-hosted code because it can run " "user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6686); AnnotateMozCrashReason("MOZ_ASSERT" "(" "getSelfHostedIterFor(iter) == SelfHostedIter::Deny" ") (" "yield* is prohibited in self-hosted code because it can run " "user-modifiable iteration code" ")"); do { *((volatile int* )__null) = 6686; __attribute__((nomerge)) ::abort(); } while ( false); } } while (false) |
6685 | "yield* is prohibited in self-hosted code because it can run "do { static_assert( mozilla::detail::AssertionConditionType< decltype(getSelfHostedIterFor(iter) == SelfHostedIter::Deny)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(getSelfHostedIterFor(iter) == SelfHostedIter::Deny)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("getSelfHostedIterFor(iter) == SelfHostedIter::Deny" " (" "yield* is prohibited in self-hosted code because it can run " "user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6686); AnnotateMozCrashReason("MOZ_ASSERT" "(" "getSelfHostedIterFor(iter) == SelfHostedIter::Deny" ") (" "yield* is prohibited in self-hosted code because it can run " "user-modifiable iteration code" ")"); do { *((volatile int* )__null) = 6686; __attribute__((nomerge)) ::abort(); } while ( false); } } while (false) |
6686 | "user-modifiable iteration code")do { static_assert( mozilla::detail::AssertionConditionType< decltype(getSelfHostedIterFor(iter) == SelfHostedIter::Deny)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(getSelfHostedIterFor(iter) == SelfHostedIter::Deny)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("getSelfHostedIterFor(iter) == SelfHostedIter::Deny" " (" "yield* is prohibited in self-hosted code because it can run " "user-modifiable iteration code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6686); AnnotateMozCrashReason("MOZ_ASSERT" "(" "getSelfHostedIterFor(iter) == SelfHostedIter::Deny" ") (" "yield* is prohibited in self-hosted code because it can run " "user-modifiable iteration code" ")"); do { *((volatile int* )__null) = 6686; __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
6687 | |
6688 | MOZ_ASSERT(sc->isSuspendableContext())do { static_assert( mozilla::detail::AssertionConditionType< decltype(sc->isSuspendableContext())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(sc->isSuspendableContext( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("sc->isSuspendableContext()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6688); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isSuspendableContext()" ")"); do { *((volatile int*)__null) = 6688; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6689 | MOZ_ASSERT(sc->asSuspendableContext()->isGenerator())do { static_assert( mozilla::detail::AssertionConditionType< decltype(sc->asSuspendableContext()->isGenerator())> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(sc->asSuspendableContext()->isGenerator()))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("sc->asSuspendableContext()->isGenerator()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6689); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->asSuspendableContext()->isGenerator()" ")"); do { *((volatile int*)__null) = 6689; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6690 | |
6691 | // Step 1. |
6692 | IteratorKind iterKind = sc->asSuspendableContext()->isAsync() |
6693 | ? IteratorKind::Async |
6694 | : IteratorKind::Sync; |
6695 | bool needsIteratorResult = sc->asSuspendableContext()->needsIteratorResult(); |
6696 | |
6697 | // Steps 2-5. |
6698 | if (!emitTree(iter)) { |
6699 | // [stack] ITERABLE |
6700 | return false; |
6701 | } |
6702 | if (iterKind == IteratorKind::Async) { |
6703 | if (!emitAsyncIterator(SelfHostedIter::Deny)) { |
6704 | // [stack] NEXT ITER |
6705 | return false; |
6706 | } |
6707 | } else { |
6708 | if (!emitIterator(SelfHostedIter::Deny)) { |
6709 | // [stack] NEXT ITER |
6710 | return false; |
6711 | } |
6712 | } |
6713 | |
6714 | // Step 6. |
6715 | // Start with NormalCompletion(undefined). |
6716 | if (!emit1(JSOp::Undefined)) { |
6717 | // [stack] NEXT ITER RECEIVED |
6718 | return false; |
6719 | } |
6720 | if (!emitPushResumeKind(GeneratorResumeKind::Next)) { |
6721 | // [stack] NEXT ITER RECEIVED RESUMEKIND |
6722 | return false; |
6723 | } |
6724 | |
6725 | const int32_t startDepth = bytecodeSection().stackDepth(); |
6726 | MOZ_ASSERT(startDepth >= 4)do { static_assert( mozilla::detail::AssertionConditionType< decltype(startDepth >= 4)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(startDepth >= 4))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("startDepth >= 4" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 6726); AnnotateMozCrashReason("MOZ_ASSERT" "(" "startDepth >= 4" ")"); do { *((volatile int*)__null) = 6726; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
6727 | |
6728 | // Step 7 is a loop. |
6729 | LoopControl loopInfo(this, StatementKind::YieldStar); |
6730 | if (!loopInfo.emitLoopHead(this, Nothing())) { |
6731 | // [stack] NEXT ITER RECEIVED RESUMEKIND |
6732 | return false; |
6733 | } |
6734 | |
6735 | // Step 7.a. Check for Normal completion. |
6736 | if (!emit1(JSOp::Dup)) { |
6737 | // [stack] NEXT ITER RECEIVED RESUMEKIND RESUMEKIND |
6738 | return false; |
6739 | } |
6740 | if (!emitPushResumeKind(GeneratorResumeKind::Next)) { |
6741 | // [stack] NEXT ITER RECEIVED RESUMEKIND RESUMEKIND NORMAL |
6742 | return false; |
6743 | } |
6744 | if (!emit1(JSOp::StrictEq)) { |
6745 | // [stack] NEXT ITER RECEIVED RESUMEKIND IS_NORMAL |
6746 | return false; |
6747 | } |
6748 | |
6749 | InternalIfEmitter ifKind(this); |
6750 | if (!ifKind.emitThenElse()) { |
6751 | // [stack] NEXT ITER RECEIVED RESUMEKIND |
6752 | return false; |
6753 | } |
6754 | { |
6755 | if (!emit1(JSOp::Pop)) { |
6756 | // [stack] NEXT ITER RECEIVED |
6757 | return false; |
6758 | } |
6759 | |
6760 | // Step 7.a.i. |
6761 | // result = iter.next(received) |
6762 | if (!emit2(JSOp::Unpick, 2)) { |
6763 | // [stack] RECEIVED NEXT ITER |
6764 | return false; |
6765 | } |
6766 | if (!emit1(JSOp::Dup2)) { |
6767 | // [stack] RECEIVED NEXT ITER NEXT ITER |
6768 | return false; |
6769 | } |
6770 | if (!emit2(JSOp::Pick, 4)) { |
6771 | // [stack] NEXT ITER NEXT ITER RECEIVED |
6772 | return false; |
6773 | } |
6774 | if (!emitCall(JSOp::Call, 1, iter)) { |
6775 | // [stack] NEXT ITER RESULT |
6776 | return false; |
6777 | } |
6778 | |
6779 | // Step 7.a.ii. |
6780 | if (iterKind == IteratorKind::Async) { |
6781 | if (!emitAwaitInInnermostScope()) { |
6782 | // [stack] NEXT ITER RESULT |
6783 | return false; |
6784 | } |
6785 | } |
6786 | |
6787 | // Step 7.a.iii. |
6788 | if (!emitCheckIsObj(CheckIsObjectKind::IteratorNext)) { |
6789 | // [stack] NEXT ITER RESULT |
6790 | return false; |
6791 | } |
6792 | |
6793 | // Bytecode for steps 7.a.iv-vii is emitted after the ifKind if-else because |
6794 | // it's shared with other branches. |
6795 | } |
6796 | |
6797 | // Step 7.b. Check for Throw completion. |
6798 | if (!ifKind.emitElseIf(Nothing())) { |
6799 | // [stack] NEXT ITER RECEIVED RESUMEKIND |
6800 | return false; |
6801 | } |
6802 | if (!emit1(JSOp::Dup)) { |
6803 | // [stack] NEXT ITER RECEIVED RESUMEKIND RESUMEKIND |
6804 | return false; |
6805 | } |
6806 | if (!emitPushResumeKind(GeneratorResumeKind::Throw)) { |
6807 | // [stack] NEXT ITER RECEIVED RESUMEKIND RESUMEKIND THROW |
6808 | return false; |
6809 | } |
6810 | if (!emit1(JSOp::StrictEq)) { |
6811 | // [stack] NEXT ITER RECEIVED RESUMEKIND IS_THROW |
6812 | return false; |
6813 | } |
6814 | if (!ifKind.emitThenElse()) { |
6815 | // [stack] NEXT ITER RECEIVED RESUMEKIND |
6816 | return false; |
6817 | } |
6818 | { |
6819 | if (!emit1(JSOp::Pop)) { |
6820 | // [stack] NEXT ITER RECEIVED |
6821 | return false; |
6822 | } |
6823 | // Step 7.b.i. |
6824 | if (!emitDupAt(1)) { |
6825 | // [stack] NEXT ITER RECEIVED ITER |
6826 | return false; |
6827 | } |
6828 | if (!emit1(JSOp::Dup)) { |
6829 | // [stack] NEXT ITER RECEIVED ITER ITER |
6830 | return false; |
6831 | } |
6832 | if (!emitAtomOp(JSOp::GetProp, |
6833 | TaggedParserAtomIndex::WellKnown::throw_())) { |
6834 | // [stack] NEXT ITER RECEIVED ITER THROW |
6835 | return false; |
6836 | } |
6837 | |
6838 | // Step 7.b.ii. |
6839 | InternalIfEmitter ifThrowMethodIsNotDefined(this); |
6840 | if (!emit1(JSOp::IsNullOrUndefined)) { |
6841 | // [stack] NEXT ITER RECEIVED ITER THROW NULL-OR-UNDEF |
6842 | return false; |
6843 | } |
6844 | |
6845 | if (!ifThrowMethodIsNotDefined.emitThenElse( |
6846 | IfEmitter::ConditionKind::Negative)) { |
6847 | // [stack] NEXT ITER RECEIVED ITER THROW |
6848 | return false; |
6849 | } |
6850 | |
6851 | // Step 7.b.ii.1. |
6852 | // RESULT = ITER.throw(EXCEPTION) |
6853 | if (!emit1(JSOp::Swap)) { |
6854 | // [stack] NEXT ITER RECEIVED THROW ITER |
6855 | return false; |
6856 | } |
6857 | if (!emit2(JSOp::Pick, 2)) { |
6858 | // [stack] NEXT ITER THROW ITER RECEIVED |
6859 | return false; |
6860 | } |
6861 | if (!emitCall(JSOp::Call, 1, iter)) { |
6862 | // [stack] NEXT ITER RESULT |
6863 | return false; |
6864 | } |
6865 | |
6866 | // Step 7.b.ii.2. |
6867 | if (iterKind == IteratorKind::Async) { |
6868 | if (!emitAwaitInInnermostScope()) { |
6869 | // [stack] NEXT ITER RESULT |
6870 | return false; |
6871 | } |
6872 | } |
6873 | |
6874 | // Step 7.b.ii.4. |
6875 | if (!emitCheckIsObj(CheckIsObjectKind::IteratorThrow)) { |
6876 | // [stack] NEXT ITER RESULT |
6877 | return false; |
6878 | } |
6879 | |
6880 | // Bytecode for steps 7.b.ii.5-8 is emitted after the ifKind if-else because |
6881 | // it's shared with other branches. |
6882 | |
6883 | // Step 7.b.iii. |
6884 | if (!ifThrowMethodIsNotDefined.emitElse()) { |
6885 | // [stack] NEXT ITER RECEIVED ITER THROW |
6886 | return false; |
6887 | } |
6888 | if (!emit1(JSOp::Pop)) { |
6889 | // [stack] NEXT ITER RECEIVED ITER |
6890 | return false; |
6891 | } |
6892 | |
6893 | // Steps 7.b.iii.1-4. |
6894 | // |
6895 | // If the iterator does not have a "throw" method, it calls IteratorClose |
6896 | // and then throws a TypeError. |
6897 | if (!emitIteratorCloseInInnermostScope(iterKind, CompletionKind::Normal)) { |
6898 | // [stack] NEXT ITER RECEIVED ITER |
6899 | return false; |
6900 | } |
6901 | // Steps 7.b.iii.5-6. |
6902 | if (!emit2(JSOp::ThrowMsg, uint8_t(ThrowMsgKind::IteratorNoThrow))) { |
6903 | // [stack] NEXT ITER RECEIVED ITER |
6904 | // [stack] # throw |
6905 | return false; |
6906 | } |
6907 | |
6908 | if (!ifThrowMethodIsNotDefined.emitEnd()) { |
6909 | return false; |
6910 | } |
6911 | } |
6912 | |
6913 | // Step 7.c. It must be a Return completion. |
6914 | if (!ifKind.emitElse()) { |
6915 | // [stack] NEXT ITER RECEIVED RESUMEKIND |
6916 | return false; |
6917 | } |
6918 | { |
6919 | if (!emit1(JSOp::Pop)) { |
6920 | // [stack] NEXT ITER RECEIVED |
6921 | return false; |
6922 | } |
6923 | |
6924 | // Step 7.c.i. |
6925 | // |
6926 | // Call iterator.return() for receiving a "forced return" completion from |
6927 | // the generator. |
6928 | |
6929 | // Step 7.c.ii. |
6930 | // |
6931 | // Get the "return" method. |
6932 | if (!emitDupAt(1)) { |
6933 | // [stack] NEXT ITER RECEIVED ITER |
6934 | return false; |
6935 | } |
6936 | if (!emit1(JSOp::Dup)) { |
6937 | // [stack] NEXT ITER RECEIVED ITER ITER |
6938 | return false; |
6939 | } |
6940 | if (!emitAtomOp(JSOp::GetProp, |
6941 | TaggedParserAtomIndex::WellKnown::return_())) { |
6942 | // [stack] NEXT ITER RECEIVED ITER RET |
6943 | return false; |
6944 | } |
6945 | |
6946 | // Step 7.c.iii. |
6947 | // |
6948 | // Do nothing if "return" is undefined or null. |
6949 | InternalIfEmitter ifReturnMethodIsDefined(this); |
6950 | if (!emit1(JSOp::IsNullOrUndefined)) { |
6951 | // [stack] NEXT ITER RECEIVED ITER RET NULL-OR-UNDEF |
6952 | return false; |
6953 | } |
6954 | |
6955 | // Step 7.c.iv. |
6956 | // |
6957 | // Call "return" with the argument passed to Generator.prototype.return. |
6958 | if (!ifReturnMethodIsDefined.emitThenElse( |
6959 | IfEmitter::ConditionKind::Negative)) { |
6960 | // [stack] NEXT ITER RECEIVED ITER RET |
6961 | return false; |
6962 | } |
6963 | if (!emit1(JSOp::Swap)) { |
6964 | // [stack] NEXT ITER RECEIVED RET ITER |
6965 | return false; |
6966 | } |
6967 | if (!emit2(JSOp::Pick, 2)) { |
6968 | // [stack] NEXT ITER RET ITER RECEIVED |
6969 | return false; |
6970 | } |
6971 | if (needsIteratorResult) { |
6972 | if (!emitAtomOp(JSOp::GetProp, |
6973 | TaggedParserAtomIndex::WellKnown::value())) { |
6974 | // [stack] NEXT ITER RET ITER VAL |
6975 | return false; |
6976 | } |
6977 | } |
6978 | if (!emitCall(JSOp::Call, 1)) { |
6979 | // [stack] NEXT ITER RESULT |
6980 | return false; |
6981 | } |
6982 | |
6983 | // Step 7.c.v. |
6984 | if (iterKind == IteratorKind::Async) { |
6985 | if (!emitAwaitInInnermostScope()) { |
6986 | // [stack] NEXT ITER RESULT |
6987 | return false; |
6988 | } |
6989 | } |
6990 | |
6991 | // Step 7.c.vi. |
6992 | if (!emitCheckIsObj(CheckIsObjectKind::IteratorReturn)) { |
6993 | // [stack] NEXT ITER RESULT |
6994 | return false; |
6995 | } |
6996 | |
6997 | // Check if the returned object from iterator.return() is done. If not, |
6998 | // continue yielding. |
6999 | |
7000 | // Steps 7.c.vii-viii. |
7001 | InternalIfEmitter ifReturnDone(this); |
7002 | if (!emit1(JSOp::Dup)) { |
7003 | // [stack] NEXT ITER RESULT RESULT |
7004 | return false; |
7005 | } |
7006 | if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::done())) { |
7007 | // [stack] NEXT ITER RESULT DONE |
7008 | return false; |
7009 | } |
7010 | if (!ifReturnDone.emitThenElse()) { |
7011 | // [stack] NEXT ITER RESULT |
7012 | return false; |
7013 | } |
7014 | |
7015 | // Step 7.c.viii.1. |
7016 | if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::value())) { |
7017 | // [stack] NEXT ITER VALUE |
7018 | return false; |
7019 | } |
7020 | if (needsIteratorResult) { |
7021 | if (!emitPrepareIteratorResult()) { |
7022 | // [stack] NEXT ITER VALUE RESULT |
7023 | return false; |
7024 | } |
7025 | if (!emit1(JSOp::Swap)) { |
7026 | // [stack] NEXT ITER RESULT VALUE |
7027 | return false; |
7028 | } |
7029 | if (!emitFinishIteratorResult(true)) { |
7030 | // [stack] NEXT ITER RESULT |
7031 | return false; |
7032 | } |
7033 | } |
7034 | |
7035 | if (!ifReturnDone.emitElse()) { |
7036 | // [stack] NEXT ITER RESULT |
7037 | return false; |
7038 | } |
7039 | |
7040 | // Jump to continue label for steps 7.c.ix-x. |
7041 | if (!emitJump(JSOp::Goto, &loopInfo.continues)) { |
7042 | // [stack] NEXT ITER RESULT |
7043 | return false; |
7044 | } |
7045 | |
7046 | if (!ifReturnDone.emitEnd()) { |
7047 | // [stack] NEXT ITER RESULT |
7048 | return false; |
7049 | } |
7050 | |
7051 | // Step 7.c.iii. |
7052 | if (!ifReturnMethodIsDefined.emitElse()) { |
7053 | // [stack] NEXT ITER RECEIVED ITER RET |
7054 | return false; |
7055 | } |
7056 | if (!emitPopN(2)) { |
7057 | // [stack] NEXT ITER RECEIVED |
7058 | return false; |
7059 | } |
7060 | if (iterKind == IteratorKind::Async) { |
7061 | // Step 7.c.iii.1. |
7062 | if (!emitAwaitInInnermostScope()) { |
7063 | // [stack] NEXT ITER RECEIVED |
7064 | return false; |
7065 | } |
7066 | } |
7067 | if (!ifReturnMethodIsDefined.emitEnd()) { |
7068 | // [stack] NEXT ITER RECEIVED |
7069 | return false; |
7070 | } |
7071 | |
7072 | // Perform a "forced generator return". |
7073 | // |
7074 | // Step 7.c.iii.2. |
7075 | // Step 7.c.viii.2. |
7076 | if (!emitGetDotGeneratorInInnermostScope()) { |
7077 | // [stack] NEXT ITER RESULT GENOBJ |
7078 | return false; |
7079 | } |
7080 | if (!emitPushResumeKind(GeneratorResumeKind::Return)) { |
7081 | // [stack] NEXT ITER RESULT GENOBJ RESUMEKIND |
7082 | return false; |
7083 | } |
7084 | if (!emit1(JSOp::CheckResumeKind)) { |
7085 | // [stack] NEXT ITER RESULT GENOBJ RESUMEKIND |
7086 | return false; |
7087 | } |
7088 | } |
7089 | |
7090 | if (!ifKind.emitEnd()) { |
7091 | // [stack] NEXT ITER RESULT |
7092 | return false; |
7093 | } |
7094 | |
7095 | // Shared tail for Normal/Throw completions. |
7096 | // |
7097 | // Steps 7.a.iv-v. |
7098 | // Steps 7.b.ii.5-6. |
7099 | // |
7100 | // [stack] NEXT ITER RESULT |
7101 | |
7102 | // if (result.done) break; |
7103 | if (!emit1(JSOp::Dup)) { |
7104 | // [stack] NEXT ITER RESULT RESULT |
7105 | return false; |
7106 | } |
7107 | if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::done())) { |
7108 | // [stack] NEXT ITER RESULT DONE |
7109 | return false; |
7110 | } |
7111 | if (!emitJump(JSOp::JumpIfTrue, &loopInfo.breaks)) { |
7112 | // [stack] NEXT ITER RESULT |
7113 | return false; |
7114 | } |
7115 | |
7116 | // Steps 7.a.vi-vii. |
7117 | // Steps 7.b.ii.7-8. |
7118 | // Steps 7.c.ix-x. |
7119 | if (!loopInfo.emitContinueTarget(this)) { |
7120 | // [stack] NEXT ITER RESULT |
7121 | return false; |
7122 | } |
7123 | if (iterKind == IteratorKind::Async) { |
7124 | if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::value())) { |
7125 | // [stack] NEXT ITER RESULT |
7126 | return false; |
7127 | } |
7128 | } |
7129 | if (!emitGetDotGeneratorInInnermostScope()) { |
7130 | // [stack] NEXT ITER RESULT GENOBJ |
7131 | return false; |
7132 | } |
7133 | if (!emitYieldOp(JSOp::Yield)) { |
7134 | // [stack] NEXT ITER RVAL GENOBJ RESUMEKIND |
7135 | return false; |
7136 | } |
7137 | if (!emit1(JSOp::Swap)) { |
7138 | // [stack] NEXT ITER RVAL RESUMEKIND GENOBJ |
7139 | return false; |
7140 | } |
7141 | if (!emit1(JSOp::Pop)) { |
7142 | // [stack] NEXT ITER RVAL RESUMEKIND |
7143 | return false; |
7144 | } |
7145 | if (!loopInfo.emitLoopEnd(this, JSOp::Goto, TryNoteKind::Loop)) { |
7146 | // [stack] NEXT ITER RVAL RESUMEKIND |
7147 | return false; |
7148 | } |
7149 | |
7150 | // Jumps to this point have 3 (instead of 4) values on the stack. |
7151 | MOZ_ASSERT(bytecodeSection().stackDepth() == startDepth)do { static_assert( mozilla::detail::AssertionConditionType< decltype(bytecodeSection().stackDepth() == startDepth)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(bytecodeSection().stackDepth() == startDepth))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("bytecodeSection().stackDepth() == startDepth" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7151); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == startDepth" ")"); do { *((volatile int*)__null) = 7151; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7152 | bytecodeSection().setStackDepth(startDepth - 1); |
7153 | |
7154 | // [stack] NEXT ITER RESULT |
7155 | |
7156 | // Step 7.a.v.1. |
7157 | // Step 7.b.ii.6.a. |
7158 | // |
7159 | // result.value |
7160 | if (!emit2(JSOp::Unpick, 2)) { |
7161 | // [stack] RESULT NEXT ITER |
7162 | return false; |
7163 | } |
7164 | if (!emitPopN(2)) { |
7165 | // [stack] RESULT |
7166 | return false; |
7167 | } |
7168 | if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::value())) { |
7169 | // [stack] VALUE |
7170 | return false; |
7171 | } |
7172 | |
7173 | MOZ_ASSERT(bytecodeSection().stackDepth() == startDepth - 3)do { static_assert( mozilla::detail::AssertionConditionType< decltype(bytecodeSection().stackDepth() == startDepth - 3)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(bytecodeSection().stackDepth() == startDepth - 3))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("bytecodeSection().stackDepth() == startDepth - 3" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7173); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().stackDepth() == startDepth - 3" ")"); do { *((volatile int*)__null) = 7173; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7174 | |
7175 | return true; |
7176 | } |
7177 | |
7178 | bool BytecodeEmitter::emitStatementList(ListNode* stmtList) { |
7179 | for (ParseNode* stmt : stmtList->contents()) { |
7180 | if (!emitTree(stmt)) { |
7181 | return false; |
7182 | } |
7183 | } |
7184 | return true; |
7185 | } |
7186 | |
7187 | bool BytecodeEmitter::emitExpressionStatement(UnaryNode* exprStmt) { |
7188 | MOZ_ASSERT(exprStmt->isKind(ParseNodeKind::ExpressionStmt))do { static_assert( mozilla::detail::AssertionConditionType< decltype(exprStmt->isKind(ParseNodeKind::ExpressionStmt))> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(exprStmt->isKind(ParseNodeKind::ExpressionStmt))) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("exprStmt->isKind(ParseNodeKind::ExpressionStmt)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7188); AnnotateMozCrashReason("MOZ_ASSERT" "(" "exprStmt->isKind(ParseNodeKind::ExpressionStmt)" ")"); do { *((volatile int*)__null) = 7188; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7189 | |
7190 | /* |
7191 | * Top-level or called-from-a-native JS_Execute/EvaluateScript, |
7192 | * debugger, and eval frames may need the value of the ultimate |
7193 | * expression statement as the script's result, despite the fact |
7194 | * that it appears useless to the compiler. |
7195 | * |
7196 | * API users may also set the ReadOnlyCompileOptions::noScriptRval option when |
7197 | * calling JS_Compile* to suppress JSOp::SetRval. |
7198 | */ |
7199 | bool wantval = false; |
7200 | bool useful = false; |
7201 | if (sc->isTopLevelContext()) { |
7202 | useful = wantval = !sc->noScriptRval(); |
7203 | } |
7204 | |
7205 | /* Don't eliminate expressions with side effects. */ |
7206 | ParseNode* expr = exprStmt->kid(); |
7207 | if (!useful) { |
7208 | if (!checkSideEffects(expr, &useful)) { |
7209 | return false; |
7210 | } |
7211 | |
7212 | /* |
7213 | * Don't eliminate apparently useless expressions if they are labeled |
7214 | * expression statements. The startOffset() test catches the case |
7215 | * where we are nesting in emitTree for a labeled compound statement. |
7216 | */ |
7217 | if (innermostNestableControl && |
7218 | innermostNestableControl->is<LabelControl>() && |
7219 | innermostNestableControl->as<LabelControl>().startOffset() >= |
7220 | bytecodeSection().offset()) { |
7221 | useful = true; |
7222 | } |
7223 | } |
7224 | |
7225 | if (useful) { |
7226 | ValueUsage valueUsage = |
7227 | wantval ? ValueUsage::WantValue : ValueUsage::IgnoreValue; |
7228 | ExpressionStatementEmitter ese(this, valueUsage); |
7229 | if (!ese.prepareForExpr(exprStmt->pn_pos.begin)) { |
7230 | return false; |
7231 | } |
7232 | if (!markStepBreakpoint()) { |
7233 | return false; |
7234 | } |
7235 | if (!emitTree(expr, valueUsage)) { |
7236 | return false; |
7237 | } |
7238 | if (!ese.emitEnd()) { |
7239 | return false; |
7240 | } |
7241 | } |
7242 | |
7243 | return true; |
7244 | } |
7245 | |
7246 | bool BytecodeEmitter::emitDeleteName(UnaryNode* deleteNode) { |
7247 | MOZ_ASSERT(deleteNode->isKind(ParseNodeKind::DeleteNameExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(deleteNode->isKind(ParseNodeKind::DeleteNameExpr) )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(deleteNode->isKind(ParseNodeKind::DeleteNameExpr) ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "deleteNode->isKind(ParseNodeKind::DeleteNameExpr)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7247); AnnotateMozCrashReason("MOZ_ASSERT" "(" "deleteNode->isKind(ParseNodeKind::DeleteNameExpr)" ")"); do { *((volatile int*)__null) = 7247; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7248 | |
7249 | NameNode* nameExpr = &deleteNode->kid()->as<NameNode>(); |
7250 | MOZ_ASSERT(nameExpr->isKind(ParseNodeKind::Name))do { static_assert( mozilla::detail::AssertionConditionType< decltype(nameExpr->isKind(ParseNodeKind::Name))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(nameExpr->isKind(ParseNodeKind::Name)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("nameExpr->isKind(ParseNodeKind::Name)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7250); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nameExpr->isKind(ParseNodeKind::Name)" ")"); do { *((volatile int*)__null) = 7250; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7251 | |
7252 | return emitAtomOp(JSOp::DelName, nameExpr->atom()); |
7253 | } |
7254 | |
7255 | bool BytecodeEmitter::emitDeleteProperty(UnaryNode* deleteNode) { |
7256 | MOZ_ASSERT(deleteNode->isKind(ParseNodeKind::DeletePropExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(deleteNode->isKind(ParseNodeKind::DeletePropExpr) )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(deleteNode->isKind(ParseNodeKind::DeletePropExpr) ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "deleteNode->isKind(ParseNodeKind::DeletePropExpr)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7256); AnnotateMozCrashReason("MOZ_ASSERT" "(" "deleteNode->isKind(ParseNodeKind::DeletePropExpr)" ")"); do { *((volatile int*)__null) = 7256; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7257 | |
7258 | PropertyAccess* propExpr = &deleteNode->kid()->as<PropertyAccess>(); |
7259 | PropOpEmitter poe(this, PropOpEmitter::Kind::Delete, |
7260 | propExpr->as<PropertyAccess>().isSuper() |
7261 | ? PropOpEmitter::ObjKind::Super |
7262 | : PropOpEmitter::ObjKind::Other); |
7263 | if (propExpr->isSuper()) { |
7264 | // The expression |delete super.foo;| has to evaluate |super.foo|, |
7265 | // which could throw if |this| hasn't yet been set by a |super(...)| |
7266 | // call or the super-base is not an object, before throwing a |
7267 | // ReferenceError for attempting to delete a super-reference. |
7268 | UnaryNode* base = &propExpr->expression().as<UnaryNode>(); |
7269 | if (!emitGetThisForSuperBase(base)) { |
7270 | // [stack] THIS |
7271 | return false; |
7272 | } |
7273 | } else { |
7274 | if (!poe.prepareForObj()) { |
7275 | return false; |
7276 | } |
7277 | if (!emitPropLHS(propExpr)) { |
7278 | // [stack] OBJ |
7279 | return false; |
7280 | } |
7281 | } |
7282 | |
7283 | if (!poe.emitDelete(propExpr->key().atom())) { |
7284 | // [stack] # if Super |
7285 | // [stack] THIS |
7286 | // [stack] # otherwise |
7287 | // [stack] SUCCEEDED |
7288 | return false; |
7289 | } |
7290 | |
7291 | return true; |
7292 | } |
7293 | |
7294 | bool BytecodeEmitter::emitDeleteElement(UnaryNode* deleteNode) { |
7295 | MOZ_ASSERT(deleteNode->isKind(ParseNodeKind::DeleteElemExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(deleteNode->isKind(ParseNodeKind::DeleteElemExpr) )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(deleteNode->isKind(ParseNodeKind::DeleteElemExpr) ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "deleteNode->isKind(ParseNodeKind::DeleteElemExpr)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7295); AnnotateMozCrashReason("MOZ_ASSERT" "(" "deleteNode->isKind(ParseNodeKind::DeleteElemExpr)" ")"); do { *((volatile int*)__null) = 7295; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7296 | |
7297 | PropertyByValue* elemExpr = &deleteNode->kid()->as<PropertyByValue>(); |
7298 | bool isSuper = elemExpr->isSuper(); |
7299 | DebugOnly<bool> isPrivate = |
7300 | elemExpr->key().isKind(ParseNodeKind::PrivateName); |
7301 | MOZ_ASSERT(!isPrivate)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!isPrivate)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!isPrivate))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!isPrivate", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7301); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!isPrivate" ")"); do { *((volatile int*)__null) = 7301; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7302 | ElemOpEmitter eoe( |
7303 | this, ElemOpEmitter::Kind::Delete, |
7304 | isSuper ? ElemOpEmitter::ObjKind::Super : ElemOpEmitter::ObjKind::Other); |
7305 | if (isSuper) { |
7306 | // The expression |delete super[foo];| has to evaluate |super[foo]|, |
7307 | // which could throw if |this| hasn't yet been set by a |super(...)| |
7308 | // call, or trigger side-effects when evaluating ToPropertyKey(foo), |
7309 | // or also throw when the super-base is not an object, before throwing |
7310 | // a ReferenceError for attempting to delete a super-reference. |
7311 | if (!eoe.prepareForObj()) { |
7312 | // [stack] |
7313 | return false; |
7314 | } |
7315 | |
7316 | UnaryNode* base = &elemExpr->expression().as<UnaryNode>(); |
7317 | if (!emitGetThisForSuperBase(base)) { |
7318 | // [stack] THIS |
7319 | return false; |
7320 | } |
7321 | if (!eoe.prepareForKey()) { |
7322 | // [stack] THIS |
7323 | return false; |
7324 | } |
7325 | if (!emitTree(&elemExpr->key())) { |
7326 | // [stack] THIS KEY |
7327 | return false; |
7328 | } |
7329 | } else { |
7330 | if (!emitElemObjAndKey(elemExpr, false, eoe)) { |
7331 | // [stack] OBJ KEY |
7332 | return false; |
7333 | } |
7334 | } |
7335 | if (!eoe.emitDelete()) { |
7336 | // [stack] # if Super |
7337 | // [stack] THIS |
7338 | // [stack] # otherwise |
7339 | // [stack] SUCCEEDED |
7340 | return false; |
7341 | } |
7342 | |
7343 | return true; |
7344 | } |
7345 | |
7346 | bool BytecodeEmitter::emitDeleteExpression(UnaryNode* deleteNode) { |
7347 | MOZ_ASSERT(deleteNode->isKind(ParseNodeKind::DeleteExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(deleteNode->isKind(ParseNodeKind::DeleteExpr))> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(deleteNode->isKind(ParseNodeKind::DeleteExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("deleteNode->isKind(ParseNodeKind::DeleteExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7347); AnnotateMozCrashReason("MOZ_ASSERT" "(" "deleteNode->isKind(ParseNodeKind::DeleteExpr)" ")"); do { *((volatile int*)__null) = 7347; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7348 | |
7349 | ParseNode* expression = deleteNode->kid(); |
7350 | |
7351 | // If useless, just emit JSOp::True; otherwise convert |delete <expr>| to |
7352 | // effectively |<expr>, true|. |
7353 | bool useful = false; |
7354 | if (!checkSideEffects(expression, &useful)) { |
7355 | return false; |
7356 | } |
7357 | |
7358 | if (useful) { |
7359 | if (!emitTree(expression)) { |
7360 | return false; |
7361 | } |
7362 | if (!emit1(JSOp::Pop)) { |
7363 | return false; |
7364 | } |
7365 | } |
7366 | |
7367 | return emit1(JSOp::True); |
7368 | } |
7369 | |
7370 | bool BytecodeEmitter::emitDeleteOptionalChain(UnaryNode* deleteNode) { |
7371 | MOZ_ASSERT(deleteNode->isKind(ParseNodeKind::DeleteOptionalChainExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(deleteNode->isKind(ParseNodeKind::DeleteOptionalChainExpr ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(deleteNode->isKind(ParseNodeKind::DeleteOptionalChainExpr )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("deleteNode->isKind(ParseNodeKind::DeleteOptionalChainExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7371); AnnotateMozCrashReason("MOZ_ASSERT" "(" "deleteNode->isKind(ParseNodeKind::DeleteOptionalChainExpr)" ")"); do { *((volatile int*)__null) = 7371; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7372 | |
7373 | OptionalEmitter oe(this, bytecodeSection().stackDepth()); |
7374 | |
7375 | ParseNode* kid = deleteNode->kid(); |
7376 | switch (kid->getKind()) { |
7377 | case ParseNodeKind::ElemExpr: |
7378 | case ParseNodeKind::OptionalElemExpr: { |
7379 | auto* elemExpr = &kid->as<PropertyByValueBase>(); |
7380 | if (!emitDeleteElementInOptChain(elemExpr, oe)) { |
7381 | // [stack] # If shortcircuit |
7382 | // [stack] UNDEFINED-OR-NULL |
7383 | // [stack] # otherwise |
7384 | // [stack] SUCCEEDED |
7385 | return false; |
7386 | } |
7387 | |
7388 | break; |
7389 | } |
7390 | case ParseNodeKind::ArgumentsLength: |
7391 | case ParseNodeKind::DotExpr: |
7392 | case ParseNodeKind::OptionalDotExpr: { |
7393 | auto* propExpr = &kid->as<PropertyAccessBase>(); |
7394 | if (!emitDeletePropertyInOptChain(propExpr, oe)) { |
7395 | // [stack] # If shortcircuit |
7396 | // [stack] UNDEFINED-OR-NULL |
7397 | // [stack] # otherwise |
7398 | // [stack] SUCCEEDED |
7399 | return false; |
7400 | } |
7401 | break; |
7402 | } |
7403 | default: |
7404 | MOZ_ASSERT_UNREACHABLE("Unrecognized optional delete ParseNodeKind")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "Unrecognized optional delete ParseNodeKind" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7404); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "Unrecognized optional delete ParseNodeKind" ")"); do { *((volatile int*)__null) = 7404; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7405 | } |
7406 | |
7407 | if (!oe.emitOptionalJumpTarget(JSOp::True)) { |
7408 | // [stack] # If shortcircuit |
7409 | // [stack] TRUE |
7410 | // [stack] # otherwise |
7411 | // [stack] SUCCEEDED |
7412 | return false; |
7413 | } |
7414 | |
7415 | return true; |
7416 | } |
7417 | |
7418 | bool BytecodeEmitter::emitDeletePropertyInOptChain(PropertyAccessBase* propExpr, |
7419 | OptionalEmitter& oe) { |
7420 | MOZ_ASSERT_IF(propExpr->is<PropertyAccess>(),do { if (propExpr->is<PropertyAccess>()) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(!propExpr ->as<PropertyAccess>().isSuper())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!propExpr->as<PropertyAccess >().isSuper()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!propExpr->as<PropertyAccess>().isSuper()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7421); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!propExpr->as<PropertyAccess>().isSuper()" ")"); do { *((volatile int*)__null) = 7421; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
7421 | !propExpr->as<PropertyAccess>().isSuper())do { if (propExpr->is<PropertyAccess>()) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(!propExpr ->as<PropertyAccess>().isSuper())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!propExpr->as<PropertyAccess >().isSuper()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!propExpr->as<PropertyAccess>().isSuper()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7421); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!propExpr->as<PropertyAccess>().isSuper()" ")"); do { *((volatile int*)__null) = 7421; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
7422 | PropOpEmitter poe(this, PropOpEmitter::Kind::Delete, |
7423 | PropOpEmitter::ObjKind::Other); |
7424 | |
7425 | if (!poe.prepareForObj()) { |
7426 | // [stack] |
7427 | return false; |
7428 | } |
7429 | if (!emitOptionalTree(&propExpr->expression(), oe)) { |
7430 | // [stack] OBJ |
7431 | return false; |
7432 | } |
7433 | if (propExpr->isKind(ParseNodeKind::OptionalDotExpr)) { |
7434 | if (!oe.emitJumpShortCircuit()) { |
7435 | // [stack] # if Jump |
7436 | // [stack] UNDEFINED-OR-NULL |
7437 | // [stack] # otherwise |
7438 | // [stack] OBJ |
7439 | return false; |
7440 | } |
7441 | } |
7442 | |
7443 | if (!poe.emitDelete(propExpr->key().atom())) { |
7444 | // [stack] SUCCEEDED |
7445 | return false; |
7446 | } |
7447 | |
7448 | return true; |
7449 | } |
7450 | |
7451 | bool BytecodeEmitter::emitDeleteElementInOptChain(PropertyByValueBase* elemExpr, |
7452 | OptionalEmitter& oe) { |
7453 | MOZ_ASSERT_IF(elemExpr->is<PropertyByValue>(),do { if (elemExpr->is<PropertyByValue>()) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(!elemExpr ->as<PropertyByValue>().isSuper())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!elemExpr->as<PropertyByValue >().isSuper()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!elemExpr->as<PropertyByValue>().isSuper()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7454); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elemExpr->as<PropertyByValue>().isSuper()" ")"); do { *((volatile int*)__null) = 7454; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
7454 | !elemExpr->as<PropertyByValue>().isSuper())do { if (elemExpr->is<PropertyByValue>()) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(!elemExpr ->as<PropertyByValue>().isSuper())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!elemExpr->as<PropertyByValue >().isSuper()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!elemExpr->as<PropertyByValue>().isSuper()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7454); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elemExpr->as<PropertyByValue>().isSuper()" ")"); do { *((volatile int*)__null) = 7454; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
7455 | ElemOpEmitter eoe(this, ElemOpEmitter::Kind::Delete, |
7456 | ElemOpEmitter::ObjKind::Other); |
7457 | |
7458 | if (!eoe.prepareForObj()) { |
7459 | // [stack] |
7460 | return false; |
7461 | } |
7462 | |
7463 | if (!emitOptionalTree(&elemExpr->expression(), oe)) { |
7464 | // [stack] OBJ |
7465 | return false; |
7466 | } |
7467 | |
7468 | if (elemExpr->isKind(ParseNodeKind::OptionalElemExpr)) { |
7469 | if (!oe.emitJumpShortCircuit()) { |
7470 | // [stack] # if Jump |
7471 | // [stack] UNDEFINED-OR-NULL |
7472 | // [stack] # otherwise |
7473 | // [stack] OBJ |
7474 | return false; |
7475 | } |
7476 | } |
7477 | |
7478 | if (!eoe.prepareForKey()) { |
7479 | // [stack] OBJ |
7480 | return false; |
7481 | } |
7482 | |
7483 | if (!emitTree(&elemExpr->key())) { |
7484 | // [stack] OBJ KEY |
7485 | return false; |
7486 | } |
7487 | |
7488 | if (!eoe.emitDelete()) { |
7489 | // [stack] SUCCEEDED |
7490 | return false; |
7491 | } |
7492 | |
7493 | return true; |
7494 | } |
7495 | |
7496 | bool BytecodeEmitter::emitDebugCheckSelfHosted() { |
7497 | // [stack] CALLEE |
7498 | |
7499 | #ifdef DEBUG1 |
7500 | if (!emit1(JSOp::DebugCheckSelfHosted)) { |
7501 | // [stack] CALLEE |
7502 | return false; |
7503 | } |
7504 | #endif |
7505 | |
7506 | return true; |
7507 | } |
7508 | |
7509 | bool BytecodeEmitter::emitSelfHostedCallFunction(CallNode* callNode, JSOp op) { |
7510 | // Special-casing of callFunction to emit bytecode that directly |
7511 | // invokes the callee with the correct |this| object and arguments. |
7512 | // callFunction(fun, thisArg, arg0, arg1) thus becomes: |
7513 | // - emit lookup for fun |
7514 | // - emit lookup for thisArg |
7515 | // - emit lookups for arg0, arg1 |
7516 | // |
7517 | // argc is set to the amount of actually emitted args and the |
7518 | // emitting of args below is disabled by setting emitArgs to false. |
7519 | NameNode* calleeNode = &callNode->callee()->as<NameNode>(); |
7520 | ListNode* argsList = callNode->args(); |
7521 | |
7522 | MOZ_ASSERT(argsList->count() >= 2)do { static_assert( mozilla::detail::AssertionConditionType< decltype(argsList->count() >= 2)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(argsList->count() >= 2 ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "argsList->count() >= 2", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7522); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() >= 2" ")"); do { *((volatile int*)__null) = 7522; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7523 | |
7524 | MOZ_ASSERT(callNode->callOp() == JSOp::Call)do { static_assert( mozilla::detail::AssertionConditionType< decltype(callNode->callOp() == JSOp::Call)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(callNode->callOp() == JSOp ::Call))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("callNode->callOp() == JSOp::Call", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7524); AnnotateMozCrashReason("MOZ_ASSERT" "(" "callNode->callOp() == JSOp::Call" ")"); do { *((volatile int*)__null) = 7524; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7525 | |
7526 | bool constructing = |
7527 | calleeNode->name() == |
7528 | TaggedParserAtomIndex::WellKnown::constructContentFunction(); |
7529 | ParseNode* funNode = argsList->head(); |
7530 | |
7531 | if (!emitTree(funNode)) { |
7532 | // [stack] CALLEE |
7533 | return false; |
7534 | } |
7535 | |
7536 | #ifdef DEBUG1 |
7537 | MOZ_ASSERT(op == JSOp::Call || op == JSOp::CallContent ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(op == JSOp::Call || op == JSOp::CallContent || op == JSOp::NewContent)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(op == JSOp::Call || op == JSOp ::CallContent || op == JSOp::NewContent))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("op == JSOp::Call || op == JSOp::CallContent || op == JSOp::NewContent" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7538); AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::Call || op == JSOp::CallContent || op == JSOp::NewContent" ")"); do { *((volatile int*)__null) = 7538; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
7538 | op == JSOp::NewContent)do { static_assert( mozilla::detail::AssertionConditionType< decltype(op == JSOp::Call || op == JSOp::CallContent || op == JSOp::NewContent)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(op == JSOp::Call || op == JSOp ::CallContent || op == JSOp::NewContent))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("op == JSOp::Call || op == JSOp::CallContent || op == JSOp::NewContent" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7538); AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::Call || op == JSOp::CallContent || op == JSOp::NewContent" ")"); do { *((volatile int*)__null) = 7538; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7539 | if (op == JSOp::Call) { |
7540 | if (!emitDebugCheckSelfHosted()) { |
7541 | // [stack] CALLEE |
7542 | return false; |
7543 | } |
7544 | } |
7545 | #endif |
7546 | |
7547 | ParseNode* thisOrNewTarget = funNode->pn_next; |
7548 | if (constructing) { |
7549 | // Save off the new.target value, but here emit a proper |this| for a |
7550 | // constructing call. |
7551 | if (!emit1(JSOp::IsConstructing)) { |
7552 | // [stack] CALLEE IS_CONSTRUCTING |
7553 | return false; |
7554 | } |
7555 | } else { |
7556 | // It's |this|, emit it. |
7557 | if (!emitTree(thisOrNewTarget)) { |
7558 | // [stack] CALLEE THIS |
7559 | return false; |
7560 | } |
7561 | } |
7562 | |
7563 | for (ParseNode* argpn : argsList->contentsFrom(thisOrNewTarget->pn_next)) { |
7564 | if (!emitTree(argpn)) { |
7565 | // [stack] CALLEE ... ARGS... |
7566 | return false; |
7567 | } |
7568 | } |
7569 | |
7570 | if (constructing) { |
7571 | if (!emitTree(thisOrNewTarget)) { |
7572 | // [stack] CALLEE IS_CONSTRUCTING ARGS... NEW.TARGET |
7573 | return false; |
7574 | } |
7575 | } |
7576 | |
7577 | uint32_t argc = argsList->count() - 2; |
7578 | if (!emitCall(op, argc)) { |
7579 | // [stack] RVAL |
7580 | return false; |
7581 | } |
7582 | |
7583 | return true; |
7584 | } |
7585 | |
7586 | bool BytecodeEmitter::emitSelfHostedResumeGenerator(CallNode* callNode) { |
7587 | ListNode* argsList = callNode->args(); |
7588 | |
7589 | // Syntax: resumeGenerator(gen, value, 'next'|'throw'|'return') |
7590 | MOZ_ASSERT(argsList->count() == 3)do { static_assert( mozilla::detail::AssertionConditionType< decltype(argsList->count() == 3)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(argsList->count() == 3))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 3" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7590); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 3" ")"); do { *((volatile int*)__null) = 7590; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7591 | |
7592 | ParseNode* genNode = argsList->head(); |
7593 | if (!emitTree(genNode)) { |
7594 | // [stack] GENERATOR |
7595 | return false; |
7596 | } |
7597 | |
7598 | ParseNode* valNode = genNode->pn_next; |
7599 | if (!emitTree(valNode)) { |
7600 | // [stack] GENERATOR VALUE |
7601 | return false; |
7602 | } |
7603 | |
7604 | ParseNode* kindNode = valNode->pn_next; |
7605 | MOZ_ASSERT(kindNode->isKind(ParseNodeKind::StringExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(kindNode->isKind(ParseNodeKind::StringExpr))>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(kindNode->isKind(ParseNodeKind::StringExpr)))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("kindNode->isKind(ParseNodeKind::StringExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7605); AnnotateMozCrashReason("MOZ_ASSERT" "(" "kindNode->isKind(ParseNodeKind::StringExpr)" ")"); do { *((volatile int*)__null) = 7605; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7606 | GeneratorResumeKind kind = |
7607 | ParserAtomToResumeKind(kindNode->as<NameNode>().atom()); |
7608 | MOZ_ASSERT(!kindNode->pn_next)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!kindNode->pn_next)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!kindNode->pn_next))), 0) )) { do { } while (false); MOZ_ReportAssertionFailure("!kindNode->pn_next" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7608); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!kindNode->pn_next" ")"); do { *((volatile int*)__null) = 7608; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7609 | |
7610 | if (!emitPushResumeKind(kind)) { |
7611 | // [stack] GENERATOR VALUE RESUMEKIND |
7612 | return false; |
7613 | } |
7614 | |
7615 | if (!emit1(JSOp::Resume)) { |
7616 | // [stack] RVAL |
7617 | return false; |
7618 | } |
7619 | |
7620 | return true; |
7621 | } |
7622 | |
7623 | bool BytecodeEmitter::emitSelfHostedForceInterpreter() { |
7624 | // JSScript::hasForceInterpreterOp() relies on JSOp::ForceInterpreter being |
7625 | // the first bytecode op in the script. |
7626 | MOZ_ASSERT(bytecodeSection().code().empty())do { static_assert( mozilla::detail::AssertionConditionType< decltype(bytecodeSection().code().empty())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(bytecodeSection().code().empty ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("bytecodeSection().code().empty()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7626); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeSection().code().empty()" ")"); do { *((volatile int*)__null) = 7626; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7627 | |
7628 | if (!emit1(JSOp::ForceInterpreter)) { |
7629 | return false; |
7630 | } |
7631 | if (!emit1(JSOp::Undefined)) { |
7632 | return false; |
7633 | } |
7634 | |
7635 | return true; |
7636 | } |
7637 | |
7638 | bool BytecodeEmitter::emitSelfHostedAllowContentIter(CallNode* callNode) { |
7639 | ListNode* argsList = callNode->args(); |
7640 | |
7641 | MOZ_ASSERT(argsList->count() == 1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(argsList->count() == 1)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(argsList->count() == 1))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 1" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7641); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1" ")"); do { *((volatile int*)__null) = 7641; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7642 | |
7643 | // We're just here as a sentinel. Pass the value through directly. |
7644 | return emitTree(argsList->head()); |
7645 | } |
7646 | |
7647 | bool BytecodeEmitter::emitSelfHostedAllowContentIterWith(CallNode* callNode) { |
7648 | ListNode* argsList = callNode->args(); |
7649 | |
7650 | MOZ_ASSERT(argsList->count() == 2 || argsList->count() == 3)do { static_assert( mozilla::detail::AssertionConditionType< decltype(argsList->count() == 2 || argsList->count() == 3)>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(argsList->count() == 2 || argsList->count() == 3))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("argsList->count() == 2 || argsList->count() == 3", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7650); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2 || argsList->count() == 3" ")"); do { *((volatile int*)__null) = 7650; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7651 | |
7652 | // We're just here as a sentinel. Pass the value through directly. |
7653 | return emitTree(argsList->head()); |
7654 | } |
7655 | |
7656 | bool BytecodeEmitter::emitSelfHostedAllowContentIterWithNext( |
7657 | CallNode* callNode) { |
7658 | ListNode* argsList = callNode->args(); |
7659 | |
7660 | MOZ_ASSERT(argsList->count() == 2)do { static_assert( mozilla::detail::AssertionConditionType< decltype(argsList->count() == 2)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(argsList->count() == 2))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 2" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7660); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2" ")"); do { *((volatile int*)__null) = 7660; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7661 | |
7662 | // We're just here as a sentinel. Pass the value through directly. |
7663 | return emitTree(argsList->head()); |
7664 | } |
7665 | |
7666 | bool BytecodeEmitter::emitSelfHostedDefineDataProperty(CallNode* callNode) { |
7667 | ListNode* argsList = callNode->args(); |
7668 | |
7669 | // Only optimize when 3 arguments are passed. |
7670 | MOZ_ASSERT(argsList->count() == 3)do { static_assert( mozilla::detail::AssertionConditionType< decltype(argsList->count() == 3)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(argsList->count() == 3))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 3" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7670); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 3" ")"); do { *((volatile int*)__null) = 7670; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7671 | |
7672 | ParseNode* objNode = argsList->head(); |
7673 | if (!emitTree(objNode)) { |
7674 | return false; |
7675 | } |
7676 | |
7677 | ParseNode* idNode = objNode->pn_next; |
7678 | if (!emitTree(idNode)) { |
7679 | return false; |
7680 | } |
7681 | |
7682 | ParseNode* valNode = idNode->pn_next; |
7683 | if (!emitTree(valNode)) { |
7684 | return false; |
7685 | } |
7686 | |
7687 | // This will leave the object on the stack instead of pushing |undefined|, |
7688 | // but that's fine because the self-hosted code doesn't use the return |
7689 | // value. |
7690 | return emit1(JSOp::InitElem); |
7691 | } |
7692 | |
7693 | bool BytecodeEmitter::emitSelfHostedHasOwn(CallNode* callNode) { |
7694 | ListNode* argsList = callNode->args(); |
7695 | |
7696 | MOZ_ASSERT(argsList->count() == 2)do { static_assert( mozilla::detail::AssertionConditionType< decltype(argsList->count() == 2)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(argsList->count() == 2))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 2" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7696); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2" ")"); do { *((volatile int*)__null) = 7696; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7697 | |
7698 | ParseNode* idNode = argsList->head(); |
7699 | if (!emitTree(idNode)) { |
7700 | return false; |
7701 | } |
7702 | |
7703 | ParseNode* objNode = idNode->pn_next; |
7704 | if (!emitTree(objNode)) { |
7705 | return false; |
7706 | } |
7707 | |
7708 | return emit1(JSOp::HasOwn); |
7709 | } |
7710 | |
7711 | bool BytecodeEmitter::emitSelfHostedGetPropertySuper(CallNode* callNode) { |
7712 | ListNode* argsList = callNode->args(); |
7713 | |
7714 | MOZ_ASSERT(argsList->count() == 3)do { static_assert( mozilla::detail::AssertionConditionType< decltype(argsList->count() == 3)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(argsList->count() == 3))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 3" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7714); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 3" ")"); do { *((volatile int*)__null) = 7714; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7715 | |
7716 | ParseNode* objNode = argsList->head(); |
7717 | ParseNode* idNode = objNode->pn_next; |
7718 | ParseNode* receiverNode = idNode->pn_next; |
7719 | |
7720 | if (!emitTree(receiverNode)) { |
7721 | return false; |
7722 | } |
7723 | |
7724 | if (!emitTree(idNode)) { |
7725 | return false; |
7726 | } |
7727 | |
7728 | if (!emitTree(objNode)) { |
7729 | return false; |
7730 | } |
7731 | |
7732 | return emitElemOpBase(JSOp::GetElemSuper); |
7733 | } |
7734 | |
7735 | bool BytecodeEmitter::emitSelfHostedToNumeric(CallNode* callNode) { |
7736 | ListNode* argsList = callNode->args(); |
7737 | |
7738 | MOZ_ASSERT(argsList->count() == 1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(argsList->count() == 1)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(argsList->count() == 1))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 1" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7738); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1" ")"); do { *((volatile int*)__null) = 7738; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7739 | |
7740 | ParseNode* argNode = argsList->head(); |
7741 | |
7742 | if (!emitTree(argNode)) { |
7743 | return false; |
7744 | } |
7745 | |
7746 | return emit1(JSOp::ToNumeric); |
7747 | } |
7748 | |
7749 | bool BytecodeEmitter::emitSelfHostedToString(CallNode* callNode) { |
7750 | ListNode* argsList = callNode->args(); |
7751 | |
7752 | MOZ_ASSERT(argsList->count() == 1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(argsList->count() == 1)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(argsList->count() == 1))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 1" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7752); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1" ")"); do { *((volatile int*)__null) = 7752; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7753 | |
7754 | ParseNode* argNode = argsList->head(); |
7755 | |
7756 | if (!emitTree(argNode)) { |
7757 | return false; |
7758 | } |
7759 | |
7760 | return emit1(JSOp::ToString); |
7761 | } |
7762 | |
7763 | bool BytecodeEmitter::emitSelfHostedIsNullOrUndefined(CallNode* callNode) { |
7764 | ListNode* argsList = callNode->args(); |
7765 | |
7766 | MOZ_ASSERT(argsList->count() == 1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(argsList->count() == 1)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(argsList->count() == 1))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 1" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7766); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1" ")"); do { *((volatile int*)__null) = 7766; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7767 | |
7768 | ParseNode* argNode = argsList->head(); |
7769 | |
7770 | if (!emitTree(argNode)) { |
7771 | // [stack] ARG |
7772 | return false; |
7773 | } |
7774 | if (!emit1(JSOp::IsNullOrUndefined)) { |
7775 | // [stack] ARG IS_NULL_OR_UNDEF |
7776 | return false; |
7777 | } |
7778 | if (!emit1(JSOp::Swap)) { |
7779 | // [stack] IS_NULL_OR_UNDEF ARG |
7780 | return false; |
7781 | } |
7782 | if (!emit1(JSOp::Pop)) { |
7783 | // [stack] IS_NULL_OR_UNDEF |
7784 | return false; |
7785 | } |
7786 | return true; |
7787 | } |
7788 | |
7789 | bool BytecodeEmitter::emitSelfHostedIteratorClose(CallNode* callNode) { |
7790 | ListNode* argsList = callNode->args(); |
7791 | MOZ_ASSERT(argsList->count() == 1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(argsList->count() == 1)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(argsList->count() == 1))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 1" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7791); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1" ")"); do { *((volatile int*)__null) = 7791; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7792 | |
7793 | ParseNode* argNode = argsList->head(); |
7794 | if (!emitTree(argNode)) { |
7795 | // [stack] ARG |
7796 | return false; |
7797 | } |
7798 | |
7799 | if (!emit2(JSOp::CloseIter, uint8_t(CompletionKind::Normal))) { |
7800 | // [stack] |
7801 | return false; |
7802 | } |
7803 | |
7804 | // This is still a call node, so we must generate a stack value. |
7805 | if (!emit1(JSOp::Undefined)) { |
7806 | // [stack] RVAL |
7807 | return false; |
7808 | } |
7809 | |
7810 | return true; |
7811 | } |
7812 | |
7813 | bool BytecodeEmitter::emitSelfHostedGetBuiltinConstructorOrPrototype( |
7814 | CallNode* callNode, bool isConstructor) { |
7815 | ListNode* argsList = callNode->args(); |
7816 | |
7817 | MOZ_ASSERT(argsList->count() == 1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(argsList->count() == 1)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(argsList->count() == 1))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 1" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7817); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1" ")"); do { *((volatile int*)__null) = 7817; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7818 | |
7819 | ParseNode* argNode = argsList->head(); |
7820 | |
7821 | if (!argNode->isKind(ParseNodeKind::StringExpr)) { |
7822 | reportError(callNode, JSMSG_UNEXPECTED_TYPE, "built-in name", |
7823 | "not a string constant"); |
7824 | return false; |
7825 | } |
7826 | |
7827 | auto name = argNode->as<NameNode>().atom(); |
7828 | |
7829 | BuiltinObjectKind kind; |
7830 | if (isConstructor) { |
7831 | kind = BuiltinConstructorForName(name); |
7832 | } else { |
7833 | kind = BuiltinPrototypeForName(name); |
7834 | } |
7835 | |
7836 | if (kind == BuiltinObjectKind::None) { |
7837 | reportError(callNode, JSMSG_UNEXPECTED_TYPE, "built-in name", |
7838 | "not a valid built-in"); |
7839 | return false; |
7840 | } |
7841 | |
7842 | return emitBuiltinObject(kind); |
7843 | } |
7844 | |
7845 | bool BytecodeEmitter::emitSelfHostedGetBuiltinConstructor(CallNode* callNode) { |
7846 | return emitSelfHostedGetBuiltinConstructorOrPrototype( |
7847 | callNode, /* isConstructor = */ true); |
7848 | } |
7849 | |
7850 | bool BytecodeEmitter::emitSelfHostedGetBuiltinPrototype(CallNode* callNode) { |
7851 | return emitSelfHostedGetBuiltinConstructorOrPrototype( |
7852 | callNode, /* isConstructor = */ false); |
7853 | } |
7854 | |
7855 | JS::SymbolCode ParserAtomToSymbolCode(TaggedParserAtomIndex atom) { |
7856 | // NOTE: This is a linear search, but the set of entries is quite small and |
7857 | // this is only used for initial self-hosted parse. |
7858 | #define MATCH_WELL_KNOWN_SYMBOL(NAME) \ |
7859 | if (atom == TaggedParserAtomIndex::WellKnown::NAME()) { \ |
7860 | return JS::SymbolCode::NAME; \ |
7861 | } |
7862 | JS_FOR_EACH_WELL_KNOWN_SYMBOL(MATCH_WELL_KNOWN_SYMBOL)MATCH_WELL_KNOWN_SYMBOL(isConcatSpreadable) MATCH_WELL_KNOWN_SYMBOL (iterator) MATCH_WELL_KNOWN_SYMBOL(match) MATCH_WELL_KNOWN_SYMBOL (replace) MATCH_WELL_KNOWN_SYMBOL(search) MATCH_WELL_KNOWN_SYMBOL (species) MATCH_WELL_KNOWN_SYMBOL(hasInstance) MATCH_WELL_KNOWN_SYMBOL (split) MATCH_WELL_KNOWN_SYMBOL(toPrimitive) MATCH_WELL_KNOWN_SYMBOL (toStringTag) MATCH_WELL_KNOWN_SYMBOL(unscopables) MATCH_WELL_KNOWN_SYMBOL (asyncIterator) MATCH_WELL_KNOWN_SYMBOL(matchAll) |
7863 | #undef MATCH_WELL_KNOWN_SYMBOL |
7864 | |
7865 | return JS::SymbolCode::Limit; |
7866 | } |
7867 | |
7868 | bool BytecodeEmitter::emitSelfHostedGetBuiltinSymbol(CallNode* callNode) { |
7869 | ListNode* argsList = callNode->args(); |
7870 | |
7871 | MOZ_ASSERT(argsList->count() == 1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(argsList->count() == 1)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(argsList->count() == 1))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 1" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7871); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1" ")"); do { *((volatile int*)__null) = 7871; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7872 | |
7873 | ParseNode* argNode = argsList->head(); |
7874 | |
7875 | if (!argNode->isKind(ParseNodeKind::StringExpr)) { |
7876 | reportError(callNode, JSMSG_UNEXPECTED_TYPE, "built-in name", |
7877 | "not a string constant"); |
7878 | return false; |
7879 | } |
7880 | |
7881 | auto name = argNode->as<NameNode>().atom(); |
7882 | |
7883 | JS::SymbolCode code = ParserAtomToSymbolCode(name); |
7884 | if (code == JS::SymbolCode::Limit) { |
7885 | reportError(callNode, JSMSG_UNEXPECTED_TYPE, "built-in name", |
7886 | "not a valid built-in"); |
7887 | return false; |
7888 | } |
7889 | |
7890 | return emit2(JSOp::Symbol, uint8_t(code)); |
7891 | } |
7892 | |
7893 | bool BytecodeEmitter::emitSelfHostedArgumentsLength(CallNode* callNode) { |
7894 | MOZ_ASSERT(!sc->asFunctionBox()->needsArgsObj())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!sc->asFunctionBox()->needsArgsObj())>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(!sc->asFunctionBox()->needsArgsObj()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!sc->asFunctionBox()->needsArgsObj()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7894); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sc->asFunctionBox()->needsArgsObj()" ")"); do { *((volatile int*)__null) = 7894; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7895 | sc->asFunctionBox()->setUsesArgumentsIntrinsics(); |
7896 | |
7897 | MOZ_ASSERT(callNode->args()->count() == 0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(callNode->args()->count() == 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(callNode->args()->count () == 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("callNode->args()->count() == 0", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7897); AnnotateMozCrashReason("MOZ_ASSERT" "(" "callNode->args()->count() == 0" ")"); do { *((volatile int*)__null) = 7897; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7898 | |
7899 | return emit1(JSOp::ArgumentsLength); |
7900 | } |
7901 | |
7902 | bool BytecodeEmitter::emitSelfHostedGetArgument(CallNode* callNode) { |
7903 | MOZ_ASSERT(!sc->asFunctionBox()->needsArgsObj())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!sc->asFunctionBox()->needsArgsObj())>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(!sc->asFunctionBox()->needsArgsObj()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!sc->asFunctionBox()->needsArgsObj()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7903); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sc->asFunctionBox()->needsArgsObj()" ")"); do { *((volatile int*)__null) = 7903; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7904 | sc->asFunctionBox()->setUsesArgumentsIntrinsics(); |
7905 | |
7906 | ListNode* argsList = callNode->args(); |
7907 | MOZ_ASSERT(argsList->count() == 1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(argsList->count() == 1)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(argsList->count() == 1))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 1" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7907); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1" ")"); do { *((volatile int*)__null) = 7907; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7908 | |
7909 | ParseNode* argNode = argsList->head(); |
7910 | if (!emitTree(argNode)) { |
7911 | return false; |
7912 | } |
7913 | |
7914 | return emit1(JSOp::GetActualArg); |
7915 | } |
7916 | |
7917 | #ifdef DEBUG1 |
7918 | void BytecodeEmitter::assertSelfHostedExpectedTopLevel(ParseNode* node) { |
7919 | // The function argument is expected to be a simple binding/function name. |
7920 | // Eg. `function foo() { }; SpecialIntrinsic(foo)` |
7921 | MOZ_ASSERT(node->isKind(ParseNodeKind::Name),do { static_assert( mozilla::detail::AssertionConditionType< decltype(node->isKind(ParseNodeKind::Name))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(node->isKind(ParseNodeKind ::Name)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("node->isKind(ParseNodeKind::Name)" " (" "argument must be a function name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7922); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::Name)" ") (" "argument must be a function name" ")"); do { *((volatile int*)__null) = 7922; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
7922 | "argument must be a function name")do { static_assert( mozilla::detail::AssertionConditionType< decltype(node->isKind(ParseNodeKind::Name))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(node->isKind(ParseNodeKind ::Name)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("node->isKind(ParseNodeKind::Name)" " (" "argument must be a function name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7922); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::Name)" ") (" "argument must be a function name" ")"); do { *((volatile int*)__null) = 7922; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
7923 | TaggedParserAtomIndex targetName = node->as<NameNode>().name(); |
7924 | |
7925 | // The special intrinsics must follow the target functions definition. A |
7926 | // simple assert is fine here since any hoisted function will cause a non-null |
7927 | // value to be set here. |
7928 | MOZ_ASSERT(prevSelfHostedTopLevelFunction)do { static_assert( mozilla::detail::AssertionConditionType< decltype(prevSelfHostedTopLevelFunction)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(prevSelfHostedTopLevelFunction ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "prevSelfHostedTopLevelFunction", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7928); AnnotateMozCrashReason("MOZ_ASSERT" "(" "prevSelfHostedTopLevelFunction" ")"); do { *((volatile int*)__null) = 7928; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7929 | |
7930 | // The target function must match the most recently defined top-level |
7931 | // self-hosted function. |
7932 | MOZ_ASSERT(prevSelfHostedTopLevelFunction->explicitName() == targetName,do { static_assert( mozilla::detail::AssertionConditionType< decltype(prevSelfHostedTopLevelFunction->explicitName() == targetName)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(prevSelfHostedTopLevelFunction-> explicitName() == targetName))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("prevSelfHostedTopLevelFunction->explicitName() == targetName" " (" "selfhost decorator must immediately follow target function" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7933); AnnotateMozCrashReason("MOZ_ASSERT" "(" "prevSelfHostedTopLevelFunction->explicitName() == targetName" ") (" "selfhost decorator must immediately follow target function" ")"); do { *((volatile int*)__null) = 7933; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
7933 | "selfhost decorator must immediately follow target function")do { static_assert( mozilla::detail::AssertionConditionType< decltype(prevSelfHostedTopLevelFunction->explicitName() == targetName)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(prevSelfHostedTopLevelFunction-> explicitName() == targetName))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("prevSelfHostedTopLevelFunction->explicitName() == targetName" " (" "selfhost decorator must immediately follow target function" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7933); AnnotateMozCrashReason("MOZ_ASSERT" "(" "prevSelfHostedTopLevelFunction->explicitName() == targetName" ") (" "selfhost decorator must immediately follow target function" ")"); do { *((volatile int*)__null) = 7933; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7934 | } |
7935 | #endif |
7936 | |
7937 | bool BytecodeEmitter::emitSelfHostedSetIsInlinableLargeFunction( |
7938 | CallNode* callNode) { |
7939 | #ifdef DEBUG1 |
7940 | ListNode* argsList = callNode->args(); |
7941 | |
7942 | MOZ_ASSERT(argsList->count() == 1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(argsList->count() == 1)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(argsList->count() == 1))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 1" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7942); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 1" ")"); do { *((volatile int*)__null) = 7942; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7943 | |
7944 | assertSelfHostedExpectedTopLevel(argsList->head()); |
7945 | #endif |
7946 | |
7947 | MOZ_ASSERT(prevSelfHostedTopLevelFunction->isInitialCompilation)do { static_assert( mozilla::detail::AssertionConditionType< decltype(prevSelfHostedTopLevelFunction->isInitialCompilation )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(prevSelfHostedTopLevelFunction->isInitialCompilation ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "prevSelfHostedTopLevelFunction->isInitialCompilation", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7947); AnnotateMozCrashReason("MOZ_ASSERT" "(" "prevSelfHostedTopLevelFunction->isInitialCompilation" ")"); do { *((volatile int*)__null) = 7947; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7948 | prevSelfHostedTopLevelFunction->setIsInlinableLargeFunction(); |
7949 | |
7950 | // This is still a call node, so we must generate a stack value. |
7951 | return emit1(JSOp::Undefined); |
7952 | } |
7953 | |
7954 | bool BytecodeEmitter::emitSelfHostedSetCanonicalName(CallNode* callNode) { |
7955 | ListNode* argsList = callNode->args(); |
7956 | |
7957 | MOZ_ASSERT(argsList->count() == 2)do { static_assert( mozilla::detail::AssertionConditionType< decltype(argsList->count() == 2)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(argsList->count() == 2))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 2" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7957); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2" ")"); do { *((volatile int*)__null) = 7957; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7958 | |
7959 | #ifdef DEBUG1 |
7960 | assertSelfHostedExpectedTopLevel(argsList->head()); |
7961 | #endif |
7962 | |
7963 | ParseNode* nameNode = argsList->last(); |
7964 | MOZ_ASSERT(nameNode->isKind(ParseNodeKind::StringExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(nameNode->isKind(ParseNodeKind::StringExpr))>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(nameNode->isKind(ParseNodeKind::StringExpr)))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("nameNode->isKind(ParseNodeKind::StringExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7964); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nameNode->isKind(ParseNodeKind::StringExpr)" ")"); do { *((volatile int*)__null) = 7964; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7965 | TaggedParserAtomIndex specName = nameNode->as<NameNode>().atom(); |
7966 | // Canonical name must be atomized. |
7967 | compilationState.parserAtoms.markUsedByStencil(specName, |
7968 | ParserAtom::Atomize::Yes); |
7969 | |
7970 | // Store the canonical name for instantiation. |
7971 | prevSelfHostedTopLevelFunction->functionStencil().setSelfHostedCanonicalName( |
7972 | specName); |
7973 | |
7974 | return emit1(JSOp::Undefined); |
7975 | } |
7976 | |
7977 | #ifdef DEBUG1 |
7978 | void BytecodeEmitter::assertSelfHostedUnsafeGetReservedSlot( |
7979 | ListNode* argsList) { |
7980 | MOZ_ASSERT(argsList->count() == 2)do { static_assert( mozilla::detail::AssertionConditionType< decltype(argsList->count() == 2)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(argsList->count() == 2))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 2" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7980); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 2" ")"); do { *((volatile int*)__null) = 7980; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7981 | |
7982 | ParseNode* objNode = argsList->head(); |
7983 | ParseNode* slotNode = objNode->pn_next; |
7984 | |
7985 | // Ensure that the slot argument is fixed, this is required by the JITs. |
7986 | MOZ_ASSERT(slotNode->isKind(ParseNodeKind::NumberExpr),do { static_assert( mozilla::detail::AssertionConditionType< decltype(slotNode->isKind(ParseNodeKind::NumberExpr))>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(slotNode->isKind(ParseNodeKind::NumberExpr)))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("slotNode->isKind(ParseNodeKind::NumberExpr)" " (" "slot argument must be a constant" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7987); AnnotateMozCrashReason("MOZ_ASSERT" "(" "slotNode->isKind(ParseNodeKind::NumberExpr)" ") (" "slot argument must be a constant" ")"); do { *((volatile int*)__null) = 7987; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
7987 | "slot argument must be a constant")do { static_assert( mozilla::detail::AssertionConditionType< decltype(slotNode->isKind(ParseNodeKind::NumberExpr))>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(slotNode->isKind(ParseNodeKind::NumberExpr)))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("slotNode->isKind(ParseNodeKind::NumberExpr)" " (" "slot argument must be a constant" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7987); AnnotateMozCrashReason("MOZ_ASSERT" "(" "slotNode->isKind(ParseNodeKind::NumberExpr)" ") (" "slot argument must be a constant" ")"); do { *((volatile int*)__null) = 7987; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
7988 | } |
7989 | |
7990 | void BytecodeEmitter::assertSelfHostedUnsafeSetReservedSlot( |
7991 | ListNode* argsList) { |
7992 | MOZ_ASSERT(argsList->count() == 3)do { static_assert( mozilla::detail::AssertionConditionType< decltype(argsList->count() == 3)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(argsList->count() == 3))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("argsList->count() == 3" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7992); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsList->count() == 3" ")"); do { *((volatile int*)__null) = 7992; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
7993 | |
7994 | ParseNode* objNode = argsList->head(); |
7995 | ParseNode* slotNode = objNode->pn_next; |
7996 | |
7997 | // Ensure that the slot argument is fixed, this is required by the JITs. |
7998 | MOZ_ASSERT(slotNode->isKind(ParseNodeKind::NumberExpr),do { static_assert( mozilla::detail::AssertionConditionType< decltype(slotNode->isKind(ParseNodeKind::NumberExpr))>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(slotNode->isKind(ParseNodeKind::NumberExpr)))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("slotNode->isKind(ParseNodeKind::NumberExpr)" " (" "slot argument must be a constant" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7999); AnnotateMozCrashReason("MOZ_ASSERT" "(" "slotNode->isKind(ParseNodeKind::NumberExpr)" ") (" "slot argument must be a constant" ")"); do { *((volatile int*)__null) = 7999; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
7999 | "slot argument must be a constant")do { static_assert( mozilla::detail::AssertionConditionType< decltype(slotNode->isKind(ParseNodeKind::NumberExpr))>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(slotNode->isKind(ParseNodeKind::NumberExpr)))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("slotNode->isKind(ParseNodeKind::NumberExpr)" " (" "slot argument must be a constant" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 7999); AnnotateMozCrashReason("MOZ_ASSERT" "(" "slotNode->isKind(ParseNodeKind::NumberExpr)" ") (" "slot argument must be a constant" ")"); do { *((volatile int*)__null) = 7999; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
8000 | } |
8001 | #endif |
8002 | |
8003 | /* A version of emitCalleeAndThis for the optional cases: |
8004 | * * a?.() |
8005 | * * a?.b() |
8006 | * * a?.["b"]() |
8007 | * * (a?.b)() |
8008 | * * a?.#b() |
8009 | * |
8010 | * See emitCallOrNew and emitOptionalCall for more context. |
8011 | */ |
8012 | bool BytecodeEmitter::emitOptionalCalleeAndThis(ParseNode* callee, |
8013 | CallNode* call, |
8014 | CallOrNewEmitter& cone, |
8015 | OptionalEmitter& oe) { |
8016 | AutoCheckRecursionLimit recursion(fc); |
8017 | if (!recursion.check(fc)) { |
8018 | return false; |
8019 | } |
8020 | |
8021 | switch (ParseNodeKind kind = callee->getKind()) { |
8022 | case ParseNodeKind::Name: { |
8023 | auto name = callee->as<NameNode>().name(); |
8024 | if (!cone.emitNameCallee(name)) { |
8025 | // [stack] CALLEE THIS |
8026 | return false; |
8027 | } |
8028 | break; |
8029 | } |
8030 | |
8031 | case ParseNodeKind::OptionalDotExpr: { |
8032 | MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting)do { static_assert( mozilla::detail::AssertionConditionType< decltype(emitterMode != BytecodeEmitter::SelfHosting)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(emitterMode != BytecodeEmitter::SelfHosting))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("emitterMode != BytecodeEmitter::SelfHosting" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8032); AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode != BytecodeEmitter::SelfHosting" ")"); do { *((volatile int*)__null) = 8032; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8033 | OptionalPropertyAccess* prop = &callee->as<OptionalPropertyAccess>(); |
8034 | bool isSuper = false; |
8035 | |
8036 | PropOpEmitter& poe = cone.prepareForPropCallee(isSuper); |
8037 | if (!emitOptionalDotExpression(prop, poe, isSuper, oe)) { |
8038 | // [stack] CALLEE THIS |
8039 | return false; |
8040 | } |
8041 | break; |
8042 | } |
8043 | case ParseNodeKind::ArgumentsLength: |
8044 | case ParseNodeKind::DotExpr: { |
8045 | MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting)do { static_assert( mozilla::detail::AssertionConditionType< decltype(emitterMode != BytecodeEmitter::SelfHosting)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(emitterMode != BytecodeEmitter::SelfHosting))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("emitterMode != BytecodeEmitter::SelfHosting" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8045); AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode != BytecodeEmitter::SelfHosting" ")"); do { *((volatile int*)__null) = 8045; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8046 | PropertyAccess* prop = &callee->as<PropertyAccess>(); |
8047 | bool isSuper = prop->isSuper(); |
8048 | |
8049 | PropOpEmitter& poe = cone.prepareForPropCallee(isSuper); |
8050 | if (!emitOptionalDotExpression(prop, poe, isSuper, oe)) { |
8051 | // [stack] CALLEE THIS |
8052 | return false; |
8053 | } |
8054 | break; |
8055 | } |
8056 | |
8057 | case ParseNodeKind::OptionalElemExpr: { |
8058 | OptionalPropertyByValue* elem = &callee->as<OptionalPropertyByValue>(); |
8059 | bool isSuper = false; |
8060 | MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!elem->key().isKind(ParseNodeKind::PrivateName))> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!elem->key().isKind(ParseNodeKind::PrivateName))) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!elem->key().isKind(ParseNodeKind::PrivateName)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8060); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)" ")"); do { *((volatile int*)__null) = 8060; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8061 | ElemOpEmitter& eoe = cone.prepareForElemCallee(isSuper); |
8062 | if (!emitOptionalElemExpression(elem, eoe, isSuper, oe)) { |
8063 | // [stack] CALLEE THIS |
8064 | return false; |
8065 | } |
8066 | break; |
8067 | } |
8068 | case ParseNodeKind::ElemExpr: { |
8069 | PropertyByValue* elem = &callee->as<PropertyByValue>(); |
8070 | bool isSuper = elem->isSuper(); |
8071 | MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!elem->key().isKind(ParseNodeKind::PrivateName))> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!elem->key().isKind(ParseNodeKind::PrivateName))) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!elem->key().isKind(ParseNodeKind::PrivateName)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8071); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)" ")"); do { *((volatile int*)__null) = 8071; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8072 | ElemOpEmitter& eoe = cone.prepareForElemCallee(isSuper); |
8073 | if (!emitOptionalElemExpression(elem, eoe, isSuper, oe)) { |
8074 | // [stack] CALLEE THIS |
8075 | return false; |
8076 | } |
8077 | break; |
8078 | } |
8079 | |
8080 | case ParseNodeKind::PrivateMemberExpr: |
8081 | case ParseNodeKind::OptionalPrivateMemberExpr: { |
8082 | PrivateMemberAccessBase* privateExpr = |
8083 | &callee->as<PrivateMemberAccessBase>(); |
8084 | PrivateOpEmitter& xoe = |
8085 | cone.prepareForPrivateCallee(privateExpr->privateName().name()); |
8086 | if (!emitOptionalPrivateExpression(privateExpr, xoe, oe)) { |
8087 | // [stack] CALLEE THIS |
8088 | return false; |
8089 | } |
8090 | break; |
8091 | } |
8092 | |
8093 | case ParseNodeKind::Function: |
8094 | if (!cone.prepareForFunctionCallee()) { |
8095 | return false; |
8096 | } |
8097 | if (!emitOptionalTree(callee, oe)) { |
8098 | // [stack] CALLEE |
8099 | return false; |
8100 | } |
8101 | break; |
8102 | |
8103 | case ParseNodeKind::OptionalChain: { |
8104 | return emitCalleeAndThisForOptionalChain(&callee->as<UnaryNode>(), call, |
8105 | cone); |
8106 | } |
8107 | |
8108 | default: |
8109 | MOZ_RELEASE_ASSERT(kind != ParseNodeKind::SuperBase)do { static_assert( mozilla::detail::AssertionConditionType< decltype(kind != ParseNodeKind::SuperBase)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(kind != ParseNodeKind::SuperBase ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "kind != ParseNodeKind::SuperBase", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8109); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "kind != ParseNodeKind::SuperBase" ")"); do { *((volatile int*)__null) = 8109; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8110 | |
8111 | if (!cone.prepareForOtherCallee()) { |
8112 | return false; |
8113 | } |
8114 | if (!emitOptionalTree(callee, oe)) { |
8115 | // [stack] CALLEE |
8116 | return false; |
8117 | } |
8118 | break; |
8119 | } |
8120 | |
8121 | if (!cone.emitThis()) { |
8122 | // [stack] CALLEE THIS |
8123 | return false; |
8124 | } |
8125 | |
8126 | return true; |
8127 | } |
8128 | |
8129 | bool BytecodeEmitter::emitCalleeAndThis(ParseNode* callee, CallNode* maybeCall, |
8130 | CallOrNewEmitter& cone) { |
8131 | MOZ_ASSERT_IF(maybeCall, maybeCall->callee() == callee)do { if (maybeCall) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(maybeCall->callee() == callee)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(maybeCall->callee() == callee ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "maybeCall->callee() == callee", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8131); AnnotateMozCrashReason("MOZ_ASSERT" "(" "maybeCall->callee() == callee" ")"); do { *((volatile int*)__null) = 8131; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
8132 | |
8133 | switch (callee->getKind()) { |
8134 | case ParseNodeKind::Name: { |
8135 | auto name = callee->as<NameNode>().name(); |
8136 | if (!cone.emitNameCallee(name)) { |
8137 | // [stack] CALLEE THIS? |
8138 | return false; |
8139 | } |
8140 | break; |
8141 | } |
8142 | case ParseNodeKind::ArgumentsLength: |
8143 | case ParseNodeKind::DotExpr: { |
8144 | MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting)do { static_assert( mozilla::detail::AssertionConditionType< decltype(emitterMode != BytecodeEmitter::SelfHosting)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(emitterMode != BytecodeEmitter::SelfHosting))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("emitterMode != BytecodeEmitter::SelfHosting" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8144); AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode != BytecodeEmitter::SelfHosting" ")"); do { *((volatile int*)__null) = 8144; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8145 | PropertyAccess* prop = &callee->as<PropertyAccess>(); |
8146 | bool isSuper = prop->isSuper(); |
8147 | |
8148 | PropOpEmitter& poe = cone.prepareForPropCallee(isSuper); |
8149 | if (!poe.prepareForObj()) { |
8150 | return false; |
8151 | } |
8152 | if (isSuper) { |
8153 | UnaryNode* base = &prop->expression().as<UnaryNode>(); |
8154 | if (!emitGetThisForSuperBase(base)) { |
8155 | // [stack] THIS |
8156 | return false; |
8157 | } |
8158 | } else { |
8159 | if (!emitPropLHS(prop)) { |
8160 | // [stack] OBJ |
8161 | return false; |
8162 | } |
8163 | } |
8164 | if (!poe.emitGet(prop->key().atom())) { |
8165 | // [stack] CALLEE THIS? |
8166 | return false; |
8167 | } |
8168 | |
8169 | break; |
8170 | } |
8171 | case ParseNodeKind::ElemExpr: { |
8172 | MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting)do { static_assert( mozilla::detail::AssertionConditionType< decltype(emitterMode != BytecodeEmitter::SelfHosting)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(emitterMode != BytecodeEmitter::SelfHosting))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("emitterMode != BytecodeEmitter::SelfHosting" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8172); AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode != BytecodeEmitter::SelfHosting" ")"); do { *((volatile int*)__null) = 8172; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8173 | PropertyByValue* elem = &callee->as<PropertyByValue>(); |
8174 | bool isSuper = elem->isSuper(); |
8175 | MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!elem->key().isKind(ParseNodeKind::PrivateName))> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!elem->key().isKind(ParseNodeKind::PrivateName))) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!elem->key().isKind(ParseNodeKind::PrivateName)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8175); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)" ")"); do { *((volatile int*)__null) = 8175; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8176 | ElemOpEmitter& eoe = cone.prepareForElemCallee(isSuper); |
8177 | if (!emitElemObjAndKey(elem, isSuper, eoe)) { |
8178 | // [stack] # if Super |
8179 | // [stack] THIS? THIS KEY |
8180 | // [stack] # otherwise |
8181 | // [stack] OBJ? OBJ KEY |
8182 | return false; |
8183 | } |
8184 | if (!eoe.emitGet()) { |
8185 | // [stack] CALLEE THIS? |
8186 | return false; |
8187 | } |
8188 | |
8189 | break; |
8190 | } |
8191 | case ParseNodeKind::PrivateMemberExpr: { |
8192 | MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting)do { static_assert( mozilla::detail::AssertionConditionType< decltype(emitterMode != BytecodeEmitter::SelfHosting)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(emitterMode != BytecodeEmitter::SelfHosting))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("emitterMode != BytecodeEmitter::SelfHosting" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8192); AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode != BytecodeEmitter::SelfHosting" ")"); do { *((volatile int*)__null) = 8192; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8193 | PrivateMemberAccessBase* privateExpr = |
8194 | &callee->as<PrivateMemberAccessBase>(); |
8195 | PrivateOpEmitter& xoe = |
8196 | cone.prepareForPrivateCallee(privateExpr->privateName().name()); |
8197 | if (!emitTree(&privateExpr->expression())) { |
8198 | // [stack] OBJ |
8199 | return false; |
8200 | } |
8201 | if (!xoe.emitReference()) { |
8202 | // [stack] OBJ NAME |
8203 | return false; |
8204 | } |
8205 | if (!xoe.emitGetForCallOrNew()) { |
8206 | // [stack] CALLEE THIS |
8207 | return false; |
8208 | } |
8209 | |
8210 | break; |
8211 | } |
8212 | case ParseNodeKind::Function: |
8213 | if (!cone.prepareForFunctionCallee()) { |
8214 | return false; |
8215 | } |
8216 | if (!emitTree(callee)) { |
8217 | // [stack] CALLEE |
8218 | return false; |
8219 | } |
8220 | break; |
8221 | case ParseNodeKind::SuperBase: |
8222 | MOZ_ASSERT(maybeCall)do { static_assert( mozilla::detail::AssertionConditionType< decltype(maybeCall)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(maybeCall))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("maybeCall", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8222); AnnotateMozCrashReason("MOZ_ASSERT" "(" "maybeCall" ")" ); do { *((volatile int*)__null) = 8222; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8223 | MOZ_ASSERT(maybeCall->isKind(ParseNodeKind::SuperCallExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(maybeCall->isKind(ParseNodeKind::SuperCallExpr))> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(maybeCall->isKind(ParseNodeKind::SuperCallExpr))) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("maybeCall->isKind(ParseNodeKind::SuperCallExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8223); AnnotateMozCrashReason("MOZ_ASSERT" "(" "maybeCall->isKind(ParseNodeKind::SuperCallExpr)" ")"); do { *((volatile int*)__null) = 8223; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8224 | MOZ_ASSERT(callee->isKind(ParseNodeKind::SuperBase))do { static_assert( mozilla::detail::AssertionConditionType< decltype(callee->isKind(ParseNodeKind::SuperBase))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(callee->isKind(ParseNodeKind::SuperBase)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("callee->isKind(ParseNodeKind::SuperBase)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8224); AnnotateMozCrashReason("MOZ_ASSERT" "(" "callee->isKind(ParseNodeKind::SuperBase)" ")"); do { *((volatile int*)__null) = 8224; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8225 | if (!cone.emitSuperCallee()) { |
8226 | // [stack] CALLEE IsConstructing |
8227 | return false; |
8228 | } |
8229 | break; |
8230 | case ParseNodeKind::OptionalChain: { |
8231 | MOZ_ASSERT(maybeCall)do { static_assert( mozilla::detail::AssertionConditionType< decltype(maybeCall)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(maybeCall))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("maybeCall", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8231); AnnotateMozCrashReason("MOZ_ASSERT" "(" "maybeCall" ")" ); do { *((volatile int*)__null) = 8231; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8232 | return emitCalleeAndThisForOptionalChain(&callee->as<UnaryNode>(), |
8233 | maybeCall, cone); |
8234 | } |
8235 | default: |
8236 | if (!cone.prepareForOtherCallee()) { |
8237 | return false; |
8238 | } |
8239 | if (!emitTree(callee)) { |
8240 | return false; |
8241 | } |
8242 | break; |
8243 | } |
8244 | |
8245 | if (!cone.emitThis()) { |
8246 | // [stack] CALLEE THIS |
8247 | return false; |
8248 | } |
8249 | |
8250 | return true; |
8251 | } |
8252 | |
8253 | ParseNode* BytecodeEmitter::getCoordNode(ParseNode* callNode, |
8254 | ParseNode* calleeNode, JSOp op, |
8255 | ListNode* argsList) { |
8256 | ParseNode* coordNode = callNode; |
8257 | if (op == JSOp::Call || op == JSOp::SpreadCall) { |
8258 | // Default to using the location of the `(` itself. |
8259 | // obj[expr]() // expression |
8260 | // ^ // column coord |
8261 | coordNode = argsList; |
8262 | |
8263 | switch (calleeNode->getKind()) { |
8264 | case ParseNodeKind::ArgumentsLength: |
8265 | case ParseNodeKind::DotExpr: |
8266 | // Use the position of a property access identifier. |
8267 | // |
8268 | // obj().aprop() // expression |
8269 | // ^ // column coord |
8270 | // |
8271 | // Note: Because of the constant folding logic in FoldElement, |
8272 | // this case also applies for constant string properties. |
8273 | // |
8274 | // obj()['aprop']() // expression |
8275 | // ^ // column coord |
8276 | coordNode = &calleeNode->as<PropertyAccess>().key(); |
8277 | break; |
8278 | case ParseNodeKind::Name: { |
8279 | // Use the start of callee name unless it is at a separator |
8280 | // or has no args. |
8281 | // |
8282 | // 2 + obj() // expression |
8283 | // ^ // column coord |
8284 | // |
8285 | if (argsList->empty() || |
8286 | !bytecodeSection().atSeparator(calleeNode->pn_pos.begin)) { |
8287 | // Use the start of callee names. |
8288 | coordNode = calleeNode; |
8289 | } |
8290 | break; |
8291 | } |
8292 | |
8293 | default: |
8294 | break; |
8295 | } |
8296 | } |
8297 | return coordNode; |
8298 | } |
8299 | |
8300 | bool BytecodeEmitter::emitArguments(ListNode* argsList, bool isCall, |
8301 | bool isSpread, CallOrNewEmitter& cone) { |
8302 | uint32_t argc = argsList->count(); |
8303 | if (argc >= ARGC_LIMIT) { |
8304 | reportError(argsList, |
8305 | isCall ? JSMSG_TOO_MANY_FUN_ARGS : JSMSG_TOO_MANY_CON_ARGS); |
8306 | return false; |
8307 | } |
8308 | if (!isSpread) { |
8309 | if (!cone.prepareForNonSpreadArguments()) { |
8310 | // [stack] CALLEE THIS |
8311 | return false; |
8312 | } |
8313 | for (ParseNode* arg : argsList->contents()) { |
8314 | if (!updateSourceCoordNotesIfNonLiteral(arg)) { |
8315 | return false; |
8316 | } |
8317 | if (!emitTree(arg)) { |
8318 | // [stack] CALLEE THIS ARG* |
8319 | return false; |
8320 | } |
8321 | } |
8322 | } else if (cone.wantSpreadOperand()) { |
8323 | auto* spreadNode = &argsList->head()->as<UnaryNode>(); |
8324 | if (!updateSourceCoordNotesIfNonLiteral(spreadNode->kid())) { |
8325 | return false; |
8326 | } |
8327 | if (!emitTree(spreadNode->kid())) { |
8328 | // [stack] CALLEE THIS ARG0 |
8329 | return false; |
8330 | } |
8331 | |
8332 | if (!cone.emitSpreadArgumentsTest()) { |
8333 | // [stack] CALLEE THIS ARG0 |
8334 | return false; |
8335 | } |
8336 | |
8337 | if (cone.wantSpreadIteration()) { |
8338 | if (!emitSpreadIntoArray(spreadNode)) { |
8339 | // [stack] CALLEE THIS ARR |
8340 | return false; |
8341 | } |
8342 | } |
8343 | |
8344 | if (!cone.emitSpreadArgumentsTestEnd()) { |
8345 | // [stack] CALLEE THIS ARR |
8346 | return false; |
8347 | } |
8348 | } else { |
8349 | if (!cone.prepareForSpreadArguments()) { |
8350 | // [stack] CALLEE THIS |
8351 | return false; |
8352 | } |
8353 | if (!emitArray(argsList)) { |
8354 | // [stack] CALLEE THIS ARR |
8355 | return false; |
8356 | } |
8357 | } |
8358 | |
8359 | return true; |
8360 | } |
8361 | |
8362 | bool BytecodeEmitter::emitOptionalCall(CallNode* callNode, OptionalEmitter& oe, |
8363 | ValueUsage valueUsage) { |
8364 | /* |
8365 | * A modified version of emitCallOrNew that handles optional calls. |
8366 | * |
8367 | * These include the following: |
8368 | * a?.() |
8369 | * a.b?.() |
8370 | * a.["b"]?.() |
8371 | * (a?.b)?.() |
8372 | * |
8373 | * See CallOrNewEmitter for more context. |
8374 | */ |
8375 | ParseNode* calleeNode = callNode->callee(); |
8376 | ListNode* argsList = callNode->args(); |
8377 | bool isSpread = IsSpreadOp(callNode->callOp()); |
8378 | JSOp op = callNode->callOp(); |
8379 | uint32_t argc = argsList->count(); |
8380 | bool isOptimizableSpread = isSpread && argc == 1; |
8381 | |
8382 | CallOrNewEmitter cone(this, op, |
8383 | isOptimizableSpread |
8384 | ? CallOrNewEmitter::ArgumentsKind::SingleSpread |
8385 | : CallOrNewEmitter::ArgumentsKind::Other, |
8386 | valueUsage); |
8387 | |
8388 | ParseNode* coordNode = getCoordNode(callNode, calleeNode, op, argsList); |
8389 | |
8390 | if (!emitOptionalCalleeAndThis(calleeNode, callNode, cone, oe)) { |
8391 | // [stack] CALLEE THIS |
8392 | return false; |
8393 | } |
8394 | |
8395 | if (callNode->isKind(ParseNodeKind::OptionalCallExpr)) { |
8396 | if (!oe.emitJumpShortCircuitForCall()) { |
8397 | // [stack] CALLEE THIS |
8398 | return false; |
8399 | } |
8400 | } |
8401 | |
8402 | if (!emitArguments(argsList, /* isCall = */ true, isSpread, cone)) { |
8403 | // [stack] CALLEE THIS ARGS... |
8404 | return false; |
8405 | } |
8406 | |
8407 | if (!cone.emitEnd(argc, coordNode->pn_pos.begin)) { |
8408 | // [stack] RVAL |
8409 | return false; |
8410 | } |
8411 | |
8412 | return true; |
8413 | } |
8414 | |
8415 | bool BytecodeEmitter::emitCallOrNew(CallNode* callNode, ValueUsage valueUsage) { |
8416 | /* |
8417 | * Emit callable invocation or operator new (constructor call) code. |
8418 | * First, emit code for the left operand to evaluate the callable or |
8419 | * constructable object expression. |
8420 | * |
8421 | * Then (or in a call case that has no explicit reference-base |
8422 | * object) we emit JSOp::Undefined to produce the undefined |this| |
8423 | * value required for calls (which non-strict mode functions |
8424 | * will box into the global object). |
8425 | */ |
8426 | bool isCall = callNode->isKind(ParseNodeKind::CallExpr) || |
8427 | callNode->isKind(ParseNodeKind::TaggedTemplateExpr); |
8428 | ParseNode* calleeNode = callNode->callee(); |
8429 | ListNode* argsList = callNode->args(); |
8430 | JSOp op = callNode->callOp(); |
8431 | |
8432 | if (calleeNode->isKind(ParseNodeKind::Name) && |
8433 | emitterMode == BytecodeEmitter::SelfHosting && op == JSOp::Call) { |
8434 | // Calls to "forceInterpreter", "callFunction", |
8435 | // "callContentFunction", or "resumeGenerator" in self-hosted |
8436 | // code generate inline bytecode. |
8437 | // |
8438 | // NOTE: The list of special instruction names has to be kept in sync with |
8439 | // "js/src/builtin/.eslintrc.js". |
8440 | auto calleeName = calleeNode->as<NameNode>().name(); |
8441 | if (calleeName == TaggedParserAtomIndex::WellKnown::callFunction()) { |
8442 | return emitSelfHostedCallFunction(callNode, JSOp::Call); |
8443 | } |
8444 | if (calleeName == TaggedParserAtomIndex::WellKnown::callContentFunction()) { |
8445 | return emitSelfHostedCallFunction(callNode, JSOp::CallContent); |
8446 | } |
8447 | if (calleeName == |
8448 | TaggedParserAtomIndex::WellKnown::constructContentFunction()) { |
8449 | return emitSelfHostedCallFunction(callNode, JSOp::NewContent); |
8450 | } |
8451 | if (calleeName == TaggedParserAtomIndex::WellKnown::resumeGenerator()) { |
8452 | return emitSelfHostedResumeGenerator(callNode); |
8453 | } |
8454 | if (calleeName == TaggedParserAtomIndex::WellKnown::forceInterpreter()) { |
8455 | return emitSelfHostedForceInterpreter(); |
8456 | } |
8457 | if (calleeName == TaggedParserAtomIndex::WellKnown::allowContentIter()) { |
8458 | return emitSelfHostedAllowContentIter(callNode); |
8459 | } |
8460 | if (calleeName == |
8461 | TaggedParserAtomIndex::WellKnown::allowContentIterWith()) { |
8462 | return emitSelfHostedAllowContentIterWith(callNode); |
8463 | } |
8464 | if (calleeName == |
8465 | TaggedParserAtomIndex::WellKnown::allowContentIterWithNext()) { |
8466 | return emitSelfHostedAllowContentIterWithNext(callNode); |
8467 | } |
8468 | if (calleeName == TaggedParserAtomIndex::WellKnown::DefineDataProperty() && |
8469 | argsList->count() == 3) { |
8470 | return emitSelfHostedDefineDataProperty(callNode); |
8471 | } |
8472 | if (calleeName == TaggedParserAtomIndex::WellKnown::hasOwn()) { |
8473 | return emitSelfHostedHasOwn(callNode); |
8474 | } |
8475 | if (calleeName == TaggedParserAtomIndex::WellKnown::getPropertySuper()) { |
8476 | return emitSelfHostedGetPropertySuper(callNode); |
8477 | } |
8478 | if (calleeName == TaggedParserAtomIndex::WellKnown::ToNumeric()) { |
8479 | return emitSelfHostedToNumeric(callNode); |
8480 | } |
8481 | if (calleeName == TaggedParserAtomIndex::WellKnown::ToString()) { |
8482 | return emitSelfHostedToString(callNode); |
8483 | } |
8484 | if (calleeName == |
8485 | TaggedParserAtomIndex::WellKnown::GetBuiltinConstructor()) { |
8486 | return emitSelfHostedGetBuiltinConstructor(callNode); |
8487 | } |
8488 | if (calleeName == TaggedParserAtomIndex::WellKnown::GetBuiltinPrototype()) { |
8489 | return emitSelfHostedGetBuiltinPrototype(callNode); |
8490 | } |
8491 | if (calleeName == TaggedParserAtomIndex::WellKnown::GetBuiltinSymbol()) { |
8492 | return emitSelfHostedGetBuiltinSymbol(callNode); |
8493 | } |
8494 | if (calleeName == TaggedParserAtomIndex::WellKnown::ArgumentsLength()) { |
8495 | return emitSelfHostedArgumentsLength(callNode); |
8496 | } |
8497 | if (calleeName == TaggedParserAtomIndex::WellKnown::GetArgument()) { |
8498 | return emitSelfHostedGetArgument(callNode); |
8499 | } |
8500 | if (calleeName == |
8501 | TaggedParserAtomIndex::WellKnown::SetIsInlinableLargeFunction()) { |
8502 | return emitSelfHostedSetIsInlinableLargeFunction(callNode); |
8503 | } |
8504 | if (calleeName == TaggedParserAtomIndex::WellKnown::SetCanonicalName()) { |
8505 | return emitSelfHostedSetCanonicalName(callNode); |
8506 | } |
8507 | if (calleeName == TaggedParserAtomIndex::WellKnown::IsNullOrUndefined()) { |
8508 | return emitSelfHostedIsNullOrUndefined(callNode); |
8509 | } |
8510 | if (calleeName == TaggedParserAtomIndex::WellKnown::IteratorClose()) { |
8511 | return emitSelfHostedIteratorClose(callNode); |
8512 | } |
8513 | #ifdef DEBUG1 |
8514 | if (calleeName == |
8515 | TaggedParserAtomIndex::WellKnown::UnsafeGetReservedSlot() || |
8516 | calleeName == TaggedParserAtomIndex::WellKnown:: |
8517 | UnsafeGetObjectFromReservedSlot() || |
8518 | calleeName == TaggedParserAtomIndex::WellKnown:: |
8519 | UnsafeGetInt32FromReservedSlot() || |
8520 | calleeName == TaggedParserAtomIndex::WellKnown:: |
8521 | UnsafeGetStringFromReservedSlot()) { |
8522 | // Make sure that this call is correct, but don't emit any special code. |
8523 | assertSelfHostedUnsafeGetReservedSlot(argsList); |
8524 | } |
8525 | if (calleeName == |
8526 | TaggedParserAtomIndex::WellKnown::UnsafeSetReservedSlot()) { |
8527 | // Make sure that this call is correct, but don't emit any special code. |
8528 | assertSelfHostedUnsafeSetReservedSlot(argsList); |
8529 | } |
8530 | #endif |
8531 | // Fall through |
8532 | } |
8533 | |
8534 | uint32_t argc = argsList->count(); |
8535 | bool isSpread = IsSpreadOp(op); |
8536 | bool isOptimizableSpread = isSpread && argc == 1; |
8537 | bool isDefaultDerivedClassConstructor = |
8538 | sc->isFunctionBox() && sc->asFunctionBox()->isDerivedClassConstructor() && |
8539 | sc->asFunctionBox()->isSyntheticFunction(); |
8540 | MOZ_ASSERT_IF(isDefaultDerivedClassConstructor, isOptimizableSpread)do { if (isDefaultDerivedClassConstructor) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(isOptimizableSpread )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(isOptimizableSpread))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("isOptimizableSpread", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8540); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isOptimizableSpread" ")"); do { *((volatile int*)__null) = 8540; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
8541 | CallOrNewEmitter cone( |
8542 | this, op, |
8543 | isOptimizableSpread |
8544 | ? isDefaultDerivedClassConstructor |
8545 | ? CallOrNewEmitter::ArgumentsKind::PassthroughRest |
8546 | : CallOrNewEmitter::ArgumentsKind::SingleSpread |
8547 | : CallOrNewEmitter::ArgumentsKind::Other, |
8548 | valueUsage); |
8549 | |
8550 | if (!emitCalleeAndThis(calleeNode, callNode, cone)) { |
8551 | // [stack] CALLEE THIS |
8552 | return false; |
8553 | } |
8554 | if (!emitArguments(argsList, isCall, isSpread, cone)) { |
8555 | // [stack] CALLEE THIS ARGS... |
8556 | return false; |
8557 | } |
8558 | |
8559 | // Push new.target for construct calls. |
8560 | if (IsConstructOp(op)) { |
8561 | if (op == JSOp::SuperCall || op == JSOp::SpreadSuperCall) { |
8562 | if (!emitNewTarget(callNode)) { |
8563 | // [stack] CALLEE THIS ARGS.. NEW.TARGET |
8564 | return false; |
8565 | } |
8566 | } else { |
8567 | // Repush the callee as new.target |
8568 | uint32_t effectiveArgc = isSpread ? 1 : argc; |
8569 | if (!emitDupAt(effectiveArgc + 1)) { |
8570 | // [stack] CALLEE THIS ARGS.. CALLEE |
8571 | return false; |
8572 | } |
8573 | } |
8574 | } |
8575 | |
8576 | ParseNode* coordNode = getCoordNode(callNode, calleeNode, op, argsList); |
8577 | |
8578 | if (!cone.emitEnd(argc, coordNode->pn_pos.begin)) { |
8579 | // [stack] RVAL |
8580 | return false; |
8581 | } |
8582 | |
8583 | return true; |
8584 | } |
8585 | |
8586 | // This list must be kept in the same order in several places: |
8587 | // - The binary operators in ParseNode.h , |
8588 | // - the binary operators in TokenKind.h |
8589 | // - the precedence list in Parser.cpp |
8590 | static const JSOp ParseNodeKindToJSOp[] = { |
8591 | // Some binary ops require special code generation (PrivateIn); |
8592 | // these should not use BinaryOpParseNodeKindToJSOp. This table fills those |
8593 | // slots with Nops to make the rest of the table lookup work. |
8594 | JSOp::Coalesce, JSOp::Or, JSOp::And, JSOp::BitOr, JSOp::BitXor, |
8595 | JSOp::BitAnd, JSOp::StrictEq, JSOp::Eq, JSOp::StrictNe, JSOp::Ne, |
8596 | JSOp::Lt, JSOp::Le, JSOp::Gt, JSOp::Ge, JSOp::Instanceof, |
8597 | JSOp::In, JSOp::Nop, JSOp::Lsh, JSOp::Rsh, JSOp::Ursh, |
8598 | JSOp::Add, JSOp::Sub, JSOp::Mul, JSOp::Div, JSOp::Mod, |
8599 | JSOp::Pow}; |
8600 | |
8601 | static inline JSOp BinaryOpParseNodeKindToJSOp(ParseNodeKind pnk) { |
8602 | MOZ_ASSERT(pnk >= ParseNodeKind::BinOpFirst)do { static_assert( mozilla::detail::AssertionConditionType< decltype(pnk >= ParseNodeKind::BinOpFirst)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pnk >= ParseNodeKind::BinOpFirst ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "pnk >= ParseNodeKind::BinOpFirst", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8602); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pnk >= ParseNodeKind::BinOpFirst" ")"); do { *((volatile int*)__null) = 8602; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8603 | MOZ_ASSERT(pnk <= ParseNodeKind::BinOpLast)do { static_assert( mozilla::detail::AssertionConditionType< decltype(pnk <= ParseNodeKind::BinOpLast)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(pnk <= ParseNodeKind::BinOpLast ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "pnk <= ParseNodeKind::BinOpLast", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8603); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pnk <= ParseNodeKind::BinOpLast" ")"); do { *((volatile int*)__null) = 8603; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8604 | int parseNodeFirst = size_t(ParseNodeKind::BinOpFirst); |
8605 | #ifdef DEBUG1 |
8606 | int jsopArraySize = std::size(ParseNodeKindToJSOp); |
8607 | int parseNodeKindListSize = |
8608 | size_t(ParseNodeKind::BinOpLast) - parseNodeFirst + 1; |
8609 | MOZ_ASSERT(jsopArraySize == parseNodeKindListSize)do { static_assert( mozilla::detail::AssertionConditionType< decltype(jsopArraySize == parseNodeKindListSize)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(jsopArraySize == parseNodeKindListSize))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("jsopArraySize == parseNodeKindListSize" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8609); AnnotateMozCrashReason("MOZ_ASSERT" "(" "jsopArraySize == parseNodeKindListSize" ")"); do { *((volatile int*)__null) = 8609; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8610 | // Ensure we don't use this to find an op for a parse node |
8611 | // requiring special emission rules. |
8612 | MOZ_ASSERT(ParseNodeKindToJSOp[size_t(pnk) - parseNodeFirst] != JSOp::Nop)do { static_assert( mozilla::detail::AssertionConditionType< decltype(ParseNodeKindToJSOp[size_t(pnk) - parseNodeFirst] != JSOp::Nop)>::isValid, "invalid assertion condition"); if ( (__builtin_expect(!!(!(!!(ParseNodeKindToJSOp[size_t(pnk) - parseNodeFirst ] != JSOp::Nop))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("ParseNodeKindToJSOp[size_t(pnk) - parseNodeFirst] != JSOp::Nop" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8612); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ParseNodeKindToJSOp[size_t(pnk) - parseNodeFirst] != JSOp::Nop" ")"); do { *((volatile int*)__null) = 8612; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8613 | #endif |
8614 | return ParseNodeKindToJSOp[size_t(pnk) - parseNodeFirst]; |
8615 | } |
8616 | |
8617 | bool BytecodeEmitter::emitRightAssociative(ListNode* node) { |
8618 | // ** is the only right-associative operator. |
8619 | MOZ_ASSERT(node->isKind(ParseNodeKind::PowExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(node->isKind(ParseNodeKind::PowExpr))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(node->isKind(ParseNodeKind::PowExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("node->isKind(ParseNodeKind::PowExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8619); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::PowExpr)" ")"); do { *((volatile int*)__null) = 8619; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8620 | |
8621 | // Right-associative operator chain. |
8622 | for (ParseNode* subexpr : node->contents()) { |
8623 | if (!updateSourceCoordNotesIfNonLiteral(subexpr)) { |
8624 | return false; |
8625 | } |
8626 | if (!emitTree(subexpr)) { |
8627 | return false; |
8628 | } |
8629 | } |
8630 | for (uint32_t i = 0; i < node->count() - 1; i++) { |
8631 | if (!emit1(JSOp::Pow)) { |
8632 | return false; |
8633 | } |
8634 | } |
8635 | return true; |
8636 | } |
8637 | |
8638 | bool BytecodeEmitter::emitLeftAssociative(ListNode* node) { |
8639 | // Left-associative operator chain. |
8640 | if (!emitTree(node->head())) { |
8641 | return false; |
8642 | } |
8643 | JSOp op = BinaryOpParseNodeKindToJSOp(node->getKind()); |
8644 | ParseNode* nextExpr = node->head()->pn_next; |
8645 | do { |
8646 | if (!updateSourceCoordNotesIfNonLiteral(nextExpr)) { |
8647 | return false; |
8648 | } |
8649 | if (!emitTree(nextExpr)) { |
8650 | return false; |
8651 | } |
8652 | if (!emit1(op)) { |
8653 | return false; |
8654 | } |
8655 | } while ((nextExpr = nextExpr->pn_next)); |
8656 | return true; |
8657 | } |
8658 | |
8659 | bool BytecodeEmitter::emitPrivateInExpr(ListNode* node) { |
8660 | MOZ_ASSERT(node->head()->isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType< decltype(node->head()->isKind(ParseNodeKind::PrivateName ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(node->head()->isKind(ParseNodeKind::PrivateName )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("node->head()->isKind(ParseNodeKind::PrivateName)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8660); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->head()->isKind(ParseNodeKind::PrivateName)" ")"); do { *((volatile int*)__null) = 8660; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8661 | |
8662 | NameNode& privateNameNode = node->head()->as<NameNode>(); |
8663 | TaggedParserAtomIndex privateName = privateNameNode.name(); |
8664 | |
8665 | PrivateOpEmitter xoe(this, PrivateOpEmitter::Kind::ErgonomicBrandCheck, |
8666 | privateName); |
8667 | |
8668 | ParseNode* valueNode = node->head()->pn_next; |
8669 | MOZ_ASSERT(valueNode->pn_next == nullptr)do { static_assert( mozilla::detail::AssertionConditionType< decltype(valueNode->pn_next == nullptr)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(valueNode->pn_next == nullptr ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "valueNode->pn_next == nullptr", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8669); AnnotateMozCrashReason("MOZ_ASSERT" "(" "valueNode->pn_next == nullptr" ")"); do { *((volatile int*)__null) = 8669; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8670 | |
8671 | if (!emitTree(valueNode)) { |
8672 | // [stack] OBJ |
8673 | return false; |
8674 | } |
8675 | |
8676 | if (!xoe.emitReference()) { |
8677 | // [stack] OBJ BRAND if private method |
8678 | // [stack] OBJ NAME if private field or accessor. |
8679 | return false; |
8680 | } |
8681 | |
8682 | if (!xoe.emitBrandCheck()) { |
8683 | // [stack] OBJ BRAND BOOL if private method |
8684 | // [stack] OBJ NAME BOOL if private field or accessor. |
8685 | return false; |
8686 | } |
8687 | |
8688 | if (!emitUnpickN(2)) { |
8689 | // [stack] BOOL OBJ BRAND if private method |
8690 | // [stack] BOOL OBJ NAME if private field or accessor. |
8691 | return false; |
8692 | } |
8693 | |
8694 | if (!emitPopN(2)) { |
8695 | // [stack] BOOL |
8696 | return false; |
8697 | } |
8698 | |
8699 | return true; |
8700 | } |
8701 | |
8702 | /* |
8703 | * Special `emitTree` for Optional Chaining case. |
8704 | * Examples of this are `emitOptionalChain`, `emitDeleteOptionalChain` and |
8705 | * `emitCalleeAndThisForOptionalChain`. |
8706 | */ |
8707 | bool BytecodeEmitter::emitOptionalTree( |
8708 | ParseNode* pn, OptionalEmitter& oe, |
8709 | ValueUsage valueUsage /* = ValueUsage::WantValue */) { |
8710 | AutoCheckRecursionLimit recursion(fc); |
8711 | if (!recursion.check(fc)) { |
8712 | return false; |
8713 | } |
8714 | ParseNodeKind kind = pn->getKind(); |
8715 | switch (kind) { |
8716 | case ParseNodeKind::OptionalDotExpr: { |
8717 | OptionalPropertyAccess* prop = &pn->as<OptionalPropertyAccess>(); |
8718 | bool isSuper = false; |
8719 | PropOpEmitter poe(this, PropOpEmitter::Kind::Get, |
8720 | PropOpEmitter::ObjKind::Other); |
8721 | if (!emitOptionalDotExpression(prop, poe, isSuper, oe)) { |
8722 | return false; |
8723 | } |
8724 | break; |
8725 | } |
8726 | case ParseNodeKind::ArgumentsLength: |
8727 | case ParseNodeKind::DotExpr: { |
8728 | PropertyAccess* prop = &pn->as<PropertyAccess>(); |
8729 | bool isSuper = prop->isSuper(); |
8730 | PropOpEmitter poe(this, PropOpEmitter::Kind::Get, |
8731 | isSuper ? PropOpEmitter::ObjKind::Super |
8732 | : PropOpEmitter::ObjKind::Other); |
8733 | if (!emitOptionalDotExpression(prop, poe, isSuper, oe)) { |
8734 | return false; |
8735 | } |
8736 | break; |
8737 | } |
8738 | |
8739 | case ParseNodeKind::OptionalElemExpr: { |
8740 | OptionalPropertyByValue* elem = &pn->as<OptionalPropertyByValue>(); |
8741 | bool isSuper = false; |
8742 | MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!elem->key().isKind(ParseNodeKind::PrivateName))> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!elem->key().isKind(ParseNodeKind::PrivateName))) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!elem->key().isKind(ParseNodeKind::PrivateName)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8742); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)" ")"); do { *((volatile int*)__null) = 8742; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8743 | ElemOpEmitter eoe(this, ElemOpEmitter::Kind::Get, |
8744 | ElemOpEmitter::ObjKind::Other); |
8745 | |
8746 | if (!emitOptionalElemExpression(elem, eoe, isSuper, oe)) { |
8747 | return false; |
8748 | } |
8749 | break; |
8750 | } |
8751 | case ParseNodeKind::ElemExpr: { |
8752 | PropertyByValue* elem = &pn->as<PropertyByValue>(); |
8753 | bool isSuper = elem->isSuper(); |
8754 | MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!elem->key().isKind(ParseNodeKind::PrivateName))> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!elem->key().isKind(ParseNodeKind::PrivateName))) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!elem->key().isKind(ParseNodeKind::PrivateName)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8754); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)" ")"); do { *((volatile int*)__null) = 8754; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8755 | ElemOpEmitter eoe(this, ElemOpEmitter::Kind::Get, |
8756 | isSuper ? ElemOpEmitter::ObjKind::Super |
8757 | : ElemOpEmitter::ObjKind::Other); |
8758 | |
8759 | if (!emitOptionalElemExpression(elem, eoe, isSuper, oe)) { |
8760 | return false; |
8761 | } |
8762 | break; |
8763 | } |
8764 | case ParseNodeKind::PrivateMemberExpr: |
8765 | case ParseNodeKind::OptionalPrivateMemberExpr: { |
8766 | PrivateMemberAccessBase* privateExpr = &pn->as<PrivateMemberAccessBase>(); |
8767 | PrivateOpEmitter xoe(this, PrivateOpEmitter::Kind::Get, |
8768 | privateExpr->privateName().name()); |
8769 | if (!emitOptionalPrivateExpression(privateExpr, xoe, oe)) { |
8770 | return false; |
8771 | } |
8772 | break; |
8773 | } |
8774 | case ParseNodeKind::CallExpr: |
8775 | case ParseNodeKind::OptionalCallExpr: |
8776 | if (!emitOptionalCall(&pn->as<CallNode>(), oe, valueUsage)) { |
8777 | return false; |
8778 | } |
8779 | break; |
8780 | // List of accepted ParseNodeKinds that might appear only at the beginning |
8781 | // of an Optional Chain. |
8782 | // For example, a taggedTemplateExpr node might occur if we have |
8783 | // `test`?.b, with `test` as the taggedTemplateExpr ParseNode. |
8784 | default: |
8785 | #ifdef DEBUG1 |
8786 | // https://tc39.es/ecma262/#sec-primary-expression |
8787 | bool isPrimaryExpression = |
8788 | kind == ParseNodeKind::ThisExpr || kind == ParseNodeKind::Name || |
8789 | kind == ParseNodeKind::PrivateName || |
8790 | kind == ParseNodeKind::NullExpr || kind == ParseNodeKind::TrueExpr || |
8791 | kind == ParseNodeKind::FalseExpr || |
8792 | kind == ParseNodeKind::NumberExpr || |
8793 | kind == ParseNodeKind::BigIntExpr || |
8794 | kind == ParseNodeKind::StringExpr || |
8795 | kind == ParseNodeKind::ArrayExpr || |
8796 | kind == ParseNodeKind::ObjectExpr || |
8797 | kind == ParseNodeKind::Function || kind == ParseNodeKind::ClassDecl || |
8798 | kind == ParseNodeKind::RegExpExpr || |
8799 | kind == ParseNodeKind::TemplateStringExpr || |
8800 | kind == ParseNodeKind::TemplateStringListExpr || |
8801 | kind == ParseNodeKind::RawUndefinedExpr || pn->isInParens(); |
8802 | |
8803 | // https://tc39.es/ecma262/#sec-left-hand-side-expressions |
8804 | bool isMemberExpression = isPrimaryExpression || |
8805 | kind == ParseNodeKind::TaggedTemplateExpr || |
8806 | kind == ParseNodeKind::NewExpr || |
8807 | kind == ParseNodeKind::NewTargetExpr || |
8808 | kind == ParseNodeKind::ImportMetaExpr; |
8809 | |
8810 | bool isCallExpression = kind == ParseNodeKind::SetThis || |
8811 | kind == ParseNodeKind::CallImportExpr; |
8812 | |
8813 | MOZ_ASSERT(isMemberExpression || isCallExpression,do { static_assert( mozilla::detail::AssertionConditionType< decltype(isMemberExpression || isCallExpression)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(isMemberExpression || isCallExpression))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("isMemberExpression || isCallExpression" " (" "Unknown ParseNodeKind for OptionalChain" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8814); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isMemberExpression || isCallExpression" ") (" "Unknown ParseNodeKind for OptionalChain" ")"); do { * ((volatile int*)__null) = 8814; __attribute__((nomerge)) ::abort (); } while (false); } } while (false) |
8814 | "Unknown ParseNodeKind for OptionalChain")do { static_assert( mozilla::detail::AssertionConditionType< decltype(isMemberExpression || isCallExpression)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(isMemberExpression || isCallExpression))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("isMemberExpression || isCallExpression" " (" "Unknown ParseNodeKind for OptionalChain" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8814); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isMemberExpression || isCallExpression" ") (" "Unknown ParseNodeKind for OptionalChain" ")"); do { * ((volatile int*)__null) = 8814; __attribute__((nomerge)) ::abort (); } while (false); } } while (false); |
8815 | #endif |
8816 | return emitTree(pn); |
8817 | } |
8818 | return true; |
8819 | } |
8820 | |
8821 | // Handle the case of a call made on a OptionalChainParseNode. |
8822 | // For example `(a?.b)()` and `(a?.b)?.()`. |
8823 | bool BytecodeEmitter::emitCalleeAndThisForOptionalChain( |
8824 | UnaryNode* optionalChain, CallNode* callNode, CallOrNewEmitter& cone) { |
8825 | ParseNode* calleeNode = optionalChain->kid(); |
8826 | |
8827 | // Create a new OptionalEmitter, in order to emit the right bytecode |
8828 | // in isolation. |
8829 | OptionalEmitter oe(this, bytecodeSection().stackDepth()); |
8830 | |
8831 | if (!emitOptionalCalleeAndThis(calleeNode, callNode, cone, oe)) { |
8832 | // [stack] CALLEE THIS |
8833 | return false; |
8834 | } |
8835 | |
8836 | // complete the jump if necessary. This will set both the "this" value |
8837 | // and the "callee" value to undefined, if the callee is undefined. It |
8838 | // does not matter much what the this value is, the function call will |
8839 | // fail if it is not optional, and be set to undefined otherwise. |
8840 | if (!oe.emitOptionalJumpTarget(JSOp::Undefined, |
8841 | OptionalEmitter::Kind::Reference)) { |
8842 | // [stack] # If shortcircuit |
8843 | // [stack] UNDEFINED UNDEFINED |
8844 | // [stack] # otherwise |
8845 | // [stack] CALLEE THIS |
8846 | return false; |
8847 | } |
8848 | return true; |
8849 | } |
8850 | |
8851 | bool BytecodeEmitter::emitOptionalChain(UnaryNode* optionalChain, |
8852 | ValueUsage valueUsage) { |
8853 | ParseNode* expr = optionalChain->kid(); |
8854 | |
8855 | OptionalEmitter oe(this, bytecodeSection().stackDepth()); |
8856 | |
8857 | if (!emitOptionalTree(expr, oe, valueUsage)) { |
8858 | // [stack] VAL |
8859 | return false; |
8860 | } |
8861 | |
8862 | if (!oe.emitOptionalJumpTarget(JSOp::Undefined)) { |
8863 | // [stack] # If shortcircuit |
8864 | // [stack] UNDEFINED |
8865 | // [stack] # otherwise |
8866 | // [stack] VAL |
8867 | return false; |
8868 | } |
8869 | |
8870 | return true; |
8871 | } |
8872 | |
8873 | bool BytecodeEmitter::emitOptionalDotExpression(PropertyAccessBase* prop, |
8874 | PropOpEmitter& poe, |
8875 | bool isSuper, |
8876 | OptionalEmitter& oe) { |
8877 | if (!poe.prepareForObj()) { |
8878 | // [stack] |
8879 | return false; |
8880 | } |
8881 | |
8882 | if (isSuper) { |
8883 | UnaryNode* base = &prop->expression().as<UnaryNode>(); |
8884 | if (!emitGetThisForSuperBase(base)) { |
8885 | // [stack] OBJ |
8886 | return false; |
8887 | } |
8888 | } else { |
8889 | if (!emitOptionalTree(&prop->expression(), oe)) { |
8890 | // [stack] OBJ |
8891 | return false; |
8892 | } |
8893 | } |
8894 | |
8895 | if (prop->isKind(ParseNodeKind::OptionalDotExpr)) { |
8896 | MOZ_ASSERT(!isSuper)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!isSuper)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!isSuper))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!isSuper", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8896); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!isSuper" ")" ); do { *((volatile int*)__null) = 8896; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8897 | if (!oe.emitJumpShortCircuit()) { |
8898 | // [stack] # if Jump |
8899 | // [stack] UNDEFINED-OR-NULL |
8900 | // [stack] # otherwise |
8901 | // [stack] OBJ |
8902 | return false; |
8903 | } |
8904 | } |
8905 | |
8906 | if (!poe.emitGet(prop->key().atom())) { |
8907 | // [stack] PROP |
8908 | return false; |
8909 | } |
8910 | |
8911 | return true; |
8912 | } |
8913 | |
8914 | bool BytecodeEmitter::emitOptionalElemExpression(PropertyByValueBase* elem, |
8915 | ElemOpEmitter& eoe, |
8916 | bool isSuper, |
8917 | OptionalEmitter& oe) { |
8918 | if (!eoe.prepareForObj()) { |
8919 | // [stack] |
8920 | return false; |
8921 | } |
8922 | |
8923 | if (isSuper) { |
8924 | UnaryNode* base = &elem->expression().as<UnaryNode>(); |
8925 | if (!emitGetThisForSuperBase(base)) { |
8926 | // [stack] OBJ |
8927 | return false; |
8928 | } |
8929 | } else { |
8930 | if (!emitOptionalTree(&elem->expression(), oe)) { |
8931 | // [stack] OBJ |
8932 | return false; |
8933 | } |
8934 | } |
8935 | |
8936 | if (elem->isKind(ParseNodeKind::OptionalElemExpr)) { |
8937 | MOZ_ASSERT(!isSuper)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!isSuper)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!isSuper))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!isSuper", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8937); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!isSuper" ")" ); do { *((volatile int*)__null) = 8937; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
8938 | if (!oe.emitJumpShortCircuit()) { |
8939 | // [stack] # if Jump |
8940 | // [stack] UNDEFINED-OR-NULL |
8941 | // [stack] # otherwise |
8942 | // [stack] OBJ |
8943 | return false; |
8944 | } |
8945 | } |
8946 | |
8947 | if (!eoe.prepareForKey()) { |
8948 | // [stack] OBJ? OBJ |
8949 | return false; |
8950 | } |
8951 | |
8952 | if (!emitTree(&elem->key())) { |
8953 | // [stack] OBJ? OBJ KEY |
8954 | return false; |
8955 | } |
8956 | |
8957 | if (!eoe.emitGet()) { |
8958 | // [stack] ELEM |
8959 | return false; |
8960 | } |
8961 | |
8962 | return true; |
8963 | } |
8964 | |
8965 | bool BytecodeEmitter::emitOptionalPrivateExpression( |
8966 | PrivateMemberAccessBase* privateExpr, PrivateOpEmitter& xoe, |
8967 | OptionalEmitter& oe) { |
8968 | if (!emitOptionalTree(&privateExpr->expression(), oe)) { |
8969 | // [stack] OBJ |
8970 | return false; |
8971 | } |
8972 | |
8973 | if (privateExpr->isKind(ParseNodeKind::OptionalPrivateMemberExpr)) { |
8974 | if (!oe.emitJumpShortCircuit()) { |
8975 | // [stack] # if Jump |
8976 | // [stack] UNDEFINED-OR-NULL |
8977 | // [stack] # otherwise |
8978 | // [stack] OBJ |
8979 | return false; |
8980 | } |
8981 | } |
8982 | |
8983 | if (!xoe.emitReference()) { |
8984 | // [stack] OBJ NAME |
8985 | return false; |
8986 | } |
8987 | if (!xoe.emitGet()) { |
8988 | // [stack] CALLEE THIS # if call |
8989 | // [stack] VALUE # otherwise |
8990 | return false; |
8991 | } |
8992 | |
8993 | return true; |
8994 | } |
8995 | |
8996 | bool BytecodeEmitter::emitShortCircuit(ListNode* node, ValueUsage valueUsage) { |
8997 | MOZ_ASSERT(node->isKind(ParseNodeKind::OrExpr) ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(node->isKind(ParseNodeKind::OrExpr) || node->isKind (ParseNodeKind::CoalesceExpr) || node->isKind(ParseNodeKind ::AndExpr))>::isValid, "invalid assertion condition"); if ( (__builtin_expect(!!(!(!!(node->isKind(ParseNodeKind::OrExpr ) || node->isKind(ParseNodeKind::CoalesceExpr) || node-> isKind(ParseNodeKind::AndExpr)))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("node->isKind(ParseNodeKind::OrExpr) || node->isKind(ParseNodeKind::CoalesceExpr) || node->isKind(ParseNodeKind::AndExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8999); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::OrExpr) || node->isKind(ParseNodeKind::CoalesceExpr) || node->isKind(ParseNodeKind::AndExpr)" ")"); do { *((volatile int*)__null) = 8999; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
8998 | node->isKind(ParseNodeKind::CoalesceExpr) ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(node->isKind(ParseNodeKind::OrExpr) || node->isKind (ParseNodeKind::CoalesceExpr) || node->isKind(ParseNodeKind ::AndExpr))>::isValid, "invalid assertion condition"); if ( (__builtin_expect(!!(!(!!(node->isKind(ParseNodeKind::OrExpr ) || node->isKind(ParseNodeKind::CoalesceExpr) || node-> isKind(ParseNodeKind::AndExpr)))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("node->isKind(ParseNodeKind::OrExpr) || node->isKind(ParseNodeKind::CoalesceExpr) || node->isKind(ParseNodeKind::AndExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8999); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::OrExpr) || node->isKind(ParseNodeKind::CoalesceExpr) || node->isKind(ParseNodeKind::AndExpr)" ")"); do { *((volatile int*)__null) = 8999; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
8999 | node->isKind(ParseNodeKind::AndExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(node->isKind(ParseNodeKind::OrExpr) || node->isKind (ParseNodeKind::CoalesceExpr) || node->isKind(ParseNodeKind ::AndExpr))>::isValid, "invalid assertion condition"); if ( (__builtin_expect(!!(!(!!(node->isKind(ParseNodeKind::OrExpr ) || node->isKind(ParseNodeKind::CoalesceExpr) || node-> isKind(ParseNodeKind::AndExpr)))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("node->isKind(ParseNodeKind::OrExpr) || node->isKind(ParseNodeKind::CoalesceExpr) || node->isKind(ParseNodeKind::AndExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 8999); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::OrExpr) || node->isKind(ParseNodeKind::CoalesceExpr) || node->isKind(ParseNodeKind::AndExpr)" ")"); do { *((volatile int*)__null) = 8999; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9000 | |
9001 | /* |
9002 | * JSOp::Or converts the operand on the stack to boolean, leaves the original |
9003 | * value on the stack and jumps if true; otherwise it falls into the next |
9004 | * bytecode, which pops the left operand and then evaluates the right operand. |
9005 | * The jump goes around the right operand evaluation. |
9006 | * |
9007 | * JSOp::And converts the operand on the stack to boolean and jumps if false; |
9008 | * otherwise it falls into the right operand's bytecode. |
9009 | */ |
9010 | |
9011 | TDZCheckCache tdzCache(this); |
9012 | |
9013 | JSOp op; |
9014 | switch (node->getKind()) { |
9015 | case ParseNodeKind::OrExpr: |
9016 | op = JSOp::Or; |
9017 | break; |
9018 | case ParseNodeKind::CoalesceExpr: |
9019 | op = JSOp::Coalesce; |
9020 | break; |
9021 | case ParseNodeKind::AndExpr: |
9022 | op = JSOp::And; |
9023 | break; |
9024 | default: |
9025 | MOZ_CRASH("Unexpected ParseNodeKind")do { do { } while (false); MOZ_ReportCrash("" "Unexpected ParseNodeKind" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9025); AnnotateMozCrashReason("MOZ_CRASH(" "Unexpected ParseNodeKind" ")"); do { *((volatile int*)__null) = 9025; __attribute__((nomerge )) ::abort(); } while (false); } while (false); |
9026 | } |
9027 | |
9028 | JumpList jump; |
9029 | |
9030 | // Left-associative operator chain: avoid too much recursion. |
9031 | // |
9032 | // Emit all nodes but the last. |
9033 | for (ParseNode* expr : node->contentsTo(node->last())) { |
9034 | if (!emitTree(expr)) { |
9035 | return false; |
9036 | } |
9037 | if (!emitJump(op, &jump)) { |
9038 | return false; |
9039 | } |
9040 | if (!emit1(JSOp::Pop)) { |
9041 | return false; |
9042 | } |
9043 | } |
9044 | |
9045 | // Emit the last node |
9046 | if (!emitTree(node->last(), valueUsage)) { |
9047 | return false; |
9048 | } |
9049 | |
9050 | if (!emitJumpTargetAndPatch(jump)) { |
9051 | return false; |
9052 | } |
9053 | return true; |
9054 | } |
9055 | |
9056 | bool BytecodeEmitter::emitSequenceExpr(ListNode* node, ValueUsage valueUsage) { |
9057 | for (ParseNode* child : node->contentsTo(node->last())) { |
9058 | if (!updateSourceCoordNotes(child->pn_pos.begin)) { |
9059 | return false; |
9060 | } |
9061 | if (!emitTree(child, ValueUsage::IgnoreValue)) { |
9062 | return false; |
9063 | } |
9064 | if (!emit1(JSOp::Pop)) { |
9065 | return false; |
9066 | } |
9067 | } |
9068 | |
9069 | ParseNode* child = node->last(); |
9070 | if (!updateSourceCoordNotes(child->pn_pos.begin)) { |
9071 | return false; |
9072 | } |
9073 | if (!emitTree(child, valueUsage)) { |
9074 | return false; |
9075 | } |
9076 | return true; |
9077 | } |
9078 | |
9079 | // Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See |
9080 | // the comment on emitSwitch. |
9081 | MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitIncOrDec(UnaryNode* incDec, |
9082 | ValueUsage valueUsage) { |
9083 | switch (incDec->kid()->getKind()) { |
9084 | case ParseNodeKind::ArgumentsLength: |
9085 | case ParseNodeKind::DotExpr: |
9086 | return emitPropIncDec(incDec, valueUsage); |
9087 | case ParseNodeKind::ElemExpr: |
9088 | return emitElemIncDec(incDec, valueUsage); |
9089 | case ParseNodeKind::PrivateMemberExpr: |
9090 | return emitPrivateIncDec(incDec, valueUsage); |
9091 | case ParseNodeKind::CallExpr: |
9092 | return emitCallIncDec(incDec); |
9093 | default: |
9094 | return emitNameIncDec(incDec, valueUsage); |
9095 | } |
9096 | } |
9097 | |
9098 | // Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See |
9099 | // the comment on emitSwitch. |
9100 | MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitLabeledStatement( |
9101 | const LabeledStatement* labeledStmt) { |
9102 | auto name = labeledStmt->label(); |
9103 | LabelEmitter label(this); |
9104 | |
9105 | label.emitLabel(name); |
9106 | |
9107 | if (!emitTree(labeledStmt->statement())) { |
9108 | return false; |
9109 | } |
9110 | if (!label.emitEnd()) { |
9111 | return false; |
9112 | } |
9113 | |
9114 | return true; |
9115 | } |
9116 | |
9117 | bool BytecodeEmitter::emitConditionalExpression( |
9118 | ConditionalExpression& conditional, ValueUsage valueUsage) { |
9119 | CondEmitter cond(this); |
9120 | if (!cond.emitCond()) { |
9121 | return false; |
9122 | } |
9123 | |
9124 | ParseNode* conditionNode = &conditional.condition(); |
9125 | auto conditionKind = IfEmitter::ConditionKind::Positive; |
9126 | if (conditionNode->isKind(ParseNodeKind::NotExpr)) { |
9127 | conditionNode = conditionNode->as<UnaryNode>().kid(); |
9128 | conditionKind = IfEmitter::ConditionKind::Negative; |
9129 | } |
9130 | |
9131 | // NOTE: NotExpr of conditionNode may be unwrapped, and in that case the |
9132 | // negation is handled by conditionKind. |
9133 | if (!emitTree(conditionNode)) { |
9134 | return false; |
9135 | } |
9136 | |
9137 | if (!cond.emitThenElse(conditionKind)) { |
9138 | return false; |
9139 | } |
9140 | |
9141 | if (!emitTree(&conditional.thenExpression(), valueUsage)) { |
9142 | return false; |
9143 | } |
9144 | |
9145 | if (!cond.emitElse()) { |
9146 | return false; |
9147 | } |
9148 | |
9149 | if (!emitTree(&conditional.elseExpression(), valueUsage)) { |
9150 | return false; |
9151 | } |
9152 | |
9153 | if (!cond.emitEnd()) { |
9154 | return false; |
9155 | } |
9156 | MOZ_ASSERT(cond.pushed() == 1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(cond.pushed() == 1)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(cond.pushed() == 1))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("cond.pushed() == 1" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9156); AnnotateMozCrashReason("MOZ_ASSERT" "(" "cond.pushed() == 1" ")"); do { *((volatile int*)__null) = 9156; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9157 | |
9158 | return true; |
9159 | } |
9160 | |
9161 | // Check for an object-literal property list that can be handled by the |
9162 | // ObjLiteral writer. We ensure that for each `prop: value` pair, the key is a |
9163 | // constant name or numeric index, there is no accessor specified, and the value |
9164 | // can be encoded by an ObjLiteral instruction (constant number, string, |
9165 | // boolean, null/undefined). |
9166 | void BytecodeEmitter::isPropertyListObjLiteralCompatible(ListNode* obj, |
9167 | bool* withValues, |
9168 | bool* withoutValues) { |
9169 | bool keysOK = true; |
9170 | bool valuesOK = true; |
9171 | uint32_t propCount = 0; |
9172 | |
9173 | for (ParseNode* propdef : obj->contents()) { |
9174 | if (!propdef->is<BinaryNode>()) { |
9175 | keysOK = false; |
9176 | break; |
9177 | } |
9178 | propCount++; |
9179 | |
9180 | BinaryNode* prop = &propdef->as<BinaryNode>(); |
9181 | ParseNode* key = prop->left(); |
9182 | ParseNode* value = prop->right(); |
9183 | |
9184 | // Computed keys not OK (ObjLiteral data stores constant keys). |
9185 | if (key->isKind(ParseNodeKind::ComputedName)) { |
9186 | keysOK = false; |
9187 | break; |
9188 | } |
9189 | |
9190 | // BigIntExprs should have been lowered to computed names at parse |
9191 | // time, and so should be excluded above. |
9192 | MOZ_ASSERT(!key->isKind(ParseNodeKind::BigIntExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!key->isKind(ParseNodeKind::BigIntExpr))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(!key->isKind(ParseNodeKind::BigIntExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!key->isKind(ParseNodeKind::BigIntExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9192); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!key->isKind(ParseNodeKind::BigIntExpr)" ")"); do { *((volatile int*)__null) = 9192; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9193 | |
9194 | // Numeric keys OK as long as they are integers and in range. |
9195 | if (key->isKind(ParseNodeKind::NumberExpr)) { |
9196 | double numValue = key->as<NumericLiteral>().value(); |
9197 | int32_t i = 0; |
9198 | if (!NumberIsInt32(numValue, &i)) { |
9199 | keysOK = false; |
9200 | break; |
9201 | } |
9202 | if (!ObjLiteralWriter::arrayIndexInRange(i)) { |
9203 | keysOK = false; |
9204 | break; |
9205 | } |
9206 | } |
9207 | |
9208 | MOZ_ASSERT(key->isKind(ParseNodeKind::ObjectPropertyName) ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(key->isKind(ParseNodeKind::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr) || key->isKind( ParseNodeKind::NumberExpr))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(key->isKind(ParseNodeKind ::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr ) || key->isKind(ParseNodeKind::NumberExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("key->isKind(ParseNodeKind::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9210); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr)" ")"); do { *((volatile int*)__null) = 9210; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
9209 | key->isKind(ParseNodeKind::StringExpr) ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(key->isKind(ParseNodeKind::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr) || key->isKind( ParseNodeKind::NumberExpr))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(key->isKind(ParseNodeKind ::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr ) || key->isKind(ParseNodeKind::NumberExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("key->isKind(ParseNodeKind::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9210); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr)" ")"); do { *((volatile int*)__null) = 9210; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
9210 | key->isKind(ParseNodeKind::NumberExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(key->isKind(ParseNodeKind::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr) || key->isKind( ParseNodeKind::NumberExpr))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(key->isKind(ParseNodeKind ::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr ) || key->isKind(ParseNodeKind::NumberExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("key->isKind(ParseNodeKind::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9210); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr)" ")"); do { *((volatile int*)__null) = 9210; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9211 | |
9212 | AccessorType accessorType = |
9213 | prop->is<PropertyDefinition>() |
9214 | ? prop->as<PropertyDefinition>().accessorType() |
9215 | : AccessorType::None; |
9216 | if (accessorType != AccessorType::None) { |
9217 | keysOK = false; |
9218 | break; |
9219 | } |
9220 | |
9221 | if (!isRHSObjLiteralCompatible(value)) { |
9222 | valuesOK = false; |
9223 | } |
9224 | } |
9225 | |
9226 | if (propCount > SharedPropMap::MaxPropsForNonDictionary) { |
9227 | // JSOp::NewObject cannot accept dictionary-mode objects. |
9228 | keysOK = false; |
9229 | } |
9230 | |
9231 | *withValues = keysOK && valuesOK; |
9232 | *withoutValues = keysOK; |
9233 | } |
9234 | |
9235 | bool BytecodeEmitter::isArrayObjLiteralCompatible(ListNode* array) { |
9236 | for (ParseNode* elem : array->contents()) { |
9237 | if (elem->isKind(ParseNodeKind::Spread)) { |
9238 | return false; |
9239 | } |
9240 | if (!isRHSObjLiteralCompatible(elem)) { |
9241 | return false; |
9242 | } |
9243 | } |
9244 | return true; |
9245 | } |
9246 | |
9247 | bool BytecodeEmitter::emitPropertyList(ListNode* obj, PropertyEmitter& pe, |
9248 | PropListType type) { |
9249 | // [stack] CTOR? OBJ |
9250 | |
9251 | size_t curFieldKeyIndex = 0; |
9252 | size_t curStaticFieldKeyIndex = 0; |
9253 | for (ParseNode* propdef : obj->contents()) { |
9254 | if (propdef->is<ClassField>()) { |
9255 | MOZ_ASSERT(type == ClassBody)do { static_assert( mozilla::detail::AssertionConditionType< decltype(type == ClassBody)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(type == ClassBody))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("type == ClassBody" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9255); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == ClassBody" ")"); do { *((volatile int*)__null) = 9255; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9256 | // Only handle computing field keys here: the .initializers lambda array |
9257 | // is created elsewhere. |
9258 | ClassField* field = &propdef->as<ClassField>(); |
9259 | if (field->name().getKind() == ParseNodeKind::ComputedName) { |
9260 | auto fieldKeys = |
9261 | field->isStatic() |
9262 | ? TaggedParserAtomIndex::WellKnown::dot_staticFieldKeys_() |
9263 | : TaggedParserAtomIndex::WellKnown::dot_fieldKeys_(); |
9264 | if (!emitGetName(fieldKeys)) { |
9265 | // [stack] CTOR OBJ ARRAY |
9266 | return false; |
9267 | } |
9268 | |
9269 | ParseNode* nameExpr = field->name().as<UnaryNode>().kid(); |
9270 | |
9271 | if (!emitTree(nameExpr, ValueUsage::WantValue)) { |
9272 | // [stack] CTOR OBJ ARRAY KEY |
9273 | return false; |
9274 | } |
9275 | |
9276 | if (!emit1(JSOp::ToPropertyKey)) { |
9277 | // [stack] CTOR OBJ ARRAY KEY |
9278 | return false; |
9279 | } |
9280 | |
9281 | size_t fieldKeysIndex; |
9282 | if (field->isStatic()) { |
9283 | fieldKeysIndex = curStaticFieldKeyIndex++; |
9284 | } else { |
9285 | fieldKeysIndex = curFieldKeyIndex++; |
9286 | } |
9287 | |
9288 | if (!emitUint32Operand(JSOp::InitElemArray, fieldKeysIndex)) { |
9289 | // [stack] CTOR OBJ ARRAY |
9290 | return false; |
9291 | } |
9292 | |
9293 | if (!emit1(JSOp::Pop)) { |
9294 | // [stack] CTOR OBJ |
9295 | return false; |
9296 | } |
9297 | } |
9298 | continue; |
9299 | } |
9300 | |
9301 | if (propdef->isKind(ParseNodeKind::StaticClassBlock)) { |
9302 | // Static class blocks are emitted as part of |
9303 | // emitCreateMemberInitializers. |
9304 | continue; |
9305 | } |
9306 | |
9307 | if (propdef->is<LexicalScopeNode>()) { |
9308 | // Constructors are sometimes wrapped in LexicalScopeNodes. As we |
9309 | // already handled emitting the constructor, skip it. |
9310 | MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType< decltype(propdef->as<LexicalScopeNode>().scopeBody() ->is<ClassMethod>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(propdef->as<LexicalScopeNode >().scopeBody()->is<ClassMethod>()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("propdef->as<LexicalScopeNode>().scopeBody()->is<ClassMethod>()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9311); AnnotateMozCrashReason("MOZ_ASSERT" "(" "propdef->as<LexicalScopeNode>().scopeBody()->is<ClassMethod>()" ")"); do { *((volatile int*)__null) = 9311; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
9311 | propdef->as<LexicalScopeNode>().scopeBody()->is<ClassMethod>())do { static_assert( mozilla::detail::AssertionConditionType< decltype(propdef->as<LexicalScopeNode>().scopeBody() ->is<ClassMethod>())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(propdef->as<LexicalScopeNode >().scopeBody()->is<ClassMethod>()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("propdef->as<LexicalScopeNode>().scopeBody()->is<ClassMethod>()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9311); AnnotateMozCrashReason("MOZ_ASSERT" "(" "propdef->as<LexicalScopeNode>().scopeBody()->is<ClassMethod>()" ")"); do { *((volatile int*)__null) = 9311; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9312 | continue; |
9313 | } |
9314 | |
9315 | // Handle __proto__: v specially because *only* this form, and no other |
9316 | // involving "__proto__", performs [[Prototype]] mutation. |
9317 | if (propdef->isKind(ParseNodeKind::MutateProto)) { |
9318 | // [stack] OBJ |
9319 | MOZ_ASSERT(type == ObjectLiteral)do { static_assert( mozilla::detail::AssertionConditionType< decltype(type == ObjectLiteral)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(type == ObjectLiteral))), 0) )) { do { } while (false); MOZ_ReportAssertionFailure("type == ObjectLiteral" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9319); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == ObjectLiteral" ")"); do { *((volatile int*)__null) = 9319; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9320 | if (!pe.prepareForProtoValue(propdef->pn_pos.begin)) { |
9321 | // [stack] OBJ |
9322 | return false; |
9323 | } |
9324 | if (!emitTree(propdef->as<UnaryNode>().kid())) { |
9325 | // [stack] OBJ PROTO |
9326 | return false; |
9327 | } |
9328 | if (!pe.emitMutateProto()) { |
9329 | // [stack] OBJ |
9330 | return false; |
9331 | } |
9332 | continue; |
9333 | } |
9334 | |
9335 | if (propdef->isKind(ParseNodeKind::Spread)) { |
9336 | MOZ_ASSERT(type == ObjectLiteral)do { static_assert( mozilla::detail::AssertionConditionType< decltype(type == ObjectLiteral)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(type == ObjectLiteral))), 0) )) { do { } while (false); MOZ_ReportAssertionFailure("type == ObjectLiteral" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9336); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == ObjectLiteral" ")"); do { *((volatile int*)__null) = 9336; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9337 | // [stack] OBJ |
9338 | if (!pe.prepareForSpreadOperand(propdef->pn_pos.begin)) { |
9339 | // [stack] OBJ OBJ |
9340 | return false; |
9341 | } |
9342 | if (!emitTree(propdef->as<UnaryNode>().kid())) { |
9343 | // [stack] OBJ OBJ VAL |
9344 | return false; |
9345 | } |
9346 | if (!pe.emitSpread()) { |
9347 | // [stack] OBJ |
9348 | return false; |
9349 | } |
9350 | continue; |
9351 | } |
9352 | |
9353 | BinaryNode* prop = &propdef->as<BinaryNode>(); |
9354 | |
9355 | ParseNode* key = prop->left(); |
9356 | AccessorType accessorType; |
9357 | if (prop->is<ClassMethod>()) { |
9358 | ClassMethod& method = prop->as<ClassMethod>(); |
9359 | accessorType = method.accessorType(); |
9360 | |
9361 | if (!method.isStatic() && key->isKind(ParseNodeKind::PrivateName) && |
9362 | accessorType != AccessorType::None) { |
9363 | // Private non-static accessors are stamped onto instances from |
9364 | // initializers; see emitCreateMemberInitializers. |
9365 | continue; |
9366 | } |
9367 | } else if (prop->is<PropertyDefinition>()) { |
9368 | accessorType = prop->as<PropertyDefinition>().accessorType(); |
9369 | } else { |
9370 | accessorType = AccessorType::None; |
9371 | } |
9372 | |
9373 | auto emitValue = [this, &key, &prop, accessorType, &pe]() { |
9374 | // [stack] CTOR? OBJ CTOR? KEY? |
9375 | |
9376 | ParseNode* propVal = prop->right(); |
9377 | if (propVal->isDirectRHSAnonFunction()) { |
9378 | // The following branches except for the last `else` clause emit the |
9379 | // cases handled in NameResolver::resolveFun (see NameFunctions.cpp) |
9380 | if (key->isKind(ParseNodeKind::ObjectPropertyName) || |
9381 | key->isKind(ParseNodeKind::PrivateName) || |
9382 | key->isKind(ParseNodeKind::StringExpr)) { |
9383 | auto keyAtom = key->as<NameNode>().atom(); |
9384 | if (!emitAnonymousFunctionWithName(propVal, keyAtom)) { |
9385 | // [stack] CTOR? OBJ CTOR? VAL |
9386 | return false; |
9387 | } |
9388 | } else if (key->isKind(ParseNodeKind::NumberExpr)) { |
9389 | MOZ_ASSERT(accessorType == AccessorType::None)do { static_assert( mozilla::detail::AssertionConditionType< decltype(accessorType == AccessorType::None)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(accessorType == AccessorType ::None))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("accessorType == AccessorType::None", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9389); AnnotateMozCrashReason("MOZ_ASSERT" "(" "accessorType == AccessorType::None" ")"); do { *((volatile int*)__null) = 9389; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9390 | |
9391 | auto keyAtom = key->as<NumericLiteral>().toAtom(fc, parserAtoms()); |
9392 | if (!keyAtom) { |
9393 | return false; |
9394 | } |
9395 | if (!emitAnonymousFunctionWithName(propVal, keyAtom)) { |
9396 | // [stack] CTOR? OBJ CTOR? KEY VAL |
9397 | return false; |
9398 | } |
9399 | } else if (key->isKind(ParseNodeKind::ComputedName) && |
9400 | (key->as<UnaryNode>().kid()->isKind( |
9401 | ParseNodeKind::NumberExpr) || |
9402 | key->as<UnaryNode>().kid()->isKind( |
9403 | ParseNodeKind::StringExpr)) && |
9404 | accessorType == AccessorType::None) { |
9405 | ParseNode* keyKid = key->as<UnaryNode>().kid(); |
9406 | if (keyKid->isKind(ParseNodeKind::NumberExpr)) { |
9407 | auto keyAtom = |
9408 | keyKid->as<NumericLiteral>().toAtom(fc, parserAtoms()); |
9409 | if (!keyAtom) { |
9410 | return false; |
9411 | } |
9412 | if (!emitAnonymousFunctionWithName(propVal, keyAtom)) { |
9413 | // [stack] CTOR? OBJ CTOR? KEY VAL |
9414 | return false; |
9415 | } |
9416 | } else { |
9417 | MOZ_ASSERT(keyKid->isKind(ParseNodeKind::StringExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(keyKid->isKind(ParseNodeKind::StringExpr))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(keyKid->isKind(ParseNodeKind::StringExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("keyKid->isKind(ParseNodeKind::StringExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9417); AnnotateMozCrashReason("MOZ_ASSERT" "(" "keyKid->isKind(ParseNodeKind::StringExpr)" ")"); do { *((volatile int*)__null) = 9417; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9418 | auto keyAtom = keyKid->as<NameNode>().atom(); |
9419 | if (!emitAnonymousFunctionWithName(propVal, keyAtom)) { |
9420 | // [stack] CTOR? OBJ CTOR? KEY VAL |
9421 | return false; |
9422 | } |
9423 | } |
9424 | } else { |
9425 | // Either a proper computed property name or a synthetic computed |
9426 | // property name for BigInt keys. |
9427 | MOZ_ASSERT(key->isKind(ParseNodeKind::ComputedName))do { static_assert( mozilla::detail::AssertionConditionType< decltype(key->isKind(ParseNodeKind::ComputedName))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(key->isKind(ParseNodeKind::ComputedName)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("key->isKind(ParseNodeKind::ComputedName)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9427); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::ComputedName)" ")"); do { *((volatile int*)__null) = 9427; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9428 | |
9429 | FunctionPrefixKind prefix = |
9430 | accessorType == AccessorType::None ? FunctionPrefixKind::None |
9431 | : accessorType == AccessorType::Getter ? FunctionPrefixKind::Get |
9432 | : FunctionPrefixKind::Set; |
9433 | |
9434 | if (!emitAnonymousFunctionWithComputedName(propVal, prefix)) { |
9435 | // [stack] CTOR? OBJ CTOR? KEY VAL |
9436 | return false; |
9437 | } |
9438 | } |
9439 | } else { |
9440 | if (!emitTree(propVal)) { |
9441 | // [stack] CTOR? OBJ CTOR? KEY? VAL |
9442 | return false; |
9443 | } |
9444 | } |
9445 | |
9446 | if (propVal->is<FunctionNode>() && |
9447 | propVal->as<FunctionNode>().funbox()->needsHomeObject()) { |
9448 | if (!pe.emitInitHomeObject()) { |
9449 | // [stack] CTOR? OBJ CTOR? KEY? FUN |
9450 | return false; |
9451 | } |
9452 | } |
9453 | |
9454 | #ifdef ENABLE_DECORATORS |
9455 | if (prop->is<ClassMethod>()) { |
9456 | ClassMethod& method = prop->as<ClassMethod>(); |
9457 | if (method.decorators() && !method.decorators()->empty()) { |
9458 | DecoratorEmitter::Kind kind; |
9459 | switch (method.accessorType()) { |
9460 | case AccessorType::Getter: |
9461 | kind = DecoratorEmitter::Getter; |
9462 | break; |
9463 | case AccessorType::Setter: |
9464 | kind = DecoratorEmitter::Setter; |
9465 | break; |
9466 | case AccessorType::None: |
9467 | kind = DecoratorEmitter::Method; |
9468 | break; |
9469 | } |
9470 | |
9471 | if (!method.isStatic()) { |
9472 | bool hasKeyOnStack = key->isKind(ParseNodeKind::NumberExpr) || |
9473 | key->isKind(ParseNodeKind::ComputedName); |
9474 | if (!emitDupAt(hasKeyOnStack ? 4 : 3)) { |
9475 | // [stack] ADDINIT OBJ KEY? VAL ADDINIT |
9476 | return false; |
9477 | } |
9478 | } else { |
9479 | // TODO: See bug 1868220 for support for static methods. |
9480 | // Note: Key will be present if this has a private name. |
9481 | if (!emit1(JSOp::Undefined)) { |
9482 | // [stack] CTOR OBJ CTOR KEY? VAL ADDINIT |
9483 | return false; |
9484 | } |
9485 | } |
9486 | |
9487 | if (!emit1(JSOp::Swap)) { |
9488 | // [stack] ADDINIT CTOR? OBJ CTOR? KEY? ADDINIT VAL |
9489 | return false; |
9490 | } |
9491 | |
9492 | // The decorators are applied to the current value on the stack, |
9493 | // possibly replacing it. |
9494 | DecoratorEmitter de(this); |
9495 | if (!de.emitApplyDecoratorsToElementDefinition( |
9496 | kind, key, method.decorators(), method.isStatic())) { |
9497 | // [stack] ADDINIT CTOR? OBJ CTOR? KEY? ADDINIT VAL |
9498 | return false; |
9499 | } |
9500 | |
9501 | if (!emit1(JSOp::Swap)) { |
9502 | // [stack] ADDINIT CTOR? OBJ CTOR? KEY? VAL ADDINIT |
9503 | return false; |
9504 | } |
9505 | |
9506 | if (!emitPopN(1)) { |
9507 | // [stack] ADDINIT CTOR? OBJ CTOR? KEY? VAL |
9508 | return false; |
9509 | } |
9510 | } |
9511 | } |
9512 | #endif |
9513 | |
9514 | return true; |
9515 | }; |
9516 | |
9517 | PropertyEmitter::Kind kind = |
9518 | (type == ClassBody && propdef->as<ClassMethod>().isStatic()) |
9519 | ? PropertyEmitter::Kind::Static |
9520 | : PropertyEmitter::Kind::Prototype; |
9521 | if (key->isKind(ParseNodeKind::ObjectPropertyName) || |
9522 | key->isKind(ParseNodeKind::StringExpr)) { |
9523 | // [stack] CTOR? OBJ |
9524 | |
9525 | auto keyAtom = key->as<NameNode>().atom(); |
9526 | |
9527 | // emitClass took care of constructor already. |
9528 | if (type == ClassBody && |
9529 | keyAtom == TaggedParserAtomIndex::WellKnown::constructor() && |
9530 | !propdef->as<ClassMethod>().isStatic()) { |
9531 | continue; |
9532 | } |
9533 | |
9534 | if (!pe.prepareForPropValue(propdef->pn_pos.begin, kind)) { |
9535 | // [stack] CTOR? OBJ CTOR? |
9536 | return false; |
9537 | } |
9538 | |
9539 | if (!emitValue()) { |
9540 | // [stack] CTOR? OBJ CTOR? VAL |
9541 | return false; |
9542 | } |
9543 | |
9544 | if (!pe.emitInit(accessorType, keyAtom)) { |
9545 | // [stack] CTOR? OBJ |
9546 | return false; |
9547 | } |
9548 | |
9549 | continue; |
9550 | } |
9551 | |
9552 | if (key->isKind(ParseNodeKind::NumberExpr)) { |
9553 | // [stack] CTOR? OBJ |
9554 | if (!pe.prepareForIndexPropKey(propdef->pn_pos.begin, kind)) { |
9555 | // [stack] CTOR? OBJ CTOR? |
9556 | return false; |
9557 | } |
9558 | if (!emitNumberOp(key->as<NumericLiteral>().value())) { |
9559 | // [stack] CTOR? OBJ CTOR? KEY |
9560 | return false; |
9561 | } |
9562 | if (!pe.prepareForIndexPropValue()) { |
9563 | // [stack] CTOR? OBJ CTOR? KEY |
9564 | return false; |
9565 | } |
9566 | if (!emitValue()) { |
9567 | // [stack] CTOR? OBJ CTOR? KEY VAL |
9568 | return false; |
9569 | } |
9570 | |
9571 | if (!pe.emitInitIndexOrComputed(accessorType)) { |
9572 | // [stack] CTOR? OBJ |
9573 | return false; |
9574 | } |
9575 | |
9576 | continue; |
9577 | } |
9578 | |
9579 | if (key->isKind(ParseNodeKind::ComputedName)) { |
9580 | // Either a proper computed property name or a synthetic computed property |
9581 | // name for BigInt keys. |
9582 | |
9583 | // [stack] CTOR? OBJ |
9584 | |
9585 | if (!pe.prepareForComputedPropKey(propdef->pn_pos.begin, kind)) { |
9586 | // [stack] CTOR? OBJ CTOR? |
9587 | return false; |
9588 | } |
9589 | if (!emitTree(key->as<UnaryNode>().kid())) { |
9590 | // [stack] CTOR? OBJ CTOR? KEY |
9591 | return false; |
9592 | } |
9593 | if (!pe.prepareForComputedPropValue()) { |
9594 | // [stack] CTOR? OBJ CTOR? KEY |
9595 | return false; |
9596 | } |
9597 | if (!emitValue()) { |
9598 | // [stack] CTOR? OBJ CTOR? KEY VAL |
9599 | return false; |
9600 | } |
9601 | |
9602 | if (!pe.emitInitIndexOrComputed(accessorType)) { |
9603 | // [stack] CTOR? OBJ |
9604 | return false; |
9605 | } |
9606 | |
9607 | continue; |
9608 | } |
9609 | |
9610 | MOZ_ASSERT(key->isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType< decltype(key->isKind(ParseNodeKind::PrivateName))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(key->isKind(ParseNodeKind::PrivateName)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("key->isKind(ParseNodeKind::PrivateName)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9610); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::PrivateName)" ")"); do { *((volatile int*)__null) = 9610; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9611 | MOZ_ASSERT(type == ClassBody)do { static_assert( mozilla::detail::AssertionConditionType< decltype(type == ClassBody)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(type == ClassBody))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("type == ClassBody" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9611); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == ClassBody" ")"); do { *((volatile int*)__null) = 9611; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9612 | |
9613 | auto* privateName = &key->as<NameNode>(); |
9614 | |
9615 | if (kind == PropertyEmitter::Kind::Prototype) { |
9616 | MOZ_ASSERT(accessorType == AccessorType::None)do { static_assert( mozilla::detail::AssertionConditionType< decltype(accessorType == AccessorType::None)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(accessorType == AccessorType ::None))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("accessorType == AccessorType::None", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9616); AnnotateMozCrashReason("MOZ_ASSERT" "(" "accessorType == AccessorType::None" ")"); do { *((volatile int*)__null) = 9616; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9617 | if (!pe.prepareForPrivateMethod()) { |
9618 | // [stack] CTOR OBJ |
9619 | return false; |
9620 | } |
9621 | NameOpEmitter noe(this, privateName->atom(), |
9622 | NameOpEmitter::Kind::SimpleAssignment); |
9623 | |
9624 | // Ensure the NameOp emitter doesn't push an environment onto the stack, |
9625 | // because that would change the stack location of the home object. |
9626 | MOZ_ASSERT(noe.loc().kind() == NameLocation::Kind::FrameSlot ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(noe.loc().kind() == NameLocation::Kind::FrameSlot || noe.loc().kind() == NameLocation::Kind::EnvironmentCoordinate )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(noe.loc().kind() == NameLocation::Kind::FrameSlot || noe.loc().kind() == NameLocation::Kind::EnvironmentCoordinate ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "noe.loc().kind() == NameLocation::Kind::FrameSlot || noe.loc().kind() == NameLocation::Kind::EnvironmentCoordinate" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9627); AnnotateMozCrashReason("MOZ_ASSERT" "(" "noe.loc().kind() == NameLocation::Kind::FrameSlot || noe.loc().kind() == NameLocation::Kind::EnvironmentCoordinate" ")"); do { *((volatile int*)__null) = 9627; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
9627 | noe.loc().kind() == NameLocation::Kind::EnvironmentCoordinate)do { static_assert( mozilla::detail::AssertionConditionType< decltype(noe.loc().kind() == NameLocation::Kind::FrameSlot || noe.loc().kind() == NameLocation::Kind::EnvironmentCoordinate )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(noe.loc().kind() == NameLocation::Kind::FrameSlot || noe.loc().kind() == NameLocation::Kind::EnvironmentCoordinate ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "noe.loc().kind() == NameLocation::Kind::FrameSlot || noe.loc().kind() == NameLocation::Kind::EnvironmentCoordinate" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9627); AnnotateMozCrashReason("MOZ_ASSERT" "(" "noe.loc().kind() == NameLocation::Kind::FrameSlot || noe.loc().kind() == NameLocation::Kind::EnvironmentCoordinate" ")"); do { *((volatile int*)__null) = 9627; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9628 | |
9629 | if (!noe.prepareForRhs()) { |
9630 | // [stack] CTOR OBJ |
9631 | return false; |
9632 | } |
9633 | if (!emitValue()) { |
9634 | // [stack] CTOR OBJ METHOD |
9635 | return false; |
9636 | } |
9637 | if (!noe.emitAssignment()) { |
9638 | // [stack] CTOR OBJ METHOD |
9639 | return false; |
9640 | } |
9641 | if (!emit1(JSOp::Pop)) { |
9642 | // [stack] CTOR OBJ |
9643 | return false; |
9644 | } |
9645 | if (!pe.skipInit()) { |
9646 | // [stack] CTOR OBJ |
9647 | return false; |
9648 | } |
9649 | continue; |
9650 | } |
9651 | |
9652 | MOZ_ASSERT(kind == PropertyEmitter::Kind::Static)do { static_assert( mozilla::detail::AssertionConditionType< decltype(kind == PropertyEmitter::Kind::Static)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(! !(kind == PropertyEmitter::Kind::Static))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("kind == PropertyEmitter::Kind::Static" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9652); AnnotateMozCrashReason("MOZ_ASSERT" "(" "kind == PropertyEmitter::Kind::Static" ")"); do { *((volatile int*)__null) = 9652; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9653 | |
9654 | // [stack] CTOR OBJ |
9655 | |
9656 | if (!pe.prepareForPrivateStaticMethod(propdef->pn_pos.begin)) { |
9657 | // [stack] CTOR OBJ CTOR |
9658 | return false; |
9659 | } |
9660 | if (!emitGetPrivateName(privateName)) { |
9661 | // [stack] CTOR OBJ CTOR KEY |
9662 | return false; |
9663 | } |
9664 | if (!emitValue()) { |
9665 | // [stack] CTOR OBJ CTOR KEY VAL |
9666 | return false; |
9667 | } |
9668 | |
9669 | if (!pe.emitPrivateStaticMethod(accessorType)) { |
9670 | // [stack] CTOR OBJ |
9671 | return false; |
9672 | } |
9673 | |
9674 | if (privateName->privateNameKind() == PrivateNameKind::Setter) { |
9675 | if (!emitDupAt(1)) { |
9676 | // [stack] CTOR OBJ CTOR |
9677 | return false; |
9678 | } |
9679 | if (!emitGetPrivateName(privateName)) { |
9680 | // [stack] CTOR OBJ CTOR NAME |
9681 | return false; |
9682 | } |
9683 | if (!emitAtomOp(JSOp::GetIntrinsic, |
9684 | TaggedParserAtomIndex::WellKnown::NoPrivateGetter())) { |
9685 | // [stack] CTOR OBJ CTOR NAME FUN |
9686 | return false; |
9687 | } |
9688 | if (!emit1(JSOp::InitHiddenElemGetter)) { |
9689 | // [stack] CTOR OBJ CTOR |
9690 | return false; |
9691 | } |
9692 | if (!emit1(JSOp::Pop)) { |
9693 | // [stack] CTOR OBJ |
9694 | return false; |
9695 | } |
9696 | } |
9697 | } |
9698 | |
9699 | return true; |
9700 | } |
9701 | |
9702 | bool BytecodeEmitter::emitPropertyListObjLiteral(ListNode* obj, JSOp op, |
9703 | bool useObjLiteralValues) { |
9704 | ObjLiteralWriter writer; |
9705 | |
9706 | #ifdef DEBUG1 |
9707 | // In self-hosted JS, we check duplication only on debug build. |
9708 | mozilla::Maybe<mozilla::HashSet<frontend::TaggedParserAtomIndex, |
9709 | frontend::TaggedParserAtomIndexHasher>> |
9710 | selfHostedPropNames; |
9711 | if (emitterMode == BytecodeEmitter::SelfHosting) { |
9712 | selfHostedPropNames.emplace(); |
9713 | } |
9714 | #endif |
9715 | |
9716 | if (op == JSOp::Object) { |
9717 | writer.beginObject(op); |
9718 | } else { |
9719 | MOZ_ASSERT(op == JSOp::NewObject)do { static_assert( mozilla::detail::AssertionConditionType< decltype(op == JSOp::NewObject)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(op == JSOp::NewObject))), 0) )) { do { } while (false); MOZ_ReportAssertionFailure("op == JSOp::NewObject" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9719); AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::NewObject" ")"); do { *((volatile int*)__null) = 9719; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9720 | writer.beginShape(op); |
9721 | } |
9722 | |
9723 | for (ParseNode* propdef : obj->contents()) { |
9724 | BinaryNode* prop = &propdef->as<BinaryNode>(); |
9725 | ParseNode* key = prop->left(); |
9726 | |
9727 | if (key->is<NameNode>()) { |
9728 | if (emitterMode == BytecodeEmitter::SelfHosting) { |
9729 | auto propName = key->as<NameNode>().atom(); |
9730 | #ifdef DEBUG1 |
9731 | // Self-hosted JS shouldn't contain duplicate properties. |
9732 | auto p = selfHostedPropNames->lookupForAdd(propName); |
9733 | MOZ_ASSERT(!p)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!p)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(!p))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("!p", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9733); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!p" ")"); do { *((volatile int*)__null) = 9733; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); |
9734 | if (!selfHostedPropNames->add(p, propName)) { |
9735 | js::ReportOutOfMemory(fc); |
9736 | return false; |
9737 | } |
9738 | #endif |
9739 | writer.setPropNameNoDuplicateCheck(parserAtoms(), propName); |
9740 | } else { |
9741 | if (!writer.setPropName(parserAtoms(), key->as<NameNode>().atom())) { |
9742 | return false; |
9743 | } |
9744 | } |
9745 | } else { |
9746 | double numValue = key->as<NumericLiteral>().value(); |
9747 | int32_t i = 0; |
9748 | DebugOnly<bool> numIsInt = |
9749 | NumberIsInt32(numValue, &i); // checked previously. |
9750 | MOZ_ASSERT(numIsInt)do { static_assert( mozilla::detail::AssertionConditionType< decltype(numIsInt)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(numIsInt))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("numIsInt", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9750); AnnotateMozCrashReason("MOZ_ASSERT" "(" "numIsInt" ")" ); do { *((volatile int*)__null) = 9750; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9751 | MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType< decltype(ObjLiteralWriter::arrayIndexInRange(i))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(ObjLiteralWriter::arrayIndexInRange(i)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("ObjLiteralWriter::arrayIndexInRange(i)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9752); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ObjLiteralWriter::arrayIndexInRange(i)" ")"); do { *((volatile int*)__null) = 9752; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
9752 | ObjLiteralWriter::arrayIndexInRange(i))do { static_assert( mozilla::detail::AssertionConditionType< decltype(ObjLiteralWriter::arrayIndexInRange(i))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(ObjLiteralWriter::arrayIndexInRange(i)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("ObjLiteralWriter::arrayIndexInRange(i)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9752); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ObjLiteralWriter::arrayIndexInRange(i)" ")"); do { *((volatile int*)__null) = 9752; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); // checked previously. |
9753 | |
9754 | // Ignore indexed properties if we're not storing property values, and |
9755 | // rely on InitElem ops to define those. These properties will be either |
9756 | // dense elements (not possible to represent in the literal's shape) or |
9757 | // sparse elements (enumerated separately, so this doesn't affect property |
9758 | // iteration order). |
9759 | if (!useObjLiteralValues) { |
9760 | continue; |
9761 | } |
9762 | |
9763 | writer.setPropIndex(i); |
9764 | } |
9765 | |
9766 | if (useObjLiteralValues) { |
9767 | MOZ_ASSERT(op == JSOp::Object)do { static_assert( mozilla::detail::AssertionConditionType< decltype(op == JSOp::Object)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(op == JSOp::Object))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("op == JSOp::Object" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9767); AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::Object" ")"); do { *((volatile int*)__null) = 9767; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9768 | ParseNode* value = prop->right(); |
9769 | if (!emitObjLiteralValue(writer, value)) { |
9770 | return false; |
9771 | } |
9772 | } else { |
9773 | if (!writer.propWithUndefinedValue(fc)) { |
9774 | return false; |
9775 | } |
9776 | } |
9777 | } |
9778 | |
9779 | GCThingIndex index; |
9780 | if (!addObjLiteralData(writer, &index)) { |
9781 | return false; |
9782 | } |
9783 | |
9784 | // JSOp::Object may only be used by (top-level) run-once scripts. |
9785 | MOZ_ASSERT_IF(op == JSOp::Object,do { if (op == JSOp::Object) { do { static_assert( mozilla::detail ::AssertionConditionType<decltype(sc->isTopLevelContext () && sc->treatAsRunOnce())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(sc->isTopLevelContext() && sc->treatAsRunOnce()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("sc->isTopLevelContext() && sc->treatAsRunOnce()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9786); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isTopLevelContext() && sc->treatAsRunOnce()" ")"); do { *((volatile int*)__null) = 9786; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
9786 | sc->isTopLevelContext() && sc->treatAsRunOnce())do { if (op == JSOp::Object) { do { static_assert( mozilla::detail ::AssertionConditionType<decltype(sc->isTopLevelContext () && sc->treatAsRunOnce())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(sc->isTopLevelContext() && sc->treatAsRunOnce()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("sc->isTopLevelContext() && sc->treatAsRunOnce()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9786); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isTopLevelContext() && sc->treatAsRunOnce()" ")"); do { *((volatile int*)__null) = 9786; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
9787 | |
9788 | if (!emitGCIndexOp(op, index)) { |
9789 | // [stack] OBJ |
9790 | return false; |
9791 | } |
9792 | |
9793 | return true; |
9794 | } |
9795 | |
9796 | bool BytecodeEmitter::emitDestructuringRestExclusionSetObjLiteral( |
9797 | ListNode* pattern) { |
9798 | // Note: if we want to squeeze out a little more performance, we could switch |
9799 | // to the `JSOp::Object` opcode, because the exclusion set object is never |
9800 | // exposed to the user, so it's safe to bake the object into the bytecode. |
9801 | constexpr JSOp op = JSOp::NewObject; |
9802 | |
9803 | ObjLiteralWriter writer; |
9804 | writer.beginShape(op); |
9805 | |
9806 | for (ParseNode* member : pattern->contents()) { |
9807 | if (member->isKind(ParseNodeKind::Spread)) { |
9808 | MOZ_ASSERT(!member->pn_next, "unexpected trailing element after spread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!member->pn_next)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!member->pn_next))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!member->pn_next" " (" "unexpected trailing element after spread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9808); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!member->pn_next" ") (" "unexpected trailing element after spread" ")"); do { * ((volatile int*)__null) = 9808; __attribute__((nomerge)) ::abort (); } while (false); } } while (false); |
9809 | break; |
9810 | } |
9811 | |
9812 | TaggedParserAtomIndex atom; |
9813 | if (member->isKind(ParseNodeKind::MutateProto)) { |
9814 | atom = TaggedParserAtomIndex::WellKnown::proto_(); |
9815 | } else { |
9816 | ParseNode* key = member->as<BinaryNode>().left(); |
9817 | atom = key->as<NameNode>().atom(); |
9818 | } |
9819 | |
9820 | if (!writer.setPropName(parserAtoms(), atom)) { |
9821 | return false; |
9822 | } |
9823 | |
9824 | if (!writer.propWithUndefinedValue(fc)) { |
9825 | return false; |
9826 | } |
9827 | } |
9828 | |
9829 | GCThingIndex index; |
9830 | if (!addObjLiteralData(writer, &index)) { |
9831 | return false; |
9832 | } |
9833 | |
9834 | if (!emitGCIndexOp(op, index)) { |
9835 | // [stack] OBJ |
9836 | return false; |
9837 | } |
9838 | |
9839 | return true; |
9840 | } |
9841 | |
9842 | bool BytecodeEmitter::emitObjLiteralArray(ListNode* array) { |
9843 | MOZ_ASSERT(checkSingletonContext())do { static_assert( mozilla::detail::AssertionConditionType< decltype(checkSingletonContext())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(checkSingletonContext()))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("checkSingletonContext()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9843); AnnotateMozCrashReason("MOZ_ASSERT" "(" "checkSingletonContext()" ")"); do { *((volatile int*)__null) = 9843; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9844 | |
9845 | constexpr JSOp op = JSOp::Object; |
9846 | |
9847 | ObjLiteralWriter writer; |
9848 | writer.beginArray(op); |
9849 | |
9850 | writer.beginDenseArrayElements(); |
9851 | for (ParseNode* elem : array->contents()) { |
9852 | if (!emitObjLiteralValue(writer, elem)) { |
9853 | return false; |
9854 | } |
9855 | } |
9856 | |
9857 | GCThingIndex index; |
9858 | if (!addObjLiteralData(writer, &index)) { |
9859 | return false; |
9860 | } |
9861 | |
9862 | if (!emitGCIndexOp(op, index)) { |
9863 | // [stack] OBJ |
9864 | return false; |
9865 | } |
9866 | |
9867 | return true; |
9868 | } |
9869 | |
9870 | bool BytecodeEmitter::isRHSObjLiteralCompatible(ParseNode* value) { |
9871 | return value->isKind(ParseNodeKind::NumberExpr) || |
9872 | value->isKind(ParseNodeKind::TrueExpr) || |
9873 | value->isKind(ParseNodeKind::FalseExpr) || |
9874 | value->isKind(ParseNodeKind::NullExpr) || |
9875 | value->isKind(ParseNodeKind::RawUndefinedExpr) || |
9876 | value->isKind(ParseNodeKind::StringExpr) || |
9877 | value->isKind(ParseNodeKind::TemplateStringExpr); |
9878 | } |
9879 | |
9880 | bool BytecodeEmitter::emitObjLiteralValue(ObjLiteralWriter& writer, |
9881 | ParseNode* value) { |
9882 | MOZ_ASSERT(isRHSObjLiteralCompatible(value))do { static_assert( mozilla::detail::AssertionConditionType< decltype(isRHSObjLiteralCompatible(value))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(isRHSObjLiteralCompatible(value )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("isRHSObjLiteralCompatible(value)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9882); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isRHSObjLiteralCompatible(value)" ")"); do { *((volatile int*)__null) = 9882; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
9883 | if (value->isKind(ParseNodeKind::NumberExpr)) { |
9884 | double numValue = value->as<NumericLiteral>().value(); |
9885 | int32_t i = 0; |
9886 | js::Value v; |
9887 | if (NumberIsInt32(numValue, &i)) { |
9888 | v.setInt32(i); |
9889 | } else { |
9890 | v.setDouble(numValue); |
9891 | } |
9892 | if (!writer.propWithConstNumericValue(fc, v)) { |
9893 | return false; |
9894 | } |
9895 | } else if (value->isKind(ParseNodeKind::TrueExpr)) { |
9896 | if (!writer.propWithTrueValue(fc)) { |
9897 | return false; |
9898 | } |
9899 | } else if (value->isKind(ParseNodeKind::FalseExpr)) { |
9900 | if (!writer.propWithFalseValue(fc)) { |
9901 | return false; |
9902 | } |
9903 | } else if (value->isKind(ParseNodeKind::NullExpr)) { |
9904 | if (!writer.propWithNullValue(fc)) { |
9905 | return false; |
9906 | } |
9907 | } else if (value->isKind(ParseNodeKind::RawUndefinedExpr)) { |
9908 | if (!writer.propWithUndefinedValue(fc)) { |
9909 | return false; |
9910 | } |
9911 | } else if (value->isKind(ParseNodeKind::StringExpr) || |
9912 | value->isKind(ParseNodeKind::TemplateStringExpr)) { |
9913 | if (!writer.propWithAtomValue(fc, parserAtoms(), |
9914 | value->as<NameNode>().atom())) { |
9915 | return false; |
9916 | } |
9917 | } else { |
9918 | MOZ_CRASH("Unexpected parse node")do { do { } while (false); MOZ_ReportCrash("" "Unexpected parse node" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 9918); AnnotateMozCrashReason("MOZ_CRASH(" "Unexpected parse node" ")"); do { *((volatile int*)__null) = 9918; __attribute__((nomerge )) ::abort(); } while (false); } while (false); |
9919 | } |
9920 | return true; |
9921 | } |
9922 | |
9923 | static bool NeedsPrivateBrand(ParseNode* member) { |
9924 | return member->is<ClassMethod>() && |
9925 | member->as<ClassMethod>().name().isKind(ParseNodeKind::PrivateName) && |
9926 | !member->as<ClassMethod>().isStatic(); |
9927 | } |
9928 | |
9929 | #ifdef ENABLE_DECORATORS |
9930 | static bool HasDecorators(ParseNode* member) { |
9931 | return member->is<ClassMethod>() && member->as<ClassMethod>().decorators(); |
9932 | } |
9933 | #endif |
9934 | |
9935 | mozilla::Maybe<MemberInitializers> BytecodeEmitter::setupMemberInitializers( |
9936 | ListNode* classMembers, FieldPlacement placement) { |
9937 | bool isStatic = placement == FieldPlacement::Static; |
9938 | |
9939 | size_t numFields = 0; |
9940 | size_t numPrivateInitializers = 0; |
9941 | bool hasPrivateBrand = false; |
9942 | #ifdef ENABLE_DECORATORS |
9943 | bool hasDecorators = false; |
9944 | #endif |
9945 | for (ParseNode* member : classMembers->contents()) { |
9946 | if (NeedsFieldInitializer(member, isStatic)) { |
9947 | numFields++; |
9948 | } else if (NeedsAccessorInitializer(member, isStatic)) { |
9949 | numPrivateInitializers++; |
9950 | hasPrivateBrand = true; |
9951 | } else if (NeedsPrivateBrand(member)) { |
9952 | hasPrivateBrand = true; |
9953 | } |
9954 | #ifdef ENABLE_DECORATORS |
9955 | if (!hasDecorators && HasDecorators(member)) { |
9956 | hasDecorators = true; |
9957 | } |
9958 | #endif |
9959 | } |
9960 | |
9961 | // If there are more initializers than can be represented, return invalid. |
9962 | if (numFields + numPrivateInitializers > |
9963 | MemberInitializers::MaxInitializers) { |
9964 | return Nothing(); |
9965 | } |
9966 | return Some(MemberInitializers(hasPrivateBrand, |
9967 | #ifdef ENABLE_DECORATORS |
9968 | hasDecorators, |
9969 | #endif |
9970 | numFields + numPrivateInitializers)); |
9971 | } |
9972 | |
9973 | // Purpose of .fieldKeys: |
9974 | // Computed field names (`["x"] = 2;`) must be ran at class-evaluation time, |
9975 | // not object construction time. The transformation to do so is roughly as |
9976 | // follows: |
9977 | // |
9978 | // class C { |
9979 | // [keyExpr] = valueExpr; |
9980 | // } |
9981 | // --> |
9982 | // let .fieldKeys = [keyExpr]; |
9983 | // let .initializers = [ |
9984 | // () => { |
9985 | // this[.fieldKeys[0]] = valueExpr; |
9986 | // } |
9987 | // ]; |
9988 | // class C { |
9989 | // constructor() { |
9990 | // .initializers[0](); |
9991 | // } |
9992 | // } |
9993 | // |
9994 | // BytecodeEmitter::emitCreateFieldKeys does `let .fieldKeys = [...];` |
9995 | // BytecodeEmitter::emitPropertyList fills in the elements of the array. |
9996 | // See GeneralParser::fieldInitializer for the `this[.fieldKeys[0]]` part. |
9997 | bool BytecodeEmitter::emitCreateFieldKeys(ListNode* obj, |
9998 | FieldPlacement placement) { |
9999 | bool isStatic = placement == FieldPlacement::Static; |
10000 | auto isFieldWithComputedName = [isStatic](ParseNode* propdef) { |
10001 | return propdef->is<ClassField>() && |
10002 | propdef->as<ClassField>().isStatic() == isStatic && |
10003 | propdef->as<ClassField>().name().getKind() == |
10004 | ParseNodeKind::ComputedName; |
10005 | }; |
10006 | |
10007 | size_t numFieldKeys = std::count_if( |
10008 | obj->contents().begin(), obj->contents().end(), isFieldWithComputedName); |
10009 | if (numFieldKeys == 0) { |
10010 | return true; |
10011 | } |
10012 | |
10013 | auto fieldKeys = |
10014 | isStatic ? TaggedParserAtomIndex::WellKnown::dot_staticFieldKeys_() |
10015 | : TaggedParserAtomIndex::WellKnown::dot_fieldKeys_(); |
10016 | NameOpEmitter noe(this, fieldKeys, NameOpEmitter::Kind::Initialize); |
10017 | if (!noe.prepareForRhs()) { |
10018 | return false; |
10019 | } |
10020 | |
10021 | if (!emitUint32Operand(JSOp::NewArray, numFieldKeys)) { |
10022 | // [stack] ARRAY |
10023 | return false; |
10024 | } |
10025 | |
10026 | if (!noe.emitAssignment()) { |
10027 | // [stack] ARRAY |
10028 | return false; |
10029 | } |
10030 | |
10031 | if (!emit1(JSOp::Pop)) { |
10032 | // [stack] |
10033 | return false; |
10034 | } |
10035 | |
10036 | return true; |
10037 | } |
10038 | |
10039 | static bool HasInitializer(ParseNode* node, bool isStaticContext) { |
10040 | return (node->is<ClassField>() && |
10041 | node->as<ClassField>().isStatic() == isStaticContext) || |
10042 | (isStaticContext && node->is<StaticClassBlock>()); |
10043 | } |
10044 | |
10045 | static FunctionNode* GetInitializer(ParseNode* node, bool isStaticContext) { |
10046 | MOZ_ASSERT(HasInitializer(node, isStaticContext))do { static_assert( mozilla::detail::AssertionConditionType< decltype(HasInitializer(node, isStaticContext))>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(! !(HasInitializer(node, isStaticContext)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("HasInitializer(node, isStaticContext)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 10046); AnnotateMozCrashReason("MOZ_ASSERT" "(" "HasInitializer(node, isStaticContext)" ")"); do { *((volatile int*)__null) = 10046; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10047 | MOZ_ASSERT_IF(!node->is<ClassField>(), isStaticContext)do { if (!node->is<ClassField>()) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(isStaticContext )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(isStaticContext))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("isStaticContext", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 10047); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isStaticContext" ")"); do { *((volatile int*)__null) = 10047; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); } } while (false); |
10048 | return node->is<ClassField>() ? node->as<ClassField>().initializer() |
10049 | : node->as<StaticClassBlock>().function(); |
10050 | } |
10051 | |
10052 | static bool IsPrivateInstanceAccessor(const ClassMethod* classMethod) { |
10053 | return !classMethod->isStatic() && |
10054 | classMethod->name().isKind(ParseNodeKind::PrivateName) && |
10055 | classMethod->accessorType() != AccessorType::None; |
10056 | } |
10057 | |
10058 | bool BytecodeEmitter::emitCreateMemberInitializers(ClassEmitter& ce, |
10059 | ListNode* obj, |
10060 | FieldPlacement placement |
10061 | #ifdef ENABLE_DECORATORS |
10062 | , |
10063 | bool hasHeritage |
10064 | #endif |
10065 | ) { |
10066 | // FieldPlacement::Instance, hasHeritage == false |
10067 | // [stack] HOME |
10068 | // |
10069 | // FieldPlacement::Instance, hasHeritage == true |
10070 | // [stack] HOME HERIT |
10071 | // |
10072 | // FieldPlacement::Static |
10073 | // [stack] CTOR HOME |
10074 | #ifdef ENABLE_DECORATORS |
10075 | MOZ_ASSERT_IF(placement == FieldPlacement::Static, !hasHeritage)do { if (placement == FieldPlacement::Static) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(!hasHeritage )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!hasHeritage))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!hasHeritage", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 10075); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!hasHeritage" ")"); do { *((volatile int*)__null) = 10075; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); } } while (false); |
10076 | #endif |
10077 | mozilla::Maybe<MemberInitializers> memberInitializers = |
10078 | setupMemberInitializers(obj, placement); |
10079 | if (!memberInitializers) { |
10080 | ReportAllocationOverflow(fc); |
10081 | return false; |
10082 | } |
10083 | |
10084 | size_t numInitializers = memberInitializers->numMemberInitializers; |
10085 | if (numInitializers == 0) { |
10086 | return true; |
10087 | } |
10088 | |
10089 | bool isStatic = placement == FieldPlacement::Static; |
10090 | if (!ce.prepareForMemberInitializers(numInitializers, isStatic)) { |
10091 | // [stack] HOME HERIT? ARR |
10092 | // or: |
10093 | // [stack] CTOR HOME ARR |
10094 | return false; |
10095 | } |
10096 | |
10097 | // Private accessors could be used in the field initializers, so make sure |
10098 | // accessor initializers appear earlier in the .initializers array so they |
10099 | // run first. Static private methods are not initialized using initializers |
10100 | // (emitPropertyList emits bytecode to stamp them onto the constructor), so |
10101 | // skip this step if isStatic. |
10102 | if (!isStatic) { |
10103 | if (!emitPrivateMethodInitializers(ce, obj)) { |
10104 | return false; |
10105 | } |
10106 | } |
10107 | |
10108 | for (ParseNode* propdef : obj->contents()) { |
10109 | if (!HasInitializer(propdef, isStatic)) { |
10110 | continue; |
10111 | } |
10112 | |
10113 | FunctionNode* initializer = GetInitializer(propdef, isStatic); |
10114 | |
10115 | if (!ce.prepareForMemberInitializer()) { |
10116 | return false; |
10117 | } |
10118 | if (!emitTree(initializer)) { |
10119 | // [stack] HOME HERIT? ARR LAMBDA |
10120 | // or: |
10121 | // [stack] CTOR HOME ARR LAMBDA |
10122 | return false; |
10123 | } |
10124 | if (initializer->funbox()->needsHomeObject()) { |
10125 | MOZ_ASSERT(initializer->funbox()->allowSuperProperty())do { static_assert( mozilla::detail::AssertionConditionType< decltype(initializer->funbox()->allowSuperProperty())> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(initializer->funbox()->allowSuperProperty()))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("initializer->funbox()->allowSuperProperty()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 10125); AnnotateMozCrashReason("MOZ_ASSERT" "(" "initializer->funbox()->allowSuperProperty()" ")"); do { *((volatile int*)__null) = 10125; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10126 | if (!ce.emitMemberInitializerHomeObject(isStatic)) { |
10127 | // [stack] HOME HERIT? ARR LAMBDA |
10128 | // or: |
10129 | // [stack] CTOR HOME ARR LAMBDA |
10130 | return false; |
10131 | } |
10132 | } |
10133 | if (!ce.emitStoreMemberInitializer()) { |
10134 | // [stack] HOME HERIT? ARR |
10135 | // or: |
10136 | // [stack] CTOR HOME ARR |
10137 | return false; |
10138 | } |
10139 | } |
10140 | |
10141 | #ifdef ENABLE_DECORATORS |
10142 | // Index to use to append new initializers returned by decorators to the array |
10143 | if (!emitNumberOp(numInitializers)) { |
10144 | // [stack] HOME HERIT? ARR I |
10145 | // or: |
10146 | // [stack] CTOR HOME ARR I |
10147 | return false; |
10148 | } |
10149 | |
10150 | for (ParseNode* propdef : obj->contents()) { |
10151 | if (!propdef->is<ClassField>()) { |
10152 | continue; |
10153 | } |
10154 | ClassField* field = &propdef->as<ClassField>(); |
10155 | if (field->isStatic() != isStatic) { |
10156 | continue; |
10157 | } |
10158 | if (field->decorators() && !field->decorators()->empty()) { |
10159 | DecoratorEmitter de(this); |
10160 | if (!field->hasAccessor()) { |
10161 | if (!emitDupAt((hasHeritage || isStatic) ? 4 : 3)) { |
10162 | // [stack] ADDINIT HOME HERIT? ARR I ADDINIT |
10163 | // or: |
10164 | // [stack] ADDINIT CTOR HOME ARR I ADDINIT |
10165 | return false; |
10166 | } |
10167 | if (!de.emitApplyDecoratorsToFieldDefinition( |
10168 | &field->name(), field->decorators(), field->isStatic())) { |
10169 | // [stack] HOME HERIT? ARR I ADDINIT INITS |
10170 | // or: |
10171 | // [stack] CTOR HOME ARR I ADDINIT INITS |
10172 | return false; |
10173 | } |
10174 | if (!emit1(JSOp::Swap)) { |
10175 | // [stack] HOME HERIT? ARR I INITS ADDINIT |
10176 | // or: |
10177 | // [stack] CTOR HOME ARR I INITS ADDINIT |
10178 | return false; |
10179 | } |
10180 | if (!emitPopN(1)) { |
10181 | // [stack] ADDINIT HOME HERIT? ARR I INITS |
10182 | // or: |
10183 | // [stack] ADDINIT CTOR HOME ARR I INITS |
10184 | return false; |
10185 | } |
10186 | } else { |
10187 | ClassMethod* accessorGetterNode = field->accessorGetterNode(); |
10188 | auto accessorGetterKeyAtom = |
10189 | accessorGetterNode->left()->as<NameNode>().atom(); |
10190 | ClassMethod* accessorSetterNode = field->accessorSetterNode(); |
10191 | auto accessorSetterKeyAtom = |
10192 | accessorSetterNode->left()->as<NameNode>().atom(); |
10193 | if (!IsPrivateInstanceAccessor(accessorGetterNode)) { |
10194 | if (!emitTree(&accessorGetterNode->method())) { |
10195 | // [stack] ADDINIT HOME HERIT? ARR I GET |
10196 | // or: |
10197 | // [stack] ADDINIT CTOR HOME ARR I GET |
10198 | return false; |
10199 | } |
10200 | if (!emitTree(&accessorSetterNode->method())) { |
10201 | // [stack] ADDINIT HOME HERIT? ARR I GET |
10202 | // SET |
10203 | // or: |
10204 | // [stack] ADDINIT CTOR HOME ARR I GET SET |
10205 | return false; |
10206 | } |
10207 | } else { |
10208 | MOZ_ASSERT(IsPrivateInstanceAccessor(accessorSetterNode))do { static_assert( mozilla::detail::AssertionConditionType< decltype(IsPrivateInstanceAccessor(accessorSetterNode))>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(IsPrivateInstanceAccessor(accessorSetterNode)))), 0) )) { do { } while (false); MOZ_ReportAssertionFailure("IsPrivateInstanceAccessor(accessorSetterNode)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 10208); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsPrivateInstanceAccessor(accessorSetterNode)" ")"); do { *((volatile int*)__null) = 10208; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10209 | auto getAccessor = [this]( |
10210 | ClassMethod* classMethod, |
10211 | TaggedParserAtomIndex& updatedAtom) -> bool { |
10212 | // [stack] |
10213 | |
10214 | // Synthesize a name for the lexical variable that will store the |
10215 | // private method body. |
10216 | TaggedParserAtomIndex name = |
10217 | classMethod->name().as<NameNode>().atom(); |
10218 | AccessorType accessorType = classMethod->accessorType(); |
10219 | StringBuffer storedMethodName(fc); |
10220 | if (!storedMethodName.append(parserAtoms(), name)) { |
10221 | return false; |
10222 | } |
10223 | if (!storedMethodName.append(accessorType == AccessorType::Getter |
10224 | ? ".getter" |
10225 | : ".setter")) { |
10226 | return false; |
10227 | } |
10228 | updatedAtom = storedMethodName.finishParserAtom(parserAtoms(), fc); |
10229 | if (!updatedAtom) { |
10230 | return false; |
10231 | } |
10232 | |
10233 | return emitGetName(updatedAtom); |
10234 | // [stack] ACCESSOR |
10235 | }; |
10236 | |
10237 | if (!getAccessor(accessorGetterNode, accessorGetterKeyAtom)) { |
10238 | // [stack] ADDINIT HOME HERIT? ARR I GET |
10239 | // or: |
10240 | // [stack] ADDINIT CTOR HOME ARR I GET |
10241 | return false; |
10242 | }; |
10243 | |
10244 | if (!getAccessor(accessorSetterNode, accessorSetterKeyAtom)) { |
10245 | // [stack] ADDINIT HOME HERIT? ARR I GET SET |
10246 | // or: |
10247 | // [stack] ADDINIT CTOR HOME ARR I GET SET |
10248 | return false; |
10249 | }; |
10250 | } |
10251 | |
10252 | if (!emitDupAt((hasHeritage || isStatic) ? 6 : 5)) { |
10253 | // [stack] ADDINIT HOME HERIT? ARR I GET SET ADDINIT |
10254 | // or: |
10255 | // [stack] ADDINIT CTOR HOME ARR I GET SET ADDINIT |
10256 | return false; |
10257 | } |
10258 | |
10259 | if (!emitUnpickN(2)) { |
10260 | // [stack] ADDINIT HOME HERIT? ARR I ADDINIT GET SET |
10261 | // or: |
10262 | // [stack] ADDINIT CTOR HOME ARR I ADDINIT GET SET |
10263 | return false; |
10264 | } |
10265 | |
10266 | if (!de.emitApplyDecoratorsToAccessorDefinition( |
10267 | &field->name(), field->decorators(), field->isStatic())) { |
10268 | // [stack] ADDINIT HOME HERIT? ARR I ADDINIT GET SET INITS |
10269 | // or: |
10270 | // [stack] ADDINIT CTOR HOME ARR I ADDINIT GET SET INITS |
10271 | return false; |
10272 | } |
10273 | |
10274 | if (!emitPickN(3)) { |
10275 | // [stack] HOME HERIT? ARR I GET SET INITS ADDINIT |
10276 | // or: |
10277 | // [stack] CTOR HOME ARR I GET SET INITS ADDINIT |
10278 | return false; |
10279 | } |
10280 | |
10281 | if (!emitPopN(1)) { |
10282 | // [stack] ADDINIT HOME HERIT? ARR I GET SET INITS |
10283 | // or: |
10284 | // [stack] ADDINIT CTOR HOME ARR I GET SET INITS |
10285 | return false; |
10286 | } |
10287 | |
10288 | if (!emitUnpickN(2)) { |
10289 | // [stack] ADDINIT HOME HERIT? ARR I INITS GET SET |
10290 | // or: |
10291 | // [stack] ADDINIT CTOR HOME ARR I INITS GET SET |
10292 | return false; |
10293 | } |
10294 | |
10295 | if (!IsPrivateInstanceAccessor(accessorGetterNode)) { |
10296 | if (!isStatic) { |
10297 | if (!emitDupAt(hasHeritage ? 6 : 5)) { |
10298 | // [stack] ADDINIT HOME HERIT? ARR I INITS GET SET HOME |
10299 | return false; |
10300 | } |
10301 | } else { |
10302 | if (!emitDupAt(6)) { |
10303 | // [stack] ADDINIT CTOR HOME ARR I INITS GET SET CTOR |
10304 | return false; |
10305 | } |
10306 | if (!emitDupAt(6)) { |
10307 | // [stack] ADDINIT CTOR HOME ARR I INITS GET SET CTOR HOME |
10308 | return false; |
10309 | } |
10310 | } |
10311 | |
10312 | PropertyEmitter::Kind kind = field->isStatic() |
10313 | ? PropertyEmitter::Kind::Static |
10314 | : PropertyEmitter::Kind::Prototype; |
10315 | if (!accessorGetterNode->name().isKind(ParseNodeKind::PrivateName)) { |
10316 | MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType< decltype(!accessorSetterNode->name().isKind(ParseNodeKind:: PrivateName))>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(!accessorSetterNode->name().isKind (ParseNodeKind::PrivateName)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!accessorSetterNode->name().isKind(ParseNodeKind::PrivateName)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 10317); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!accessorSetterNode->name().isKind(ParseNodeKind::PrivateName)" ")"); do { *((volatile int*)__null) = 10317; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
10317 | !accessorSetterNode->name().isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!accessorSetterNode->name().isKind(ParseNodeKind:: PrivateName))>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(!accessorSetterNode->name().isKind (ParseNodeKind::PrivateName)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!accessorSetterNode->name().isKind(ParseNodeKind::PrivateName)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 10317); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!accessorSetterNode->name().isKind(ParseNodeKind::PrivateName)" ")"); do { *((volatile int*)__null) = 10317; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10318 | |
10319 | if (!ce.prepareForPropValue(propdef->pn_pos.begin, kind)) { |
10320 | // [stack] ADDINIT HOME HERIT? ARR I INITS GET SET HOME |
10321 | // or: |
10322 | // [stack] ADDINIT CTOR HOME ARR I INITS GET SET CTOR HOME CTOR |
10323 | return false; |
10324 | } |
10325 | if (!emitPickN(isStatic ? 3 : 1)) { |
10326 | // [stack] ADDINIT HOME HERIT? ARR I INITS GET HOME SET |
10327 | // or: |
10328 | // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME CTOR SET |
10329 | return false; |
10330 | } |
10331 | if (!ce.emitInit(AccessorType::Setter, accessorSetterKeyAtom)) { |
10332 | // [stack] ADDINIT HOME HERIT? ARR I INITS GET HOME |
10333 | // or: |
10334 | // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME |
10335 | return false; |
10336 | } |
10337 | |
10338 | if (!ce.prepareForPropValue(propdef->pn_pos.begin, kind)) { |
10339 | // [stack] ADDINIT HOME HERIT? ARR I INITS GET HOME |
10340 | // or: |
10341 | // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME CTOR |
10342 | return false; |
10343 | } |
10344 | if (!emitPickN(isStatic ? 3 : 1)) { |
10345 | // [stack] ADDINIT HOME HERIT? ARR I INITS HOME GET |
10346 | // or: |
10347 | // [stack] ADDINIT CTOR HOME ARR I INITS CTOR HOME CTOR GET |
10348 | return false; |
10349 | } |
10350 | if (!ce.emitInit(AccessorType::Getter, accessorGetterKeyAtom)) { |
10351 | // [stack] ADDINIT HOME HERIT? ARR I INITS HOME |
10352 | // or: |
10353 | // [stack] ADDINIT CTOR HOME ARR I INITS CTOR HOME |
10354 | return false; |
10355 | } |
10356 | } else { |
10357 | MOZ_ASSERT(isStatic)do { static_assert( mozilla::detail::AssertionConditionType< decltype(isStatic)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(isStatic))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("isStatic", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 10357); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isStatic" ")" ); do { *((volatile int*)__null) = 10357; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
10358 | // The getter and setter share the same name. |
10359 | if (!emitNewPrivateName(accessorSetterKeyAtom, |
10360 | accessorSetterKeyAtom)) { |
10361 | return false; |
10362 | } |
10363 | if (!ce.prepareForPrivateStaticMethod(propdef->pn_pos.begin)) { |
10364 | // [stack] ADDINIT CTOR HOME ARR I INITS GET SET CTOR HOME CTOR |
10365 | return false; |
10366 | } |
10367 | if (!emitGetPrivateName( |
10368 | &accessorSetterNode->name().as<NameNode>())) { |
10369 | // [stack] ADDINIT CTOR HOME ARR I INITS GET SET CTOR HOME CTOR |
10370 | // KEY |
10371 | return false; |
10372 | } |
10373 | if (!emitPickN(4)) { |
10374 | // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME CTOR KEY |
10375 | // SET |
10376 | return false; |
10377 | } |
10378 | if (!ce.emitPrivateStaticMethod(AccessorType::Setter)) { |
10379 | // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME |
10380 | return false; |
10381 | } |
10382 | |
10383 | if (!ce.prepareForPrivateStaticMethod(propdef->pn_pos.begin)) { |
10384 | // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME CTOR |
10385 | return false; |
10386 | } |
10387 | if (!emitGetPrivateName( |
10388 | &accessorGetterNode->name().as<NameNode>())) { |
10389 | // [stack] ADDINIT CTOR HOME ARR I INITS GET CTOR HOME CTOR KEY |
10390 | return false; |
10391 | } |
10392 | if (!emitPickN(4)) { |
10393 | // [stack] ADDINIT CTOR HOME ARR I INITS CTOR HOME CTOR KEY GET |
10394 | return false; |
10395 | } |
10396 | if (!ce.emitPrivateStaticMethod(AccessorType::Getter)) { |
10397 | // [stack] ADDINIT CTOR HOME ARR I INITS CTOR HOME |
10398 | return false; |
10399 | } |
10400 | } |
10401 | |
10402 | if (!isStatic) { |
10403 | if (!emitPopN(1)) { |
10404 | // [stack] ADDINIT HOME HERIT? ARR I INITS |
10405 | return false; |
10406 | } |
10407 | } else { |
10408 | if (!emitPopN(2)) { |
10409 | // [stack] ADDINIT CTOR HOME ARR I INITS |
10410 | return false; |
10411 | } |
10412 | } |
10413 | } else { |
10414 | MOZ_ASSERT(IsPrivateInstanceAccessor(accessorSetterNode))do { static_assert( mozilla::detail::AssertionConditionType< decltype(IsPrivateInstanceAccessor(accessorSetterNode))>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(IsPrivateInstanceAccessor(accessorSetterNode)))), 0) )) { do { } while (false); MOZ_ReportAssertionFailure("IsPrivateInstanceAccessor(accessorSetterNode)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 10414); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsPrivateInstanceAccessor(accessorSetterNode)" ")"); do { *((volatile int*)__null) = 10414; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10415 | |
10416 | if (!emitLexicalInitialization(accessorSetterKeyAtom)) { |
10417 | // [stack] ADDINIT HOME HERIT? ARR I INITS GET SET |
10418 | // or: |
10419 | // [stack] ADDINIT CTOR HOME ARR I INITS GET SET |
10420 | return false; |
10421 | } |
10422 | |
10423 | if (!emitPopN(1)) { |
10424 | // [stack] ADDINIT HOME HERIT? ARR I INITS GET |
10425 | // or: |
10426 | // [stack] ADDINIT CTOR HOME ARR I INITS GET |
10427 | return false; |
10428 | } |
10429 | |
10430 | if (!emitLexicalInitialization(accessorGetterKeyAtom)) { |
10431 | // [stack] ADDINIT HOME HERIT? ARR I INITS GET |
10432 | // or: |
10433 | // [stack] ADDINIT CTOR HOME ARR I INITS GET |
10434 | return false; |
10435 | } |
10436 | |
10437 | if (!emitPopN(1)) { |
10438 | // [stack] ADDINIT HOME HERIT? ARR I INITS |
10439 | // or: |
10440 | // [stack] ADDINIT CTOR HOME ARR I INITS |
10441 | return false; |
10442 | } |
10443 | } |
10444 | } |
10445 | if (!emit1(JSOp::InitElemInc)) { |
10446 | // [stack] ADDINIT HOME HERIT? ARR I |
10447 | // or: |
10448 | // [stack] ADDINIT CTOR HOME ARR I |
10449 | return false; |
10450 | } |
10451 | } |
10452 | } |
10453 | |
10454 | // Pop I |
10455 | if (!emitPopN(1)) { |
10456 | // [stack] ADDINIT HOME HERIT? ARR |
10457 | // or: |
10458 | // [stack] ADDINIT CTOR HOME ARR |
10459 | return false; |
10460 | } |
10461 | #endif |
10462 | |
10463 | if (!ce.emitMemberInitializersEnd()) { |
10464 | // [stack] ADDINIT HOME HERIT? |
10465 | // or: |
10466 | // [stack] ADDINIT CTOR HOME |
10467 | return false; |
10468 | } |
10469 | |
10470 | return true; |
10471 | } |
10472 | |
10473 | bool BytecodeEmitter::emitPrivateMethodInitializers(ClassEmitter& ce, |
10474 | ListNode* obj) { |
10475 | for (ParseNode* propdef : obj->contents()) { |
10476 | if (!propdef->is<ClassMethod>()) { |
10477 | continue; |
10478 | } |
10479 | auto* classMethod = &propdef->as<ClassMethod>(); |
10480 | |
10481 | // Skip over anything which isn't a private instance accessor. |
10482 | if (!IsPrivateInstanceAccessor(classMethod)) { |
10483 | continue; |
10484 | } |
10485 | |
10486 | if (!ce.prepareForMemberInitializer()) { |
10487 | // [stack] HOMEOBJ HERITAGE? ARRAY |
10488 | // or: |
10489 | // [stack] CTOR HOMEOBJ ARRAY |
10490 | return false; |
10491 | } |
10492 | |
10493 | // Synthesize a name for the lexical variable that will store the |
10494 | // private method body. |
10495 | TaggedParserAtomIndex name = classMethod->name().as<NameNode>().atom(); |
10496 | AccessorType accessorType = classMethod->accessorType(); |
10497 | StringBuffer storedMethodName(fc); |
10498 | if (!storedMethodName.append(parserAtoms(), name)) { |
10499 | return false; |
10500 | } |
10501 | if (!storedMethodName.append( |
10502 | accessorType == AccessorType::Getter ? ".getter" : ".setter")) { |
10503 | return false; |
10504 | } |
10505 | auto storedMethodAtom = |
10506 | storedMethodName.finishParserAtom(parserAtoms(), fc); |
10507 | |
10508 | // Emit the private method body and store it as a lexical var. |
10509 | if (!emitFunction(&classMethod->method())) { |
10510 | // [stack] HOMEOBJ HERITAGE? ARRAY METHOD |
10511 | // or: |
10512 | // [stack] CTOR HOMEOBJ ARRAY METHOD |
10513 | return false; |
10514 | } |
10515 | // The private method body needs to access the home object, |
10516 | // and the CE knows where that is on the stack. |
10517 | if (classMethod->method().funbox()->needsHomeObject()) { |
10518 | if (!ce.emitMemberInitializerHomeObject(false)) { |
10519 | // [stack] HOMEOBJ HERITAGE? ARRAY METHOD |
10520 | // or: |
10521 | // [stack] CTOR HOMEOBJ ARRAY METHOD |
10522 | return false; |
10523 | } |
10524 | } |
10525 | if (!emitLexicalInitialization(storedMethodAtom)) { |
10526 | // [stack] HOMEOBJ HERITAGE? ARRAY METHOD |
10527 | // or: |
10528 | // [stack] CTOR HOMEOBJ ARRAY METHOD |
10529 | return false; |
10530 | } |
10531 | if (!emit1(JSOp::Pop)) { |
10532 | // [stack] HOMEOBJ HERITAGE? ARRAY |
10533 | // or: |
10534 | // [stack] CTOR HOMEOBJ ARRAY |
10535 | return false; |
10536 | } |
10537 | |
10538 | if (!emitPrivateMethodInitializer(classMethod, storedMethodAtom)) { |
10539 | // [stack] HOMEOBJ HERITAGE? ARRAY |
10540 | // or: |
10541 | // [stack] CTOR HOMEOBJ ARRAY |
10542 | return false; |
10543 | } |
10544 | |
10545 | // Store the emitted initializer function into the .initializers array. |
10546 | if (!ce.emitStoreMemberInitializer()) { |
10547 | // [stack] HOMEOBJ HERITAGE? ARRAY |
10548 | // or: |
10549 | // [stack] CTOR HOMEOBJ ARRAY |
10550 | return false; |
10551 | } |
10552 | } |
10553 | |
10554 | return true; |
10555 | } |
10556 | |
10557 | bool BytecodeEmitter::emitPrivateMethodInitializer( |
10558 | ClassMethod* classMethod, TaggedParserAtomIndex storedMethodAtom) { |
10559 | MOZ_ASSERT(IsPrivateInstanceAccessor(classMethod))do { static_assert( mozilla::detail::AssertionConditionType< decltype(IsPrivateInstanceAccessor(classMethod))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(IsPrivateInstanceAccessor(classMethod)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsPrivateInstanceAccessor(classMethod)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 10559); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsPrivateInstanceAccessor(classMethod)" ")"); do { *((volatile int*)__null) = 10559; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10560 | |
10561 | auto* name = &classMethod->name().as<NameNode>(); |
10562 | |
10563 | // Emit the synthesized initializer function. |
10564 | FunctionNode* funNode = classMethod->initializerIfPrivate(); |
10565 | MOZ_ASSERT(funNode)do { static_assert( mozilla::detail::AssertionConditionType< decltype(funNode)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(funNode))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("funNode", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 10565); AnnotateMozCrashReason("MOZ_ASSERT" "(" "funNode" ")" ); do { *((volatile int*)__null) = 10565; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
10566 | FunctionBox* funbox = funNode->funbox(); |
10567 | FunctionEmitter fe(this, funbox, funNode->syntaxKind(), |
10568 | FunctionEmitter::IsHoisted::No); |
10569 | if (!fe.prepareForNonLazy()) { |
10570 | // [stack] |
10571 | return false; |
10572 | } |
10573 | |
10574 | BytecodeEmitter bce2(this, funbox); |
10575 | if (!bce2.init(funNode->pn_pos)) { |
10576 | return false; |
10577 | } |
10578 | ParamsBodyNode* paramsBody = funNode->body(); |
10579 | FunctionScriptEmitter fse(&bce2, funbox, Nothing(), Nothing()); |
10580 | if (!fse.prepareForParameters()) { |
10581 | // [stack] |
10582 | return false; |
10583 | } |
10584 | if (!bce2.emitFunctionFormalParameters(paramsBody)) { |
10585 | // [stack] |
10586 | return false; |
10587 | } |
10588 | if (!fse.prepareForBody()) { |
10589 | // [stack] |
10590 | return false; |
10591 | } |
10592 | |
10593 | if (!bce2.emit1(JSOp::FunctionThis)) { |
10594 | // [stack] THIS |
10595 | return false; |
10596 | } |
10597 | if (!bce2.emitGetPrivateName(name)) { |
10598 | // [stack] THIS NAME |
10599 | return false; |
10600 | } |
10601 | if (!bce2.emitGetName(storedMethodAtom)) { |
10602 | // [stack] THIS NAME METHOD |
10603 | return false; |
10604 | } |
10605 | |
10606 | switch (name->privateNameKind()) { |
10607 | case PrivateNameKind::Setter: |
10608 | if (!bce2.emit1(JSOp::InitHiddenElemSetter)) { |
10609 | // [stack] THIS |
10610 | return false; |
10611 | } |
10612 | if (!bce2.emitGetPrivateName(name)) { |
10613 | // [stack] THIS NAME |
10614 | return false; |
10615 | } |
10616 | if (!bce2.emitAtomOp( |
10617 | JSOp::GetIntrinsic, |
10618 | TaggedParserAtomIndex::WellKnown::NoPrivateGetter())) { |
10619 | // [stack] THIS NAME FUN |
10620 | return false; |
10621 | } |
10622 | if (!bce2.emit1(JSOp::InitHiddenElemGetter)) { |
10623 | // [stack] THIS |
10624 | return false; |
10625 | } |
10626 | break; |
10627 | case PrivateNameKind::Getter: |
10628 | case PrivateNameKind::GetterSetter: |
10629 | if (classMethod->accessorType() == AccessorType::Getter) { |
10630 | if (!bce2.emit1(JSOp::InitHiddenElemGetter)) { |
10631 | // [stack] THIS |
10632 | return false; |
10633 | } |
10634 | } else { |
10635 | if (!bce2.emit1(JSOp::InitHiddenElemSetter)) { |
10636 | // [stack] THIS |
10637 | return false; |
10638 | } |
10639 | } |
10640 | break; |
10641 | default: |
10642 | MOZ_CRASH("Invalid op")do { do { } while (false); MOZ_ReportCrash("" "Invalid op", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 10642); AnnotateMozCrashReason("MOZ_CRASH(" "Invalid op" ")" ); do { *((volatile int*)__null) = 10642; __attribute__((nomerge )) ::abort(); } while (false); } while (false); |
10643 | } |
10644 | |
10645 | // Pop remaining THIS. |
10646 | if (!bce2.emit1(JSOp::Pop)) { |
10647 | // [stack] |
10648 | return false; |
10649 | } |
10650 | |
10651 | if (!fse.emitEndBody()) { |
10652 | // [stack] |
10653 | return false; |
10654 | } |
10655 | if (!fse.intoStencil()) { |
10656 | return false; |
10657 | } |
10658 | |
10659 | if (!fe.emitNonLazyEnd()) { |
10660 | // [stack] HOMEOBJ HERITAGE? ARRAY FUN |
10661 | // or: |
10662 | // [stack] CTOR HOMEOBJ ARRAY FUN |
10663 | return false; |
10664 | } |
10665 | |
10666 | return true; |
10667 | } |
10668 | |
10669 | const MemberInitializers& BytecodeEmitter::findMemberInitializersForCall() { |
10670 | for (BytecodeEmitter* current = this; current; current = current->parent) { |
10671 | if (current->sc->isFunctionBox()) { |
10672 | FunctionBox* funbox = current->sc->asFunctionBox(); |
10673 | |
10674 | if (funbox->isArrow()) { |
10675 | continue; |
10676 | } |
10677 | |
10678 | // If we found a non-arrow / non-constructor we were never allowed to |
10679 | // expect fields in the first place. |
10680 | MOZ_RELEASE_ASSERT(funbox->isClassConstructor())do { static_assert( mozilla::detail::AssertionConditionType< decltype(funbox->isClassConstructor())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(funbox->isClassConstructor ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("funbox->isClassConstructor()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 10680); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "funbox->isClassConstructor()" ")"); do { *((volatile int*)__null) = 10680; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10681 | |
10682 | return funbox->useMemberInitializers() ? funbox->memberInitializers() |
10683 | : MemberInitializers::Empty(); |
10684 | } |
10685 | } |
10686 | |
10687 | MOZ_RELEASE_ASSERT(compilationState.scopeContext.memberInitializers)do { static_assert( mozilla::detail::AssertionConditionType< decltype(compilationState.scopeContext.memberInitializers)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(compilationState.scopeContext.memberInitializers))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("compilationState.scopeContext.memberInitializers" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 10687); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "compilationState.scopeContext.memberInitializers" ")"); do { *((volatile int*)__null) = 10687; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10688 | return *compilationState.scopeContext.memberInitializers; |
10689 | } |
10690 | |
10691 | bool BytecodeEmitter::emitInitializeInstanceMembers( |
10692 | bool isDerivedClassConstructor) { |
10693 | const MemberInitializers& memberInitializers = |
10694 | findMemberInitializersForCall(); |
10695 | MOZ_ASSERT(memberInitializers.valid)do { static_assert( mozilla::detail::AssertionConditionType< decltype(memberInitializers.valid)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(memberInitializers.valid))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("memberInitializers.valid" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 10695); AnnotateMozCrashReason("MOZ_ASSERT" "(" "memberInitializers.valid" ")"); do { *((volatile int*)__null) = 10695; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
10696 | |
10697 | if (memberInitializers.hasPrivateBrand) { |
10698 | // This is guaranteed to run after super(), so we don't need TDZ checks. |
10699 | if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_this_())) { |
10700 | // [stack] THIS |
10701 | return false; |
10702 | } |
10703 | if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_privateBrand_())) { |
10704 | // [stack] THIS BRAND |
10705 | return false; |
10706 | } |
10707 | if (isDerivedClassConstructor) { |
10708 | if (!emitCheckPrivateField(ThrowCondition::ThrowHas, |
10709 | ThrowMsgKind::PrivateBrandDoubleInit)) { |
10710 | // [stack] THIS BRAND BOOL |
10711 | return false; |
10712 | } |
10713 | if (!emit1(JSOp::Pop)) { |
10714 | // [stack] THIS BRAND |
10715 | return false; |
10716 | } |
10717 | } |
10718 | if (!emit1(JSOp::Null)) { |
10719 | // [stack] THIS BRAND NULL |
10720 | return false; |
10721 | } |
10722 | if (!emit1(JSOp::InitHiddenElem)) { |
10723 | // [stack] THIS |
10724 | return false; |
10725 | } |
10726 | if (!emit1(JSOp::Pop)) { |
10727 | // [stack] |
10728 | return false; |
10729 | } |
10730 | } |
10731 | |
10732 | size_t numInitializers = memberInitializers.numMemberInitializers; |
10733 | if (numInitializers > 0) { |
10734 | if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_initializers_())) { |
10735 | // [stack] ARRAY |
10736 | return false; |
10737 | } |
10738 | |
10739 | for (size_t index = 0; index < numInitializers; index++) { |
10740 | if (index < numInitializers - 1) { |
10741 | // We Dup to keep the array around (it is consumed in the bytecode |
10742 | // below) for next iterations of this loop, except for the last |
10743 | // iteration, which avoids an extra Pop at the end of the loop. |
10744 | if (!emit1(JSOp::Dup)) { |
10745 | // [stack] ARRAY ARRAY |
10746 | return false; |
10747 | } |
10748 | } |
10749 | |
10750 | if (!emitNumberOp(index)) { |
10751 | // [stack] ARRAY? ARRAY INDEX |
10752 | return false; |
10753 | } |
10754 | |
10755 | if (!emit1(JSOp::GetElem)) { |
10756 | // [stack] ARRAY? FUNC |
10757 | return false; |
10758 | } |
10759 | |
10760 | // This is guaranteed to run after super(), so we don't need TDZ checks. |
10761 | if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_this_())) { |
10762 | // [stack] ARRAY? FUNC THIS |
10763 | return false; |
10764 | } |
10765 | |
10766 | // Callee is always internal function. |
10767 | if (!emitCall(JSOp::CallIgnoresRv, 0)) { |
10768 | // [stack] ARRAY? RVAL |
10769 | return false; |
10770 | } |
10771 | |
10772 | if (!emit1(JSOp::Pop)) { |
10773 | // [stack] ARRAY? |
10774 | return false; |
10775 | } |
10776 | } |
10777 | #ifdef ENABLE_DECORATORS |
10778 | if (memberInitializers.hasDecorators) { |
10779 | // Decorators Proposal |
10780 | // https://arai-a.github.io/ecma262-compare/?pr=2417&id=sec-initializeinstanceelements |
10781 | // 4. For each element e of elements, do |
10782 | // 4.a. If elementRecord.[[Kind]] is field or accessor, then |
10783 | // 4.a.i. Perform ? InitializeFieldOrAccessor(O, elementRecord). |
10784 | // |
10785 | |
10786 | // TODO: (See Bug 1817993) At the moment, we're applying the |
10787 | // initialization logic in two steps. The pre-decorator initialization |
10788 | // code runs, stores the initial value, and then we retrieve it here and |
10789 | // apply the initializers added by decorators. We should unify these two |
10790 | // steps. |
10791 | if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_initializers_())) { |
10792 | // [stack] ARRAY |
10793 | return false; |
10794 | } |
10795 | |
10796 | if (!emit1(JSOp::Dup)) { |
10797 | // [stack] ARRAY ARRAY |
10798 | return false; |
10799 | } |
10800 | |
10801 | if (!emitAtomOp(JSOp::GetProp, |
10802 | TaggedParserAtomIndex::WellKnown::length())) { |
10803 | // [stack] ARRAY LENGTH |
10804 | return false; |
10805 | } |
10806 | |
10807 | if (!emitNumberOp(static_cast<double>(numInitializers))) { |
10808 | // [stack] ARRAY LENGTH INDEX |
10809 | return false; |
10810 | } |
10811 | |
10812 | InternalWhileEmitter wh(this); |
10813 | // At this point, we have no context to determine offsets in the |
10814 | // code for this while statement. Ideally, it would correspond to |
10815 | // the field we're initializing. |
10816 | if (!wh.emitCond()) { |
10817 | // [stack] ARRAY LENGTH INDEX |
10818 | return false; |
10819 | } |
10820 | |
10821 | if (!emit1(JSOp::Dup)) { |
10822 | // [stack] ARRAY LENGTH INDEX INDEX |
10823 | return false; |
10824 | } |
10825 | |
10826 | if (!emitDupAt(2)) { |
10827 | // [stack] ARRAY LENGTH INDEX INDEX LENGTH |
10828 | return false; |
10829 | } |
10830 | |
10831 | if (!emit1(JSOp::Lt)) { |
10832 | // [stack] ARRAY LENGTH INDEX BOOL |
10833 | return false; |
10834 | } |
10835 | |
10836 | if (!wh.emitBody()) { |
10837 | // [stack] ARRAY LENGTH INDEX |
10838 | return false; |
10839 | } |
10840 | |
10841 | if (!emitDupAt(2)) { |
10842 | // [stack] ARRAY LENGTH INDEX ARRAY |
10843 | return false; |
10844 | } |
10845 | |
10846 | if (!emitDupAt(1)) { |
10847 | // [stack] ARRAY LENGTH INDEX ARRAY INDEX |
10848 | return false; |
10849 | } |
10850 | |
10851 | // Retrieve initializers for this field |
10852 | if (!emit1(JSOp::GetElem)) { |
10853 | // [stack] ARRAY LENGTH INDEX INITIALIZERS |
10854 | return false; |
10855 | } |
10856 | |
10857 | // This is guaranteed to run after super(), so we don't need TDZ checks. |
10858 | if (!emitGetName(TaggedParserAtomIndex::WellKnown::dot_this_())) { |
10859 | // [stack] ARRAY LENGTH INDEX INITIALIZERS THIS |
10860 | return false; |
10861 | } |
10862 | |
10863 | if (!emit1(JSOp::Swap)) { |
10864 | // [stack] ARRAY LENGTH INDEX THIS INITIALIZERS |
10865 | return false; |
10866 | } |
10867 | |
10868 | DecoratorEmitter de(this); |
10869 | if (!de.emitInitializeFieldOrAccessor()) { |
10870 | // [stack] ARRAY LENGTH INDEX |
10871 | return false; |
10872 | } |
10873 | |
10874 | if (!emit1(JSOp::Inc)) { |
10875 | // [stack] ARRAY LENGTH INDEX |
10876 | return false; |
10877 | } |
10878 | |
10879 | if (!wh.emitEnd()) { |
10880 | // [stack] ARRAY LENGTH INDEX |
10881 | return false; |
10882 | } |
10883 | |
10884 | if (!emitPopN(3)) { |
10885 | // [stack] |
10886 | return false; |
10887 | } |
10888 | // 5. Return unused. |
10889 | |
10890 | if (!de.emitCallExtraInitializers(TaggedParserAtomIndex::WellKnown:: |
10891 | dot_instanceExtraInitializers_())) { |
10892 | return false; |
10893 | } |
10894 | } |
10895 | #endif |
10896 | } |
10897 | return true; |
10898 | } |
10899 | |
10900 | bool BytecodeEmitter::emitInitializeStaticFields(ListNode* classMembers) { |
10901 | auto isStaticField = [](ParseNode* propdef) { |
10902 | return HasInitializer(propdef, true); |
10903 | }; |
10904 | size_t numFields = |
10905 | std::count_if(classMembers->contents().begin(), |
10906 | classMembers->contents().end(), isStaticField); |
10907 | |
10908 | if (numFields == 0) { |
10909 | return true; |
10910 | } |
10911 | |
10912 | if (!emitGetName( |
10913 | TaggedParserAtomIndex::WellKnown::dot_staticInitializers_())) { |
10914 | // [stack] CTOR ARRAY |
10915 | return false; |
10916 | } |
10917 | |
10918 | for (size_t fieldIndex = 0; fieldIndex < numFields; fieldIndex++) { |
10919 | bool hasNext = fieldIndex < numFields - 1; |
10920 | if (hasNext) { |
10921 | // We Dup to keep the array around (it is consumed in the bytecode below) |
10922 | // for next iterations of this loop, except for the last iteration, which |
10923 | // avoids an extra Pop at the end of the loop. |
10924 | if (!emit1(JSOp::Dup)) { |
10925 | // [stack] CTOR ARRAY ARRAY |
10926 | return false; |
10927 | } |
10928 | } |
10929 | |
10930 | if (!emitNumberOp(fieldIndex)) { |
10931 | // [stack] CTOR ARRAY? ARRAY INDEX |
10932 | return false; |
10933 | } |
10934 | |
10935 | if (!emit1(JSOp::GetElem)) { |
10936 | // [stack] CTOR ARRAY? FUNC |
10937 | return false; |
10938 | } |
10939 | |
10940 | if (!emitDupAt(1 + hasNext)) { |
10941 | // [stack] CTOR ARRAY? FUNC CTOR |
10942 | return false; |
10943 | } |
10944 | |
10945 | // Callee is always internal function. |
10946 | if (!emitCall(JSOp::CallIgnoresRv, 0)) { |
10947 | // [stack] CTOR ARRAY? RVAL |
10948 | return false; |
10949 | } |
10950 | |
10951 | if (!emit1(JSOp::Pop)) { |
10952 | // [stack] CTOR ARRAY? |
10953 | return false; |
10954 | } |
10955 | } |
10956 | |
10957 | #ifdef ENABLE_DECORATORS |
10958 | // Decorators Proposal |
10959 | // https://arai-a.github.io/ecma262-compare/?pr=2417&id=sec-initializeinstanceelements |
10960 | // 4. For each element e of elements, do |
10961 | // 4.a. If elementRecord.[[Kind]] is field or accessor, then |
10962 | // 4.a.i. Perform ? InitializeFieldOrAccessor(O, elementRecord). |
10963 | // |
10964 | |
10965 | // TODO: (See Bug 1817993) At the moment, we're applying the initialization |
10966 | // logic in two steps. The pre-decorator initialization code runs, stores |
10967 | // the initial value, and then we retrieve it here and apply the |
10968 | // initializers added by decorators. We should unify these two steps. |
10969 | if (!emitGetName( |
10970 | TaggedParserAtomIndex::WellKnown::dot_staticInitializers_())) { |
10971 | // [stack] CTOR ARRAY |
10972 | return false; |
10973 | } |
10974 | |
10975 | if (!emit1(JSOp::Dup)) { |
10976 | // [stack] CTOR ARRAY ARRAY |
10977 | return false; |
10978 | } |
10979 | |
10980 | if (!emitAtomOp(JSOp::GetProp, TaggedParserAtomIndex::WellKnown::length())) { |
10981 | // [stack] CTOR ARRAY LENGTH |
10982 | return false; |
10983 | } |
10984 | |
10985 | if (!emitNumberOp(static_cast<double>(numFields))) { |
10986 | // [stack] CTOR ARRAY LENGTH INDEX |
10987 | return false; |
10988 | } |
10989 | |
10990 | InternalWhileEmitter wh(this); |
10991 | // At this point, we have no context to determine offsets in the |
10992 | // code for this while statement. Ideally, it would correspond to |
10993 | // the field we're initializing. |
10994 | if (!wh.emitCond()) { |
10995 | // [stack] CTOR ARRAY LENGTH INDEX |
10996 | return false; |
10997 | } |
10998 | |
10999 | if (!emit1(JSOp::Dup)) { |
11000 | // [stack] CTOR ARRAY LENGTH INDEX INDEX |
11001 | return false; |
11002 | } |
11003 | |
11004 | if (!emitDupAt(2)) { |
11005 | // [stack] CTOR ARRAY LENGTH INDEX INDEX LENGTH |
11006 | return false; |
11007 | } |
11008 | |
11009 | if (!emit1(JSOp::Lt)) { |
11010 | // [stack] CTOR ARRAY LENGTH INDEX BOOL |
11011 | return false; |
11012 | } |
11013 | |
11014 | if (!wh.emitBody()) { |
11015 | // [stack] CTOR ARRAY LENGTH INDEX |
11016 | return false; |
11017 | } |
11018 | |
11019 | if (!emitDupAt(2)) { |
11020 | // [stack] CTOR ARRAY LENGTH INDEX ARRAY |
11021 | return false; |
11022 | } |
11023 | |
11024 | if (!emitDupAt(1)) { |
11025 | // [stack] CTOR ARRAY LENGTH INDEX ARRAY INDEX |
11026 | return false; |
11027 | } |
11028 | |
11029 | // Retrieve initializers for this field |
11030 | if (!emit1(JSOp::GetElem)) { |
11031 | // [stack] CTOR ARRAY LENGTH INDEX INITIALIZERS |
11032 | return false; |
11033 | } |
11034 | |
11035 | if (!emitDupAt(4)) { |
11036 | // [stack] CTOR ARRAY LENGTH INDEX INITIALIZERS CTOR |
11037 | return false; |
11038 | } |
11039 | |
11040 | if (!emit1(JSOp::Swap)) { |
11041 | // [stack] CTOR ARRAY LENGTH INDEX CTOR INITIALIZERS |
11042 | return false; |
11043 | } |
11044 | |
11045 | DecoratorEmitter de(this); |
11046 | if (!de.emitInitializeFieldOrAccessor()) { |
11047 | // [stack] CTOR ARRAY LENGTH INDEX |
11048 | return false; |
11049 | } |
11050 | |
11051 | if (!emit1(JSOp::Inc)) { |
11052 | // [stack] CTOR ARRAY LENGTH INDEX |
11053 | return false; |
11054 | } |
11055 | |
11056 | if (!wh.emitEnd()) { |
11057 | // [stack] CTOR ARRAY LENGTH INDEX |
11058 | return false; |
11059 | } |
11060 | |
11061 | if (!emitPopN(3)) { |
11062 | // [stack] CTOR |
11063 | return false; |
11064 | } |
11065 | // 5. Return unused. |
11066 | #endif |
11067 | |
11068 | // Overwrite |.staticInitializers| and |.staticFieldKeys| with undefined to |
11069 | // avoid keeping the arrays alive indefinitely. |
11070 | auto clearStaticFieldSlot = [&](TaggedParserAtomIndex name) { |
11071 | NameOpEmitter noe(this, name, NameOpEmitter::Kind::SimpleAssignment); |
11072 | if (!noe.prepareForRhs()) { |
11073 | // [stack] ENV? VAL? |
11074 | return false; |
11075 | } |
11076 | |
11077 | if (!emit1(JSOp::Undefined)) { |
11078 | // [stack] ENV? VAL? UNDEFINED |
11079 | return false; |
11080 | } |
11081 | |
11082 | if (!noe.emitAssignment()) { |
11083 | // [stack] VAL |
11084 | return false; |
11085 | } |
11086 | |
11087 | if (!emit1(JSOp::Pop)) { |
11088 | // [stack] |
11089 | return false; |
11090 | } |
11091 | |
11092 | return true; |
11093 | }; |
11094 | |
11095 | if (!clearStaticFieldSlot( |
11096 | TaggedParserAtomIndex::WellKnown::dot_staticInitializers_())) { |
11097 | return false; |
11098 | } |
11099 | |
11100 | auto isStaticFieldWithComputedName = [](ParseNode* propdef) { |
11101 | return propdef->is<ClassField>() && propdef->as<ClassField>().isStatic() && |
11102 | propdef->as<ClassField>().name().getKind() == |
11103 | ParseNodeKind::ComputedName; |
11104 | }; |
11105 | |
11106 | if (std::any_of(classMembers->contents().begin(), |
11107 | classMembers->contents().end(), |
11108 | isStaticFieldWithComputedName)) { |
11109 | if (!clearStaticFieldSlot( |
11110 | TaggedParserAtomIndex::WellKnown::dot_staticFieldKeys_())) { |
11111 | return false; |
11112 | } |
11113 | } |
11114 | |
11115 | return true; |
11116 | } |
11117 | |
11118 | // Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See |
11119 | // the comment on emitSwitch. |
11120 | MOZ_NEVER_INLINE__attribute__((noinline)) bool BytecodeEmitter::emitObject(ListNode* objNode) { |
11121 | // Note: this method uses the ObjLiteralWriter and emits ObjLiteralStencil |
11122 | // objects into the GCThingList, which will evaluate them into real GC objects |
11123 | // or shapes during JSScript::fullyInitFromEmitter. Eventually we want |
11124 | // JSOp::Object to be a real opcode, but for now, performance constraints |
11125 | // limit us to evaluating object literals at the end of parse, when we're |
11126 | // allowed to allocate GC things. |
11127 | // |
11128 | // There are four cases here, in descending order of preference: |
11129 | // |
11130 | // 1. The list of property names is "normal" and constant (no computed |
11131 | // values, no integer indices), the values are all simple constants |
11132 | // (numbers, booleans, strings), *and* this occurs in a run-once |
11133 | // (singleton) context. In this case, we can emit ObjLiteral |
11134 | // instructions to build an object with values, and the object will be |
11135 | // attached to a JSOp::Object opcode, whose semantics are for the backend |
11136 | // to simply steal the object from the script. |
11137 | // |
11138 | // 2. The list of property names is "normal" and constant as above, *and* this |
11139 | // occurs in a run-once (singleton) context, but some values are complex |
11140 | // (computed expressions, sub-objects, functions, etc.). In this case, we |
11141 | // can still use JSOp::Object (because singleton context), but the object |
11142 | // has |undefined| property values and InitProp ops are emitted to set the |
11143 | // values. |
11144 | // |
11145 | // 3. The list of property names is "normal" and constant as above, but this |
11146 | // occurs in a non-run-once (non-singleton) context. In this case, we can |
11147 | // use the ObjLiteral functionality to describe an *empty* object (all |
11148 | // values left undefined) with the right fields, which will become a |
11149 | // JSOp::NewObject opcode using the object's shape to speed up the creation |
11150 | // of the object each time it executes. The emitted bytecode still needs |
11151 | // InitProp ops to set the values in this case. |
11152 | // |
11153 | // 4. Any other case. As a fallback, we use NewInit to create a new, empty |
11154 | // object (i.e., `{}`) and then emit bytecode to initialize its properties |
11155 | // one-by-one. |
11156 | |
11157 | bool useObjLiteral = false; |
11158 | bool useObjLiteralValues = false; |
11159 | isPropertyListObjLiteralCompatible(objNode, &useObjLiteralValues, |
11160 | &useObjLiteral); |
11161 | |
11162 | // [stack] |
11163 | // |
11164 | ObjectEmitter oe(this); |
11165 | if (useObjLiteral) { |
11166 | bool singleton = checkSingletonContext() && |
11167 | !objNode->hasNonConstInitializer() && objNode->head(); |
11168 | JSOp op; |
11169 | if (singleton) { |
11170 | // Case 1 or 2. |
11171 | op = JSOp::Object; |
11172 | } else { |
11173 | // Case 3. |
11174 | useObjLiteralValues = false; |
11175 | op = JSOp::NewObject; |
11176 | } |
11177 | |
11178 | // Use an ObjLiteral op. This will record ObjLiteral insns in the |
11179 | // objLiteralWriter's buffer and add a fixup to the list of ObjLiteral |
11180 | // fixups so that at GC-publish time at the end of parse, the full object |
11181 | // (case 1 or 2) or shape (case 3) can be allocated and the bytecode can be |
11182 | // patched to refer to it. |
11183 | if (!emitPropertyListObjLiteral(objNode, op, useObjLiteralValues)) { |
11184 | // [stack] OBJ |
11185 | return false; |
11186 | } |
11187 | // Put the ObjectEmitter in the right state. This tells it that there will |
11188 | // already be an object on the stack as a result of the (eventual) |
11189 | // NewObject or Object op, and prepares it to emit values if needed. |
11190 | if (!oe.emitObjectWithTemplateOnStack()) { |
11191 | // [stack] OBJ |
11192 | return false; |
11193 | } |
11194 | if (!useObjLiteralValues) { |
11195 | // Case 2 or 3 above: we still need to emit bytecode to fill in the |
11196 | // object's property values. |
11197 | if (!emitPropertyList(objNode, oe, ObjectLiteral)) { |
11198 | // [stack] OBJ |
11199 | return false; |
11200 | } |
11201 | } |
11202 | } else { |
11203 | // Case 4 above: no ObjLiteral use, just bytecode to build the object from |
11204 | // scratch. |
11205 | if (!oe.emitObject(objNode->count())) { |
11206 | // [stack] OBJ |
11207 | return false; |
11208 | } |
11209 | if (!emitPropertyList(objNode, oe, ObjectLiteral)) { |
11210 | // [stack] OBJ |
11211 | return false; |
11212 | } |
11213 | } |
11214 | |
11215 | if (!oe.emitEnd()) { |
11216 | // [stack] OBJ |
11217 | return false; |
11218 | } |
11219 | |
11220 | return true; |
11221 | } |
11222 | |
11223 | bool BytecodeEmitter::emitArrayLiteral(ListNode* array) { |
11224 | // Emit JSOp::Object if the array consists entirely of primitive values and we |
11225 | // are in a singleton context. |
11226 | if (checkSingletonContext() && !array->hasNonConstInitializer() && |
11227 | !array->empty() && isArrayObjLiteralCompatible(array)) { |
11228 | return emitObjLiteralArray(array); |
11229 | } |
11230 | |
11231 | return emitArray(array); |
11232 | } |
11233 | |
11234 | bool BytecodeEmitter::emitArray(ListNode* array) { |
11235 | /* |
11236 | * Emit code for [a, b, c] that is equivalent to constructing a new |
11237 | * array and in source order evaluating each element value and adding |
11238 | * it to the array, without invoking latent setters. We use the |
11239 | * JSOp::NewInit and JSOp::InitElemArray bytecodes to ignore setters and |
11240 | * to avoid dup'ing and popping the array as each element is added, as |
11241 | * JSOp::SetElem/JSOp::SetProp would do. |
11242 | */ |
11243 | |
11244 | uint32_t nspread = 0; |
11245 | for (ParseNode* elem : array->contents()) { |
11246 | if (elem->isKind(ParseNodeKind::Spread)) { |
11247 | nspread++; |
11248 | } |
11249 | } |
11250 | |
11251 | // Array literal's length is limited to NELEMENTS_LIMIT in parser. |
11252 | static_assert(NativeObject::MAX_DENSE_ELEMENTS_COUNT <= INT32_MAX(2147483647), |
11253 | "array literals' maximum length must not exceed limits " |
11254 | "required by BaselineCompiler::emit_NewArray, " |
11255 | "BaselineCompiler::emit_InitElemArray, " |
11256 | "and DoSetElemFallback's handling of JSOp::InitElemArray"); |
11257 | |
11258 | uint32_t count = array->count(); |
11259 | MOZ_ASSERT(count >= nspread)do { static_assert( mozilla::detail::AssertionConditionType< decltype(count >= nspread)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(count >= nspread))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("count >= nspread" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11259); AnnotateMozCrashReason("MOZ_ASSERT" "(" "count >= nspread" ")"); do { *((volatile int*)__null) = 11259; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
11260 | MOZ_ASSERT(count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT,do { static_assert( mozilla::detail::AssertionConditionType< decltype(count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT" " (" "the parser must throw an error if the array exceeds maximum " "length" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11262); AnnotateMozCrashReason("MOZ_ASSERT" "(" "count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT" ") (" "the parser must throw an error if the array exceeds maximum " "length" ")"); do { *((volatile int*)__null) = 11262; __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false) |
11261 | "the parser must throw an error if the array exceeds maximum "do { static_assert( mozilla::detail::AssertionConditionType< decltype(count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT" " (" "the parser must throw an error if the array exceeds maximum " "length" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11262); AnnotateMozCrashReason("MOZ_ASSERT" "(" "count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT" ") (" "the parser must throw an error if the array exceeds maximum " "length" ")"); do { *((volatile int*)__null) = 11262; __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false) |
11262 | "length")do { static_assert( mozilla::detail::AssertionConditionType< decltype(count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT" " (" "the parser must throw an error if the array exceeds maximum " "length" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11262); AnnotateMozCrashReason("MOZ_ASSERT" "(" "count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT" ") (" "the parser must throw an error if the array exceeds maximum " "length" ")"); do { *((volatile int*)__null) = 11262; __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false); |
11263 | |
11264 | // For arrays with spread, this is a very pessimistic allocation, the |
11265 | // minimum possible final size. |
11266 | if (!emitUint32Operand(JSOp::NewArray, count - nspread)) { |
11267 | // [stack] ARRAY |
11268 | return false; |
11269 | } |
11270 | |
11271 | uint32_t index = 0; |
11272 | bool afterSpread = false; |
11273 | for (ParseNode* elem : array->contents()) { |
11274 | if (elem->isKind(ParseNodeKind::Spread)) { |
11275 | if (!afterSpread) { |
11276 | afterSpread = true; |
11277 | if (!emitNumberOp(index)) { |
11278 | // [stack] ARRAY INDEX |
11279 | return false; |
11280 | } |
11281 | } |
11282 | |
11283 | ParseNode* expr = elem->as<UnaryNode>().kid(); |
11284 | SelfHostedIter selfHostedIter = getSelfHostedIterFor(expr); |
11285 | |
11286 | if (!updateSourceCoordNotes(elem->pn_pos.begin)) { |
11287 | return false; |
11288 | } |
11289 | if (!emitIterable(expr, selfHostedIter)) { |
11290 | // [stack] ARRAY INDEX ITERABLE |
11291 | return false; |
11292 | } |
11293 | if (!emitIterator(selfHostedIter)) { |
11294 | // [stack] ARRAY INDEX NEXT ITER |
11295 | return false; |
11296 | } |
11297 | if (!emit2(JSOp::Pick, 3)) { |
11298 | // [stack] INDEX NEXT ITER ARRAY |
11299 | return false; |
11300 | } |
11301 | if (!emit2(JSOp::Pick, 3)) { |
11302 | // [stack] NEXT ITER ARRAY INDEX |
11303 | return false; |
11304 | } |
11305 | if (!emitSpread(selfHostedIter)) { |
11306 | // [stack] ARRAY INDEX |
11307 | return false; |
11308 | } |
11309 | } else { |
11310 | if (!updateSourceCoordNotesIfNonLiteral(elem)) { |
11311 | return false; |
11312 | } |
11313 | if (elem->isKind(ParseNodeKind::Elision)) { |
11314 | if (!emit1(JSOp::Hole)) { |
11315 | return false; |
11316 | } |
11317 | } else { |
11318 | if (!emitTree(elem, ValueUsage::WantValue)) { |
11319 | // [stack] ARRAY INDEX? VALUE |
11320 | return false; |
11321 | } |
11322 | } |
11323 | |
11324 | if (afterSpread) { |
11325 | if (!emit1(JSOp::InitElemInc)) { |
11326 | // [stack] ARRAY (INDEX+1) |
11327 | return false; |
11328 | } |
11329 | } else { |
11330 | if (!emitUint32Operand(JSOp::InitElemArray, index)) { |
11331 | // [stack] ARRAY |
11332 | return false; |
11333 | } |
11334 | } |
11335 | } |
11336 | |
11337 | index++; |
11338 | } |
11339 | MOZ_ASSERT(index == count)do { static_assert( mozilla::detail::AssertionConditionType< decltype(index == count)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(index == count))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("index == count" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11339); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index == count" ")"); do { *((volatile int*)__null) = 11339; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
11340 | if (afterSpread) { |
11341 | if (!emit1(JSOp::Pop)) { |
11342 | // [stack] ARRAY |
11343 | return false; |
11344 | } |
11345 | } |
11346 | return true; |
11347 | } |
11348 | |
11349 | bool BytecodeEmitter::emitSpreadIntoArray(UnaryNode* elem) { |
11350 | MOZ_ASSERT(elem->isKind(ParseNodeKind::Spread))do { static_assert( mozilla::detail::AssertionConditionType< decltype(elem->isKind(ParseNodeKind::Spread))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(elem->isKind(ParseNodeKind::Spread)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("elem->isKind(ParseNodeKind::Spread)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11350); AnnotateMozCrashReason("MOZ_ASSERT" "(" "elem->isKind(ParseNodeKind::Spread)" ")"); do { *((volatile int*)__null) = 11350; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
11351 | |
11352 | if (!updateSourceCoordNotes(elem->pn_pos.begin)) { |
11353 | // [stack] VALUE |
11354 | return false; |
11355 | } |
11356 | |
11357 | SelfHostedIter selfHostedIter = getSelfHostedIterFor(elem->kid()); |
11358 | MOZ_ASSERT(selfHostedIter == SelfHostedIter::Deny ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(selfHostedIter == SelfHostedIter::Deny || selfHostedIter == SelfHostedIter::AllowContent)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(selfHostedIter == SelfHostedIter ::Deny || selfHostedIter == SelfHostedIter::AllowContent))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter == SelfHostedIter::Deny || selfHostedIter == SelfHostedIter::AllowContent" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11359); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter == SelfHostedIter::Deny || selfHostedIter == SelfHostedIter::AllowContent" ")"); do { *((volatile int*)__null) = 11359; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
11359 | selfHostedIter == SelfHostedIter::AllowContent)do { static_assert( mozilla::detail::AssertionConditionType< decltype(selfHostedIter == SelfHostedIter::Deny || selfHostedIter == SelfHostedIter::AllowContent)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(selfHostedIter == SelfHostedIter ::Deny || selfHostedIter == SelfHostedIter::AllowContent))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("selfHostedIter == SelfHostedIter::Deny || selfHostedIter == SelfHostedIter::AllowContent" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11359); AnnotateMozCrashReason("MOZ_ASSERT" "(" "selfHostedIter == SelfHostedIter::Deny || selfHostedIter == SelfHostedIter::AllowContent" ")"); do { *((volatile int*)__null) = 11359; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
11360 | |
11361 | if (!emitIterator(selfHostedIter)) { |
11362 | // [stack] NEXT ITER |
11363 | return false; |
11364 | } |
11365 | |
11366 | if (!emitUint32Operand(JSOp::NewArray, 0)) { |
11367 | // [stack] NEXT ITER ARRAY |
11368 | return false; |
11369 | } |
11370 | |
11371 | if (!emitNumberOp(0)) { |
11372 | // [stack] NEXT ITER ARRAY INDEX |
11373 | return false; |
11374 | } |
11375 | |
11376 | if (!emitSpread(selfHostedIter)) { |
11377 | // [stack] ARRAY INDEX |
11378 | return false; |
11379 | } |
11380 | |
11381 | if (!emit1(JSOp::Pop)) { |
11382 | // [stack] ARRAY |
11383 | return false; |
11384 | } |
11385 | return true; |
11386 | } |
11387 | |
11388 | #ifdef ENABLE_RECORD_TUPLE |
11389 | bool BytecodeEmitter::emitRecordLiteral(ListNode* record) { |
11390 | if (!emitUint32Operand(JSOp::InitRecord, record->count())) { |
11391 | // [stack] RECORD |
11392 | return false; |
11393 | } |
11394 | |
11395 | for (ParseNode* propdef : record->contents()) { |
11396 | if (propdef->isKind(ParseNodeKind::Spread)) { |
11397 | if (!emitTree(propdef->as<UnaryNode>().kid())) { |
11398 | // [stack] RECORD SPREADEE |
11399 | return false; |
11400 | } |
11401 | if (!emit1(JSOp::AddRecordSpread)) { |
11402 | // [stack] RECORD |
11403 | return false; |
11404 | } |
11405 | } else { |
11406 | BinaryNode* prop = &propdef->as<BinaryNode>(); |
11407 | |
11408 | ParseNode* key = prop->left(); |
11409 | ParseNode* value = prop->right(); |
11410 | |
11411 | switch (key->getKind()) { |
11412 | case ParseNodeKind::ObjectPropertyName: |
11413 | if (!emitStringOp(JSOp::String, key->as<NameNode>().atom())) { |
11414 | return false; |
11415 | } |
11416 | break; |
11417 | case ParseNodeKind::ComputedName: |
11418 | if (!emitTree(key->as<UnaryNode>().kid())) { |
11419 | return false; |
11420 | } |
11421 | break; |
11422 | default: |
11423 | MOZ_ASSERT(key->isKind(ParseNodeKind::StringExpr) ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(key->isKind(ParseNodeKind::StringExpr) || key-> isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind ::BigIntExpr))>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(key->isKind(ParseNodeKind::StringExpr ) || key->isKind(ParseNodeKind::NumberExpr) || key->isKind (ParseNodeKind::BigIntExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11425); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr)" ")"); do { *((volatile int*)__null) = 11425; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
11424 | key->isKind(ParseNodeKind::NumberExpr) ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(key->isKind(ParseNodeKind::StringExpr) || key-> isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind ::BigIntExpr))>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(key->isKind(ParseNodeKind::StringExpr ) || key->isKind(ParseNodeKind::NumberExpr) || key->isKind (ParseNodeKind::BigIntExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11425); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr)" ")"); do { *((volatile int*)__null) = 11425; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
11425 | key->isKind(ParseNodeKind::BigIntExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(key->isKind(ParseNodeKind::StringExpr) || key-> isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind ::BigIntExpr))>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(key->isKind(ParseNodeKind::StringExpr ) || key->isKind(ParseNodeKind::NumberExpr) || key->isKind (ParseNodeKind::BigIntExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11425); AnnotateMozCrashReason("MOZ_ASSERT" "(" "key->isKind(ParseNodeKind::StringExpr) || key->isKind(ParseNodeKind::NumberExpr) || key->isKind(ParseNodeKind::BigIntExpr)" ")"); do { *((volatile int*)__null) = 11425; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
11426 | if (!emitTree(key)) { |
11427 | return false; |
11428 | } |
11429 | break; |
11430 | } |
11431 | // [stack] RECORD KEY |
11432 | |
11433 | if (!emitTree(value)) { |
11434 | // [stack] RECORD KEY VALUE |
11435 | return false; |
11436 | } |
11437 | |
11438 | if (!emit1(JSOp::AddRecordProperty)) { |
11439 | // [stack] RECORD |
11440 | return false; |
11441 | } |
11442 | } |
11443 | } |
11444 | |
11445 | if (!emit1(JSOp::FinishRecord)) { |
11446 | // [stack] RECORD |
11447 | return false; |
11448 | } |
11449 | |
11450 | return true; |
11451 | } |
11452 | |
11453 | bool BytecodeEmitter::emitTupleLiteral(ListNode* tuple) { |
11454 | if (!emitUint32Operand(JSOp::InitTuple, tuple->count())) { |
11455 | // [stack] TUPLE |
11456 | return false; |
11457 | } |
11458 | |
11459 | for (ParseNode* elt : tuple->contents()) { |
11460 | if (elt->isKind(ParseNodeKind::Spread)) { |
11461 | ParseNode* expr = elt->as<UnaryNode>().kid(); |
11462 | auto selfHostedIter = getSelfHostedIterFor(expr); |
11463 | |
11464 | if (!emitIterable(expr, selfHostedIter)) { |
11465 | // [stack] TUPLE ITERABLE |
11466 | return false; |
11467 | } |
11468 | if (!emitIterator(selfHostedIter)) { |
11469 | // [stack] TUPLE NEXT ITER |
11470 | return false; |
11471 | } |
11472 | if (!emit2(JSOp::Pick, 2)) { |
11473 | // [stack] NEXT ITER TUPLE |
11474 | return false; |
11475 | } |
11476 | if (!emitSpread(selfHostedIter, /* spreadeeStackItems = */ 1, |
11477 | JSOp::AddTupleElement)) { |
11478 | // [stack] TUPLE |
11479 | return false; |
11480 | } |
11481 | } else { |
11482 | // Update location to throw errors about non-primitive elements |
11483 | // in the correct position. |
11484 | if (!updateSourceCoordNotesIfNonLiteral(elt)) { |
11485 | return false; |
11486 | } |
11487 | |
11488 | if (!emitTree(elt)) { |
11489 | // [stack] TUPLE VALUE |
11490 | return false; |
11491 | } |
11492 | |
11493 | if (!emit1(JSOp::AddTupleElement)) { |
11494 | // [stack] TUPLE |
11495 | return false; |
11496 | } |
11497 | } |
11498 | } |
11499 | |
11500 | if (!emit1(JSOp::FinishTuple)) { |
11501 | // [stack] TUPLE |
11502 | return false; |
11503 | } |
11504 | |
11505 | return true; |
11506 | } |
11507 | #endif |
11508 | |
11509 | static inline JSOp UnaryOpParseNodeKindToJSOp(ParseNodeKind pnk) { |
11510 | switch (pnk) { |
11511 | case ParseNodeKind::ThrowStmt: |
11512 | return JSOp::Throw; |
11513 | case ParseNodeKind::VoidExpr: |
11514 | return JSOp::Void; |
11515 | case ParseNodeKind::NotExpr: |
11516 | return JSOp::Not; |
11517 | case ParseNodeKind::BitNotExpr: |
11518 | return JSOp::BitNot; |
11519 | case ParseNodeKind::PosExpr: |
11520 | return JSOp::Pos; |
11521 | case ParseNodeKind::NegExpr: |
11522 | return JSOp::Neg; |
11523 | default: |
11524 | MOZ_CRASH("unexpected unary op")do { do { } while (false); MOZ_ReportCrash("" "unexpected unary op" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11524); AnnotateMozCrashReason("MOZ_CRASH(" "unexpected unary op" ")"); do { *((volatile int*)__null) = 11524; __attribute__(( nomerge)) ::abort(); } while (false); } while (false); |
11525 | } |
11526 | } |
11527 | |
11528 | bool BytecodeEmitter::emitUnary(UnaryNode* unaryNode) { |
11529 | if (!updateSourceCoordNotes(unaryNode->pn_pos.begin)) { |
11530 | return false; |
11531 | } |
11532 | |
11533 | JSOp op = UnaryOpParseNodeKindToJSOp(unaryNode->getKind()); |
11534 | ValueUsage valueUsage = |
11535 | op == JSOp::Void ? ValueUsage::IgnoreValue : ValueUsage::WantValue; |
11536 | if (!emitTree(unaryNode->kid(), valueUsage)) { |
11537 | return false; |
11538 | } |
11539 | return emit1(op); |
11540 | } |
11541 | |
11542 | bool BytecodeEmitter::emitTypeof(UnaryNode* typeofNode, JSOp op) { |
11543 | MOZ_ASSERT(op == JSOp::Typeof || op == JSOp::TypeofExpr)do { static_assert( mozilla::detail::AssertionConditionType< decltype(op == JSOp::Typeof || op == JSOp::TypeofExpr)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(op == JSOp::Typeof || op == JSOp::TypeofExpr))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("op == JSOp::Typeof || op == JSOp::TypeofExpr" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11543); AnnotateMozCrashReason("MOZ_ASSERT" "(" "op == JSOp::Typeof || op == JSOp::TypeofExpr" ")"); do { *((volatile int*)__null) = 11543; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
11544 | |
11545 | if (!updateSourceCoordNotes(typeofNode->pn_pos.begin)) { |
11546 | return false; |
11547 | } |
11548 | |
11549 | if (!emitTree(typeofNode->kid())) { |
11550 | return false; |
11551 | } |
11552 | |
11553 | return emit1(op); |
11554 | } |
11555 | |
11556 | bool BytecodeEmitter::tryEmitTypeofEq(ListNode* node, bool* emitted) { |
11557 | // Emit specialized opcode for `typeof val == "type` or `typeof val != "type` |
11558 | // if possible. |
11559 | // |
11560 | // NOTE: Given the comparison is done for string, `==` and `===` have |
11561 | // no difference. Same for `!=` and `!==`. |
11562 | MOZ_ASSERT(node->isKind(ParseNodeKind::StrictEqExpr) ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(node->isKind(ParseNodeKind::StrictEqExpr) || node ->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind ::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr))> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(node->isKind(ParseNodeKind::StrictEqExpr) || node ->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind ::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("node->isKind(ParseNodeKind::StrictEqExpr) || node->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11565); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::StrictEqExpr) || node->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)" ")"); do { *((volatile int*)__null) = 11565; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
11563 | node->isKind(ParseNodeKind::EqExpr) ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(node->isKind(ParseNodeKind::StrictEqExpr) || node ->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind ::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr))> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(node->isKind(ParseNodeKind::StrictEqExpr) || node ->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind ::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("node->isKind(ParseNodeKind::StrictEqExpr) || node->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11565); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::StrictEqExpr) || node->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)" ")"); do { *((volatile int*)__null) = 11565; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
11564 | node->isKind(ParseNodeKind::StrictNeExpr) ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(node->isKind(ParseNodeKind::StrictEqExpr) || node ->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind ::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr))> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(node->isKind(ParseNodeKind::StrictEqExpr) || node ->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind ::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("node->isKind(ParseNodeKind::StrictEqExpr) || node->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11565); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::StrictEqExpr) || node->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)" ")"); do { *((volatile int*)__null) = 11565; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
11565 | node->isKind(ParseNodeKind::NeExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(node->isKind(ParseNodeKind::StrictEqExpr) || node ->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind ::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr))> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(node->isKind(ParseNodeKind::StrictEqExpr) || node ->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind ::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("node->isKind(ParseNodeKind::StrictEqExpr) || node->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11565); AnnotateMozCrashReason("MOZ_ASSERT" "(" "node->isKind(ParseNodeKind::StrictEqExpr) || node->isKind(ParseNodeKind::EqExpr) || node->isKind(ParseNodeKind::StrictNeExpr) || node->isKind(ParseNodeKind::NeExpr)" ")"); do { *((volatile int*)__null) = 11565; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
11566 | |
11567 | if (node->count() != 2) { |
11568 | *emitted = false; |
11569 | return true; |
11570 | } |
11571 | |
11572 | ParseNode* left = node->head(); |
11573 | ParseNode* right = left->pn_next; |
11574 | MOZ_ASSERT(right)do { static_assert( mozilla::detail::AssertionConditionType< decltype(right)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(right))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("right", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11574); AnnotateMozCrashReason("MOZ_ASSERT" "(" "right" ")" ); do { *((volatile int*)__null) = 11574; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
11575 | |
11576 | UnaryNode* typeofNode; |
11577 | NameNode* typenameNode; |
11578 | JSOp op; |
11579 | |
11580 | if (node->isKind(ParseNodeKind::StrictEqExpr) || |
11581 | node->isKind(ParseNodeKind::EqExpr)) { |
11582 | op = JSOp::Eq; |
11583 | } else { |
11584 | op = JSOp::Ne; |
11585 | } |
11586 | |
11587 | // NOTE: ParseNodeKind::TypeOfExpr cannot use JSOp::TypeofEq. |
11588 | // See JSOp::GetName document. |
11589 | if (left->isKind(ParseNodeKind::TypeOfNameExpr) && |
11590 | right->isKind(ParseNodeKind::StringExpr)) { |
11591 | typeofNode = &left->as<UnaryNode>(); |
11592 | typenameNode = &right->as<NameNode>(); |
11593 | } else if (right->isKind(ParseNodeKind::TypeOfNameExpr) && |
11594 | left->isKind(ParseNodeKind::StringExpr)) { |
11595 | typeofNode = &right->as<UnaryNode>(); |
11596 | typenameNode = &left->as<NameNode>(); |
11597 | } else { |
11598 | *emitted = false; |
11599 | return true; |
11600 | } |
11601 | |
11602 | JSType type; |
11603 | TaggedParserAtomIndex typeName = typenameNode->atom(); |
11604 | if (typeName == TaggedParserAtomIndex::WellKnown::undefined()) { |
11605 | type = JSTYPE_UNDEFINED; |
11606 | } else if (typeName == TaggedParserAtomIndex::WellKnown::object()) { |
11607 | type = JSTYPE_OBJECT; |
11608 | } else if (typeName == TaggedParserAtomIndex::WellKnown::function()) { |
11609 | type = JSTYPE_FUNCTION; |
11610 | } else if (typeName == TaggedParserAtomIndex::WellKnown::string()) { |
11611 | type = JSTYPE_STRING; |
11612 | } else if (typeName == TaggedParserAtomIndex::WellKnown::number()) { |
11613 | type = JSTYPE_NUMBER; |
11614 | } else if (typeName == TaggedParserAtomIndex::WellKnown::boolean()) { |
11615 | type = JSTYPE_BOOLEAN; |
11616 | } else if (typeName == TaggedParserAtomIndex::WellKnown::symbol()) { |
11617 | type = JSTYPE_SYMBOL; |
11618 | } else if (typeName == TaggedParserAtomIndex::WellKnown::bigint()) { |
11619 | type = JSTYPE_BIGINT; |
11620 | } |
11621 | #ifdef ENABLE_RECORD_TUPLE |
11622 | else if (typeName == TaggedParserAtomIndex::WellKnown::record()) { |
11623 | type = JSTYPE_RECORD; |
11624 | } else if (typeName == TaggedParserAtomIndex::WellKnown::tuple()) { |
11625 | type = JSTYPE_TUPLE; |
11626 | } |
11627 | #endif |
11628 | else { |
11629 | *emitted = false; |
11630 | return true; |
11631 | } |
11632 | |
11633 | if (!updateSourceCoordNotes(typeofNode->pn_pos.begin)) { |
11634 | return false; |
11635 | } |
11636 | |
11637 | if (!emitTree(typeofNode->kid())) { |
11638 | // [stack] VAL |
11639 | return false; |
11640 | } |
11641 | |
11642 | if (!emit2(JSOp::TypeofEq, TypeofEqOperand(type, op).rawValue())) { |
11643 | // [stack] CMP |
11644 | return false; |
11645 | } |
11646 | |
11647 | *emitted = true; |
11648 | return true; |
11649 | } |
11650 | |
11651 | bool BytecodeEmitter::emitFunctionFormalParameters(ParamsBodyNode* paramsBody) { |
11652 | FunctionBox* funbox = sc->asFunctionBox(); |
11653 | |
11654 | bool hasRest = funbox->hasRest(); |
11655 | |
11656 | FunctionParamsEmitter fpe(this, funbox); |
11657 | for (ParseNode* arg : paramsBody->parameters()) { |
11658 | ParseNode* bindingElement = arg; |
11659 | ParseNode* initializer = nullptr; |
11660 | if (arg->isKind(ParseNodeKind::AssignExpr)) { |
11661 | bindingElement = arg->as<BinaryNode>().left(); |
11662 | initializer = arg->as<BinaryNode>().right(); |
11663 | } |
11664 | bool hasInitializer = !!initializer; |
11665 | bool isRest = |
11666 | hasRest && arg->pn_next == *std::end(paramsBody->parameters()); |
11667 | bool isDestructuring = !bindingElement->isKind(ParseNodeKind::Name); |
11668 | |
11669 | // Left-hand sides are either simple names or destructuring patterns. |
11670 | MOZ_ASSERT(bindingElement->isKind(ParseNodeKind::Name) ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(bindingElement->isKind(ParseNodeKind::Name) || bindingElement ->isKind(ParseNodeKind::ArrayExpr) || bindingElement->isKind (ParseNodeKind::ObjectExpr))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(bindingElement->isKind(ParseNodeKind ::Name) || bindingElement->isKind(ParseNodeKind::ArrayExpr ) || bindingElement->isKind(ParseNodeKind::ObjectExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("bindingElement->isKind(ParseNodeKind::Name) || bindingElement->isKind(ParseNodeKind::ArrayExpr) || bindingElement->isKind(ParseNodeKind::ObjectExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11672); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bindingElement->isKind(ParseNodeKind::Name) || bindingElement->isKind(ParseNodeKind::ArrayExpr) || bindingElement->isKind(ParseNodeKind::ObjectExpr)" ")"); do { *((volatile int*)__null) = 11672; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
11671 | bindingElement->isKind(ParseNodeKind::ArrayExpr) ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(bindingElement->isKind(ParseNodeKind::Name) || bindingElement ->isKind(ParseNodeKind::ArrayExpr) || bindingElement->isKind (ParseNodeKind::ObjectExpr))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(bindingElement->isKind(ParseNodeKind ::Name) || bindingElement->isKind(ParseNodeKind::ArrayExpr ) || bindingElement->isKind(ParseNodeKind::ObjectExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("bindingElement->isKind(ParseNodeKind::Name) || bindingElement->isKind(ParseNodeKind::ArrayExpr) || bindingElement->isKind(ParseNodeKind::ObjectExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11672); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bindingElement->isKind(ParseNodeKind::Name) || bindingElement->isKind(ParseNodeKind::ArrayExpr) || bindingElement->isKind(ParseNodeKind::ObjectExpr)" ")"); do { *((volatile int*)__null) = 11672; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
11672 | bindingElement->isKind(ParseNodeKind::ObjectExpr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(bindingElement->isKind(ParseNodeKind::Name) || bindingElement ->isKind(ParseNodeKind::ArrayExpr) || bindingElement->isKind (ParseNodeKind::ObjectExpr))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(bindingElement->isKind(ParseNodeKind ::Name) || bindingElement->isKind(ParseNodeKind::ArrayExpr ) || bindingElement->isKind(ParseNodeKind::ObjectExpr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("bindingElement->isKind(ParseNodeKind::Name) || bindingElement->isKind(ParseNodeKind::ArrayExpr) || bindingElement->isKind(ParseNodeKind::ObjectExpr)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11672); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bindingElement->isKind(ParseNodeKind::Name) || bindingElement->isKind(ParseNodeKind::ArrayExpr) || bindingElement->isKind(ParseNodeKind::ObjectExpr)" ")"); do { *((volatile int*)__null) = 11672; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
11673 | |
11674 | auto emitDefaultInitializer = [this, &initializer, &bindingElement]() { |
11675 | // [stack] |
11676 | |
11677 | if (!this->emitInitializer(initializer, bindingElement)) { |
11678 | // [stack] DEFAULT |
11679 | return false; |
11680 | } |
11681 | return true; |
11682 | }; |
11683 | |
11684 | auto emitDestructuring = [this, &bindingElement]() { |
11685 | // [stack] ARG |
11686 | |
11687 | if (!this->emitDestructuringOps(&bindingElement->as<ListNode>(), |
11688 | DestructuringFlavor::Declaration)) { |
11689 | // [stack] ARG |
11690 | return false; |
11691 | } |
11692 | |
11693 | return true; |
11694 | }; |
11695 | |
11696 | if (isRest) { |
11697 | if (isDestructuring) { |
11698 | if (!fpe.prepareForDestructuringRest()) { |
11699 | // [stack] |
11700 | return false; |
11701 | } |
11702 | if (!emitDestructuring()) { |
11703 | // [stack] |
11704 | return false; |
11705 | } |
11706 | if (!fpe.emitDestructuringRestEnd()) { |
11707 | // [stack] |
11708 | return false; |
11709 | } |
11710 | } else { |
11711 | auto paramName = bindingElement->as<NameNode>().name(); |
11712 | if (!fpe.emitRest(paramName)) { |
11713 | // [stack] |
11714 | return false; |
11715 | } |
11716 | } |
11717 | |
11718 | continue; |
11719 | } |
11720 | |
11721 | if (isDestructuring) { |
11722 | if (hasInitializer) { |
11723 | if (!fpe.prepareForDestructuringDefaultInitializer()) { |
11724 | // [stack] |
11725 | return false; |
11726 | } |
11727 | if (!emitDefaultInitializer()) { |
11728 | // [stack] |
11729 | return false; |
11730 | } |
11731 | if (!fpe.prepareForDestructuringDefault()) { |
11732 | // [stack] |
11733 | return false; |
11734 | } |
11735 | if (!emitDestructuring()) { |
11736 | // [stack] |
11737 | return false; |
11738 | } |
11739 | if (!fpe.emitDestructuringDefaultEnd()) { |
11740 | // [stack] |
11741 | return false; |
11742 | } |
11743 | } else { |
11744 | if (!fpe.prepareForDestructuring()) { |
11745 | // [stack] |
11746 | return false; |
11747 | } |
11748 | if (!emitDestructuring()) { |
11749 | // [stack] |
11750 | return false; |
11751 | } |
11752 | if (!fpe.emitDestructuringEnd()) { |
11753 | // [stack] |
11754 | return false; |
11755 | } |
11756 | } |
11757 | |
11758 | continue; |
11759 | } |
11760 | |
11761 | if (hasInitializer) { |
11762 | if (!fpe.prepareForDefault()) { |
11763 | // [stack] |
11764 | return false; |
11765 | } |
11766 | if (!emitDefaultInitializer()) { |
11767 | // [stack] |
11768 | return false; |
11769 | } |
11770 | auto paramName = bindingElement->as<NameNode>().name(); |
11771 | if (!fpe.emitDefaultEnd(paramName)) { |
11772 | // [stack] |
11773 | return false; |
11774 | } |
11775 | |
11776 | continue; |
11777 | } |
11778 | |
11779 | auto paramName = bindingElement->as<NameNode>().name(); |
11780 | if (!fpe.emitSimple(paramName)) { |
11781 | // [stack] |
11782 | return false; |
11783 | } |
11784 | } |
11785 | |
11786 | return true; |
11787 | } |
11788 | |
11789 | bool BytecodeEmitter::emitInitializeFunctionSpecialNames() { |
11790 | FunctionBox* funbox = sc->asFunctionBox(); |
11791 | |
11792 | // [stack] |
11793 | |
11794 | auto emitInitializeFunctionSpecialName = |
11795 | [](BytecodeEmitter* bce, TaggedParserAtomIndex name, JSOp op) { |
11796 | // A special name must be slotful, either on the frame or on the |
11797 | // call environment. |
11798 | MOZ_ASSERT(bce->lookupName(name).hasKnownSlot())do { static_assert( mozilla::detail::AssertionConditionType< decltype(bce->lookupName(name).hasKnownSlot())>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(bce->lookupName(name).hasKnownSlot()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("bce->lookupName(name).hasKnownSlot()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11798); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bce->lookupName(name).hasKnownSlot()" ")"); do { *((volatile int*)__null) = 11798; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
11799 | |
11800 | NameOpEmitter noe(bce, name, NameOpEmitter::Kind::Initialize); |
11801 | if (!noe.prepareForRhs()) { |
11802 | // [stack] |
11803 | return false; |
11804 | } |
11805 | if (!bce->emit1(op)) { |
11806 | // [stack] THIS/ARGUMENTS/NEW.TARGET |
11807 | return false; |
11808 | } |
11809 | if (!noe.emitAssignment()) { |
11810 | // [stack] THIS/ARGUMENTS/NEW.TARGET |
11811 | return false; |
11812 | } |
11813 | if (!bce->emit1(JSOp::Pop)) { |
11814 | // [stack] |
11815 | return false; |
11816 | } |
11817 | |
11818 | return true; |
11819 | }; |
11820 | |
11821 | // Do nothing if the function doesn't have an arguments binding. |
11822 | if (funbox->needsArgsObj()) { |
11823 | // Self-hosted code should use the more efficient ArgumentsLength and |
11824 | // GetArgument intrinsics instead of `arguments`. |
11825 | MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting)do { static_assert( mozilla::detail::AssertionConditionType< decltype(emitterMode != BytecodeEmitter::SelfHosting)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(emitterMode != BytecodeEmitter::SelfHosting))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("emitterMode != BytecodeEmitter::SelfHosting" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11825); AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode != BytecodeEmitter::SelfHosting" ")"); do { *((volatile int*)__null) = 11825; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
11826 | if (!emitInitializeFunctionSpecialName( |
11827 | this, TaggedParserAtomIndex::WellKnown::arguments(), |
11828 | JSOp::Arguments)) { |
11829 | // [stack] |
11830 | return false; |
11831 | } |
11832 | } |
11833 | |
11834 | // Do nothing if the function doesn't have a this-binding (this |
11835 | // happens for instance if it doesn't use this/eval or if it's an |
11836 | // arrow function). |
11837 | if (funbox->functionHasThisBinding()) { |
11838 | if (!emitInitializeFunctionSpecialName( |
11839 | this, TaggedParserAtomIndex::WellKnown::dot_this_(), |
11840 | JSOp::FunctionThis)) { |
11841 | return false; |
11842 | } |
11843 | } |
11844 | |
11845 | // Do nothing if the function doesn't have a new.target-binding (this happens |
11846 | // for instance if it doesn't use new.target/eval or if it's an arrow |
11847 | // function). |
11848 | if (funbox->functionHasNewTargetBinding()) { |
11849 | if (!emitInitializeFunctionSpecialName( |
11850 | this, TaggedParserAtomIndex::WellKnown::dot_newTarget_(), |
11851 | JSOp::NewTarget)) { |
11852 | return false; |
11853 | } |
11854 | } |
11855 | |
11856 | // Do nothing if the function doesn't implicitly return a promise result. |
11857 | if (funbox->needsPromiseResult()) { |
11858 | if (!emitInitializeFunctionSpecialName( |
11859 | this, TaggedParserAtomIndex::WellKnown::dot_generator_(), |
11860 | JSOp::Generator)) { |
11861 | // [stack] |
11862 | return false; |
11863 | } |
11864 | } |
11865 | return true; |
11866 | } |
11867 | |
11868 | bool BytecodeEmitter::emitLexicalInitialization(NameNode* name) { |
11869 | return emitLexicalInitialization(name->name()); |
11870 | } |
11871 | |
11872 | bool BytecodeEmitter::emitLexicalInitialization(TaggedParserAtomIndex name) { |
11873 | NameOpEmitter noe(this, name, NameOpEmitter::Kind::Initialize); |
11874 | if (!noe.prepareForRhs()) { |
11875 | return false; |
11876 | } |
11877 | |
11878 | // The caller has pushed the RHS to the top of the stack. Assert that the |
11879 | // binding can be initialized without a binding object on the stack, and that |
11880 | // no JSOp::BindName or JSOp::BindGName ops were emitted. |
11881 | MOZ_ASSERT(noe.loc().isLexical() || noe.loc().isSynthetic() ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(noe.loc().isLexical() || noe.loc().isSynthetic() || noe .loc().isPrivateMethod())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(noe.loc().isLexical() || noe .loc().isSynthetic() || noe.loc().isPrivateMethod()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("noe.loc().isLexical() || noe.loc().isSynthetic() || noe.loc().isPrivateMethod()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11882); AnnotateMozCrashReason("MOZ_ASSERT" "(" "noe.loc().isLexical() || noe.loc().isSynthetic() || noe.loc().isPrivateMethod()" ")"); do { *((volatile int*)__null) = 11882; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
11882 | noe.loc().isPrivateMethod())do { static_assert( mozilla::detail::AssertionConditionType< decltype(noe.loc().isLexical() || noe.loc().isSynthetic() || noe .loc().isPrivateMethod())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(noe.loc().isLexical() || noe .loc().isSynthetic() || noe.loc().isPrivateMethod()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("noe.loc().isLexical() || noe.loc().isSynthetic() || noe.loc().isPrivateMethod()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11882); AnnotateMozCrashReason("MOZ_ASSERT" "(" "noe.loc().isLexical() || noe.loc().isSynthetic() || noe.loc().isPrivateMethod()" ")"); do { *((volatile int*)__null) = 11882; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
11883 | MOZ_ASSERT(!noe.emittedBindOp())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!noe.emittedBindOp())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!noe.emittedBindOp()))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("!noe.emittedBindOp()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11883); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!noe.emittedBindOp()" ")"); do { *((volatile int*)__null) = 11883; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
11884 | |
11885 | if (!noe.emitAssignment()) { |
11886 | return false; |
11887 | } |
11888 | |
11889 | return true; |
11890 | } |
11891 | |
11892 | static MOZ_ALWAYS_INLINEinline ParseNode* FindConstructor(ListNode* classMethods) { |
11893 | for (ParseNode* classElement : classMethods->contents()) { |
11894 | ParseNode* unwrappedElement = classElement; |
11895 | if (unwrappedElement->is<LexicalScopeNode>()) { |
11896 | unwrappedElement = unwrappedElement->as<LexicalScopeNode>().scopeBody(); |
11897 | } |
11898 | if (unwrappedElement->is<ClassMethod>()) { |
11899 | ClassMethod& method = unwrappedElement->as<ClassMethod>(); |
11900 | ParseNode& methodName = method.name(); |
11901 | if (!method.isStatic() && |
11902 | (methodName.isKind(ParseNodeKind::ObjectPropertyName) || |
11903 | methodName.isKind(ParseNodeKind::StringExpr)) && |
11904 | methodName.as<NameNode>().atom() == |
11905 | TaggedParserAtomIndex::WellKnown::constructor()) { |
11906 | return classElement; |
11907 | } |
11908 | } |
11909 | } |
11910 | return nullptr; |
11911 | } |
11912 | |
11913 | bool BytecodeEmitter::emitNewPrivateName(TaggedParserAtomIndex bindingName, |
11914 | TaggedParserAtomIndex symbolName) { |
11915 | if (!emitAtomOp(JSOp::NewPrivateName, symbolName)) { |
11916 | // [stack] HERITAGE PRIVATENAME |
11917 | return false; |
11918 | } |
11919 | |
11920 | // Add a binding for #name => privatename |
11921 | if (!emitLexicalInitialization(bindingName)) { |
11922 | // [stack] HERITAGE PRIVATENAME |
11923 | return false; |
11924 | } |
11925 | |
11926 | // Pop Private name off the stack. |
11927 | if (!emit1(JSOp::Pop)) { |
11928 | // [stack] HERITAGE |
11929 | return false; |
11930 | } |
11931 | |
11932 | return true; |
11933 | } |
11934 | |
11935 | bool BytecodeEmitter::emitNewPrivateNames( |
11936 | TaggedParserAtomIndex privateBrandName, ListNode* classMembers) { |
11937 | bool hasPrivateBrand = false; |
11938 | |
11939 | for (ParseNode* classElement : classMembers->contents()) { |
11940 | ParseNode* elementName; |
11941 | if (classElement->is<ClassMethod>()) { |
11942 | elementName = &classElement->as<ClassMethod>().name(); |
11943 | } else if (classElement->is<ClassField>()) { |
11944 | elementName = &classElement->as<ClassField>().name(); |
11945 | } else { |
11946 | continue; |
11947 | } |
11948 | |
11949 | if (!elementName->isKind(ParseNodeKind::PrivateName)) { |
11950 | continue; |
11951 | } |
11952 | |
11953 | // Non-static private methods' private names are optimized away. |
11954 | bool isOptimized = false; |
11955 | if (classElement->is<ClassMethod>() && |
11956 | !classElement->as<ClassMethod>().isStatic()) { |
11957 | hasPrivateBrand = true; |
11958 | if (classElement->as<ClassMethod>().accessorType() == |
11959 | AccessorType::None) { |
11960 | isOptimized = true; |
11961 | } |
11962 | } |
11963 | |
11964 | if (!isOptimized) { |
11965 | auto privateName = elementName->as<NameNode>().name(); |
11966 | if (!emitNewPrivateName(privateName, privateName)) { |
11967 | return false; |
11968 | } |
11969 | } |
11970 | } |
11971 | |
11972 | if (hasPrivateBrand) { |
11973 | // We don't make a private name for every optimized method, but we need one |
11974 | // private name per class, the `.privateBrand`. |
11975 | if (!emitNewPrivateName( |
11976 | TaggedParserAtomIndex::WellKnown::dot_privateBrand_(), |
11977 | privateBrandName)) { |
11978 | return false; |
11979 | } |
11980 | } |
11981 | return true; |
11982 | } |
11983 | |
11984 | // This follows ES6 14.5.14 (ClassDefinitionEvaluation) and ES6 14.5.15 |
11985 | // (BindingClassDeclarationEvaluation). |
11986 | bool BytecodeEmitter::emitClass( |
11987 | ClassNode* classNode, |
11988 | ClassNameKind nameKind /* = ClassNameKind::BindingName */, |
11989 | TaggedParserAtomIndex |
11990 | nameForAnonymousClass /* = TaggedParserAtomIndex::null() */) { |
11991 | MOZ_ASSERT((nameKind == ClassNameKind::InferredName) ==do { static_assert( mozilla::detail::AssertionConditionType< decltype((nameKind == ClassNameKind::InferredName) == bool(nameForAnonymousClass ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!((nameKind == ClassNameKind::InferredName) == bool(nameForAnonymousClass )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("(nameKind == ClassNameKind::InferredName) == bool(nameForAnonymousClass)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11992); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(nameKind == ClassNameKind::InferredName) == bool(nameForAnonymousClass)" ")"); do { *((volatile int*)__null) = 11992; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
11992 | bool(nameForAnonymousClass))do { static_assert( mozilla::detail::AssertionConditionType< decltype((nameKind == ClassNameKind::InferredName) == bool(nameForAnonymousClass ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!((nameKind == ClassNameKind::InferredName) == bool(nameForAnonymousClass )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("(nameKind == ClassNameKind::InferredName) == bool(nameForAnonymousClass)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 11992); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(nameKind == ClassNameKind::InferredName) == bool(nameForAnonymousClass)" ")"); do { *((volatile int*)__null) = 11992; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
11993 | |
11994 | ParseNode* heritageExpression = classNode->heritage(); |
11995 | ListNode* classMembers = classNode->memberList(); |
11996 | ParseNode* constructor = FindConstructor(classMembers); |
11997 | |
11998 | // If |nameKind != ClassNameKind::ComputedName| |
11999 | // [stack] |
12000 | // Else |
12001 | // [stack] NAME |
12002 | |
12003 | ClassEmitter ce(this); |
12004 | TaggedParserAtomIndex innerName; |
12005 | ClassEmitter::Kind kind = ClassEmitter::Kind::Expression; |
12006 | if (ClassNames* names = classNode->names()) { |
12007 | MOZ_ASSERT(nameKind == ClassNameKind::BindingName)do { static_assert( mozilla::detail::AssertionConditionType< decltype(nameKind == ClassNameKind::BindingName)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(nameKind == ClassNameKind::BindingName))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("nameKind == ClassNameKind::BindingName" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12007); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nameKind == ClassNameKind::BindingName" ")"); do { *((volatile int*)__null) = 12007; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12008 | innerName = names->innerBinding()->name(); |
12009 | MOZ_ASSERT(innerName)do { static_assert( mozilla::detail::AssertionConditionType< decltype(innerName)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(innerName))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("innerName", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12009); AnnotateMozCrashReason("MOZ_ASSERT" "(" "innerName" ")"); do { *((volatile int*)__null) = 12009; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12010 | |
12011 | if (names->outerBinding()) { |
12012 | MOZ_ASSERT(names->outerBinding()->name())do { static_assert( mozilla::detail::AssertionConditionType< decltype(names->outerBinding()->name())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(names->outerBinding()-> name()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("names->outerBinding()->name()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12012); AnnotateMozCrashReason("MOZ_ASSERT" "(" "names->outerBinding()->name()" ")"); do { *((volatile int*)__null) = 12012; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12013 | MOZ_ASSERT(names->outerBinding()->name() == innerName)do { static_assert( mozilla::detail::AssertionConditionType< decltype(names->outerBinding()->name() == innerName)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(names->outerBinding()->name() == innerName))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("names->outerBinding()->name() == innerName" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12013); AnnotateMozCrashReason("MOZ_ASSERT" "(" "names->outerBinding()->name() == innerName" ")"); do { *((volatile int*)__null) = 12013; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12014 | kind = ClassEmitter::Kind::Declaration; |
12015 | } |
12016 | } |
12017 | |
12018 | if (LexicalScopeNode* scopeBindings = classNode->scopeBindings()) { |
12019 | if (!ce.emitScope(scopeBindings->scopeBindings())) { |
12020 | // [stack] |
12021 | return false; |
12022 | } |
12023 | } |
12024 | |
12025 | bool isDerived = !!heritageExpression; |
12026 | if (isDerived) { |
12027 | if (!updateSourceCoordNotes(classNode->pn_pos.begin)) { |
12028 | return false; |
12029 | } |
12030 | if (!markStepBreakpoint()) { |
12031 | return false; |
12032 | } |
12033 | if (!emitTree(heritageExpression)) { |
12034 | // [stack] HERITAGE |
12035 | return false; |
12036 | } |
12037 | } |
12038 | |
12039 | // The class body scope holds any private names. Those mustn't be visible in |
12040 | // the heritage expression and hence the scope must be emitted after the |
12041 | // heritage expression. |
12042 | if (ClassBodyScopeNode* bodyScopeBindings = classNode->bodyScopeBindings()) { |
12043 | if (!ce.emitBodyScope(bodyScopeBindings->scopeBindings())) { |
12044 | // [stack] HERITAGE |
12045 | return false; |
12046 | } |
12047 | |
12048 | // The spec does not say anything about private brands being symbols. It's |
12049 | // an implementation detail. So we can give the special private brand |
12050 | // symbol any description we want and users won't normally see it. For |
12051 | // debugging, use the class name. |
12052 | auto privateBrandName = innerName; |
12053 | if (!innerName) { |
12054 | privateBrandName = nameForAnonymousClass |
12055 | ? nameForAnonymousClass |
12056 | : TaggedParserAtomIndex::WellKnown::anonymous(); |
12057 | } |
12058 | if (!emitNewPrivateNames(privateBrandName, classMembers)) { |
12059 | return false; |
12060 | } |
12061 | } |
12062 | |
12063 | bool hasNameOnStack = nameKind == ClassNameKind::ComputedName; |
12064 | if (isDerived) { |
12065 | if (!ce.emitDerivedClass(innerName, nameForAnonymousClass, |
12066 | hasNameOnStack)) { |
12067 | // [stack] HOMEOBJ HERITAGE |
12068 | return false; |
12069 | } |
12070 | } else { |
12071 | if (!ce.emitClass(innerName, nameForAnonymousClass, hasNameOnStack)) { |
12072 | // [stack] HOMEOBJ |
12073 | return false; |
12074 | } |
12075 | } |
12076 | |
12077 | // Stack currently has HOMEOBJ followed by optional HERITAGE. When HERITAGE |
12078 | // is not used, an implicit value of %FunctionPrototype% is implied. |
12079 | |
12080 | // See |Parser::classMember(...)| for the reason why |.initializers| is |
12081 | // created within its own scope. |
12082 | Maybe<LexicalScopeEmitter> lse; |
12083 | FunctionNode* ctor; |
12084 | #ifdef ENABLE_DECORATORS |
12085 | bool extraInitializersPresent = false; |
12086 | #endif |
12087 | if (constructor->is<LexicalScopeNode>()) { |
12088 | LexicalScopeNode* constructorScope = &constructor->as<LexicalScopeNode>(); |
12089 | |
12090 | MOZ_ASSERT(!constructorScope->isEmptyScope())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!constructorScope->isEmptyScope())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!constructorScope->isEmptyScope ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!constructorScope->isEmptyScope()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12090); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!constructorScope->isEmptyScope()" ")"); do { *((volatile int*)__null) = 12090; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12091 | #ifdef ENABLE_DECORATORS |
12092 | // With decorators enabled we expect to see |.initializers|, |
12093 | // and |.instanceExtraInitializers| in this scope. |
12094 | MOZ_ASSERT(constructorScope->scopeBindings()->length == 2)do { static_assert( mozilla::detail::AssertionConditionType< decltype(constructorScope->scopeBindings()->length == 2 )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(constructorScope->scopeBindings()->length == 2 ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "constructorScope->scopeBindings()->length == 2", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12094); AnnotateMozCrashReason("MOZ_ASSERT" "(" "constructorScope->scopeBindings()->length == 2" ")"); do { *((volatile int*)__null) = 12094; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12095 | MOZ_ASSERT(GetScopeDataTrailingNames(constructorScope->scopeBindings())[0]do { static_assert( mozilla::detail::AssertionConditionType< decltype(GetScopeDataTrailingNames(constructorScope->scopeBindings ())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_ ())>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(GetScopeDataTrailingNames(constructorScope->scopeBindings ())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_ ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12097); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()" ")"); do { *((volatile int*)__null) = 12097; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
12096 | .name() ==do { static_assert( mozilla::detail::AssertionConditionType< decltype(GetScopeDataTrailingNames(constructorScope->scopeBindings ())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_ ())>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(GetScopeDataTrailingNames(constructorScope->scopeBindings ())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_ ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12097); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()" ")"); do { *((volatile int*)__null) = 12097; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
12097 | TaggedParserAtomIndex::WellKnown::dot_initializers_())do { static_assert( mozilla::detail::AssertionConditionType< decltype(GetScopeDataTrailingNames(constructorScope->scopeBindings ())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_ ())>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(GetScopeDataTrailingNames(constructorScope->scopeBindings ())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_ ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12097); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()" ")"); do { *((volatile int*)__null) = 12097; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12098 | MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType< decltype(GetScopeDataTrailingNames(constructorScope->scopeBindings ())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_ ())>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(GetScopeDataTrailingNames(constructorScope->scopeBindings ())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_ ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("GetScopeDataTrailingNames(constructorScope->scopeBindings())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12101); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_()" ")"); do { *((volatile int*)__null) = 12101; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
12099 | GetScopeDataTrailingNames(constructorScope->scopeBindings())[1]do { static_assert( mozilla::detail::AssertionConditionType< decltype(GetScopeDataTrailingNames(constructorScope->scopeBindings ())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_ ())>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(GetScopeDataTrailingNames(constructorScope->scopeBindings ())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_ ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("GetScopeDataTrailingNames(constructorScope->scopeBindings())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12101); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_()" ")"); do { *((volatile int*)__null) = 12101; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
12100 | .name() ==do { static_assert( mozilla::detail::AssertionConditionType< decltype(GetScopeDataTrailingNames(constructorScope->scopeBindings ())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_ ())>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(GetScopeDataTrailingNames(constructorScope->scopeBindings ())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_ ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("GetScopeDataTrailingNames(constructorScope->scopeBindings())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12101); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_()" ")"); do { *((volatile int*)__null) = 12101; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
12101 | TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_())do { static_assert( mozilla::detail::AssertionConditionType< decltype(GetScopeDataTrailingNames(constructorScope->scopeBindings ())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_ ())>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(GetScopeDataTrailingNames(constructorScope->scopeBindings ())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_ ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("GetScopeDataTrailingNames(constructorScope->scopeBindings())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12101); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[1] .name() == TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_()" ")"); do { *((volatile int*)__null) = 12101; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12102 | |
12103 | // We should only call this code if we know decorators are present, see bug |
12104 | // 1871147. |
12105 | lse.emplace(this); |
12106 | if (!lse->emitScope(ScopeKind::Lexical, |
12107 | constructorScope->scopeBindings())) { |
12108 | return false; |
12109 | } |
12110 | |
12111 | // TODO: See bug 1868220 for support for static extra initializers. |
12112 | if (!ce.prepareForExtraInitializers(TaggedParserAtomIndex::WellKnown:: |
12113 | dot_instanceExtraInitializers_())) { |
12114 | return false; |
12115 | } |
12116 | |
12117 | if (classNode->addInitializerFunction()) { |
12118 | DecoratorEmitter de(this); |
12119 | if (!de.emitCreateAddInitializerFunction( |
12120 | classNode->addInitializerFunction(), |
12121 | TaggedParserAtomIndex::WellKnown:: |
12122 | dot_instanceExtraInitializers_())) { |
12123 | // [stack] HOMEOBJ HERITAGE? ADDINIT |
12124 | return false; |
12125 | } |
12126 | |
12127 | if (!emitUnpickN(isDerived ? 2 : 1)) { |
12128 | // [stack] ADDINIT HOMEOBJ HERITAGE? |
12129 | return false; |
12130 | } |
12131 | |
12132 | extraInitializersPresent = true; |
12133 | } |
12134 | #else |
12135 | // The constructor scope should only contain the |.initializers| binding. |
12136 | MOZ_ASSERT(constructorScope->scopeBindings()->length == 1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(constructorScope->scopeBindings()->length == 1 )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(constructorScope->scopeBindings()->length == 1 ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "constructorScope->scopeBindings()->length == 1", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12136); AnnotateMozCrashReason("MOZ_ASSERT" "(" "constructorScope->scopeBindings()->length == 1" ")"); do { *((volatile int*)__null) = 12136; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12137 | MOZ_ASSERT(GetScopeDataTrailingNames(constructorScope->scopeBindings())[0]do { static_assert( mozilla::detail::AssertionConditionType< decltype(GetScopeDataTrailingNames(constructorScope->scopeBindings ())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_ ())>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(GetScopeDataTrailingNames(constructorScope->scopeBindings ())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_ ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12139); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()" ")"); do { *((volatile int*)__null) = 12139; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
12138 | .name() ==do { static_assert( mozilla::detail::AssertionConditionType< decltype(GetScopeDataTrailingNames(constructorScope->scopeBindings ())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_ ())>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(GetScopeDataTrailingNames(constructorScope->scopeBindings ())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_ ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12139); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()" ")"); do { *((volatile int*)__null) = 12139; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
12139 | TaggedParserAtomIndex::WellKnown::dot_initializers_())do { static_assert( mozilla::detail::AssertionConditionType< decltype(GetScopeDataTrailingNames(constructorScope->scopeBindings ())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_ ())>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(GetScopeDataTrailingNames(constructorScope->scopeBindings ())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_ ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12139); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetScopeDataTrailingNames(constructorScope->scopeBindings())[0] .name() == TaggedParserAtomIndex::WellKnown::dot_initializers_()" ")"); do { *((volatile int*)__null) = 12139; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12140 | #endif |
12141 | |
12142 | auto needsInitializer = [](ParseNode* propdef) { |
12143 | return NeedsFieldInitializer(propdef, false) || |
12144 | NeedsAccessorInitializer(propdef, false); |
12145 | }; |
12146 | |
12147 | // As an optimization omit the |.initializers| binding when no instance |
12148 | // fields or private methods are present. |
12149 | bool needsInitializers = |
12150 | std::any_of(classMembers->contents().begin(), |
12151 | classMembers->contents().end(), needsInitializer); |
12152 | if (needsInitializers) { |
12153 | #ifndef ENABLE_DECORATORS |
12154 | lse.emplace(this); |
12155 | if (!lse->emitScope(ScopeKind::Lexical, |
12156 | constructorScope->scopeBindings())) { |
12157 | return false; |
12158 | } |
12159 | #endif |
12160 | // Any class with field initializers will have a constructor |
12161 | if (!emitCreateMemberInitializers(ce, classMembers, |
12162 | FieldPlacement::Instance |
12163 | #ifdef ENABLE_DECORATORS |
12164 | , |
12165 | isDerived |
12166 | #endif |
12167 | )) { |
12168 | return false; |
12169 | } |
12170 | } |
12171 | |
12172 | ctor = &constructorScope->scopeBody()->as<ClassMethod>().method(); |
12173 | } else { |
12174 | // The |.initializers| binding is never emitted when in self-hosting mode. |
12175 | MOZ_ASSERT(emitterMode == BytecodeEmitter::SelfHosting)do { static_assert( mozilla::detail::AssertionConditionType< decltype(emitterMode == BytecodeEmitter::SelfHosting)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(emitterMode == BytecodeEmitter::SelfHosting))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("emitterMode == BytecodeEmitter::SelfHosting" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12175); AnnotateMozCrashReason("MOZ_ASSERT" "(" "emitterMode == BytecodeEmitter::SelfHosting" ")"); do { *((volatile int*)__null) = 12175; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12176 | ctor = &constructor->as<ClassMethod>().method(); |
12177 | } |
12178 | |
12179 | bool needsHomeObject = ctor->funbox()->needsHomeObject(); |
12180 | // HERITAGE is consumed inside emitFunction. |
12181 | if (nameKind == ClassNameKind::InferredName) { |
12182 | if (!setFunName(ctor->funbox(), nameForAnonymousClass)) { |
12183 | return false; |
12184 | } |
12185 | } |
12186 | if (!emitFunction(ctor, isDerived)) { |
12187 | // [stack] HOMEOBJ CTOR |
12188 | return false; |
12189 | } |
12190 | if (lse.isSome()) { |
12191 | if (!lse->emitEnd()) { |
12192 | return false; |
12193 | } |
12194 | lse.reset(); |
12195 | } |
12196 | if (!ce.emitInitConstructor(needsHomeObject)) { |
12197 | // [stack] CTOR HOMEOBJ |
12198 | return false; |
12199 | } |
12200 | |
12201 | if (!emitCreateFieldKeys(classMembers, FieldPlacement::Instance)) { |
12202 | return false; |
12203 | } |
12204 | |
12205 | #ifdef ENABLE_DECORATORS |
12206 | // TODO: See Bug 1868220 for support for static extra initializers. |
12207 | if (!emit1(JSOp::Undefined)) { |
12208 | // [stack] ADDINIT? CTOR HOMEOBJ UNDEFINED |
12209 | return false; |
12210 | } |
12211 | if (!emitUnpickN(2)) { |
12212 | // [stack] ADDINIT? UNDEFINED CTOR HOMEOBJ |
12213 | } |
12214 | #endif |
12215 | |
12216 | if (!emitCreateMemberInitializers(ce, classMembers, FieldPlacement::Static |
12217 | #ifdef ENABLE_DECORATORS |
12218 | , |
12219 | false |
12220 | #endif |
12221 | )) { |
12222 | return false; |
12223 | } |
12224 | |
12225 | #ifdef ENABLE_DECORATORS |
12226 | if (!emitPickN(2)) { |
12227 | // [stack] ADDINIT? CTOR HOMEOBJ UNDEFINED |
12228 | return false; |
12229 | } |
12230 | if (!emitPopN(1)) { |
12231 | // [stack] ADDINIT? CTOR HOMEOBJ |
12232 | return false; |
12233 | } |
12234 | #endif |
12235 | |
12236 | if (!emitCreateFieldKeys(classMembers, FieldPlacement::Static)) { |
12237 | return false; |
12238 | } |
12239 | |
12240 | if (!emitPropertyList(classMembers, ce, ClassBody)) { |
12241 | // [stack] CTOR HOMEOBJ |
12242 | return false; |
12243 | } |
12244 | |
12245 | #ifdef ENABLE_DECORATORS |
12246 | if (extraInitializersPresent) { |
12247 | if (!emitPickN(2)) { |
12248 | // [stack] CTOR HOMEOBJ ADDINIT |
12249 | return false; |
12250 | } |
12251 | if (!emitPopN(1)) { |
12252 | // [stack] CTOR HOMEOBJ |
12253 | return false; |
12254 | } |
12255 | } |
12256 | #endif |
12257 | |
12258 | if (!ce.emitBinding()) { |
12259 | // [stack] CTOR |
12260 | return false; |
12261 | } |
12262 | |
12263 | if (!emitInitializeStaticFields(classMembers)) { |
12264 | // [stack] CTOR |
12265 | return false; |
12266 | } |
12267 | |
12268 | #if ENABLE_DECORATORS |
12269 | if (!ce.prepareForDecorators()) { |
12270 | // [stack] CTOR |
12271 | return false; |
12272 | } |
12273 | if (classNode->decorators() != nullptr) { |
12274 | DecoratorEmitter de(this); |
12275 | NameNode* className = |
12276 | classNode->names() ? classNode->names()->innerBinding() : nullptr; |
12277 | if (!de.emitApplyDecoratorsToClassDefinition(className, |
12278 | classNode->decorators())) { |
12279 | // [stack] CTOR |
12280 | return false; |
12281 | } |
12282 | } |
12283 | #endif |
12284 | |
12285 | if (!ce.emitEnd(kind)) { |
12286 | // [stack] # class declaration |
12287 | // [stack] |
12288 | // [stack] # class expression |
12289 | // [stack] CTOR |
12290 | return false; |
12291 | } |
12292 | |
12293 | return true; |
12294 | } |
12295 | |
12296 | bool BytecodeEmitter::emitExportDefault(BinaryNode* exportNode) { |
12297 | MOZ_ASSERT(exportNode->isKind(ParseNodeKind::ExportDefaultStmt))do { static_assert( mozilla::detail::AssertionConditionType< decltype(exportNode->isKind(ParseNodeKind::ExportDefaultStmt ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(exportNode->isKind(ParseNodeKind::ExportDefaultStmt )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("exportNode->isKind(ParseNodeKind::ExportDefaultStmt)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12297); AnnotateMozCrashReason("MOZ_ASSERT" "(" "exportNode->isKind(ParseNodeKind::ExportDefaultStmt)" ")"); do { *((volatile int*)__null) = 12297; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12298 | |
12299 | ParseNode* valueNode = exportNode->left(); |
12300 | if (valueNode->isDirectRHSAnonFunction()) { |
12301 | MOZ_ASSERT(exportNode->right())do { static_assert( mozilla::detail::AssertionConditionType< decltype(exportNode->right())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(exportNode->right()))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("exportNode->right()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12301); AnnotateMozCrashReason("MOZ_ASSERT" "(" "exportNode->right()" ")"); do { *((volatile int*)__null) = 12301; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12302 | |
12303 | if (!emitAnonymousFunctionWithName( |
12304 | valueNode, TaggedParserAtomIndex::WellKnown::default_())) { |
12305 | return false; |
12306 | } |
12307 | } else { |
12308 | if (!emitTree(valueNode)) { |
12309 | return false; |
12310 | } |
12311 | } |
12312 | |
12313 | if (ParseNode* binding = exportNode->right()) { |
12314 | if (!emitLexicalInitialization(&binding->as<NameNode>())) { |
12315 | return false; |
12316 | } |
12317 | |
12318 | if (!emit1(JSOp::Pop)) { |
12319 | return false; |
12320 | } |
12321 | } |
12322 | |
12323 | return true; |
12324 | } |
12325 | |
12326 | bool BytecodeEmitter::emitTree( |
12327 | ParseNode* pn, ValueUsage valueUsage /* = ValueUsage::WantValue */, |
12328 | EmitLineNumberNote emitLineNote /* = EMIT_LINENOTE */) { |
12329 | AutoCheckRecursionLimit recursion(fc); |
12330 | if (!recursion.check(fc)) { |
12331 | return false; |
12332 | } |
12333 | |
12334 | /* Emit notes to tell the current bytecode's source line number. |
12335 | However, a couple trees require special treatment; see the |
12336 | relevant emitter functions for details. */ |
12337 | if (emitLineNote == EMIT_LINENOTE && |
12338 | !ParseNodeRequiresSpecialLineNumberNotes(pn)) { |
12339 | if (!updateLineNumberNotes(pn->pn_pos.begin)) { |
12340 | return false; |
12341 | } |
12342 | } |
12343 | |
12344 | switch (pn->getKind()) { |
12345 | case ParseNodeKind::Function: |
12346 | if (!emitFunction(&pn->as<FunctionNode>())) { |
12347 | return false; |
12348 | } |
12349 | break; |
12350 | |
12351 | case ParseNodeKind::ParamsBody: |
12352 | MOZ_ASSERT_UNREACHABLE(do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "ParamsBody should be handled in emitFunctionScript." ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12353); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "ParamsBody should be handled in emitFunctionScript." ")"); do { *((volatile int*)__null) = 12353; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
12353 | "ParamsBody should be handled in emitFunctionScript.")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "ParamsBody should be handled in emitFunctionScript." ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12353); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "ParamsBody should be handled in emitFunctionScript." ")"); do { *((volatile int*)__null) = 12353; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12354 | break; |
12355 | |
12356 | case ParseNodeKind::IfStmt: |
12357 | if (!emitIf(&pn->as<TernaryNode>())) { |
12358 | return false; |
12359 | } |
12360 | break; |
12361 | |
12362 | case ParseNodeKind::SwitchStmt: |
12363 | if (!emitSwitch(&pn->as<SwitchStatement>())) { |
12364 | return false; |
12365 | } |
12366 | break; |
12367 | |
12368 | case ParseNodeKind::WhileStmt: |
12369 | if (!emitWhile(&pn->as<BinaryNode>())) { |
12370 | return false; |
12371 | } |
12372 | break; |
12373 | |
12374 | case ParseNodeKind::DoWhileStmt: |
12375 | if (!emitDo(&pn->as<BinaryNode>())) { |
12376 | return false; |
12377 | } |
12378 | break; |
12379 | |
12380 | case ParseNodeKind::ForStmt: |
12381 | if (!emitFor(&pn->as<ForNode>())) { |
12382 | return false; |
12383 | } |
12384 | break; |
12385 | |
12386 | case ParseNodeKind::BreakStmt: |
12387 | // Ensure that the column of the 'break' is set properly. |
12388 | if (!updateSourceCoordNotes(pn->pn_pos.begin)) { |
12389 | return false; |
12390 | } |
12391 | if (!markStepBreakpoint()) { |
12392 | return false; |
12393 | } |
12394 | |
12395 | if (!emitBreak(pn->as<BreakStatement>().label())) { |
12396 | return false; |
12397 | } |
12398 | break; |
12399 | |
12400 | case ParseNodeKind::ContinueStmt: |
12401 | // Ensure that the column of the 'continue' is set properly. |
12402 | if (!updateSourceCoordNotes(pn->pn_pos.begin)) { |
12403 | return false; |
12404 | } |
12405 | if (!markStepBreakpoint()) { |
12406 | return false; |
12407 | } |
12408 | |
12409 | if (!emitContinue(pn->as<ContinueStatement>().label())) { |
12410 | return false; |
12411 | } |
12412 | break; |
12413 | |
12414 | case ParseNodeKind::WithStmt: |
12415 | if (!emitWith(&pn->as<BinaryNode>())) { |
12416 | return false; |
12417 | } |
12418 | break; |
12419 | |
12420 | case ParseNodeKind::TryStmt: |
12421 | if (!emitTry(&pn->as<TryNode>())) { |
12422 | return false; |
12423 | } |
12424 | break; |
12425 | |
12426 | case ParseNodeKind::Catch: |
12427 | if (!emitCatch(&pn->as<BinaryNode>())) { |
12428 | return false; |
12429 | } |
12430 | break; |
12431 | |
12432 | case ParseNodeKind::VarStmt: |
12433 | if (!emitDeclarationList(&pn->as<ListNode>())) { |
12434 | return false; |
12435 | } |
12436 | break; |
12437 | |
12438 | case ParseNodeKind::ReturnStmt: |
12439 | if (!emitReturn(&pn->as<UnaryNode>())) { |
12440 | return false; |
12441 | } |
12442 | break; |
12443 | |
12444 | case ParseNodeKind::YieldStarExpr: |
12445 | if (!emitYieldStar(pn->as<UnaryNode>().kid())) { |
12446 | return false; |
12447 | } |
12448 | break; |
12449 | |
12450 | case ParseNodeKind::Generator: |
12451 | if (!emit1(JSOp::Generator)) { |
12452 | return false; |
12453 | } |
12454 | break; |
12455 | |
12456 | case ParseNodeKind::InitialYield: |
12457 | if (!emitInitialYield(&pn->as<UnaryNode>())) { |
12458 | return false; |
12459 | } |
12460 | break; |
12461 | |
12462 | case ParseNodeKind::YieldExpr: |
12463 | if (!emitYield(&pn->as<UnaryNode>())) { |
12464 | return false; |
12465 | } |
12466 | break; |
12467 | |
12468 | case ParseNodeKind::AwaitExpr: |
12469 | if (!emitAwaitInInnermostScope(&pn->as<UnaryNode>())) { |
12470 | return false; |
12471 | } |
12472 | break; |
12473 | |
12474 | case ParseNodeKind::StatementList: |
12475 | if (!emitStatementList(&pn->as<ListNode>())) { |
12476 | return false; |
12477 | } |
12478 | break; |
12479 | |
12480 | case ParseNodeKind::EmptyStmt: |
12481 | break; |
12482 | |
12483 | case ParseNodeKind::ExpressionStmt: |
12484 | if (!emitExpressionStatement(&pn->as<UnaryNode>())) { |
12485 | return false; |
12486 | } |
12487 | break; |
12488 | |
12489 | case ParseNodeKind::LabelStmt: |
12490 | if (!emitLabeledStatement(&pn->as<LabeledStatement>())) { |
12491 | return false; |
12492 | } |
12493 | break; |
12494 | |
12495 | case ParseNodeKind::CommaExpr: |
12496 | if (!emitSequenceExpr(&pn->as<ListNode>(), valueUsage)) { |
12497 | return false; |
12498 | } |
12499 | break; |
12500 | |
12501 | case ParseNodeKind::InitExpr: |
12502 | case ParseNodeKind::AssignExpr: |
12503 | case ParseNodeKind::AddAssignExpr: |
12504 | case ParseNodeKind::SubAssignExpr: |
12505 | case ParseNodeKind::BitOrAssignExpr: |
12506 | case ParseNodeKind::BitXorAssignExpr: |
12507 | case ParseNodeKind::BitAndAssignExpr: |
12508 | case ParseNodeKind::LshAssignExpr: |
12509 | case ParseNodeKind::RshAssignExpr: |
12510 | case ParseNodeKind::UrshAssignExpr: |
12511 | case ParseNodeKind::MulAssignExpr: |
12512 | case ParseNodeKind::DivAssignExpr: |
12513 | case ParseNodeKind::ModAssignExpr: |
12514 | case ParseNodeKind::PowAssignExpr: { |
12515 | BinaryNode* assignNode = &pn->as<BinaryNode>(); |
12516 | if (!emitAssignmentOrInit(assignNode->getKind(), assignNode->left(), |
12517 | assignNode->right())) { |
12518 | return false; |
12519 | } |
12520 | break; |
12521 | } |
12522 | |
12523 | case ParseNodeKind::CoalesceAssignExpr: |
12524 | case ParseNodeKind::OrAssignExpr: |
12525 | case ParseNodeKind::AndAssignExpr: |
12526 | if (!emitShortCircuitAssignment(&pn->as<AssignmentNode>())) { |
12527 | return false; |
12528 | } |
12529 | break; |
12530 | |
12531 | case ParseNodeKind::ConditionalExpr: |
12532 | if (!emitConditionalExpression(pn->as<ConditionalExpression>(), |
12533 | valueUsage)) { |
12534 | return false; |
12535 | } |
12536 | break; |
12537 | |
12538 | case ParseNodeKind::OrExpr: |
12539 | case ParseNodeKind::CoalesceExpr: |
12540 | case ParseNodeKind::AndExpr: |
12541 | if (!emitShortCircuit(&pn->as<ListNode>(), valueUsage)) { |
12542 | return false; |
12543 | } |
12544 | break; |
12545 | |
12546 | case ParseNodeKind::StrictEqExpr: |
12547 | case ParseNodeKind::EqExpr: |
12548 | case ParseNodeKind::StrictNeExpr: |
12549 | case ParseNodeKind::NeExpr: { |
12550 | bool emitted; |
12551 | if (!tryEmitTypeofEq(&pn->as<ListNode>(), &emitted)) { |
12552 | return false; |
12553 | } |
12554 | if (emitted) { |
12555 | return true; |
12556 | } |
12557 | } |
12558 | [[fallthrough]]; |
12559 | |
12560 | case ParseNodeKind::AddExpr: |
12561 | case ParseNodeKind::SubExpr: |
12562 | case ParseNodeKind::BitOrExpr: |
12563 | case ParseNodeKind::BitXorExpr: |
12564 | case ParseNodeKind::BitAndExpr: |
12565 | case ParseNodeKind::LtExpr: |
12566 | case ParseNodeKind::LeExpr: |
12567 | case ParseNodeKind::GtExpr: |
12568 | case ParseNodeKind::GeExpr: |
12569 | case ParseNodeKind::InExpr: |
12570 | case ParseNodeKind::InstanceOfExpr: |
12571 | case ParseNodeKind::LshExpr: |
12572 | case ParseNodeKind::RshExpr: |
12573 | case ParseNodeKind::UrshExpr: |
12574 | case ParseNodeKind::MulExpr: |
12575 | case ParseNodeKind::DivExpr: |
12576 | case ParseNodeKind::ModExpr: |
12577 | if (!emitLeftAssociative(&pn->as<ListNode>())) { |
12578 | return false; |
12579 | } |
12580 | break; |
12581 | |
12582 | case ParseNodeKind::PrivateInExpr: |
12583 | if (!emitPrivateInExpr(&pn->as<ListNode>())) { |
12584 | return false; |
12585 | } |
12586 | break; |
12587 | |
12588 | case ParseNodeKind::PowExpr: |
12589 | if (!emitRightAssociative(&pn->as<ListNode>())) { |
12590 | return false; |
12591 | } |
12592 | break; |
12593 | |
12594 | case ParseNodeKind::TypeOfNameExpr: |
12595 | if (!emitTypeof(&pn->as<UnaryNode>(), JSOp::Typeof)) { |
12596 | return false; |
12597 | } |
12598 | break; |
12599 | |
12600 | case ParseNodeKind::TypeOfExpr: |
12601 | if (!emitTypeof(&pn->as<UnaryNode>(), JSOp::TypeofExpr)) { |
12602 | return false; |
12603 | } |
12604 | break; |
12605 | |
12606 | case ParseNodeKind::ThrowStmt: |
12607 | if (!updateSourceCoordNotes(pn->pn_pos.begin)) { |
12608 | return false; |
12609 | } |
12610 | if (!markStepBreakpoint()) { |
12611 | return false; |
12612 | } |
12613 | [[fallthrough]]; |
12614 | case ParseNodeKind::VoidExpr: |
12615 | case ParseNodeKind::NotExpr: |
12616 | case ParseNodeKind::BitNotExpr: |
12617 | case ParseNodeKind::PosExpr: |
12618 | case ParseNodeKind::NegExpr: |
12619 | if (!emitUnary(&pn->as<UnaryNode>())) { |
12620 | return false; |
12621 | } |
12622 | break; |
12623 | |
12624 | case ParseNodeKind::PreIncrementExpr: |
12625 | case ParseNodeKind::PreDecrementExpr: |
12626 | case ParseNodeKind::PostIncrementExpr: |
12627 | case ParseNodeKind::PostDecrementExpr: |
12628 | if (!emitIncOrDec(&pn->as<UnaryNode>(), valueUsage)) { |
12629 | return false; |
12630 | } |
12631 | break; |
12632 | |
12633 | case ParseNodeKind::DeleteNameExpr: |
12634 | if (!emitDeleteName(&pn->as<UnaryNode>())) { |
12635 | return false; |
12636 | } |
12637 | break; |
12638 | |
12639 | case ParseNodeKind::DeletePropExpr: |
12640 | if (!emitDeleteProperty(&pn->as<UnaryNode>())) { |
12641 | return false; |
12642 | } |
12643 | break; |
12644 | |
12645 | case ParseNodeKind::DeleteElemExpr: |
12646 | if (!emitDeleteElement(&pn->as<UnaryNode>())) { |
12647 | return false; |
12648 | } |
12649 | break; |
12650 | |
12651 | case ParseNodeKind::DeleteExpr: |
12652 | if (!emitDeleteExpression(&pn->as<UnaryNode>())) { |
12653 | return false; |
12654 | } |
12655 | break; |
12656 | |
12657 | case ParseNodeKind::DeleteOptionalChainExpr: |
12658 | if (!emitDeleteOptionalChain(&pn->as<UnaryNode>())) { |
12659 | return false; |
12660 | } |
12661 | break; |
12662 | |
12663 | case ParseNodeKind::OptionalChain: |
12664 | if (!emitOptionalChain(&pn->as<UnaryNode>(), valueUsage)) { |
12665 | return false; |
12666 | } |
12667 | break; |
12668 | |
12669 | case ParseNodeKind::DotExpr: { |
12670 | PropertyAccess* prop = &pn->as<PropertyAccess>(); |
12671 | bool isSuper = prop->isSuper(); |
12672 | PropOpEmitter poe(this, PropOpEmitter::Kind::Get, |
12673 | isSuper ? PropOpEmitter::ObjKind::Super |
12674 | : PropOpEmitter::ObjKind::Other); |
12675 | if (!poe.prepareForObj()) { |
12676 | return false; |
12677 | } |
12678 | if (isSuper) { |
12679 | UnaryNode* base = &prop->expression().as<UnaryNode>(); |
12680 | if (!emitGetThisForSuperBase(base)) { |
12681 | // [stack] THIS |
12682 | return false; |
12683 | } |
12684 | } else { |
12685 | if (!emitPropLHS(prop)) { |
12686 | // [stack] OBJ |
12687 | return false; |
12688 | } |
12689 | } |
12690 | if (!poe.emitGet(prop->key().atom())) { |
12691 | // [stack] PROP |
12692 | return false; |
12693 | } |
12694 | break; |
12695 | } |
12696 | |
12697 | case ParseNodeKind::ArgumentsLength: { |
12698 | if (sc->isFunctionBox() && |
12699 | sc->asFunctionBox()->isEligibleForArgumentsLength() && |
12700 | !sc->asFunctionBox()->needsArgsObj()) { |
12701 | if (!emit1(JSOp::ArgumentsLength)) { |
12702 | return false; |
12703 | } |
12704 | } else { |
12705 | PropOpEmitter poe(this, PropOpEmitter::Kind::Get, |
12706 | PropOpEmitter::ObjKind::Other); |
12707 | if (!poe.prepareForObj()) { |
12708 | return false; |
12709 | } |
12710 | |
12711 | NameOpEmitter noe(this, TaggedParserAtomIndex::WellKnown::arguments(), |
12712 | NameOpEmitter::Kind::Get); |
12713 | if (!noe.emitGet()) { |
12714 | return false; |
12715 | } |
12716 | if (!poe.emitGet(TaggedParserAtomIndex::WellKnown::length())) { |
12717 | return false; |
12718 | } |
12719 | } |
12720 | break; |
12721 | } |
12722 | |
12723 | case ParseNodeKind::ElemExpr: { |
12724 | PropertyByValue* elem = &pn->as<PropertyByValue>(); |
12725 | bool isSuper = elem->isSuper(); |
12726 | MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!elem->key().isKind(ParseNodeKind::PrivateName))> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!elem->key().isKind(ParseNodeKind::PrivateName))) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!elem->key().isKind(ParseNodeKind::PrivateName)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12726); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!elem->key().isKind(ParseNodeKind::PrivateName)" ")"); do { *((volatile int*)__null) = 12726; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12727 | ElemOpEmitter eoe(this, ElemOpEmitter::Kind::Get, |
12728 | isSuper ? ElemOpEmitter::ObjKind::Super |
12729 | : ElemOpEmitter::ObjKind::Other); |
12730 | if (!emitElemObjAndKey(elem, isSuper, eoe)) { |
12731 | // [stack] # if Super |
12732 | // [stack] THIS KEY |
12733 | // [stack] # otherwise |
12734 | // [stack] OBJ KEY |
12735 | return false; |
12736 | } |
12737 | if (!eoe.emitGet()) { |
12738 | // [stack] ELEM |
12739 | return false; |
12740 | } |
12741 | |
12742 | break; |
12743 | } |
12744 | |
12745 | case ParseNodeKind::PrivateMemberExpr: { |
12746 | PrivateMemberAccess* privateExpr = &pn->as<PrivateMemberAccess>(); |
12747 | PrivateOpEmitter xoe(this, PrivateOpEmitter::Kind::Get, |
12748 | privateExpr->privateName().name()); |
12749 | if (!emitTree(&privateExpr->expression())) { |
12750 | // [stack] OBJ |
12751 | return false; |
12752 | } |
12753 | if (!xoe.emitReference()) { |
12754 | // [stack] OBJ NAME |
12755 | return false; |
12756 | } |
12757 | if (!xoe.emitGet()) { |
12758 | // [stack] VALUE |
12759 | return false; |
12760 | } |
12761 | |
12762 | break; |
12763 | } |
12764 | |
12765 | case ParseNodeKind::NewExpr: |
12766 | case ParseNodeKind::TaggedTemplateExpr: |
12767 | case ParseNodeKind::CallExpr: |
12768 | case ParseNodeKind::SuperCallExpr: |
12769 | if (!emitCallOrNew(&pn->as<CallNode>(), valueUsage)) { |
12770 | return false; |
12771 | } |
12772 | break; |
12773 | |
12774 | case ParseNodeKind::LexicalScope: |
12775 | if (!emitLexicalScope(&pn->as<LexicalScopeNode>())) { |
12776 | return false; |
12777 | } |
12778 | break; |
12779 | |
12780 | case ParseNodeKind::ConstDecl: |
12781 | case ParseNodeKind::LetDecl: |
12782 | if (!emitDeclarationList(&pn->as<ListNode>())) { |
12783 | return false; |
12784 | } |
12785 | break; |
12786 | #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT |
12787 | case ParseNodeKind::UsingDecl: |
12788 | if (!emitDeclarationList(&pn->as<ListNode>())) { |
12789 | return false; |
12790 | } |
12791 | break; |
12792 | #endif |
12793 | |
12794 | case ParseNodeKind::ImportDecl: |
12795 | MOZ_ASSERT(sc->isModuleContext())do { static_assert( mozilla::detail::AssertionConditionType< decltype(sc->isModuleContext())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(sc->isModuleContext()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("sc->isModuleContext()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12795); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isModuleContext()" ")"); do { *((volatile int*)__null) = 12795; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12796 | break; |
12797 | |
12798 | case ParseNodeKind::ExportStmt: { |
12799 | MOZ_ASSERT(sc->isModuleContext())do { static_assert( mozilla::detail::AssertionConditionType< decltype(sc->isModuleContext())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(sc->isModuleContext()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("sc->isModuleContext()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12799); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isModuleContext()" ")"); do { *((volatile int*)__null) = 12799; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12800 | UnaryNode* node = &pn->as<UnaryNode>(); |
12801 | ParseNode* decl = node->kid(); |
12802 | if (decl->getKind() != ParseNodeKind::ExportSpecList) { |
12803 | if (!emitTree(decl)) { |
12804 | return false; |
12805 | } |
12806 | } |
12807 | break; |
12808 | } |
12809 | |
12810 | case ParseNodeKind::ExportDefaultStmt: |
12811 | MOZ_ASSERT(sc->isModuleContext())do { static_assert( mozilla::detail::AssertionConditionType< decltype(sc->isModuleContext())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(sc->isModuleContext()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("sc->isModuleContext()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12811); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isModuleContext()" ")"); do { *((volatile int*)__null) = 12811; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12812 | if (!emitExportDefault(&pn->as<BinaryNode>())) { |
12813 | return false; |
12814 | } |
12815 | break; |
12816 | |
12817 | case ParseNodeKind::ExportFromStmt: |
12818 | MOZ_ASSERT(sc->isModuleContext())do { static_assert( mozilla::detail::AssertionConditionType< decltype(sc->isModuleContext())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(sc->isModuleContext()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("sc->isModuleContext()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12818); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sc->isModuleContext()" ")"); do { *((volatile int*)__null) = 12818; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
12819 | break; |
12820 | |
12821 | case ParseNodeKind::CallSiteObj: |
12822 | if (!emitCallSiteObject(&pn->as<CallSiteNode>())) { |
12823 | return false; |
12824 | } |
12825 | break; |
12826 | |
12827 | case ParseNodeKind::ArrayExpr: |
12828 | if (!emitArrayLiteral(&pn->as<ListNode>())) { |
12829 | return false; |
12830 | } |
12831 | break; |
12832 | |
12833 | case ParseNodeKind::ObjectExpr: |
12834 | if (!emitObject(&pn->as<ListNode>())) { |
12835 | return false; |
12836 | } |
12837 | break; |
12838 | |
12839 | case ParseNodeKind::Name: |
12840 | if (!emitGetName(&pn->as<NameNode>())) { |
12841 | return false; |
12842 | } |
12843 | break; |
12844 | |
12845 | case ParseNodeKind::PrivateName: |
12846 | if (!emitGetPrivateName(&pn->as<NameNode>())) { |
12847 | return false; |
12848 | } |
12849 | break; |
12850 | |
12851 | case ParseNodeKind::TemplateStringListExpr: |
12852 | if (!emitTemplateString(&pn->as<ListNode>())) { |
12853 | return false; |
12854 | } |
12855 | break; |
12856 | |
12857 | case ParseNodeKind::TemplateStringExpr: |
12858 | case ParseNodeKind::StringExpr: |
12859 | if (!emitStringOp(JSOp::String, pn->as<NameNode>().atom())) { |
12860 | return false; |
12861 | } |
12862 | break; |
12863 | |
12864 | case ParseNodeKind::NumberExpr: |
12865 | if (!emitNumberOp(pn->as<NumericLiteral>().value())) { |
12866 | return false; |
12867 | } |
12868 | break; |
12869 | |
12870 | case ParseNodeKind::BigIntExpr: |
12871 | if (!emitBigIntOp(&pn->as<BigIntLiteral>())) { |
12872 | return false; |
12873 | } |
12874 | break; |
12875 | |
12876 | case ParseNodeKind::RegExpExpr: { |
12877 | GCThingIndex index; |
12878 | if (!perScriptData().gcThingList().append(&pn->as<RegExpLiteral>(), |
12879 | &index)) { |
12880 | return false; |
12881 | } |
12882 | if (!emitRegExp(index)) { |
12883 | return false; |
12884 | } |
12885 | break; |
12886 | } |
12887 | |
12888 | case ParseNodeKind::TrueExpr: |
12889 | if (!emit1(JSOp::True)) { |
12890 | return false; |
12891 | } |
12892 | break; |
12893 | case ParseNodeKind::FalseExpr: |
12894 | if (!emit1(JSOp::False)) { |
12895 | return false; |
12896 | } |
12897 | break; |
12898 | case ParseNodeKind::NullExpr: |
12899 | if (!emit1(JSOp::Null)) { |
12900 | return false; |
12901 | } |
12902 | break; |
12903 | case ParseNodeKind::RawUndefinedExpr: |
12904 | if (!emit1(JSOp::Undefined)) { |
12905 | return false; |
12906 | } |
12907 | break; |
12908 | |
12909 | case ParseNodeKind::ThisExpr: |
12910 | if (!emitThisLiteral(&pn->as<ThisLiteral>())) { |
12911 | return false; |
12912 | } |
12913 | break; |
12914 | |
12915 | case ParseNodeKind::DebuggerStmt: |
12916 | if (!updateSourceCoordNotes(pn->pn_pos.begin)) { |
12917 | return false; |
12918 | } |
12919 | if (!markStepBreakpoint()) { |
12920 | return false; |
12921 | } |
12922 | if (!emit1(JSOp::Debugger)) { |
12923 | return false; |
12924 | } |
12925 | break; |
12926 | |
12927 | case ParseNodeKind::ClassDecl: |
12928 | if (!emitClass(&pn->as<ClassNode>())) { |
12929 | return false; |
12930 | } |
12931 | break; |
12932 | |
12933 | case ParseNodeKind::NewTargetExpr: |
12934 | if (!emitNewTarget(&pn->as<NewTargetNode>())) { |
12935 | return false; |
12936 | } |
12937 | break; |
12938 | |
12939 | case ParseNodeKind::ImportMetaExpr: |
12940 | if (!emit1(JSOp::ImportMeta)) { |
12941 | return false; |
12942 | } |
12943 | break; |
12944 | |
12945 | case ParseNodeKind::CallImportExpr: { |
12946 | BinaryNode* spec = &pn->as<BinaryNode>().right()->as<BinaryNode>(); |
12947 | |
12948 | if (!emitTree(spec->left())) { |
12949 | // [stack] specifier |
12950 | return false; |
12951 | } |
12952 | |
12953 | if (!spec->right()->isKind(ParseNodeKind::PosHolder)) { |
12954 | // [stack] specifier options |
12955 | if (!emitTree(spec->right())) { |
12956 | return false; |
12957 | } |
12958 | } else { |
12959 | // [stack] specifier undefined |
12960 | if (!emit1(JSOp::Undefined)) { |
12961 | return false; |
12962 | } |
12963 | } |
12964 | |
12965 | if (!emit1(JSOp::DynamicImport)) { |
12966 | return false; |
12967 | } |
12968 | |
12969 | break; |
12970 | } |
12971 | |
12972 | case ParseNodeKind::SetThis: |
12973 | if (!emitSetThis(&pn->as<BinaryNode>())) { |
12974 | return false; |
12975 | } |
12976 | break; |
12977 | |
12978 | #ifdef ENABLE_RECORD_TUPLE |
12979 | case ParseNodeKind::RecordExpr: |
12980 | if (!emitRecordLiteral(&pn->as<ListNode>())) { |
12981 | return false; |
12982 | } |
12983 | break; |
12984 | |
12985 | case ParseNodeKind::TupleExpr: |
12986 | if (!emitTupleLiteral(&pn->as<ListNode>())) { |
12987 | return false; |
12988 | } |
12989 | break; |
12990 | #endif |
12991 | |
12992 | case ParseNodeKind::PropertyNameExpr: |
12993 | case ParseNodeKind::PosHolder: |
12994 | MOZ_FALLTHROUGH_ASSERT(do { do { } while (false); MOZ_ReportCrash("" "MOZ_FALLTHROUGH_ASSERT: " "Should never try to emit ParseNodeKind::PosHolder or ::Property" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12995); AnnotateMozCrashReason("MOZ_CRASH(" "MOZ_FALLTHROUGH_ASSERT: " "Should never try to emit ParseNodeKind::PosHolder or ::Property" ")"); do { *((volatile int*)__null) = 12995; __attribute__(( nomerge)) ::abort(); } while (false); } while (false) |
12995 | "Should never try to emit ParseNodeKind::PosHolder or ::Property")do { do { } while (false); MOZ_ReportCrash("" "MOZ_FALLTHROUGH_ASSERT: " "Should never try to emit ParseNodeKind::PosHolder or ::Property" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12995); AnnotateMozCrashReason("MOZ_CRASH(" "MOZ_FALLTHROUGH_ASSERT: " "Should never try to emit ParseNodeKind::PosHolder or ::Property" ")"); do { *((volatile int*)__null) = 12995; __attribute__(( nomerge)) ::abort(); } while (false); } while (false); |
12996 | |
12997 | default: |
12998 | MOZ_ASSERT(0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(0)>::isValid, "invalid assertion condition"); if ( (__builtin_expect(!!(!(!!(0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("0", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 12998); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0" ")"); do { *((volatile int*)__null) = 12998; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
12999 | } |
13000 | |
13001 | return true; |
13002 | } |
13003 | |
13004 | static bool AllocSrcNote(FrontendContext* fc, SrcNotesVector& notes, |
13005 | unsigned size, unsigned* index) { |
13006 | size_t oldLength = notes.length(); |
13007 | |
13008 | if (MOZ_UNLIKELY(oldLength + size > MaxSrcNotesLength)(__builtin_expect(!!(oldLength + size > MaxSrcNotesLength) , 0))) { |
13009 | ReportAllocationOverflow(fc); |
13010 | return false; |
13011 | } |
13012 | |
13013 | if (!notes.growByUninitialized(size)) { |
13014 | return false; |
13015 | } |
13016 | |
13017 | *index = oldLength; |
13018 | return true; |
13019 | } |
13020 | |
13021 | bool BytecodeEmitter::addTryNote(TryNoteKind kind, uint32_t stackDepth, |
13022 | BytecodeOffset start, BytecodeOffset end) { |
13023 | MOZ_ASSERT(!inPrologue())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!inPrologue())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!inPrologue()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!inPrologue()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 13023); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inPrologue()" ")"); do { *((volatile int*)__null) = 13023; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
13024 | return bytecodeSection().tryNoteList().append(kind, stackDepth, start, end); |
13025 | } |
13026 | |
13027 | bool BytecodeEmitter::newSrcNote(SrcNoteType type, unsigned* indexp) { |
13028 | SrcNotesVector& notes = bytecodeSection().notes(); |
13029 | unsigned index; |
13030 | |
13031 | /* |
13032 | * Compute delta from the last annotated bytecode's offset. If it's too |
13033 | * big to fit in sn, allocate one or more xdelta notes and reset sn. |
13034 | */ |
13035 | BytecodeOffset offset = bytecodeSection().offset(); |
13036 | ptrdiff_t delta = (offset - bytecodeSection().lastNoteOffset()).value(); |
13037 | bytecodeSection().setLastNoteOffset(offset); |
13038 | |
13039 | auto allocator = [&](unsigned size) -> SrcNote* { |
13040 | if (!AllocSrcNote(fc, notes, size, &index)) { |
13041 | return nullptr; |
13042 | } |
13043 | return ¬es[index]; |
13044 | }; |
13045 | |
13046 | if (!SrcNoteWriter::writeNote(type, delta, allocator)) { |
13047 | return false; |
13048 | } |
13049 | |
13050 | if (indexp) { |
13051 | *indexp = index; |
13052 | } |
13053 | |
13054 | if (type == SrcNoteType::NewLine || type == SrcNoteType::SetLine) { |
13055 | lastLineOnlySrcNoteIndex = index; |
13056 | } else { |
13057 | lastLineOnlySrcNoteIndex = LastSrcNoteIsNotLineOnly; |
13058 | } |
13059 | |
13060 | return true; |
13061 | } |
13062 | |
13063 | bool BytecodeEmitter::newSrcNote2(SrcNoteType type, ptrdiff_t offset, |
13064 | unsigned* indexp) { |
13065 | unsigned index; |
13066 | if (!newSrcNote(type, &index)) { |
13067 | return false; |
13068 | } |
13069 | if (!newSrcNoteOperand(offset)) { |
13070 | return false; |
13071 | } |
13072 | if (indexp) { |
13073 | *indexp = index; |
13074 | } |
13075 | return true; |
13076 | } |
13077 | |
13078 | bool BytecodeEmitter::convertLastNewLineToNewLineColumn( |
13079 | JS::LimitedColumnNumberOneOrigin column) { |
13080 | SrcNotesVector& notes = bytecodeSection().notes(); |
13081 | MOZ_ASSERT(lastLineOnlySrcNoteIndex == notes.length() - 1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(lastLineOnlySrcNoteIndex == notes.length() - 1)>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(lastLineOnlySrcNoteIndex == notes.length() - 1))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("lastLineOnlySrcNoteIndex == notes.length() - 1" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 13081); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lastLineOnlySrcNoteIndex == notes.length() - 1" ")"); do { *((volatile int*)__null) = 13081; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
13082 | SrcNote* sn = ¬es[lastLineOnlySrcNoteIndex]; |
13083 | MOZ_ASSERT(sn->type() == SrcNoteType::NewLine)do { static_assert( mozilla::detail::AssertionConditionType< decltype(sn->type() == SrcNoteType::NewLine)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(! !(sn->type() == SrcNoteType::NewLine))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("sn->type() == SrcNoteType::NewLine" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 13083); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sn->type() == SrcNoteType::NewLine" ")"); do { *((volatile int*)__null) = 13083; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
13084 | |
13085 | SrcNoteWriter::convertNote(sn, SrcNoteType::NewLineColumn); |
13086 | if (!newSrcNoteOperand(SrcNote::NewLineColumn::toOperand(column))) { |
13087 | return false; |
13088 | } |
13089 | |
13090 | lastLineOnlySrcNoteIndex = LastSrcNoteIsNotLineOnly; |
13091 | return true; |
13092 | } |
13093 | |
13094 | bool BytecodeEmitter::convertLastSetLineToSetLineColumn( |
13095 | JS::LimitedColumnNumberOneOrigin column) { |
13096 | SrcNotesVector& notes = bytecodeSection().notes(); |
13097 | // The Line operand is either 1 byte or 4 bytes. |
13098 | MOZ_ASSERT(lastLineOnlySrcNoteIndex == notes.length() - 1 - 1 ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(lastLineOnlySrcNoteIndex == notes.length() - 1 - 1 || lastLineOnlySrcNoteIndex == notes.length() - 1 - 4)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(lastLineOnlySrcNoteIndex == notes.length() - 1 - 1 || lastLineOnlySrcNoteIndex == notes.length() - 1 - 4))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("lastLineOnlySrcNoteIndex == notes.length() - 1 - 1 || lastLineOnlySrcNoteIndex == notes.length() - 1 - 4" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 13099); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lastLineOnlySrcNoteIndex == notes.length() - 1 - 1 || lastLineOnlySrcNoteIndex == notes.length() - 1 - 4" ")"); do { *((volatile int*)__null) = 13099; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
13099 | lastLineOnlySrcNoteIndex == notes.length() - 1 - 4)do { static_assert( mozilla::detail::AssertionConditionType< decltype(lastLineOnlySrcNoteIndex == notes.length() - 1 - 1 || lastLineOnlySrcNoteIndex == notes.length() - 1 - 4)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(lastLineOnlySrcNoteIndex == notes.length() - 1 - 1 || lastLineOnlySrcNoteIndex == notes.length() - 1 - 4))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("lastLineOnlySrcNoteIndex == notes.length() - 1 - 1 || lastLineOnlySrcNoteIndex == notes.length() - 1 - 4" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 13099); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lastLineOnlySrcNoteIndex == notes.length() - 1 - 1 || lastLineOnlySrcNoteIndex == notes.length() - 1 - 4" ")"); do { *((volatile int*)__null) = 13099; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
13100 | SrcNote* sn = ¬es[lastLineOnlySrcNoteIndex]; |
13101 | MOZ_ASSERT(sn->type() == SrcNoteType::SetLine)do { static_assert( mozilla::detail::AssertionConditionType< decltype(sn->type() == SrcNoteType::SetLine)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(! !(sn->type() == SrcNoteType::SetLine))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("sn->type() == SrcNoteType::SetLine" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 13101); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sn->type() == SrcNoteType::SetLine" ")"); do { *((volatile int*)__null) = 13101; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
13102 | |
13103 | SrcNoteWriter::convertNote(sn, SrcNoteType::SetLineColumn); |
13104 | if (!newSrcNoteOperand(SrcNote::SetLineColumn::columnToOperand(column))) { |
13105 | return false; |
13106 | } |
13107 | |
13108 | lastLineOnlySrcNoteIndex = LastSrcNoteIsNotLineOnly; |
13109 | return true; |
13110 | } |
13111 | |
13112 | bool BytecodeEmitter::newSrcNoteOperand(ptrdiff_t operand) { |
13113 | if (!SrcNote::isRepresentableOperand(operand)) { |
13114 | reportError(nullptr, JSMSG_NEED_DIET, "script"); |
13115 | return false; |
13116 | } |
13117 | |
13118 | SrcNotesVector& notes = bytecodeSection().notes(); |
13119 | |
13120 | auto allocator = [&](unsigned size) -> SrcNote* { |
13121 | unsigned index; |
13122 | if (!AllocSrcNote(fc, notes, size, &index)) { |
13123 | return nullptr; |
13124 | } |
13125 | return ¬es[index]; |
13126 | }; |
13127 | |
13128 | return SrcNoteWriter::writeOperand(operand, allocator); |
13129 | } |
13130 | |
13131 | bool BytecodeEmitter::intoScriptStencil(ScriptIndex scriptIndex) { |
13132 | js::UniquePtr<ImmutableScriptData> immutableScriptData = |
13133 | createImmutableScriptData(); |
13134 | if (!immutableScriptData) { |
13135 | return false; |
13136 | } |
13137 | |
13138 | MOZ_ASSERT(outermostScope().hasNonSyntacticScopeOnChain() ==do { static_assert( mozilla::detail::AssertionConditionType< decltype(outermostScope().hasNonSyntacticScopeOnChain() == sc ->hasNonSyntacticScope())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(outermostScope().hasNonSyntacticScopeOnChain () == sc->hasNonSyntacticScope()))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("outermostScope().hasNonSyntacticScopeOnChain() == sc->hasNonSyntacticScope()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 13139); AnnotateMozCrashReason("MOZ_ASSERT" "(" "outermostScope().hasNonSyntacticScopeOnChain() == sc->hasNonSyntacticScope()" ")"); do { *((volatile int*)__null) = 13139; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false) |
13139 | sc->hasNonSyntacticScope())do { static_assert( mozilla::detail::AssertionConditionType< decltype(outermostScope().hasNonSyntacticScopeOnChain() == sc ->hasNonSyntacticScope())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(outermostScope().hasNonSyntacticScopeOnChain () == sc->hasNonSyntacticScope()))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("outermostScope().hasNonSyntacticScopeOnChain() == sc->hasNonSyntacticScope()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 13139); AnnotateMozCrashReason("MOZ_ASSERT" "(" "outermostScope().hasNonSyntacticScopeOnChain() == sc->hasNonSyntacticScope()" ")"); do { *((volatile int*)__null) = 13139; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
13140 | |
13141 | auto& things = perScriptData().gcThingList().objects(); |
13142 | if (!compilationState.appendGCThings(fc, scriptIndex, things)) { |
13143 | return false; |
13144 | } |
13145 | |
13146 | // Hand over the ImmutableScriptData instance generated by BCE. |
13147 | auto* sharedData = |
13148 | SharedImmutableScriptData::createWith(fc, std::move(immutableScriptData)); |
13149 | if (!sharedData) { |
13150 | return false; |
13151 | } |
13152 | |
13153 | // De-duplicate the bytecode within the runtime. |
13154 | if (!compilationState.sharedData.addAndShare(fc, scriptIndex, sharedData)) { |
13155 | return false; |
13156 | } |
13157 | |
13158 | ScriptStencil& script = compilationState.scriptData[scriptIndex]; |
13159 | script.setHasSharedData(); |
13160 | |
13161 | // Update flags specific to functions. |
13162 | if (sc->isFunctionBox()) { |
13163 | FunctionBox* funbox = sc->asFunctionBox(); |
13164 | MOZ_ASSERT(&script == &funbox->functionStencil())do { static_assert( mozilla::detail::AssertionConditionType< decltype(&script == &funbox->functionStencil())> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(&script == &funbox->functionStencil()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("&script == &funbox->functionStencil()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 13164); AnnotateMozCrashReason("MOZ_ASSERT" "(" "&script == &funbox->functionStencil()" ")"); do { *((volatile int*)__null) = 13164; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
13165 | funbox->copyUpdatedImmutableFlags(); |
13166 | MOZ_ASSERT(script.isFunction())do { static_assert( mozilla::detail::AssertionConditionType< decltype(script.isFunction())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(script.isFunction()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("script.isFunction()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/frontend/BytecodeEmitter.cpp" , 13166); AnnotateMozCrashReason("MOZ_ASSERT" "(" "script.isFunction()" ")"); do { *((volatile int*)__null) = 13166; __attribute__(( nomerge)) ::abort(); } while (false); } } while (false); |
13167 | } else { |
13168 | ScriptStencilExtra& scriptExtra = compilationState.scriptExtra[scriptIndex]; |
13169 | sc->copyScriptExtraFields(scriptExtra); |
13170 | } |
13171 | |
13172 | return true; |
13173 | } |
13174 | |
13175 | SelfHostedIter BytecodeEmitter::getSelfHostedIterFor(ParseNode* parseNode) { |
13176 | if (emitterMode == BytecodeEmitter::SelfHosting && |
13177 | parseNode->isKind(ParseNodeKind::CallExpr)) { |
13178 | auto* callee = parseNode->as<CallNode>().callee(); |
13179 | if (callee->isName(TaggedParserAtomIndex::WellKnown::allowContentIter())) { |
13180 | return SelfHostedIter::AllowContent; |
13181 | } |
13182 | if (callee->isName( |
13183 | TaggedParserAtomIndex::WellKnown::allowContentIterWith())) { |
13184 | return SelfHostedIter::AllowContentWith; |
13185 | } |
13186 | if (callee->isName( |
13187 | TaggedParserAtomIndex::WellKnown::allowContentIterWithNext())) { |
13188 | return SelfHostedIter::AllowContentWithNext; |
13189 | } |
13190 | } |
13191 | |
13192 | return SelfHostedIter::Deny; |
13193 | } |
13194 | |
13195 | #if defined(DEBUG1) || defined(JS_JITSPEW1) |
13196 | void BytecodeEmitter::dumpAtom(TaggedParserAtomIndex index) const { |
13197 | parserAtoms().dump(index); |
13198 | } |
13199 | #endif |