1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2  * vim: set ts=8 sts=4 et sw=4 tw=99:
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 #ifndef jit_IonBuilder_h
8 #define jit_IonBuilder_h
9 
10 // This file declares the data structures for building a MIRGraph from a
11 // JSScript.
12 
13 #include "mozilla/LinkedList.h"
14 
15 #include "jit/BaselineInspector.h"
16 #include "jit/BytecodeAnalysis.h"
17 #include "jit/IonAnalysis.h"
18 #include "jit/IonOptimizationLevels.h"
19 #include "jit/MIR.h"
20 #include "jit/MIRGenerator.h"
21 #include "jit/MIRGraph.h"
22 #include "jit/OptimizationTracking.h"
23 
24 namespace js {
25 namespace jit {
26 
27 class CodeGenerator;
28 class CallInfo;
29 class BaselineFrameInspector;
30 
31 enum class InlinableNative : uint16_t;
32 
33 // Records information about a baseline frame for compilation that is stable
34 // when later used off thread.
35 BaselineFrameInspector*
36 NewBaselineFrameInspector(TempAllocator* temp, BaselineFrame* frame, CompileInfo* info);
37 
38 class IonBuilder
39   : public MIRGenerator,
40     public mozilla::LinkedListElement<IonBuilder>
41 {
42     enum ControlStatus {
43         ControlStatus_Error,
44         ControlStatus_Abort,
45         ControlStatus_Ended,        // There is no continuation/join point.
46         ControlStatus_Joined,       // Created a join node.
47         ControlStatus_Jumped,       // Parsing another branch at the same level.
48         ControlStatus_None          // No control flow.
49     };
50 
51     struct DeferredEdge : public TempObject
52     {
53         MBasicBlock* block;
54         DeferredEdge* next;
55 
DeferredEdgeDeferredEdge56         DeferredEdge(MBasicBlock* block, DeferredEdge* next)
57           : block(block), next(next)
58         { }
59     };
60 
61     struct ControlFlowInfo {
62         // Entry in the cfgStack.
63         uint32_t cfgEntry;
64 
65         // Label that continues go to.
66         jsbytecode* continuepc;
67 
ControlFlowInfoControlFlowInfo68         ControlFlowInfo(uint32_t cfgEntry, jsbytecode* continuepc)
69           : cfgEntry(cfgEntry),
70             continuepc(continuepc)
71         { }
72     };
73 
74     // To avoid recursion, the bytecode analyzer uses a stack where each entry
75     // is a small state machine. As we encounter branches or jumps in the
76     // bytecode, we push information about the edges on the stack so that the
77     // CFG can be built in a tree-like fashion.
78     struct CFGState {
79         enum State {
80             IF_TRUE,            // if() { }, no else.
81             IF_TRUE_EMPTY_ELSE, // if() { }, empty else
82             IF_ELSE_TRUE,       // if() { X } else { }
83             IF_ELSE_FALSE,      // if() { } else { X }
84             DO_WHILE_LOOP_BODY, // do { x } while ()
85             DO_WHILE_LOOP_COND, // do { } while (x)
86             WHILE_LOOP_COND,    // while (x) { }
87             WHILE_LOOP_BODY,    // while () { x }
88             FOR_LOOP_COND,      // for (; x;) { }
89             FOR_LOOP_BODY,      // for (; ;) { x }
90             FOR_LOOP_UPDATE,    // for (; ; x) { }
91             TABLE_SWITCH,       // switch() { x }
92             COND_SWITCH_CASE,   // switch() { case X: ... }
93             COND_SWITCH_BODY,   // switch() { case ...: X }
94             AND_OR,             // && x, || x
95             LABEL,              // label: x
96             TRY                 // try { x } catch(e) { }
97         };
98 
99         State state;            // Current state of this control structure.
100         jsbytecode* stopAt;     // Bytecode at which to stop the processing loop.
101 
102         // For if structures, this contains branch information.
103         union {
104             struct {
105                 MBasicBlock* ifFalse;
106                 jsbytecode* falseEnd;
107                 MBasicBlock* ifTrue;    // Set when the end of the true path is reached.
108                 MTest* test;
109             } branch;
110             struct {
111                 // Common entry point.
112                 MBasicBlock* entry;
113 
114                 // Whether OSR is being performed for this loop.
115                 bool osr;
116 
117                 // Position of where the loop body starts and ends.
118                 jsbytecode* bodyStart;
119                 jsbytecode* bodyEnd;
120 
121                 // pc immediately after the loop exits.
122                 jsbytecode* exitpc;
123 
124                 // pc for 'continue' jumps.
125                 jsbytecode* continuepc;
126 
127                 // Common exit point. Created lazily, so it may be nullptr.
128                 MBasicBlock* successor;
129 
130                 // Deferred break and continue targets.
131                 DeferredEdge* breaks;
132                 DeferredEdge* continues;
133 
134                 // Initial state, in case loop processing is restarted.
135                 State initialState;
136                 jsbytecode* initialPc;
137                 jsbytecode* initialStopAt;
138                 jsbytecode* loopHead;
139 
140                 // For-loops only.
141                 jsbytecode* condpc;
142                 jsbytecode* updatepc;
143                 jsbytecode* updateEnd;
144             } loop;
145             struct {
146                 // pc immediately after the switch.
147                 jsbytecode* exitpc;
148 
149                 // Deferred break and continue targets.
150                 DeferredEdge* breaks;
151 
152                 // MIR instruction
153                 MTableSwitch* ins;
154 
155                 // The number of current successor that get mapped into a block.
156                 uint32_t currentBlock;
157 
158             } tableswitch;
159             struct {
160                 // Vector of body blocks to process after the cases.
161                 FixedList<MBasicBlock*>* bodies;
162 
163                 // When processing case statements, this counter points at the
164                 // last uninitialized body.  When processing bodies, this
165                 // counter targets the next body to process.
166                 uint32_t currentIdx;
167 
168                 // Remember the block index of the default case.
169                 jsbytecode* defaultTarget;
170                 uint32_t defaultIdx;
171 
172                 // Block immediately after the switch.
173                 jsbytecode* exitpc;
174                 DeferredEdge* breaks;
175             } condswitch;
176             struct {
177                 DeferredEdge* breaks;
178             } label;
179             struct {
180                 MBasicBlock* successor;
181             } try_;
182         };
183 
isLoopCFGState184         inline bool isLoop() const {
185             switch (state) {
186               case DO_WHILE_LOOP_COND:
187               case DO_WHILE_LOOP_BODY:
188               case WHILE_LOOP_COND:
189               case WHILE_LOOP_BODY:
190               case FOR_LOOP_COND:
191               case FOR_LOOP_BODY:
192               case FOR_LOOP_UPDATE:
193                 return true;
194               default:
195                 return false;
196             }
197         }
198 
199         static CFGState If(jsbytecode* join, MTest* test);
200         static CFGState IfElse(jsbytecode* trueEnd, jsbytecode* falseEnd, MTest* test);
201         static CFGState AndOr(jsbytecode* join, MBasicBlock* lhs);
202         static CFGState TableSwitch(jsbytecode* exitpc, MTableSwitch* ins);
203         static CFGState CondSwitch(IonBuilder* builder, jsbytecode* exitpc, jsbytecode* defaultTarget);
204         static CFGState Label(jsbytecode* exitpc);
205         static CFGState Try(jsbytecode* exitpc, MBasicBlock* successor);
206     };
207 
208     static int CmpSuccessors(const void* a, const void* b);
209 
210   public:
211     IonBuilder(JSContext* analysisContext, CompileCompartment* comp,
212                const JitCompileOptions& options, TempAllocator* temp,
213                MIRGraph* graph, CompilerConstraintList* constraints,
214                BaselineInspector* inspector, CompileInfo* info,
215                const OptimizationInfo* optimizationInfo, BaselineFrameInspector* baselineFrame,
216                size_t inliningDepth = 0, uint32_t loopDepth = 0);
217 
218     // Callers of build() and buildInline() should always check whether the
219     // call overrecursed, if false is returned.  Overrecursion is not
220     // signaled as OOM and will not in general be caught by OOM paths.
221     MOZ_MUST_USE bool build();
222     MOZ_MUST_USE bool buildInline(IonBuilder* callerBuilder, MResumePoint* callerResumePoint,
223                                   CallInfo& callInfo);
224 
225   private:
226     MOZ_MUST_USE bool traverseBytecode();
227     ControlStatus snoopControlFlow(JSOp op);
228     MOZ_MUST_USE bool processIterators();
229     MOZ_MUST_USE bool inspectOpcode(JSOp op);
230     uint32_t readIndex(jsbytecode* pc);
231     JSAtom* readAtom(jsbytecode* pc);
232     bool abort(const char* message, ...) MOZ_FORMAT_PRINTF(2, 3);
233     void trackActionableAbort(const char* message);
234     void spew(const char* message);
235 
236     JSFunction* getSingleCallTarget(TemporaryTypeSet* calleeTypes);
237     MOZ_MUST_USE bool getPolyCallTargets(TemporaryTypeSet* calleeTypes, bool constructing,
238                                          ObjectVector& targets, uint32_t maxTargets);
239 
240     void popCfgStack();
241     DeferredEdge* filterDeadDeferredEdges(DeferredEdge* edge);
242     MOZ_MUST_USE bool processDeferredContinues(CFGState& state);
243     ControlStatus processControlEnd();
244     ControlStatus processCfgStack();
245     ControlStatus processCfgEntry(CFGState& state);
246     ControlStatus processIfEnd(CFGState& state);
247     ControlStatus processIfElseTrueEnd(CFGState& state);
248     ControlStatus processIfElseFalseEnd(CFGState& state);
249     ControlStatus processDoWhileBodyEnd(CFGState& state);
250     ControlStatus processDoWhileCondEnd(CFGState& state);
251     ControlStatus processWhileCondEnd(CFGState& state);
252     ControlStatus processWhileBodyEnd(CFGState& state);
253     ControlStatus processForCondEnd(CFGState& state);
254     ControlStatus processForBodyEnd(CFGState& state);
255     ControlStatus processForUpdateEnd(CFGState& state);
256     ControlStatus processNextTableSwitchCase(CFGState& state);
257     ControlStatus processCondSwitchCase(CFGState& state);
258     ControlStatus processCondSwitchBody(CFGState& state);
259     ControlStatus processSwitchBreak(JSOp op);
260     ControlStatus processSwitchEnd(DeferredEdge* breaks, jsbytecode* exitpc);
261     ControlStatus processAndOrEnd(CFGState& state);
262     ControlStatus processLabelEnd(CFGState& state);
263     ControlStatus processTryEnd(CFGState& state);
264     ControlStatus processReturn(JSOp op);
265     ControlStatus processThrow();
266     ControlStatus processContinue(JSOp op);
267     ControlStatus processBreak(JSOp op, jssrcnote* sn);
268     ControlStatus maybeLoop(JSOp op, jssrcnote* sn);
269     MOZ_MUST_USE bool pushLoop(CFGState::State state, jsbytecode* stopAt, MBasicBlock* entry,
270                                bool osr, jsbytecode* loopHead, jsbytecode* initialPc,
271                                jsbytecode* bodyStart, jsbytecode* bodyEnd,
272                                jsbytecode* exitpc, jsbytecode* continuepc);
273     MOZ_MUST_USE bool analyzeNewLoopTypes(MBasicBlock* entry, jsbytecode* start, jsbytecode* end);
274 
275     MBasicBlock* addBlock(MBasicBlock* block, uint32_t loopDepth);
276     MBasicBlock* newBlock(MBasicBlock* predecessor, jsbytecode* pc);
277     MBasicBlock* newBlock(MBasicBlock* predecessor, jsbytecode* pc, uint32_t loopDepth);
278     MBasicBlock* newBlock(MBasicBlock* predecessor, jsbytecode* pc, MResumePoint* priorResumePoint);
279     MBasicBlock* newBlockPopN(MBasicBlock* predecessor, jsbytecode* pc, uint32_t popped);
280     MBasicBlock* newBlockAfter(MBasicBlock* at, MBasicBlock* predecessor, jsbytecode* pc);
281     MBasicBlock* newOsrPreheader(MBasicBlock* header, jsbytecode* loopEntry,
282                                  jsbytecode* beforeLoopEntry);
283     MBasicBlock* newPendingLoopHeader(MBasicBlock* predecessor, jsbytecode* pc, bool osr, bool canOsr,
284                                       unsigned stackPhiCount);
newBlock(jsbytecode * pc)285     MBasicBlock* newBlock(jsbytecode* pc) {
286         return newBlock(nullptr, pc);
287     }
newBlockAfter(MBasicBlock * at,jsbytecode * pc)288     MBasicBlock* newBlockAfter(MBasicBlock* at, jsbytecode* pc) {
289         return newBlockAfter(at, nullptr, pc);
290     }
291 
292     // We want to make sure that our MTest instructions all check whether the
293     // thing being tested might emulate undefined.  So we funnel their creation
294     // through this method, to make sure that happens.  We don't want to just do
295     // the check in MTest::New, because that can run on background compilation
296     // threads, and we're not sure it's safe to touch that part of the typeset
297     // from a background thread.
298     MTest* newTest(MDefinition* ins, MBasicBlock* ifTrue, MBasicBlock* ifFalse);
299 
300     // Given a list of pending breaks, creates a new block and inserts a Goto
301     // linking each break to the new block.
302     MBasicBlock* createBreakCatchBlock(DeferredEdge* edge, jsbytecode* pc);
303 
304     // Finishes loops that do not actually loop, containing only breaks and
305     // returns or a do while loop with a condition that is constant false.
306     ControlStatus processBrokenLoop(CFGState& state);
307 
308     // Computes loop phis, places them in all successors of a loop, then
309     // handles any pending breaks.
310     ControlStatus finishLoop(CFGState& state, MBasicBlock* successor);
311 
312     // Incorporates a type/typeSet into an OSR value for a loop, after the loop
313     // body has been processed.
314     MOZ_MUST_USE bool addOsrValueTypeBarrier(uint32_t slot, MInstruction** def,
315                                              MIRType type, TemporaryTypeSet* typeSet);
316     MOZ_MUST_USE bool maybeAddOsrTypeBarriers();
317 
318     // Restarts processing of a loop if the type information at its header was
319     // incomplete.
320     ControlStatus restartLoop(const CFGState& state);
321 
322     void assertValidLoopHeadOp(jsbytecode* pc);
323 
324     ControlStatus forLoop(JSOp op, jssrcnote* sn);
325     ControlStatus whileOrForInLoop(jssrcnote* sn);
326     ControlStatus doWhileLoop(JSOp op, jssrcnote* sn);
327     ControlStatus tableSwitch(JSOp op, jssrcnote* sn);
328     ControlStatus condSwitch(JSOp op, jssrcnote* sn);
329 
330     // Please see the Big Honkin' Comment about how resume points work in
331     // IonBuilder.cpp, near the definition for this function.
332     MOZ_MUST_USE bool resume(MInstruction* ins, jsbytecode* pc, MResumePoint::Mode mode);
333     MOZ_MUST_USE bool resumeAt(MInstruction* ins, jsbytecode* pc);
334     MOZ_MUST_USE bool resumeAfter(MInstruction* ins);
335     MOZ_MUST_USE bool maybeInsertResume();
336 
337     void insertRecompileCheck();
338 
339     MOZ_MUST_USE bool initParameters();
340     void initLocals();
341     void rewriteParameter(uint32_t slotIdx, MDefinition* param, int32_t argIndex);
342     MOZ_MUST_USE bool rewriteParameters();
343     MOZ_MUST_USE bool initEnvironmentChain(MDefinition* callee = nullptr);
344     MOZ_MUST_USE bool initArgumentsObject();
345     void pushConstant(const Value& v);
346 
347     MConstant* constant(const Value& v);
348     MConstant* constantInt(int32_t i);
349     MInstruction* initializedLength(MDefinition* obj, MDefinition* elements,
350                                     JSValueType unboxedType);
351     MInstruction* setInitializedLength(MDefinition* obj, JSValueType unboxedType, size_t count);
352 
353     // Improve the type information at tests
354     MOZ_MUST_USE bool improveTypesAtTest(MDefinition* ins, bool trueBranch, MTest* test);
355     MOZ_MUST_USE bool improveTypesAtCompare(MCompare* ins, bool trueBranch, MTest* test);
356     MOZ_MUST_USE bool improveTypesAtNullOrUndefinedCompare(MCompare* ins, bool trueBranch,
357                                                            MTest* test);
358     MOZ_MUST_USE bool improveTypesAtTypeOfCompare(MCompare* ins, bool trueBranch, MTest* test);
359 
360     // Used to detect triangular structure at test.
361     MOZ_MUST_USE bool detectAndOrStructure(MPhi* ins, bool* branchIsTrue);
362     MOZ_MUST_USE bool replaceTypeSet(MDefinition* subject, TemporaryTypeSet* type, MTest* test);
363 
364     // Add a guard which ensure that the set of type which goes through this
365     // generated code correspond to the observed types for the bytecode.
366     MDefinition* addTypeBarrier(MDefinition* def, TemporaryTypeSet* observed,
367                                 BarrierKind kind, MTypeBarrier** pbarrier = nullptr);
368     MOZ_MUST_USE bool pushTypeBarrier(MDefinition* def, TemporaryTypeSet* observed,
369                                       BarrierKind kind);
370 
371     // As pushTypeBarrier, but will compute the needBarrier boolean itself based
372     // on observed and the JSFunction that we're planning to call. The
373     // JSFunction must be a DOM method or getter.
374     MOZ_MUST_USE bool pushDOMTypeBarrier(MInstruction* ins, TemporaryTypeSet* observed,
375                                          JSFunction* func);
376 
377     // If definiteType is not known or def already has the right type, just
378     // returns def.  Otherwise, returns an MInstruction that has that definite
379     // type, infallibly unboxing ins as needed.  The new instruction will be
380     // added to |current| in this case.
381     MDefinition* ensureDefiniteType(MDefinition* def, MIRType definiteType);
382 
383     // Creates a MDefinition based on the given def improved with type as TypeSet.
384     MDefinition* ensureDefiniteTypeSet(MDefinition* def, TemporaryTypeSet* types);
385 
386     void maybeMarkEmpty(MDefinition* ins);
387 
388     JSObject* getSingletonPrototype(JSFunction* target);
389 
390     MDefinition* createThisScripted(MDefinition* callee, MDefinition* newTarget);
391     MDefinition* createThisScriptedSingleton(JSFunction* target, MDefinition* callee);
392     MDefinition* createThisScriptedBaseline(MDefinition* callee);
393     MDefinition* createThis(JSFunction* target, MDefinition* callee, MDefinition* newTarget);
394     MInstruction* createNamedLambdaObject(MDefinition* callee, MDefinition* envObj);
395     MInstruction* createCallObject(MDefinition* callee, MDefinition* envObj);
396 
397     MDefinition* walkEnvironmentChain(unsigned hops);
398 
399     MInstruction* addConvertElementsToDoubles(MDefinition* elements);
400     MDefinition* addMaybeCopyElementsForWrite(MDefinition* object, bool checkNative);
401     MInstruction* addBoundsCheck(MDefinition* index, MDefinition* length);
402     MInstruction* addShapeGuard(MDefinition* obj, Shape* const shape, BailoutKind bailoutKind);
403     MInstruction* addGroupGuard(MDefinition* obj, ObjectGroup* group, BailoutKind bailoutKind);
404     MInstruction* addUnboxedExpandoGuard(MDefinition* obj, bool hasExpando, BailoutKind bailoutKind);
405     MInstruction* addSharedTypedArrayGuard(MDefinition* obj);
406 
407     MInstruction*
408     addGuardReceiverPolymorphic(MDefinition* obj, const BaselineInspector::ReceiverVector& receivers);
409 
410     MDefinition* convertShiftToMaskForStaticTypedArray(MDefinition* id,
411                                                        Scalar::Type viewType);
412 
413     bool invalidatedIdempotentCache();
414 
415     bool hasStaticEnvironmentObject(EnvironmentCoordinate ec, JSObject** pcall);
416     MOZ_MUST_USE bool loadSlot(MDefinition* obj, size_t slot, size_t nfixed, MIRType rvalType,
417                                BarrierKind barrier, TemporaryTypeSet* types);
418     MOZ_MUST_USE bool loadSlot(MDefinition* obj, Shape* shape, MIRType rvalType,
419                                BarrierKind barrier, TemporaryTypeSet* types);
420     MOZ_MUST_USE bool storeSlot(MDefinition* obj, size_t slot, size_t nfixed, MDefinition* value,
421                                 bool needsBarrier, MIRType slotType = MIRType::None);
422     MOZ_MUST_USE bool storeSlot(MDefinition* obj, Shape* shape, MDefinition* value,
423                                 bool needsBarrier, MIRType slotType = MIRType::None);
424     bool shouldAbortOnPreliminaryGroups(MDefinition *obj);
425 
426     MDefinition* tryInnerizeWindow(MDefinition* obj);
427     MDefinition* maybeUnboxForPropertyAccess(MDefinition* def);
428 
429     // jsop_getprop() helpers.
430     MOZ_MUST_USE bool checkIsDefinitelyOptimizedArguments(MDefinition* obj, bool* isOptimizedArgs);
431     MOZ_MUST_USE bool getPropTryInferredConstant(bool* emitted, MDefinition* obj,
432                                                  PropertyName* name, TemporaryTypeSet* types);
433     MOZ_MUST_USE bool getPropTryArgumentsLength(bool* emitted, MDefinition* obj);
434     MOZ_MUST_USE bool getPropTryArgumentsCallee(bool* emitted, MDefinition* obj,
435                                                 PropertyName* name);
436     MOZ_MUST_USE bool getPropTryConstant(bool* emitted, MDefinition* obj, jsid id,
437                                          TemporaryTypeSet* types);
438     MOZ_MUST_USE bool getPropTryNotDefined(bool* emitted, MDefinition* obj, jsid id,
439                                            TemporaryTypeSet* types);
440     MOZ_MUST_USE bool getPropTryDefiniteSlot(bool* emitted, MDefinition* obj, PropertyName* name,
441                                              BarrierKind barrier, TemporaryTypeSet* types);
442     MOZ_MUST_USE bool getPropTryModuleNamespace(bool* emitted, MDefinition* obj, PropertyName* name,
443                                                 BarrierKind barrier, TemporaryTypeSet* types);
444     MOZ_MUST_USE bool getPropTryUnboxed(bool* emitted, MDefinition* obj, PropertyName* name,
445                                         BarrierKind barrier, TemporaryTypeSet* types);
446     MOZ_MUST_USE bool getPropTryCommonGetter(bool* emitted, MDefinition* obj, PropertyName* name,
447                                              TemporaryTypeSet* types);
448     MOZ_MUST_USE bool getPropTryInlineAccess(bool* emitted, MDefinition* obj, PropertyName* name,
449                                              BarrierKind barrier, TemporaryTypeSet* types);
450     MOZ_MUST_USE bool getPropTryTypedObject(bool* emitted, MDefinition* obj, PropertyName* name);
451     MOZ_MUST_USE bool getPropTryScalarPropOfTypedObject(bool* emitted, MDefinition* typedObj,
452                                                         int32_t fieldOffset,
453                                                         TypedObjectPrediction fieldTypeReprs);
454     MOZ_MUST_USE bool getPropTryReferencePropOfTypedObject(bool* emitted, MDefinition* typedObj,
455                                                            int32_t fieldOffset,
456                                                            TypedObjectPrediction fieldPrediction,
457                                                            PropertyName* name);
458     MOZ_MUST_USE bool getPropTryComplexPropOfTypedObject(bool* emitted, MDefinition* typedObj,
459                                                          int32_t fieldOffset,
460                                                          TypedObjectPrediction fieldTypeReprs,
461                                                          size_t fieldIndex);
462     MOZ_MUST_USE bool getPropTryInnerize(bool* emitted, MDefinition* obj, PropertyName* name,
463                                          TemporaryTypeSet* types);
464     MOZ_MUST_USE bool getPropTryCache(bool* emitted, MDefinition* obj, PropertyName* name,
465                                       BarrierKind barrier, TemporaryTypeSet* types);
466     MOZ_MUST_USE bool getPropTrySharedStub(bool* emitted, MDefinition* obj,
467                                            TemporaryTypeSet* types);
468 
469     // jsop_setprop() helpers.
470     MOZ_MUST_USE bool setPropTryCommonSetter(bool* emitted, MDefinition* obj,
471                                              PropertyName* name, MDefinition* value);
472     MOZ_MUST_USE bool setPropTryCommonDOMSetter(bool* emitted, MDefinition* obj,
473                                                 MDefinition* value, JSFunction* setter,
474                                                 TemporaryTypeSet* objTypes);
475     MOZ_MUST_USE bool setPropTryDefiniteSlot(bool* emitted, MDefinition* obj,
476                                              PropertyName* name, MDefinition* value,
477                                              bool barrier, TemporaryTypeSet* objTypes);
478     MOZ_MUST_USE bool setPropTryUnboxed(bool* emitted, MDefinition* obj,
479                                         PropertyName* name, MDefinition* value,
480                                         bool barrier, TemporaryTypeSet* objTypes);
481     MOZ_MUST_USE bool setPropTryInlineAccess(bool* emitted, MDefinition* obj,
482                                              PropertyName* name, MDefinition* value,
483                                              bool barrier, TemporaryTypeSet* objTypes);
484     MOZ_MUST_USE bool setPropTryTypedObject(bool* emitted, MDefinition* obj,
485                                             PropertyName* name, MDefinition* value);
486     MOZ_MUST_USE bool setPropTryReferencePropOfTypedObject(bool* emitted, MDefinition* obj,
487                                                            int32_t fieldOffset, MDefinition* value,
488                                                            TypedObjectPrediction fieldPrediction,
489                                                            PropertyName* name);
490     MOZ_MUST_USE bool setPropTryScalarPropOfTypedObject(bool* emitted,
491                                                         MDefinition* obj,
492                                                         int32_t fieldOffset,
493                                                         MDefinition* value,
494                                                         TypedObjectPrediction fieldTypeReprs);
495     MOZ_MUST_USE bool setPropTryCache(bool* emitted, MDefinition* obj,
496                                       PropertyName* name, MDefinition* value,
497                                       bool barrier, TemporaryTypeSet* objTypes);
498 
499     // jsop_binary_arith helpers.
500     MBinaryArithInstruction* binaryArithInstruction(JSOp op, MDefinition* left, MDefinition* right);
501     MOZ_MUST_USE bool binaryArithTryConcat(bool* emitted, JSOp op, MDefinition* left,
502                                            MDefinition* right);
503     MOZ_MUST_USE bool binaryArithTrySpecialized(bool* emitted, JSOp op, MDefinition* left,
504                                                 MDefinition* right);
505     MOZ_MUST_USE bool binaryArithTrySpecializedOnBaselineInspector(bool* emitted, JSOp op,
506                                                                    MDefinition* left,
507                                                                    MDefinition* right);
508     MOZ_MUST_USE bool arithTrySharedStub(bool* emitted, JSOp op, MDefinition* left,
509                                          MDefinition* right);
510 
511     // jsop_bitnot helpers.
512     MOZ_MUST_USE bool bitnotTrySpecialized(bool* emitted, MDefinition* input);
513 
514     // jsop_pow helpers.
515     MOZ_MUST_USE bool powTrySpecialized(bool* emitted, MDefinition* base, MDefinition* power,
516                                         MIRType outputType);
517 
518     // jsop_compare helpers.
519     MOZ_MUST_USE bool compareTrySpecialized(bool* emitted, JSOp op, MDefinition* left,
520                                             MDefinition* right);
521     MOZ_MUST_USE bool compareTryBitwise(bool* emitted, JSOp op, MDefinition* left,
522                                         MDefinition* right);
523     MOZ_MUST_USE bool compareTrySpecializedOnBaselineInspector(bool* emitted, JSOp op,
524                                                                MDefinition* left,
525                                                                MDefinition* right);
526     MOZ_MUST_USE bool compareTrySharedStub(bool* emitted, JSOp op, MDefinition* left,
527                                            MDefinition* right);
528 
529     // jsop_newarray helpers.
530     MOZ_MUST_USE bool newArrayTrySharedStub(bool* emitted);
531     MOZ_MUST_USE bool newArrayTryTemplateObject(bool* emitted, JSObject* templateObject,
532                                                 uint32_t length);
533     MOZ_MUST_USE bool newArrayTryVM(bool* emitted, JSObject* templateObject, uint32_t length);
534 
535     // jsop_newobject helpers.
536     MOZ_MUST_USE bool newObjectTrySharedStub(bool* emitted);
537     MOZ_MUST_USE bool newObjectTryTemplateObject(bool* emitted, JSObject* templateObject);
538     MOZ_MUST_USE bool newObjectTryVM(bool* emitted, JSObject* templateObject);
539 
540     // jsop_in helpers.
541     MOZ_MUST_USE bool inTryDense(bool* emitted, MDefinition* obj, MDefinition* id);
542     MOZ_MUST_USE bool inTryFold(bool* emitted, MDefinition* obj, MDefinition* id);
543 
544     // binary data lookup helpers.
545     TypedObjectPrediction typedObjectPrediction(MDefinition* typedObj);
546     TypedObjectPrediction typedObjectPrediction(TemporaryTypeSet* types);
547     MOZ_MUST_USE bool typedObjectHasField(MDefinition* typedObj,
548                                           PropertyName* name,
549                                           size_t* fieldOffset,
550                                           TypedObjectPrediction* fieldTypeReprs,
551                                           size_t* fieldIndex);
552     MDefinition* loadTypedObjectType(MDefinition* value);
553     void loadTypedObjectData(MDefinition* typedObj,
554                              MDefinition** owner,
555                              LinearSum* ownerOffset);
556     void loadTypedObjectElements(MDefinition* typedObj,
557                                  const LinearSum& byteOffset,
558                                  uint32_t scale,
559                                  MDefinition** ownerElements,
560                                  MDefinition** ownerScaledOffset,
561                                  int32_t* ownerByteAdjustment);
562     MDefinition* typeObjectForElementFromArrayStructType(MDefinition* typedObj);
563     MDefinition* typeObjectForFieldFromStructType(MDefinition* type,
564                                                   size_t fieldIndex);
565     MOZ_MUST_USE bool storeReferenceTypedObjectValue(MDefinition* typedObj,
566                                                      const LinearSum& byteOffset,
567                                                      ReferenceTypeDescr::Type type,
568                                                      MDefinition* value,
569                                                      PropertyName* name);
570     MOZ_MUST_USE bool storeScalarTypedObjectValue(MDefinition* typedObj,
571                                                   const LinearSum& byteOffset,
572                                                   ScalarTypeDescr::Type type,
573                                                   MDefinition* value);
574     MOZ_MUST_USE bool checkTypedObjectIndexInBounds(uint32_t elemSize,
575                                                     MDefinition* obj,
576                                                     MDefinition* index,
577                                                     TypedObjectPrediction objTypeDescrs,
578                                                     LinearSum* indexAsByteOffset);
579     MOZ_MUST_USE bool pushDerivedTypedObject(bool* emitted,
580                                              MDefinition* obj,
581                                              const LinearSum& byteOffset,
582                                              TypedObjectPrediction derivedTypeDescrs,
583                                              MDefinition* derivedTypeObj);
584     MOZ_MUST_USE bool pushScalarLoadFromTypedObject(MDefinition* obj,
585                                                     const LinearSum& byteoffset,
586                                                     ScalarTypeDescr::Type type);
587     MOZ_MUST_USE bool pushReferenceLoadFromTypedObject(MDefinition* typedObj,
588                                                        const LinearSum& byteOffset,
589                                                        ReferenceTypeDescr::Type type,
590                                                        PropertyName* name);
591     JSObject* getStaticTypedArrayObject(MDefinition* obj, MDefinition* index);
592 
593     // jsop_setelem() helpers.
594     MOZ_MUST_USE bool setElemTryTypedArray(bool* emitted, MDefinition* object,
595                                            MDefinition* index, MDefinition* value);
596     MOZ_MUST_USE bool setElemTryTypedObject(bool* emitted, MDefinition* obj,
597                                             MDefinition* index, MDefinition* value);
598     MOZ_MUST_USE bool setElemTryTypedStatic(bool* emitted, MDefinition* object,
599                                             MDefinition* index, MDefinition* value);
600     MOZ_MUST_USE bool setElemTryDense(bool* emitted, MDefinition* object,
601                                       MDefinition* index, MDefinition* value, bool writeHole);
602     MOZ_MUST_USE bool setElemTryArguments(bool* emitted, MDefinition* object,
603                                           MDefinition* index, MDefinition* value);
604     MOZ_MUST_USE bool setElemTryCache(bool* emitted, MDefinition* object,
605                                       MDefinition* index, MDefinition* value);
606     MOZ_MUST_USE bool setElemTryReferenceElemOfTypedObject(bool* emitted,
607                                                            MDefinition* obj,
608                                                            MDefinition* index,
609                                                            TypedObjectPrediction objPrediction,
610                                                            MDefinition* value,
611                                                            TypedObjectPrediction elemPrediction);
612     MOZ_MUST_USE bool setElemTryScalarElemOfTypedObject(bool* emitted,
613                                                         MDefinition* obj,
614                                                         MDefinition* index,
615                                                         TypedObjectPrediction objTypeReprs,
616                                                         MDefinition* value,
617                                                         TypedObjectPrediction elemTypeReprs,
618                                                         uint32_t elemSize);
619     MOZ_MUST_USE bool initializeArrayElement(MDefinition* obj, size_t index, MDefinition* value,
620                                              JSValueType unboxedType,
621                                              bool addResumePointAndIncrementInitializedLength);
622 
623     // jsop_getelem() helpers.
624     MOZ_MUST_USE bool getElemTryDense(bool* emitted, MDefinition* obj, MDefinition* index);
625     MOZ_MUST_USE bool getElemTryGetProp(bool* emitted, MDefinition* obj, MDefinition* index);
626     MOZ_MUST_USE bool getElemTryTypedStatic(bool* emitted, MDefinition* obj, MDefinition* index);
627     MOZ_MUST_USE bool getElemTryTypedArray(bool* emitted, MDefinition* obj, MDefinition* index);
628     MOZ_MUST_USE bool getElemTryTypedObject(bool* emitted, MDefinition* obj, MDefinition* index);
629     MOZ_MUST_USE bool getElemTryString(bool* emitted, MDefinition* obj, MDefinition* index);
630     MOZ_MUST_USE bool getElemTryArguments(bool* emitted, MDefinition* obj, MDefinition* index);
631     MOZ_MUST_USE bool getElemTryArgumentsInlined(bool* emitted, MDefinition* obj,
632                                                  MDefinition* index);
633     MOZ_MUST_USE bool getElemTryCache(bool* emitted, MDefinition* obj, MDefinition* index);
634     MOZ_MUST_USE bool getElemTryScalarElemOfTypedObject(bool* emitted,
635                                                         MDefinition* obj,
636                                                         MDefinition* index,
637                                                         TypedObjectPrediction objTypeReprs,
638                                                         TypedObjectPrediction elemTypeReprs,
639                                                         uint32_t elemSize);
640     MOZ_MUST_USE bool getElemTryReferenceElemOfTypedObject(bool* emitted,
641                                                            MDefinition* obj,
642                                                            MDefinition* index,
643                                                            TypedObjectPrediction objPrediction,
644                                                            TypedObjectPrediction elemPrediction);
645     MOZ_MUST_USE bool getElemTryComplexElemOfTypedObject(bool* emitted,
646                                                          MDefinition* obj,
647                                                          MDefinition* index,
648                                                          TypedObjectPrediction objTypeReprs,
649                                                          TypedObjectPrediction elemTypeReprs,
650                                                          uint32_t elemSize);
651     TemporaryTypeSet* computeHeapType(const TemporaryTypeSet* objTypes, const jsid id);
652 
653     enum BoundsChecking { DoBoundsCheck, SkipBoundsCheck };
654 
655     MInstruction* addArrayBufferByteLength(MDefinition* obj);
656 
657     // Add instructions to compute a typed array's length and data.  Also
658     // optionally convert |*index| into a bounds-checked definition, if
659     // requested.
660     //
661     // If you only need the array's length, use addTypedArrayLength below.
662     void addTypedArrayLengthAndData(MDefinition* obj,
663                                     BoundsChecking checking,
664                                     MDefinition** index,
665                                     MInstruction** length, MInstruction** elements);
666 
667     // Add an instruction to compute a typed array's length to the current
668     // block.  If you also need the typed array's data, use the above method
669     // instead.
addTypedArrayLength(MDefinition * obj)670     MInstruction* addTypedArrayLength(MDefinition* obj) {
671         MInstruction* length;
672         addTypedArrayLengthAndData(obj, SkipBoundsCheck, nullptr, &length, nullptr);
673         return length;
674     }
675 
676     MOZ_MUST_USE bool improveThisTypesForCall();
677 
678     MDefinition* getCallee();
679     MDefinition* getAliasedVar(EnvironmentCoordinate ec);
680     MDefinition* addLexicalCheck(MDefinition* input);
681 
682     MDefinition* convertToBoolean(MDefinition* input);
683 
684     MOZ_MUST_USE bool tryFoldInstanceOf(MDefinition* lhs, JSObject* protoObject);
685     MOZ_MUST_USE bool hasOnProtoChain(TypeSet::ObjectKey* key, JSObject* protoObject,
686                                       bool* hasOnProto);
687 
688     MOZ_MUST_USE bool jsop_add(MDefinition* left, MDefinition* right);
689     MOZ_MUST_USE bool jsop_bitnot();
690     MOZ_MUST_USE bool jsop_bitop(JSOp op);
691     MOZ_MUST_USE bool jsop_binary_arith(JSOp op);
692     MOZ_MUST_USE bool jsop_binary_arith(JSOp op, MDefinition* left, MDefinition* right);
693     MOZ_MUST_USE bool jsop_pow();
694     MOZ_MUST_USE bool jsop_pos();
695     MOZ_MUST_USE bool jsop_neg();
696     MOZ_MUST_USE bool jsop_tostring();
697     MOZ_MUST_USE bool jsop_setarg(uint32_t arg);
698     MOZ_MUST_USE bool jsop_defvar(uint32_t index);
699     MOZ_MUST_USE bool jsop_deflexical(uint32_t index);
700     MOZ_MUST_USE bool jsop_deffun(uint32_t index);
701     MOZ_MUST_USE bool jsop_notearg();
702     MOZ_MUST_USE bool jsop_throwsetconst();
703     MOZ_MUST_USE bool jsop_checklexical();
704     MOZ_MUST_USE bool jsop_checkaliasedlexical(EnvironmentCoordinate ec);
705     MOZ_MUST_USE bool jsop_funcall(uint32_t argc);
706     MOZ_MUST_USE bool jsop_funapply(uint32_t argc);
707     MOZ_MUST_USE bool jsop_funapplyarguments(uint32_t argc);
708     MOZ_MUST_USE bool jsop_funapplyarray(uint32_t argc);
709     MOZ_MUST_USE bool jsop_call(uint32_t argc, bool constructing);
710     MOZ_MUST_USE bool jsop_eval(uint32_t argc);
711     MOZ_MUST_USE bool jsop_ifeq(JSOp op);
712     MOZ_MUST_USE bool jsop_try();
713     MOZ_MUST_USE bool jsop_label();
714     MOZ_MUST_USE bool jsop_condswitch();
715     MOZ_MUST_USE bool jsop_andor(JSOp op);
716     MOZ_MUST_USE bool jsop_dup2();
717     MOZ_MUST_USE bool jsop_loophead(jsbytecode* pc);
718     MOZ_MUST_USE bool jsop_compare(JSOp op);
719     MOZ_MUST_USE bool jsop_compare(JSOp op, MDefinition* left, MDefinition* right);
720     MOZ_MUST_USE bool getStaticName(JSObject* staticObject, PropertyName* name, bool* psucceeded,
721                                     MDefinition* lexicalCheck = nullptr);
722     MOZ_MUST_USE bool loadStaticSlot(JSObject* staticObject, BarrierKind barrier,
723                                      TemporaryTypeSet* types, uint32_t slot);
724     MOZ_MUST_USE bool setStaticName(JSObject* staticObject, PropertyName* name);
725     MOZ_MUST_USE bool jsop_getgname(PropertyName* name);
726     MOZ_MUST_USE bool jsop_getname(PropertyName* name);
727     MOZ_MUST_USE bool jsop_intrinsic(PropertyName* name);
728     MOZ_MUST_USE bool jsop_getimport(PropertyName* name);
729     MOZ_MUST_USE bool jsop_bindname(PropertyName* name);
730     MOZ_MUST_USE bool jsop_bindvar();
731     MOZ_MUST_USE bool jsop_getelem();
732     MOZ_MUST_USE bool jsop_getelem_dense(MDefinition* obj, MDefinition* index,
733                                          JSValueType unboxedType);
734     MOZ_MUST_USE bool jsop_getelem_typed(MDefinition* obj, MDefinition* index,
735                                          ScalarTypeDescr::Type arrayType);
736     MOZ_MUST_USE bool jsop_setelem();
737     MOZ_MUST_USE bool jsop_setelem_dense(TemporaryTypeSet::DoubleConversion conversion,
738                                          MDefinition* object, MDefinition* index,
739                                          MDefinition* value, JSValueType unboxedType,
740                                          bool writeHole, bool* emitted);
741     MOZ_MUST_USE bool jsop_setelem_typed(ScalarTypeDescr::Type arrayType,
742                                          MDefinition* object, MDefinition* index,
743                                          MDefinition* value);
744     MOZ_MUST_USE bool jsop_length();
745     MOZ_MUST_USE bool jsop_length_fastPath();
746     MOZ_MUST_USE bool jsop_arguments();
747     MOZ_MUST_USE bool jsop_arguments_getelem();
748     MOZ_MUST_USE bool jsop_runonce();
749     MOZ_MUST_USE bool jsop_rest();
750     MOZ_MUST_USE bool jsop_not();
751     MOZ_MUST_USE bool jsop_getprop(PropertyName* name);
752     MOZ_MUST_USE bool jsop_setprop(PropertyName* name);
753     MOZ_MUST_USE bool jsop_delprop(PropertyName* name);
754     MOZ_MUST_USE bool jsop_delelem();
755     MOZ_MUST_USE bool jsop_newarray(uint32_t length);
756     MOZ_MUST_USE bool jsop_newarray(JSObject* templateObject, uint32_t length);
757     MOZ_MUST_USE bool jsop_newarray_copyonwrite();
758     MOZ_MUST_USE bool jsop_newobject();
759     MOZ_MUST_USE bool jsop_initelem();
760     MOZ_MUST_USE bool jsop_initelem_array();
761     MOZ_MUST_USE bool jsop_initelem_getter_setter();
762     MOZ_MUST_USE bool jsop_mutateproto();
763     MOZ_MUST_USE bool jsop_initprop(PropertyName* name);
764     MOZ_MUST_USE bool jsop_initprop_getter_setter(PropertyName* name);
765     MOZ_MUST_USE bool jsop_regexp(RegExpObject* reobj);
766     MOZ_MUST_USE bool jsop_object(JSObject* obj);
767     MOZ_MUST_USE bool jsop_lambda(JSFunction* fun);
768     MOZ_MUST_USE bool jsop_lambda_arrow(JSFunction* fun);
769     MOZ_MUST_USE bool jsop_functionthis();
770     MOZ_MUST_USE bool jsop_globalthis();
771     MOZ_MUST_USE bool jsop_typeof();
772     MOZ_MUST_USE bool jsop_toasync();
773     MOZ_MUST_USE bool jsop_toid();
774     MOZ_MUST_USE bool jsop_iter(uint8_t flags);
775     MOZ_MUST_USE bool jsop_itermore();
776     MOZ_MUST_USE bool jsop_isnoiter();
777     MOZ_MUST_USE bool jsop_iterend();
778     MOZ_MUST_USE bool jsop_in();
779     MOZ_MUST_USE bool jsop_instanceof();
780     MOZ_MUST_USE bool jsop_getaliasedvar(EnvironmentCoordinate ec);
781     MOZ_MUST_USE bool jsop_setaliasedvar(EnvironmentCoordinate ec);
782     MOZ_MUST_USE bool jsop_debugger();
783     MOZ_MUST_USE bool jsop_newtarget();
784     MOZ_MUST_USE bool jsop_checkisobj(uint8_t kind);
785     MOZ_MUST_USE bool jsop_checkobjcoercible();
786     MOZ_MUST_USE bool jsop_pushcallobj();
787 
788     /* Inlining. */
789 
790     enum InliningStatus
791     {
792         InliningStatus_Error,
793         InliningStatus_NotInlined,
794         InliningStatus_WarmUpCountTooLow,
795         InliningStatus_Inlined
796     };
797 
798     enum InliningDecision
799     {
800         InliningDecision_Error,
801         InliningDecision_Inline,
802         InliningDecision_DontInline,
803         InliningDecision_WarmUpCountTooLow
804     };
805 
806     static InliningDecision DontInline(JSScript* targetScript, const char* reason);
807 
808     // Helper function for canInlineTarget
809     bool hasCommonInliningPath(const JSScript* scriptToInline);
810 
811     // Oracles.
812     InliningDecision canInlineTarget(JSFunction* target, CallInfo& callInfo);
813     InliningDecision makeInliningDecision(JSObject* target, CallInfo& callInfo);
814     MOZ_MUST_USE bool selectInliningTargets(const ObjectVector& targets, CallInfo& callInfo,
815                                             BoolVector& choiceSet, uint32_t* numInlineable);
816 
817     // Native inlining helpers.
818     // The typeset for the return value of our function.  These are
819     // the types it's been observed returning in the past.
820     TemporaryTypeSet* getInlineReturnTypeSet();
821     // The known MIR type of getInlineReturnTypeSet.
822     MIRType getInlineReturnType();
823 
824     // Array natives.
825     InliningStatus inlineArray(CallInfo& callInfo);
826     InliningStatus inlineArrayIsArray(CallInfo& callInfo);
827     InliningStatus inlineArrayPopShift(CallInfo& callInfo, MArrayPopShift::Mode mode);
828     InliningStatus inlineArrayPush(CallInfo& callInfo);
829     InliningStatus inlineArraySlice(CallInfo& callInfo);
830     InliningStatus inlineArrayJoin(CallInfo& callInfo);
831     InliningStatus inlineArraySplice(CallInfo& callInfo);
832 
833     // Math natives.
834     InliningStatus inlineMathAbs(CallInfo& callInfo);
835     InliningStatus inlineMathFloor(CallInfo& callInfo);
836     InliningStatus inlineMathCeil(CallInfo& callInfo);
837     InliningStatus inlineMathClz32(CallInfo& callInfo);
838     InliningStatus inlineMathRound(CallInfo& callInfo);
839     InliningStatus inlineMathSqrt(CallInfo& callInfo);
840     InliningStatus inlineMathAtan2(CallInfo& callInfo);
841     InliningStatus inlineMathHypot(CallInfo& callInfo);
842     InliningStatus inlineMathMinMax(CallInfo& callInfo, bool max);
843     InliningStatus inlineMathPow(CallInfo& callInfo);
844     InliningStatus inlineMathRandom(CallInfo& callInfo);
845     InliningStatus inlineMathImul(CallInfo& callInfo);
846     InliningStatus inlineMathFRound(CallInfo& callInfo);
847     InliningStatus inlineMathFunction(CallInfo& callInfo, MMathFunction::Function function);
848 
849     // String natives.
850     InliningStatus inlineStringObject(CallInfo& callInfo);
851     InliningStatus inlineStrCharCodeAt(CallInfo& callInfo);
852     InliningStatus inlineConstantCharCodeAt(CallInfo& callInfo);
853     InliningStatus inlineStrFromCharCode(CallInfo& callInfo);
854     InliningStatus inlineStrFromCodePoint(CallInfo& callInfo);
855     InliningStatus inlineStrCharAt(CallInfo& callInfo);
856 
857     // String intrinsics.
858     InliningStatus inlineStringReplaceString(CallInfo& callInfo);
859     InliningStatus inlineConstantStringSplitString(CallInfo& callInfo);
860     InliningStatus inlineStringSplitString(CallInfo& callInfo);
861 
862     // RegExp intrinsics.
863     InliningStatus inlineRegExpMatcher(CallInfo& callInfo);
864     InliningStatus inlineRegExpSearcher(CallInfo& callInfo);
865     InliningStatus inlineRegExpTester(CallInfo& callInfo);
866     InliningStatus inlineIsRegExpObject(CallInfo& callInfo);
867     InliningStatus inlineRegExpPrototypeOptimizable(CallInfo& callInfo);
868     InliningStatus inlineRegExpInstanceOptimizable(CallInfo& callInfo);
869     InliningStatus inlineGetFirstDollarIndex(CallInfo& callInfo);
870 
871     // Object natives and intrinsics.
872     InliningStatus inlineObjectCreate(CallInfo& callInfo);
873     InliningStatus inlineDefineDataProperty(CallInfo& callInfo);
874 
875     // Atomics natives.
876     InliningStatus inlineAtomicsCompareExchange(CallInfo& callInfo);
877     InliningStatus inlineAtomicsExchange(CallInfo& callInfo);
878     InliningStatus inlineAtomicsLoad(CallInfo& callInfo);
879     InliningStatus inlineAtomicsStore(CallInfo& callInfo);
880     InliningStatus inlineAtomicsBinop(CallInfo& callInfo, InlinableNative target);
881     InliningStatus inlineAtomicsIsLockFree(CallInfo& callInfo);
882 
883     // Slot intrinsics.
884     InliningStatus inlineUnsafeSetReservedSlot(CallInfo& callInfo);
885     InliningStatus inlineUnsafeGetReservedSlot(CallInfo& callInfo,
886                                                MIRType knownValueType);
887 
888     // Map and Set intrinsics.
889     InliningStatus inlineGetNextEntryForIterator(CallInfo& callInfo,
890                                                  MGetNextEntryForIterator::Mode mode);
891 
892     // ArrayBuffer intrinsics.
893     InliningStatus inlineArrayBufferByteLength(CallInfo& callInfo);
894     InliningStatus inlinePossiblyWrappedArrayBufferByteLength(CallInfo& callInfo);
895 
896     // TypedArray intrinsics.
897     enum WrappingBehavior { AllowWrappedTypedArrays, RejectWrappedTypedArrays };
898     InliningStatus inlineTypedArray(CallInfo& callInfo, Native native);
899     InliningStatus inlineIsTypedArrayHelper(CallInfo& callInfo, WrappingBehavior wrappingBehavior);
900     InliningStatus inlineIsTypedArray(CallInfo& callInfo);
901     InliningStatus inlineIsPossiblyWrappedTypedArray(CallInfo& callInfo);
902     InliningStatus inlineTypedArrayLength(CallInfo& callInfo);
903     InliningStatus inlinePossiblyWrappedTypedArrayLength(CallInfo& callInfo);
904     InliningStatus inlineSetDisjointTypedElements(CallInfo& callInfo);
905 
906     // TypedObject intrinsics and natives.
907     InliningStatus inlineObjectIsTypeDescr(CallInfo& callInfo);
908     InliningStatus inlineSetTypedObjectOffset(CallInfo& callInfo);
909     InliningStatus inlineConstructTypedObject(CallInfo& callInfo, TypeDescr* target);
910 
911     // SIMD intrinsics and natives.
912     InliningStatus inlineConstructSimdObject(CallInfo& callInfo, SimdTypeDescr* target);
913 
914     // SIMD helpers.
915     bool canInlineSimd(CallInfo& callInfo, JSNative native, unsigned numArgs,
916                        InlineTypedObject** templateObj);
917     MDefinition* unboxSimd(MDefinition* ins, SimdType type);
918     IonBuilder::InliningStatus boxSimd(CallInfo& callInfo, MDefinition* ins,
919                                        InlineTypedObject* templateObj);
920     MDefinition* convertToBooleanSimdLane(MDefinition* scalar);
921 
922     InliningStatus inlineSimd(CallInfo& callInfo, JSFunction* target, SimdType type);
923 
924     InliningStatus inlineSimdBinaryArith(CallInfo& callInfo, JSNative native,
925                                          MSimdBinaryArith::Operation op, SimdType type);
926     InliningStatus inlineSimdBinaryBitwise(CallInfo& callInfo, JSNative native,
927                                            MSimdBinaryBitwise::Operation op, SimdType type);
928     InliningStatus inlineSimdBinarySaturating(CallInfo& callInfo, JSNative native,
929                                               MSimdBinarySaturating::Operation op, SimdType type);
930     InliningStatus inlineSimdShift(CallInfo& callInfo, JSNative native, MSimdShift::Operation op,
931                                    SimdType type);
932     InliningStatus inlineSimdComp(CallInfo& callInfo, JSNative native,
933                                   MSimdBinaryComp::Operation op, SimdType type);
934     InliningStatus inlineSimdUnary(CallInfo& callInfo, JSNative native,
935                                    MSimdUnaryArith::Operation op, SimdType type);
936     InliningStatus inlineSimdExtractLane(CallInfo& callInfo, JSNative native, SimdType type);
937     InliningStatus inlineSimdReplaceLane(CallInfo& callInfo, JSNative native, SimdType type);
938     InliningStatus inlineSimdSplat(CallInfo& callInfo, JSNative native, SimdType type);
939     InliningStatus inlineSimdShuffle(CallInfo& callInfo, JSNative native, SimdType type,
940                                      unsigned numVectors);
941     InliningStatus inlineSimdCheck(CallInfo& callInfo, JSNative native, SimdType type);
942     InliningStatus inlineSimdConvert(CallInfo& callInfo, JSNative native, bool isCast,
943                                      SimdType from, SimdType to);
944     InliningStatus inlineSimdSelect(CallInfo& callInfo, JSNative native, SimdType type);
945 
946     MOZ_MUST_USE bool prepareForSimdLoadStore(CallInfo& callInfo, Scalar::Type simdType,
947                                               MInstruction** elements, MDefinition** index,
948                                               Scalar::Type* arrayType);
949     InliningStatus inlineSimdLoad(CallInfo& callInfo, JSNative native, SimdType type,
950                                   unsigned numElems);
951     InliningStatus inlineSimdStore(CallInfo& callInfo, JSNative native, SimdType type,
952                                    unsigned numElems);
953 
954     InliningStatus inlineSimdAnyAllTrue(CallInfo& callInfo, bool IsAllTrue, JSNative native,
955                                         SimdType type);
956 
957     // Utility intrinsics.
958     InliningStatus inlineIsCallable(CallInfo& callInfo);
959     InliningStatus inlineIsConstructor(CallInfo& callInfo);
960     InliningStatus inlineIsObject(CallInfo& callInfo);
961     InliningStatus inlineToObject(CallInfo& callInfo);
962     InliningStatus inlineIsWrappedArrayConstructor(CallInfo& callInfo);
963     InliningStatus inlineToInteger(CallInfo& callInfo);
964     InliningStatus inlineToString(CallInfo& callInfo);
965     InliningStatus inlineDump(CallInfo& callInfo);
966     InliningStatus inlineHasClass(CallInfo& callInfo, const Class* clasp,
967                                   const Class* clasp2 = nullptr,
968                                   const Class* clasp3 = nullptr,
969                                   const Class* clasp4 = nullptr);
970     InliningStatus inlineIsConstructing(CallInfo& callInfo);
971     InliningStatus inlineSubstringKernel(CallInfo& callInfo);
972     InliningStatus inlineObjectHasPrototype(CallInfo& callInfo);
973 
974     // Testing functions.
975     InliningStatus inlineBailout(CallInfo& callInfo);
976     InliningStatus inlineAssertFloat32(CallInfo& callInfo);
977     InliningStatus inlineAssertRecoveredOnBailout(CallInfo& callInfo);
978 
979     // Bind function.
980     InliningStatus inlineBoundFunction(CallInfo& callInfo, JSFunction* target);
981 
982     // Main inlining functions
983     InliningStatus inlineNativeCall(CallInfo& callInfo, JSFunction* target);
984     InliningStatus inlineNativeGetter(CallInfo& callInfo, JSFunction* target);
985     InliningStatus inlineNonFunctionCall(CallInfo& callInfo, JSObject* target);
986     InliningStatus inlineScriptedCall(CallInfo& callInfo, JSFunction* target);
987     InliningStatus inlineSingleCall(CallInfo& callInfo, JSObject* target);
988 
989     // Call functions
990     InliningStatus inlineCallsite(const ObjectVector& targets, CallInfo& callInfo);
991     MOZ_MUST_USE bool inlineCalls(CallInfo& callInfo, const ObjectVector& targets,
992                                   BoolVector& choiceSet, MGetPropertyCache* maybeCache);
993 
994     // Inlining helpers.
995     MOZ_MUST_USE bool inlineGenericFallback(JSFunction* target, CallInfo& callInfo,
996                                             MBasicBlock* dispatchBlock);
997     MOZ_MUST_USE bool inlineObjectGroupFallback(CallInfo& callInfo, MBasicBlock* dispatchBlock,
998                                                 MObjectGroupDispatch* dispatch,
999                                                 MGetPropertyCache* cache,
1000                                                 MBasicBlock** fallbackTarget);
1001 
1002     enum AtomicCheckResult {
1003         DontCheckAtomicResult,
1004         DoCheckAtomicResult
1005     };
1006 
1007     MOZ_MUST_USE bool atomicsMeetsPreconditions(CallInfo& callInfo, Scalar::Type* arrayElementType,
1008                                                 bool* requiresDynamicCheck,
1009                                                 AtomicCheckResult checkResult=DoCheckAtomicResult);
1010     void atomicsCheckBounds(CallInfo& callInfo, MInstruction** elements, MDefinition** index);
1011 
1012     MOZ_MUST_USE bool testNeedsArgumentCheck(JSFunction* target, CallInfo& callInfo);
1013 
1014     MCall* makeCallHelper(JSFunction* target, CallInfo& callInfo);
1015     MOZ_MUST_USE bool makeCall(JSFunction* target, CallInfo& callInfo);
1016 
1017     MDefinition* patchInlinedReturn(CallInfo& callInfo, MBasicBlock* exit, MBasicBlock* bottom);
1018     MDefinition* patchInlinedReturns(CallInfo& callInfo, MIRGraphReturns& returns,
1019                                      MBasicBlock* bottom);
1020     MDefinition* specializeInlinedReturn(MDefinition* rdef, MBasicBlock* exit);
1021 
1022     MOZ_MUST_USE bool objectsHaveCommonPrototype(TemporaryTypeSet* types, PropertyName* name,
1023                                                  bool isGetter, JSObject* foundProto,
1024                                                  bool* guardGlobal);
1025     void freezePropertiesForCommonPrototype(TemporaryTypeSet* types, PropertyName* name,
1026                                             JSObject* foundProto, bool allowEmptyTypesForGlobal = false);
1027     /*
1028      * Callers must pass a non-null globalGuard if they pass a non-null globalShape.
1029      */
1030     MOZ_MUST_USE bool testCommonGetterSetter(TemporaryTypeSet* types, PropertyName* name,
1031                                              bool isGetter, JSObject* foundProto,
1032                                              Shape* lastProperty, JSFunction* getterOrSetter,
1033                                              MDefinition** guard, Shape* globalShape = nullptr,
1034                                              MDefinition** globalGuard = nullptr);
1035     MOZ_MUST_USE bool testShouldDOMCall(TypeSet* inTypes,
1036                                         JSFunction* func, JSJitInfo::OpType opType);
1037 
1038     MDefinition*
1039     addShapeGuardsForGetterSetter(MDefinition* obj, JSObject* holder, Shape* holderShape,
1040                                   const BaselineInspector::ReceiverVector& receivers,
1041                                   const BaselineInspector::ObjectGroupVector& convertUnboxedGroups,
1042                                   bool isOwnProperty);
1043 
1044     MOZ_MUST_USE bool annotateGetPropertyCache(MDefinition* obj, PropertyName* name,
1045                                                MGetPropertyCache* getPropCache,
1046                                                TemporaryTypeSet* objTypes,
1047                                                TemporaryTypeSet* pushedTypes);
1048 
1049     MGetPropertyCache* getInlineableGetPropertyCache(CallInfo& callInfo);
1050 
1051     JSObject* testGlobalLexicalBinding(PropertyName* name);
1052 
1053     JSObject* testSingletonProperty(JSObject* obj, jsid id);
1054     JSObject* testSingletonPropertyTypes(MDefinition* obj, jsid id);
1055 
1056     ResultWithOOM<bool> testNotDefinedProperty(MDefinition* obj, jsid id);
1057 
1058     uint32_t getDefiniteSlot(TemporaryTypeSet* types, PropertyName* name, uint32_t* pnfixed);
1059     MDefinition* convertUnboxedObjects(MDefinition* obj);
1060     MDefinition* convertUnboxedObjects(MDefinition* obj,
1061                                        const BaselineInspector::ObjectGroupVector& list);
1062     uint32_t getUnboxedOffset(TemporaryTypeSet* types, PropertyName* name,
1063                               JSValueType* punboxedType);
1064     MInstruction* loadUnboxedProperty(MDefinition* obj, size_t offset, JSValueType unboxedType,
1065                                       BarrierKind barrier, TemporaryTypeSet* types);
1066     MInstruction* loadUnboxedValue(MDefinition* elements, size_t elementsOffset,
1067                                    MDefinition* scaledOffset, JSValueType unboxedType,
1068                                    BarrierKind barrier, TemporaryTypeSet* types);
1069     MInstruction* storeUnboxedProperty(MDefinition* obj, size_t offset, JSValueType unboxedType,
1070                                        MDefinition* value);
1071     MInstruction* storeUnboxedValue(MDefinition* obj,
1072                                     MDefinition* elements, int32_t elementsOffset,
1073                                     MDefinition* scaledOffset, JSValueType unboxedType,
1074                                     MDefinition* value, bool preBarrier = true);
1075     MOZ_MUST_USE bool checkPreliminaryGroups(MDefinition *obj);
1076     MOZ_MUST_USE bool freezePropTypeSets(TemporaryTypeSet* types,
1077                                          JSObject* foundProto, PropertyName* name);
1078     bool canInlinePropertyOpShapes(const BaselineInspector::ReceiverVector& receivers);
1079 
1080     TemporaryTypeSet* bytecodeTypes(jsbytecode* pc);
1081 
1082     // Use one of the below methods for updating the current block, rather than
1083     // updating |current| directly. setCurrent() should only be used in cases
1084     // where the block cannot have phis whose type needs to be computed.
1085 
setCurrentAndSpecializePhis(MBasicBlock * block)1086     MOZ_MUST_USE bool setCurrentAndSpecializePhis(MBasicBlock* block) {
1087         if (block) {
1088             if (!block->specializePhis(alloc()))
1089                 return false;
1090         }
1091         setCurrent(block);
1092         return true;
1093     }
1094 
setCurrent(MBasicBlock * block)1095     void setCurrent(MBasicBlock* block) {
1096         current = block;
1097     }
1098 
1099     // A builder is inextricably tied to a particular script.
1100     JSScript* script_;
1101 
1102     // script->hasIonScript() at the start of the compilation. Used to avoid
1103     // calling hasIonScript() from background compilation threads.
1104     bool scriptHasIonScript_;
1105 
1106     // If off thread compilation is successful, the final code generator is
1107     // attached here. Code has been generated, but not linked (there is not yet
1108     // an IonScript). This is heap allocated, and must be explicitly destroyed,
1109     // performed by FinishOffThreadBuilder().
1110     CodeGenerator* backgroundCodegen_;
1111 
1112     // Some aborts are actionable (e.g., using an unsupported bytecode). When
1113     // optimization tracking is enabled, the location and message of the abort
1114     // are recorded here so they may be propagated to the script's
1115     // corresponding JitcodeGlobalEntry::BaselineEntry.
1116     JSScript* actionableAbortScript_;
1117     jsbytecode* actionableAbortPc_;
1118     const char* actionableAbortMessage_;
1119 
1120     MRootList* rootList_;
1121 
1122   public:
setRootList(MRootList & rootList)1123     void setRootList(MRootList& rootList) {
1124         MOZ_ASSERT(!rootList_);
1125         rootList_ = &rootList;
1126     }
1127     void clearForBackEnd();
1128     JSObject* checkNurseryObject(JSObject* obj);
1129 
script()1130     JSScript* script() const { return script_; }
scriptHasIonScript()1131     bool scriptHasIonScript() const { return scriptHasIonScript_; }
1132 
backgroundCodegen()1133     CodeGenerator* backgroundCodegen() const { return backgroundCodegen_; }
setBackgroundCodegen(CodeGenerator * codegen)1134     void setBackgroundCodegen(CodeGenerator* codegen) { backgroundCodegen_ = codegen; }
1135 
constraints()1136     CompilerConstraintList* constraints() {
1137         return constraints_;
1138     }
1139 
isInlineBuilder()1140     bool isInlineBuilder() const {
1141         return callerBuilder_ != nullptr;
1142     }
1143 
names()1144     const JSAtomState& names() { return compartment->runtime()->names(); }
1145 
hadActionableAbort()1146     bool hadActionableAbort() const {
1147         MOZ_ASSERT(!actionableAbortScript_ ||
1148                    (actionableAbortPc_ && actionableAbortMessage_));
1149         return actionableAbortScript_ != nullptr;
1150     }
1151 
traceLogger()1152     TraceLoggerThread *traceLogger() {
1153         // Currently ionbuilder only runs on the main thread.
1154         return TraceLoggerForMainThread(compartment->runtime()->mainThread()->runtimeFromMainThread());
1155     }
1156 
actionableAbortLocationAndMessage(JSScript ** abortScript,jsbytecode ** abortPc,const char ** abortMessage)1157     void actionableAbortLocationAndMessage(JSScript** abortScript, jsbytecode** abortPc,
1158                                            const char** abortMessage)
1159     {
1160         MOZ_ASSERT(hadActionableAbort());
1161         *abortScript = actionableAbortScript_;
1162         *abortPc = actionableAbortPc_;
1163         *abortMessage = actionableAbortMessage_;
1164     }
1165 
1166     void trace(JSTracer* trc);
1167 
1168   private:
1169     MOZ_MUST_USE bool init();
1170 
1171     JSContext* analysisContext;
1172     BaselineFrameInspector* baselineFrame_;
1173 
1174     // Constraints for recording dependencies on type information.
1175     CompilerConstraintList* constraints_;
1176 
1177     // Basic analysis information about the script.
1178     BytecodeAnalysis analysis_;
analysis()1179     BytecodeAnalysis& analysis() {
1180         return analysis_;
1181     }
1182 
1183     TemporaryTypeSet* thisTypes;
1184     TemporaryTypeSet* argTypes;
1185     TemporaryTypeSet* typeArray;
1186     uint32_t typeArrayHint;
1187     uint32_t* bytecodeTypeMap;
1188 
1189     GSNCache gsn;
1190     EnvironmentCoordinateNameCache envCoordinateNameCache;
1191 
1192     jsbytecode* pc;
1193     MBasicBlock* current;
1194     uint32_t loopDepth_;
1195 
1196     Vector<BytecodeSite*, 0, JitAllocPolicy> trackedOptimizationSites_;
1197 
bytecodeSite(jsbytecode * pc)1198     BytecodeSite* bytecodeSite(jsbytecode* pc) {
1199         MOZ_ASSERT(info().inlineScriptTree()->script()->containsPC(pc));
1200         // See comment in maybeTrackedOptimizationSite.
1201         if (isOptimizationTrackingEnabled()) {
1202             if (BytecodeSite* site = maybeTrackedOptimizationSite(pc))
1203                 return site;
1204         }
1205         return new(alloc()) BytecodeSite(info().inlineScriptTree(), pc);
1206     }
1207 
1208     BytecodeSite* maybeTrackedOptimizationSite(jsbytecode* pc);
1209 
1210     MDefinition* lexicalCheck_;
1211 
setLexicalCheck(MDefinition * lexical)1212     void setLexicalCheck(MDefinition* lexical) {
1213         MOZ_ASSERT(!lexicalCheck_);
1214         lexicalCheck_ = lexical;
1215     }
takeLexicalCheck()1216     MDefinition* takeLexicalCheck() {
1217         MDefinition* lexical = lexicalCheck_;
1218         lexicalCheck_ = nullptr;
1219         return lexical;
1220     }
1221 
1222     /* Information used for inline-call builders. */
1223     MResumePoint* callerResumePoint_;
callerPC()1224     jsbytecode* callerPC() {
1225         return callerResumePoint_ ? callerResumePoint_->pc() : nullptr;
1226     }
1227     IonBuilder* callerBuilder_;
1228 
1229     IonBuilder* outermostBuilder();
1230 
1231     struct LoopHeader {
1232         jsbytecode* pc;
1233         MBasicBlock* header;
1234 
LoopHeaderLoopHeader1235         LoopHeader(jsbytecode* pc, MBasicBlock* header)
1236           : pc(pc), header(header)
1237         {}
1238     };
1239 
1240     Vector<CFGState, 8, JitAllocPolicy> cfgStack_;
1241     Vector<ControlFlowInfo, 4, JitAllocPolicy> loops_;
1242     Vector<ControlFlowInfo, 0, JitAllocPolicy> switches_;
1243     Vector<ControlFlowInfo, 2, JitAllocPolicy> labels_;
1244     Vector<MInstruction*, 2, JitAllocPolicy> iterators_;
1245     Vector<LoopHeader, 0, JitAllocPolicy> loopHeaders_;
1246     BaselineInspector* inspector;
1247 
1248     size_t inliningDepth_;
1249 
1250     // Total bytecode length of all inlined scripts. Only tracked for the
1251     // outermost builder.
1252     size_t inlinedBytecodeLength_;
1253 
1254     // Cutoff to disable compilation if excessive time is spent reanalyzing
1255     // loop bodies to compute a fixpoint of the types for loop variables.
1256     static const size_t MAX_LOOP_RESTARTS = 40;
1257     size_t numLoopRestarts_;
1258 
1259     // True if script->failedBoundsCheck is set for the current script or
1260     // an outer script.
1261     bool failedBoundsCheck_;
1262 
1263     // True if script->failedShapeGuard is set for the current script or
1264     // an outer script.
1265     bool failedShapeGuard_;
1266 
1267     // True if script->failedLexicalCheck_ is set for the current script or
1268     // an outer script.
1269     bool failedLexicalCheck_;
1270 
1271     // Has an iterator other than 'for in'.
1272     bool nonStringIteration_;
1273 
1274     // If this script can use a lazy arguments object, it will be pre-created
1275     // here.
1276     MInstruction* lazyArguments_;
1277 
1278     // If this is an inline builder, the call info for the builder.
1279     const CallInfo* inlineCallInfo_;
1280 
1281     // When compiling a call with multiple targets, we are first creating a
1282     // MGetPropertyCache.  This MGetPropertyCache is following the bytecode, and
1283     // is used to recover the JSFunction.  In some cases, the Type of the object
1284     // which own the property is enough for dispatching to the right function.
1285     // In such cases we do not have read the property, except when the type
1286     // object is unknown.
1287     //
1288     // As an optimization, we can dispatch a call based on the object group,
1289     // without doing the MGetPropertyCache.  This is what is achieved by
1290     // |IonBuilder::inlineCalls|.  As we might not know all the functions, we
1291     // are adding a fallback path, where this MGetPropertyCache would be moved
1292     // into.
1293     //
1294     // In order to build the fallback path, we have to capture a resume point
1295     // ahead, for the potential fallback path.  This resume point is captured
1296     // while building MGetPropertyCache.  It is capturing the state of Baseline
1297     // before the execution of the MGetPropertyCache, such as we can safely do
1298     // it in the fallback path.
1299     //
1300     // This field is used to discard the resume point if it is not used for
1301     // building a fallback path.
1302 
1303     // Discard the prior resume point while setting a new MGetPropertyCache.
1304     void replaceMaybeFallbackFunctionGetter(MGetPropertyCache* cache);
1305 
1306     // Discard the MGetPropertyCache if it is handled by WrapMGetPropertyCache.
keepFallbackFunctionGetter(MGetPropertyCache * cache)1307     void keepFallbackFunctionGetter(MGetPropertyCache* cache) {
1308         if (cache == maybeFallbackFunctionGetter_)
1309             maybeFallbackFunctionGetter_ = nullptr;
1310     }
1311 
1312     MGetPropertyCache* maybeFallbackFunctionGetter_;
1313 
1314     // Used in tracking outcomes of optimization strategies for devtools.
1315     void startTrackingOptimizations();
1316 
1317     // The track* methods below are called often. Do not combine them with the
1318     // unchecked variants, despite the unchecked variants having no other
1319     // callers.
trackTypeInfo(JS::TrackedTypeSite site,MIRType mirType,TemporaryTypeSet * typeSet)1320     void trackTypeInfo(JS::TrackedTypeSite site, MIRType mirType,
1321                        TemporaryTypeSet* typeSet)
1322     {
1323         if (MOZ_UNLIKELY(current->trackedSite()->hasOptimizations()))
1324             trackTypeInfoUnchecked(site, mirType, typeSet);
1325     }
trackTypeInfo(JS::TrackedTypeSite site,JSObject * obj)1326     void trackTypeInfo(JS::TrackedTypeSite site, JSObject* obj) {
1327         if (MOZ_UNLIKELY(current->trackedSite()->hasOptimizations()))
1328             trackTypeInfoUnchecked(site, obj);
1329     }
trackTypeInfo(CallInfo & callInfo)1330     void trackTypeInfo(CallInfo& callInfo) {
1331         if (MOZ_UNLIKELY(current->trackedSite()->hasOptimizations()))
1332             trackTypeInfoUnchecked(callInfo);
1333     }
trackOptimizationAttempt(JS::TrackedStrategy strategy)1334     void trackOptimizationAttempt(JS::TrackedStrategy strategy) {
1335         if (MOZ_UNLIKELY(current->trackedSite()->hasOptimizations()))
1336             trackOptimizationAttemptUnchecked(strategy);
1337     }
amendOptimizationAttempt(uint32_t index)1338     void amendOptimizationAttempt(uint32_t index) {
1339         if (MOZ_UNLIKELY(current->trackedSite()->hasOptimizations()))
1340             amendOptimizationAttemptUnchecked(index);
1341     }
trackOptimizationOutcome(JS::TrackedOutcome outcome)1342     void trackOptimizationOutcome(JS::TrackedOutcome outcome) {
1343         if (MOZ_UNLIKELY(current->trackedSite()->hasOptimizations()))
1344             trackOptimizationOutcomeUnchecked(outcome);
1345     }
trackOptimizationSuccess()1346     void trackOptimizationSuccess() {
1347         if (MOZ_UNLIKELY(current->trackedSite()->hasOptimizations()))
1348             trackOptimizationSuccessUnchecked();
1349     }
1350     void trackInlineSuccess(InliningStatus status = InliningStatus_Inlined) {
1351         if (MOZ_UNLIKELY(current->trackedSite()->hasOptimizations()))
1352             trackInlineSuccessUnchecked(status);
1353     }
1354 
forceInlineCaches()1355     bool forceInlineCaches() {
1356         return MOZ_UNLIKELY(JitOptions.forceInlineCaches);
1357     }
1358 
1359     // Out-of-line variants that don't check if optimization tracking is
1360     // enabled.
1361     void trackTypeInfoUnchecked(JS::TrackedTypeSite site, MIRType mirType,
1362                                 TemporaryTypeSet* typeSet);
1363     void trackTypeInfoUnchecked(JS::TrackedTypeSite site, JSObject* obj);
1364     void trackTypeInfoUnchecked(CallInfo& callInfo);
1365     void trackOptimizationAttemptUnchecked(JS::TrackedStrategy strategy);
1366     void amendOptimizationAttemptUnchecked(uint32_t index);
1367     void trackOptimizationOutcomeUnchecked(JS::TrackedOutcome outcome);
1368     void trackOptimizationSuccessUnchecked();
1369     void trackInlineSuccessUnchecked(InliningStatus status);
1370 };
1371 
1372 class CallInfo
1373 {
1374     MDefinition* fun_;
1375     MDefinition* thisArg_;
1376     MDefinition* newTargetArg_;
1377     MDefinitionVector args_;
1378 
1379     bool constructing_;
1380     bool setter_;
1381 
1382   public:
CallInfo(TempAllocator & alloc,bool constructing)1383     CallInfo(TempAllocator& alloc, bool constructing)
1384       : fun_(nullptr),
1385         thisArg_(nullptr),
1386         newTargetArg_(nullptr),
1387         args_(alloc),
1388         constructing_(constructing),
1389         setter_(false)
1390     { }
1391 
init(CallInfo & callInfo)1392     MOZ_MUST_USE bool init(CallInfo& callInfo) {
1393         MOZ_ASSERT(constructing_ == callInfo.constructing());
1394 
1395         fun_ = callInfo.fun();
1396         thisArg_ = callInfo.thisArg();
1397 
1398         if (constructing())
1399             newTargetArg_ = callInfo.getNewTarget();
1400 
1401         if (!args_.appendAll(callInfo.argv()))
1402             return false;
1403 
1404         return true;
1405     }
1406 
init(MBasicBlock * current,uint32_t argc)1407     MOZ_MUST_USE bool init(MBasicBlock* current, uint32_t argc) {
1408         MOZ_ASSERT(args_.empty());
1409 
1410         // Get the arguments in the right order
1411         if (!args_.reserve(argc))
1412             return false;
1413 
1414         if (constructing())
1415             setNewTarget(current->pop());
1416 
1417         for (int32_t i = argc; i > 0; i--)
1418             args_.infallibleAppend(current->peek(-i));
1419         current->popn(argc);
1420 
1421         // Get |this| and |fun|
1422         setThis(current->pop());
1423         setFun(current->pop());
1424 
1425         return true;
1426     }
1427 
popFormals(MBasicBlock * current)1428     void popFormals(MBasicBlock* current) {
1429         current->popn(numFormals());
1430     }
1431 
pushFormals(MBasicBlock * current)1432     void pushFormals(MBasicBlock* current) {
1433         current->push(fun());
1434         current->push(thisArg());
1435 
1436         for (uint32_t i = 0; i < argc(); i++)
1437             current->push(getArg(i));
1438 
1439         if (constructing())
1440             current->push(getNewTarget());
1441     }
1442 
argc()1443     uint32_t argc() const {
1444         return args_.length();
1445     }
numFormals()1446     uint32_t numFormals() const {
1447         return argc() + 2 + constructing();
1448     }
1449 
setArgs(const MDefinitionVector & args)1450     MOZ_MUST_USE bool setArgs(const MDefinitionVector& args) {
1451         MOZ_ASSERT(args_.empty());
1452         return args_.appendAll(args);
1453     }
1454 
argv()1455     MDefinitionVector& argv() {
1456         return args_;
1457     }
1458 
argv()1459     const MDefinitionVector& argv() const {
1460         return args_;
1461     }
1462 
getArg(uint32_t i)1463     MDefinition* getArg(uint32_t i) const {
1464         MOZ_ASSERT(i < argc());
1465         return args_[i];
1466     }
1467 
getArgWithDefault(uint32_t i,MDefinition * defaultValue)1468     MDefinition* getArgWithDefault(uint32_t i, MDefinition* defaultValue) const {
1469         if (i < argc())
1470             return args_[i];
1471 
1472         return defaultValue;
1473     }
1474 
setArg(uint32_t i,MDefinition * def)1475     void setArg(uint32_t i, MDefinition* def) {
1476         MOZ_ASSERT(i < argc());
1477         args_[i] = def;
1478     }
1479 
thisArg()1480     MDefinition* thisArg() const {
1481         MOZ_ASSERT(thisArg_);
1482         return thisArg_;
1483     }
1484 
setThis(MDefinition * thisArg)1485     void setThis(MDefinition* thisArg) {
1486         thisArg_ = thisArg;
1487     }
1488 
constructing()1489     bool constructing() const {
1490         return constructing_;
1491     }
1492 
setNewTarget(MDefinition * newTarget)1493     void setNewTarget(MDefinition* newTarget) {
1494         MOZ_ASSERT(constructing());
1495         newTargetArg_ = newTarget;
1496     }
getNewTarget()1497     MDefinition* getNewTarget() const {
1498         MOZ_ASSERT(newTargetArg_);
1499         return newTargetArg_;
1500     }
1501 
isSetter()1502     bool isSetter() const {
1503         return setter_;
1504     }
markAsSetter()1505     void markAsSetter() {
1506         setter_ = true;
1507     }
1508 
fun()1509     MDefinition* fun() const {
1510         MOZ_ASSERT(fun_);
1511         return fun_;
1512     }
1513 
setFun(MDefinition * fun)1514     void setFun(MDefinition* fun) {
1515         fun_ = fun;
1516     }
1517 
setImplicitlyUsedUnchecked()1518     void setImplicitlyUsedUnchecked() {
1519         fun_->setImplicitlyUsedUnchecked();
1520         thisArg_->setImplicitlyUsedUnchecked();
1521         if (newTargetArg_)
1522             newTargetArg_->setImplicitlyUsedUnchecked();
1523         for (uint32_t i = 0; i < argc(); i++)
1524             getArg(i)->setImplicitlyUsedUnchecked();
1525     }
1526 };
1527 
1528 bool NeedsPostBarrier(MDefinition* value);
1529 
1530 } // namespace jit
1531 } // namespace js
1532 
1533 #endif /* jit_IonBuilder_h */
1534