Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/js/src/jit/IonBuilder.h
Line
Count
Source (jump to first uncovered line)
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
#include "mozilla/Maybe.h"
15
16
#include "jit/BaselineInspector.h"
17
#include "jit/BytecodeAnalysis.h"
18
#include "jit/IonAnalysis.h"
19
#include "jit/IonControlFlow.h"
20
#include "jit/IonOptimizationLevels.h"
21
#include "jit/MIR.h"
22
#include "jit/MIRGenerator.h"
23
#include "jit/MIRGraph.h"
24
#include "jit/OptimizationTracking.h"
25
26
namespace js {
27
namespace jit {
28
29
class CodeGenerator;
30
class CallInfo;
31
class BaselineFrameInspector;
32
33
enum class InlinableNative : uint16_t;
34
35
// Records information about a baseline frame for compilation that is stable
36
// when later used off thread.
37
BaselineFrameInspector*
38
NewBaselineFrameInspector(TempAllocator* temp, BaselineFrame* frame);
39
40
using CallTargets = Vector<JSFunction*, 6, JitAllocPolicy>;
41
42
class IonBuilder
43
  : public MIRGenerator,
44
    public mozilla::LinkedListElement<IonBuilder>
45
{
46
47
  public:
48
    IonBuilder(JSContext* analysisContext, CompileRealm* realm,
49
               const JitCompileOptions& options, TempAllocator* temp,
50
               MIRGraph* graph, CompilerConstraintList* constraints,
51
               BaselineInspector* inspector, CompileInfo* info,
52
               const OptimizationInfo* optimizationInfo, BaselineFrameInspector* baselineFrame,
53
               size_t inliningDepth = 0, uint32_t loopDepth = 0);
54
55
    // Callers of build() and buildInline() should always check whether the
56
    // call overrecursed, if false is returned.  Overrecursion is not
57
    // signaled as OOM and will not in general be caught by OOM paths.
58
    AbortReasonOr<Ok> build();
59
    AbortReasonOr<Ok> buildInline(IonBuilder* callerBuilder, MResumePoint* callerResumePoint,
60
                                  CallInfo& callInfo);
61
62
    mozilla::GenericErrorResult<AbortReason> abort(AbortReason r);
63
    mozilla::GenericErrorResult<AbortReason>
64
    abort(AbortReason r, const char* message, ...) MOZ_FORMAT_PRINTF(3, 4);
65
66
  private:
67
    AbortReasonOr<Ok> traverseBytecode();
68
    AbortReasonOr<Ok> processIterators();
69
    AbortReasonOr<Ok> inspectOpcode(JSOp op);
70
    uint32_t readIndex(jsbytecode* pc);
71
    JSAtom* readAtom(jsbytecode* pc);
72
73
    void trackActionableAbort(const char* message);
74
    void spew(const char* message);
75
76
    JSFunction* getSingleCallTarget(TemporaryTypeSet* calleeTypes);
77
    AbortReasonOr<Ok> getPolyCallTargets(TemporaryTypeSet* calleeTypes, bool constructing,
78
                                         InliningTargets& targets, uint32_t maxTargets);
79
80
    AbortReasonOr<Ok> analyzeNewLoopTypes(const CFGBlock* loopEntryBlock);
81
82
    AbortReasonOr<MBasicBlock*> newBlock(size_t stackDepth, jsbytecode* pc,
83
                                         MBasicBlock* maybePredecessor = nullptr);
84
    AbortReasonOr<MBasicBlock*> newBlock(MBasicBlock* predecessor, jsbytecode* pc,
85
                                         MResumePoint* priorResumePoint);
86
    AbortReasonOr<MBasicBlock*> newBlockPopN(MBasicBlock* predecessor, jsbytecode* pc,
87
                                             uint32_t popped);
88
    AbortReasonOr<MBasicBlock*> newBlockAfter(MBasicBlock* at, size_t stackDepth,
89
                                              jsbytecode* pc, MBasicBlock* maybePredecessor = nullptr);
90
    AbortReasonOr<MBasicBlock*> newOsrPreheader(MBasicBlock* header, jsbytecode* loopEntry,
91
                                                jsbytecode* beforeLoopEntry);
92
    AbortReasonOr<MBasicBlock*> newPendingLoopHeader(MBasicBlock* predecessor, jsbytecode* pc,
93
                                                     bool osr, bool canOsr, unsigned stackPhiCount);
94
95
56
    AbortReasonOr<MBasicBlock*> newBlock(MBasicBlock* predecessor, jsbytecode* pc) {
96
56
        return newBlock(predecessor->stackDepth(), pc, predecessor);
97
56
    }
98
99
    AbortReasonOr<Ok> visitBlock(const CFGBlock* hblock, MBasicBlock* mblock);
100
    AbortReasonOr<Ok> visitControlInstruction(CFGControlInstruction* ins, bool* restarted);
101
    AbortReasonOr<Ok> visitTest(CFGTest* test);
102
    AbortReasonOr<Ok> visitCompare(CFGCompare* compare);
103
    AbortReasonOr<Ok> visitLoopEntry(CFGLoopEntry* loopEntry);
104
    AbortReasonOr<Ok> visitReturn(CFGControlInstruction* ins);
105
    AbortReasonOr<Ok> visitGoto(CFGGoto* ins);
106
    AbortReasonOr<Ok> visitBackEdge(CFGBackEdge* ins, bool* restarted);
107
    AbortReasonOr<Ok> visitTry(CFGTry* test);
108
    AbortReasonOr<Ok> visitThrow(CFGThrow* ins);
109
    AbortReasonOr<Ok> visitTableSwitch(CFGTableSwitch* ins);
110
111
    // We want to make sure that our MTest instructions all check whether the
112
    // thing being tested might emulate undefined.  So we funnel their creation
113
    // through this method, to make sure that happens.  We don't want to just do
114
    // the check in MTest::New, because that can run on background compilation
115
    // threads, and we're not sure it's safe to touch that part of the typeset
116
    // from a background thread.
117
    MTest* newTest(MDefinition* ins, MBasicBlock* ifTrue, MBasicBlock* ifFalse);
118
119
    // Incorporates a type/typeSet into an OSR value for a loop, after the loop
120
    // body has been processed.
121
    AbortReasonOr<Ok> addOsrValueTypeBarrier(uint32_t slot, MInstruction** def,
122
                                             MIRType type, TemporaryTypeSet* typeSet);
123
    AbortReasonOr<Ok> maybeAddOsrTypeBarriers();
124
125
    // Restarts processing of a loop if the type information at its header was
126
    // incomplete.
127
    AbortReasonOr<Ok> restartLoop(const CFGBlock* header);
128
129
    // Please see the Big Honkin' Comment about how resume points work in
130
    // IonBuilder.cpp, near the definition for this function.
131
    AbortReasonOr<Ok> resume(MInstruction* ins, jsbytecode* pc, MResumePoint::Mode mode);
132
    AbortReasonOr<Ok> resumeAt(MInstruction* ins, jsbytecode* pc);
133
    AbortReasonOr<Ok> resumeAfter(MInstruction* ins);
134
    AbortReasonOr<Ok> maybeInsertResume();
135
136
    bool blockIsOSREntry(const CFGBlock* block, const CFGBlock* predecessor);
137
138
    void insertRecompileCheck();
139
140
    bool usesEnvironmentChain();
141
142
    AbortReasonOr<Ok> initParameters();
143
    void initLocals();
144
    void rewriteParameter(uint32_t slotIdx, MDefinition* param);
145
    AbortReasonOr<Ok> rewriteParameters();
146
    AbortReasonOr<Ok> initEnvironmentChain(MDefinition* callee = nullptr);
147
    void initArgumentsObject();
148
    void pushConstant(const Value& v);
149
150
    MConstant* constant(const Value& v);
151
    MConstant* constantInt(int32_t i);
152
    MInstruction* initializedLength(MDefinition* elements);
153
    MInstruction* setInitializedLength(MDefinition* obj, size_t count);
154
155
    // Improve the type information at tests
156
    AbortReasonOr<Ok> improveTypesAtTest(MDefinition* ins, bool trueBranch, MTest* test);
157
    AbortReasonOr<Ok> improveTypesAtCompare(MCompare* ins, bool trueBranch, MTest* test);
158
    AbortReasonOr<Ok> improveTypesAtNullOrUndefinedCompare(MCompare* ins, bool trueBranch,
159
                                                           MTest* test);
160
    AbortReasonOr<Ok> improveTypesAtTypeOfCompare(MCompare* ins, bool trueBranch, MTest* test);
161
162
    // Used to detect triangular structure at test.
163
    bool detectAndOrStructure(MPhi* ins, bool* branchIsTrue);
164
    AbortReasonOr<Ok> replaceTypeSet(MDefinition* subject, TemporaryTypeSet* type, MTest* test);
165
166
    // Add a guard which ensure that the set of type which goes through this
167
    // generated code correspond to the observed types for the bytecode.
168
    MDefinition* addTypeBarrier(MDefinition* def, TemporaryTypeSet* observed,
169
                                BarrierKind kind, MTypeBarrier** pbarrier = nullptr);
170
    AbortReasonOr<Ok> pushTypeBarrier(MDefinition* def, TemporaryTypeSet* observed,
171
                                      BarrierKind kind);
172
173
    // As pushTypeBarrier, but will compute the needBarrier boolean itself based
174
    // on observed and the JSFunction that we're planning to call. The
175
    // JSFunction must be a DOM method or getter.
176
    AbortReasonOr<Ok> pushDOMTypeBarrier(MInstruction* ins, TemporaryTypeSet* observed,
177
                                         JSFunction* func);
178
179
    // If definiteType is not known or def already has the right type, just
180
    // returns def.  Otherwise, returns an MInstruction that has that definite
181
    // type, infallibly unboxing ins as needed.  The new instruction will be
182
    // added to |current| in this case.
183
    MDefinition* ensureDefiniteType(MDefinition* def, MIRType definiteType);
184
185
    void maybeMarkEmpty(MDefinition* ins);
186
187
    JSObject* getSingletonPrototype(JSFunction* target);
188
189
    MDefinition* createThisScripted(MDefinition* callee, MDefinition* newTarget);
190
    MDefinition* createThisScriptedSingleton(JSFunction* target);
191
    MDefinition* createThisScriptedBaseline(MDefinition* callee);
192
    MDefinition* createThis(JSFunction* target, MDefinition* callee, MDefinition* newTarget);
193
    MInstruction* createNamedLambdaObject(MDefinition* callee, MDefinition* envObj);
194
    AbortReasonOr<MInstruction*> createCallObject(MDefinition* callee, MDefinition* envObj);
195
196
    MDefinition* walkEnvironmentChain(unsigned hops);
197
198
    MInstruction* addConvertElementsToDoubles(MDefinition* elements);
199
    MDefinition* addMaybeCopyElementsForWrite(MDefinition* object, bool checkNative);
200
201
    MInstruction* addBoundsCheck(MDefinition* index, MDefinition* length);
202
203
    MInstruction* addShapeGuard(MDefinition* obj, Shape* const shape, BailoutKind bailoutKind);
204
    MInstruction* addGroupGuard(MDefinition* obj, ObjectGroup* group, BailoutKind bailoutKind);
205
    MInstruction* addUnboxedExpandoGuard(MDefinition* obj, bool hasExpando, BailoutKind bailoutKind);
206
    MInstruction* addSharedTypedArrayGuard(MDefinition* obj);
207
208
    MInstruction*
209
    addGuardReceiverPolymorphic(MDefinition* obj, const BaselineInspector::ReceiverVector& receivers);
210
211
    bool invalidatedIdempotentCache();
212
213
    bool hasStaticEnvironmentObject(JSObject** pcall);
214
    AbortReasonOr<Ok> loadSlot(MDefinition* obj, size_t slot, size_t nfixed, MIRType rvalType,
215
                               BarrierKind barrier, TemporaryTypeSet* types);
216
    AbortReasonOr<Ok> loadSlot(MDefinition* obj, Shape* shape, MIRType rvalType,
217
                               BarrierKind barrier, TemporaryTypeSet* types);
218
    AbortReasonOr<Ok> storeSlot(MDefinition* obj, size_t slot, size_t nfixed, MDefinition* value,
219
                                bool needsBarrier, MIRType slotType = MIRType::None);
220
    AbortReasonOr<Ok> storeSlot(MDefinition* obj, Shape* shape, MDefinition* value,
221
                                bool needsBarrier, MIRType slotType = MIRType::None);
222
    bool shouldAbortOnPreliminaryGroups(MDefinition *obj);
223
224
    MDefinition* tryInnerizeWindow(MDefinition* obj);
225
    MDefinition* maybeUnboxForPropertyAccess(MDefinition* def);
226
227
    // jsop_getprop() helpers.
228
    AbortReasonOr<Ok> checkIsDefinitelyOptimizedArguments(MDefinition* obj, bool* isOptimizedArgs);
229
    AbortReasonOr<Ok> getPropTryInferredConstant(bool* emitted, MDefinition* obj,
230
                                                 PropertyName* name, TemporaryTypeSet* types);
231
    AbortReasonOr<Ok> getPropTryArgumentsLength(bool* emitted, MDefinition* obj);
232
    AbortReasonOr<Ok> getPropTryArgumentsCallee(bool* emitted, MDefinition* obj,
233
                                                PropertyName* name);
234
    AbortReasonOr<Ok> getPropTryConstant(bool* emitted, MDefinition* obj, jsid id,
235
                                         TemporaryTypeSet* types);
236
    AbortReasonOr<Ok> getPropTryNotDefined(bool* emitted, MDefinition* obj, jsid id,
237
                                           TemporaryTypeSet* types);
238
    AbortReasonOr<Ok> getPropTryDefiniteSlot(bool* emitted, MDefinition* obj, PropertyName* name,
239
                                             BarrierKind barrier, TemporaryTypeSet* types);
240
    AbortReasonOr<Ok> getPropTryModuleNamespace(bool* emitted, MDefinition* obj, PropertyName* name,
241
                                                BarrierKind barrier, TemporaryTypeSet* types);
242
    AbortReasonOr<Ok> getPropTryUnboxed(bool* emitted, MDefinition* obj, PropertyName* name,
243
                                        BarrierKind barrier, TemporaryTypeSet* types);
244
    AbortReasonOr<Ok> getPropTryCommonGetter(bool* emitted, MDefinition* obj, PropertyName* name,
245
                                             TemporaryTypeSet* types, bool innerized = false);
246
    AbortReasonOr<Ok> getPropTryInlineAccess(bool* emitted, MDefinition* obj, PropertyName* name,
247
                                             BarrierKind barrier, TemporaryTypeSet* types);
248
    AbortReasonOr<Ok> getPropTryInlineProtoAccess(bool* emitted, MDefinition* obj, PropertyName* name,
249
                                                  TemporaryTypeSet* types);
250
    AbortReasonOr<Ok> getPropTryTypedObject(bool* emitted, MDefinition* obj, PropertyName* name);
251
    AbortReasonOr<Ok> getPropTryScalarPropOfTypedObject(bool* emitted, MDefinition* typedObj,
252
                                                        int32_t fieldOffset,
253
                                                        TypedObjectPrediction fieldTypeReprs);
254
    AbortReasonOr<Ok> getPropTryReferencePropOfTypedObject(bool* emitted, MDefinition* typedObj,
255
                                                           int32_t fieldOffset,
256
                                                           TypedObjectPrediction fieldPrediction,
257
                                                           PropertyName* name);
258
    AbortReasonOr<Ok> getPropTryComplexPropOfTypedObject(bool* emitted, MDefinition* typedObj,
259
                                                         int32_t fieldOffset,
260
                                                         TypedObjectPrediction fieldTypeReprs,
261
                                                         size_t fieldIndex);
262
    AbortReasonOr<Ok> getPropTryInnerize(bool* emitted, MDefinition* obj, PropertyName* name,
263
                                         TemporaryTypeSet* types);
264
    AbortReasonOr<Ok> getPropAddCache(MDefinition* obj, PropertyName* name,
265
                                      BarrierKind barrier, TemporaryTypeSet* types);
266
267
    // jsop_setprop() helpers.
268
    AbortReasonOr<Ok> setPropTryCommonSetter(bool* emitted, MDefinition* obj,
269
                                             PropertyName* name, MDefinition* value);
270
    AbortReasonOr<Ok> setPropTryCommonDOMSetter(bool* emitted, MDefinition* obj,
271
                                                MDefinition* value, JSFunction* setter,
272
                                                TemporaryTypeSet* objTypes);
273
    AbortReasonOr<Ok> setPropTryDefiniteSlot(bool* emitted, MDefinition* obj,
274
                                             PropertyName* name, MDefinition* value,
275
                                             bool barrier);
276
    AbortReasonOr<Ok> setPropTryUnboxed(bool* emitted, MDefinition* obj,
277
                                        PropertyName* name, MDefinition* value,
278
                                        bool barrier);
279
    AbortReasonOr<Ok> setPropTryInlineAccess(bool* emitted, MDefinition* obj,
280
                                             PropertyName* name, MDefinition* value,
281
                                             bool barrier, TemporaryTypeSet* objTypes);
282
    AbortReasonOr<Ok> setPropTryTypedObject(bool* emitted, MDefinition* obj,
283
                                            PropertyName* name, MDefinition* value);
284
    AbortReasonOr<Ok> setPropTryReferencePropOfTypedObject(bool* emitted, MDefinition* obj,
285
                                                           int32_t fieldOffset, MDefinition* value,
286
                                                           TypedObjectPrediction fieldPrediction,
287
                                                           PropertyName* name);
288
    AbortReasonOr<Ok> setPropTryReferenceTypedObjectValue(bool* emitted,
289
                                                          MDefinition* typedObj,
290
                                                          const LinearSum& byteOffset,
291
                                                          ReferenceType type,
292
                                                          MDefinition* value,
293
                                                          PropertyName* name);
294
    AbortReasonOr<Ok> setPropTryScalarPropOfTypedObject(bool* emitted,
295
                                                        MDefinition* obj,
296
                                                        int32_t fieldOffset,
297
                                                        MDefinition* value,
298
                                                        TypedObjectPrediction fieldTypeReprs);
299
    AbortReasonOr<Ok> setPropTryScalarTypedObjectValue(bool* emitted,
300
                                                       MDefinition* typedObj,
301
                                                       const LinearSum& byteOffset,
302
                                                       ScalarTypeDescr::Type type,
303
                                                       MDefinition* value);
304
    AbortReasonOr<Ok> setPropTryCache(bool* emitted, MDefinition* obj,
305
                                      PropertyName* name, MDefinition* value,
306
                                      bool barrier);
307
308
    // jsop_binary_arith helpers.
309
    MBinaryArithInstruction* binaryArithInstruction(JSOp op, MDefinition* left, MDefinition* right);
310
    AbortReasonOr<Ok> binaryArithTryConcat(bool* emitted, JSOp op, MDefinition* left,
311
                                           MDefinition* right);
312
    AbortReasonOr<Ok> binaryArithTrySpecialized(bool* emitted, JSOp op, MDefinition* left,
313
                                                MDefinition* right);
314
    AbortReasonOr<Ok> binaryArithTrySpecializedOnBaselineInspector(bool* emitted, JSOp op,
315
                                                                   MDefinition* left,
316
                                                                   MDefinition* right);
317
    AbortReasonOr<Ok> arithTryBinaryStub(bool* emitted, JSOp op, MDefinition* left,
318
                                         MDefinition* right);
319
320
    // jsop_bitnot helpers.
321
    AbortReasonOr<Ok> bitnotTrySpecialized(bool* emitted, MDefinition* input);
322
323
    // jsop_pow helpers.
324
    AbortReasonOr<Ok> powTrySpecialized(bool* emitted, MDefinition* base, MDefinition* power,
325
                                        MIRType outputType);
326
327
    // jsop_compare helpers.
328
    AbortReasonOr<Ok> compareTrySpecialized(bool* emitted, JSOp op, MDefinition* left,
329
                                            MDefinition* right);
330
    AbortReasonOr<Ok> compareTryBitwise(bool* emitted, JSOp op, MDefinition* left,
331
                                        MDefinition* right);
332
    AbortReasonOr<Ok> compareTrySpecializedOnBaselineInspector(bool* emitted, JSOp op,
333
                                                               MDefinition* left,
334
                                                               MDefinition* right);
335
    AbortReasonOr<Ok> compareTryBinaryStub(bool* emitted, MDefinition* left, MDefinition* right);
336
    AbortReasonOr<Ok> compareTryCharacter(bool* emitted, JSOp op, MDefinition* left,
337
                                          MDefinition* right);
338
339
    // jsop_newarray helpers.
340
    AbortReasonOr<Ok> newArrayTryTemplateObject(bool* emitted, JSObject* templateObject,
341
                                                uint32_t length);
342
    AbortReasonOr<Ok> newArrayTryVM(bool* emitted, JSObject* templateObject, uint32_t length);
343
344
    // jsop_newobject helpers.
345
    AbortReasonOr<Ok> newObjectTryTemplateObject(bool* emitted, JSObject* templateObject);
346
    AbortReasonOr<Ok> newObjectTryVM(bool* emitted, JSObject* templateObject);
347
348
    // jsop_in/jsop_hasown helpers.
349
    AbortReasonOr<Ok> inTryDense(bool* emitted, MDefinition* obj, MDefinition* id);
350
    AbortReasonOr<Ok> hasTryNotDefined(bool* emitted, MDefinition* obj, MDefinition* id, bool ownProperty);
351
    AbortReasonOr<Ok> hasTryDefiniteSlotOrUnboxed(bool* emitted, MDefinition* obj, MDefinition* id);
352
353
    // binary data lookup helpers.
354
    TypedObjectPrediction typedObjectPrediction(MDefinition* typedObj);
355
    TypedObjectPrediction typedObjectPrediction(TemporaryTypeSet* types);
356
    bool typedObjectHasField(MDefinition* typedObj,
357
                             PropertyName* name,
358
                             size_t* fieldOffset,
359
                             TypedObjectPrediction* fieldTypeReprs,
360
                             size_t* fieldIndex,
361
                             bool* fieldMutable);
362
    MDefinition* loadTypedObjectType(MDefinition* value);
363
    AbortReasonOr<Ok> loadTypedObjectData(MDefinition* typedObj,
364
                                          MDefinition** owner,
365
                                          LinearSum* ownerOffset);
366
    AbortReasonOr<Ok> loadTypedObjectElements(MDefinition* typedObj,
367
                                              const LinearSum& byteOffset,
368
                                              uint32_t scale,
369
                                              MDefinition** ownerElements,
370
                                              MDefinition** ownerScaledOffset,
371
                                              int32_t* ownerByteAdjustment);
372
    MDefinition* typeObjectForElementFromArrayStructType(MDefinition* typedObj);
373
    MDefinition* typeObjectForFieldFromStructType(MDefinition* type,
374
                                                  size_t fieldIndex);
375
    bool checkTypedObjectIndexInBounds(uint32_t elemSize,
376
                                       MDefinition* index,
377
                                       TypedObjectPrediction objTypeDescrs,
378
                                       LinearSum* indexAsByteOffset);
379
    AbortReasonOr<Ok> pushDerivedTypedObject(bool* emitted,
380
                                             MDefinition* obj,
381
                                             const LinearSum& byteOffset,
382
                                             TypedObjectPrediction derivedTypeDescrs,
383
                                             MDefinition* derivedTypeObj);
384
    AbortReasonOr<Ok> pushScalarLoadFromTypedObject(MDefinition* obj,
385
                                                    const LinearSum& byteoffset,
386
                                                    ScalarTypeDescr::Type type);
387
    AbortReasonOr<Ok> pushReferenceLoadFromTypedObject(MDefinition* typedObj,
388
                                                       const LinearSum& byteOffset,
389
                                                       ReferenceType type,
390
                                                       PropertyName* name);
391
392
    // jsop_setelem() helpers.
393
    AbortReasonOr<Ok> setElemTryTypedArray(bool* emitted, MDefinition* object,
394
                                           MDefinition* index, MDefinition* value);
395
    AbortReasonOr<Ok> setElemTryTypedObject(bool* emitted, MDefinition* obj,
396
                                            MDefinition* index, MDefinition* value);
397
    AbortReasonOr<Ok> initOrSetElemTryDense(bool* emitted, MDefinition* object,
398
                                            MDefinition* index, MDefinition* value,
399
                                            bool writeHole);
400
    AbortReasonOr<Ok> setElemTryArguments(bool* emitted, MDefinition* object);
401
    AbortReasonOr<Ok> initOrSetElemTryCache(bool* emitted, MDefinition* object,
402
                                            MDefinition* index, MDefinition* value);
403
    AbortReasonOr<Ok> setElemTryReferenceElemOfTypedObject(bool* emitted,
404
                                                           MDefinition* obj,
405
                                                           MDefinition* index,
406
                                                           TypedObjectPrediction objPrediction,
407
                                                           MDefinition* value,
408
                                                           TypedObjectPrediction elemPrediction);
409
    AbortReasonOr<Ok> setElemTryScalarElemOfTypedObject(bool* emitted,
410
                                                        MDefinition* obj,
411
                                                        MDefinition* index,
412
                                                        TypedObjectPrediction objTypeReprs,
413
                                                        MDefinition* value,
414
                                                        TypedObjectPrediction elemTypeReprs,
415
                                                        uint32_t elemSize);
416
    AbortReasonOr<Ok> initializeArrayElement(MDefinition* obj, size_t index, MDefinition* value,
417
                                             bool addResumePointAndIncrementInitializedLength);
418
419
    // jsop_getelem() helpers.
420
    AbortReasonOr<Ok> getElemTryDense(bool* emitted, MDefinition* obj, MDefinition* index);
421
    AbortReasonOr<Ok> getElemTryGetProp(bool* emitted, MDefinition* obj, MDefinition* index);
422
    AbortReasonOr<Ok> getElemTryTypedArray(bool* emitted, MDefinition* obj, MDefinition* index);
423
    AbortReasonOr<Ok> getElemTryCallSiteObject(bool* emitted, MDefinition* obj, MDefinition* index);
424
    AbortReasonOr<Ok> getElemTryTypedObject(bool* emitted, MDefinition* obj, MDefinition* index);
425
    AbortReasonOr<Ok> getElemTryString(bool* emitted, MDefinition* obj, MDefinition* index);
426
    AbortReasonOr<Ok> getElemTryArguments(bool* emitted, MDefinition* obj, MDefinition* index);
427
    AbortReasonOr<Ok> getElemTryArgumentsInlinedConstant(bool* emitted, MDefinition* obj,
428
                                                         MDefinition* index);
429
    AbortReasonOr<Ok> getElemTryArgumentsInlinedIndex(bool* emitted, MDefinition* obj,
430
                                                      MDefinition* index);
431
    AbortReasonOr<Ok> getElemAddCache(MDefinition* obj, MDefinition* index);
432
    AbortReasonOr<Ok> getElemTryScalarElemOfTypedObject(bool* emitted,
433
                                                        MDefinition* obj,
434
                                                        MDefinition* index,
435
                                                        TypedObjectPrediction objTypeReprs,
436
                                                        TypedObjectPrediction elemTypeReprs,
437
                                                        uint32_t elemSize);
438
    AbortReasonOr<Ok> getElemTryReferenceElemOfTypedObject(bool* emitted,
439
                                                           MDefinition* obj,
440
                                                           MDefinition* index,
441
                                                           TypedObjectPrediction objPrediction,
442
                                                           TypedObjectPrediction elemPrediction);
443
    AbortReasonOr<Ok> getElemTryComplexElemOfTypedObject(bool* emitted,
444
                                                         MDefinition* obj,
445
                                                         MDefinition* index,
446
                                                         TypedObjectPrediction objTypeReprs,
447
                                                         TypedObjectPrediction elemTypeReprs,
448
                                                         uint32_t elemSize);
449
    TemporaryTypeSet* computeHeapType(const TemporaryTypeSet* objTypes, const jsid id);
450
451
    enum BoundsChecking { DoBoundsCheck, SkipBoundsCheck };
452
453
    MInstruction* addArrayBufferByteLength(MDefinition* obj);
454
455
    // Add instructions to compute a typed array's length and data.  Also
456
    // optionally convert |*index| into a bounds-checked definition, if
457
    // requested.
458
    //
459
    // If you only need the array's length, use addTypedArrayLength below.
460
    void addTypedArrayLengthAndData(MDefinition* obj,
461
                                    BoundsChecking checking,
462
                                    MDefinition** index,
463
                                    MInstruction** length, MInstruction** elements);
464
465
    // Add an instruction to compute a typed array's length to the current
466
    // block.  If you also need the typed array's data, use the above method
467
    // instead.
468
0
    MInstruction* addTypedArrayLength(MDefinition* obj) {
469
0
        MInstruction* length;
470
0
        addTypedArrayLengthAndData(obj, SkipBoundsCheck, nullptr, &length, nullptr);
471
0
        return length;
472
0
    }
473
474
    AbortReasonOr<Ok> improveThisTypesForCall();
475
476
    MDefinition* getCallee();
477
    MDefinition* getAliasedVar(EnvironmentCoordinate ec);
478
    AbortReasonOr<MDefinition*> addLexicalCheck(MDefinition* input);
479
480
    MDefinition* convertToBoolean(MDefinition* input);
481
482
    AbortReasonOr<Ok> tryFoldInstanceOf(bool* emitted, MDefinition* lhs, JSObject* protoObject);
483
    AbortReasonOr<bool> hasOnProtoChain(TypeSet::ObjectKey* key, JSObject* protoObject, bool* onProto);
484
485
    AbortReasonOr<Ok> jsop_add(MDefinition* left, MDefinition* right);
486
    AbortReasonOr<Ok> jsop_bitnot();
487
    AbortReasonOr<Ok> jsop_bitop(JSOp op);
488
    AbortReasonOr<Ok> jsop_binary_arith(JSOp op);
489
    AbortReasonOr<Ok> jsop_binary_arith(JSOp op, MDefinition* left, MDefinition* right);
490
    AbortReasonOr<Ok> jsop_pow();
491
    AbortReasonOr<Ok> jsop_pos();
492
    AbortReasonOr<Ok> jsop_neg();
493
    AbortReasonOr<Ok> jsop_tostring();
494
    AbortReasonOr<Ok> jsop_setarg(uint32_t arg);
495
    AbortReasonOr<Ok> jsop_defvar(uint32_t index);
496
    AbortReasonOr<Ok> jsop_deflexical(uint32_t index);
497
    AbortReasonOr<Ok> jsop_deffun();
498
    AbortReasonOr<Ok> jsop_notearg();
499
    AbortReasonOr<Ok> jsop_throwsetconst();
500
    AbortReasonOr<Ok> jsop_checklexical();
501
    AbortReasonOr<Ok> jsop_checkaliasedlexical(EnvironmentCoordinate ec);
502
    AbortReasonOr<Ok> jsop_funcall(uint32_t argc);
503
    AbortReasonOr<Ok> jsop_funapply(uint32_t argc);
504
    AbortReasonOr<Ok> jsop_funapplyarguments(uint32_t argc);
505
    AbortReasonOr<Ok> jsop_funapplyarray(uint32_t argc);
506
    AbortReasonOr<Ok> jsop_spreadcall();
507
    AbortReasonOr<Ok> jsop_call(uint32_t argc, bool constructing, bool ignoresReturnValue);
508
    AbortReasonOr<Ok> jsop_eval(uint32_t argc);
509
    AbortReasonOr<Ok> jsop_label();
510
    AbortReasonOr<Ok> jsop_andor(JSOp op);
511
    AbortReasonOr<Ok> jsop_dup2();
512
    AbortReasonOr<Ok> jsop_loopentry();
513
    AbortReasonOr<Ok> jsop_loophead(jsbytecode* pc);
514
    AbortReasonOr<Ok> jsop_compare(JSOp op);
515
    AbortReasonOr<Ok> jsop_compare(JSOp op, MDefinition* left, MDefinition* right);
516
    AbortReasonOr<Ok> getStaticName(bool* emitted, JSObject* staticObject, PropertyName* name,
517
                                    MDefinition* lexicalCheck = nullptr);
518
    AbortReasonOr<Ok> loadStaticSlot(JSObject* staticObject, BarrierKind barrier,
519
                                     TemporaryTypeSet* types, uint32_t slot);
520
    AbortReasonOr<Ok> setStaticName(JSObject* staticObject, PropertyName* name);
521
    AbortReasonOr<Ok> jsop_getgname(PropertyName* name);
522
    AbortReasonOr<Ok> jsop_getname(PropertyName* name);
523
    AbortReasonOr<Ok> jsop_intrinsic(PropertyName* name);
524
    AbortReasonOr<Ok> jsop_getimport(PropertyName* name);
525
    AbortReasonOr<Ok> jsop_bindname(PropertyName* name);
526
    AbortReasonOr<Ok> jsop_bindvar();
527
    AbortReasonOr<Ok> jsop_getelem();
528
    AbortReasonOr<Ok> jsop_getelem_dense(MDefinition* obj, MDefinition* index);
529
    AbortReasonOr<Ok> jsop_getelem_typed(MDefinition* obj, MDefinition* index,
530
                                         ScalarTypeDescr::Type arrayType);
531
    AbortReasonOr<Ok> jsop_setelem();
532
    AbortReasonOr<Ok> initOrSetElemDense(TemporaryTypeSet::DoubleConversion conversion,
533
                                         MDefinition* object, MDefinition* index,
534
                                         MDefinition* value, bool writeHole, bool* emitted);
535
    AbortReasonOr<Ok> jsop_setelem_typed(ScalarTypeDescr::Type arrayType,
536
                                         MDefinition* object, MDefinition* index,
537
                                         MDefinition* value);
538
    AbortReasonOr<Ok> jsop_length();
539
    bool jsop_length_fastPath();
540
    AbortReasonOr<Ok> jsop_arguments();
541
    AbortReasonOr<Ok> jsop_arguments_getelem();
542
    AbortReasonOr<Ok> jsop_runonce();
543
    AbortReasonOr<Ok> jsop_rest();
544
    AbortReasonOr<Ok> jsop_not();
545
    AbortReasonOr<Ok> jsop_superbase();
546
    AbortReasonOr<Ok> jsop_getprop_super(PropertyName* name);
547
    AbortReasonOr<Ok> jsop_getelem_super();
548
    AbortReasonOr<Ok> jsop_getprop(PropertyName* name);
549
    AbortReasonOr<Ok> jsop_setprop(PropertyName* name);
550
    AbortReasonOr<Ok> jsop_delprop(PropertyName* name);
551
    AbortReasonOr<Ok> jsop_delelem();
552
    AbortReasonOr<Ok> jsop_newarray(uint32_t length);
553
    AbortReasonOr<Ok> jsop_newarray(JSObject* templateObject, uint32_t length);
554
    AbortReasonOr<Ok> jsop_newarray_copyonwrite();
555
    AbortReasonOr<Ok> jsop_newobject();
556
    AbortReasonOr<Ok> jsop_initelem();
557
    AbortReasonOr<Ok> jsop_initelem_inc();
558
    AbortReasonOr<Ok> jsop_initelem_array();
559
    AbortReasonOr<Ok> jsop_initelem_getter_setter();
560
    AbortReasonOr<Ok> jsop_mutateproto();
561
    AbortReasonOr<Ok> jsop_initprop(PropertyName* name);
562
    AbortReasonOr<Ok> jsop_initprop_getter_setter(PropertyName* name);
563
    AbortReasonOr<Ok> jsop_regexp(RegExpObject* reobj);
564
    AbortReasonOr<Ok> jsop_object(JSObject* obj);
565
    AbortReasonOr<Ok> jsop_classconstructor();
566
    AbortReasonOr<Ok> jsop_lambda(JSFunction* fun);
567
    AbortReasonOr<Ok> jsop_lambda_arrow(JSFunction* fun);
568
    AbortReasonOr<Ok> jsop_setfunname(uint8_t prefixKind);
569
    AbortReasonOr<Ok> jsop_pushlexicalenv(uint32_t index);
570
    AbortReasonOr<Ok> jsop_copylexicalenv(bool copySlots);
571
    AbortReasonOr<Ok> jsop_functionthis();
572
    AbortReasonOr<Ok> jsop_globalthis();
573
    AbortReasonOr<Ok> jsop_typeof();
574
    AbortReasonOr<Ok> jsop_toasync();
575
    AbortReasonOr<Ok> jsop_toasyncgen();
576
    AbortReasonOr<Ok> jsop_toasynciter();
577
    AbortReasonOr<Ok> jsop_toid();
578
    AbortReasonOr<Ok> jsop_iter();
579
    AbortReasonOr<Ok> jsop_itermore();
580
    AbortReasonOr<Ok> jsop_isnoiter();
581
    AbortReasonOr<Ok> jsop_iterend();
582
    AbortReasonOr<Ok> jsop_iternext();
583
    AbortReasonOr<Ok> jsop_in();
584
    AbortReasonOr<Ok> jsop_hasown();
585
    AbortReasonOr<Ok> jsop_instanceof();
586
    AbortReasonOr<Ok> jsop_getaliasedvar(EnvironmentCoordinate ec);
587
    AbortReasonOr<Ok> jsop_setaliasedvar(EnvironmentCoordinate ec);
588
    AbortReasonOr<Ok> jsop_debugger();
589
    AbortReasonOr<Ok> jsop_newtarget();
590
    AbortReasonOr<Ok> jsop_checkisobj(uint8_t kind);
591
    AbortReasonOr<Ok> jsop_checkiscallable(uint8_t kind);
592
    AbortReasonOr<Ok> jsop_checkobjcoercible();
593
    AbortReasonOr<Ok> jsop_pushcallobj();
594
    AbortReasonOr<Ok> jsop_implicitthis(PropertyName* name);
595
    AbortReasonOr<Ok> jsop_importmeta();
596
597
    /* Inlining. */
598
599
    enum InliningStatus
600
    {
601
        InliningStatus_NotInlined,
602
        InliningStatus_WarmUpCountTooLow,
603
        InliningStatus_Inlined
604
    };
605
    using InliningResult = AbortReasonOr<InliningStatus>;
606
607
    enum InliningDecision
608
    {
609
        InliningDecision_Error,
610
        InliningDecision_Inline,
611
        InliningDecision_DontInline,
612
        InliningDecision_WarmUpCountTooLow
613
    };
614
615
    static InliningDecision DontInline(JSScript* targetScript, const char* reason);
616
617
    // Helper function for canInlineTarget
618
    bool hasCommonInliningPath(const JSScript* scriptToInline);
619
620
    // Oracles.
621
    InliningDecision canInlineTarget(JSFunction* target, CallInfo& callInfo);
622
    InliningDecision makeInliningDecision(JSObject* target, CallInfo& callInfo);
623
    AbortReasonOr<Ok> selectInliningTargets(const InliningTargets& targets, CallInfo& callInfo,
624
                                            BoolVector& choiceSet, uint32_t* numInlineable);
625
626
    // Native inlining helpers.
627
    // The typeset for the return value of our function.  These are
628
    // the types it's been observed returning in the past.
629
    TemporaryTypeSet* getInlineReturnTypeSet();
630
    // The known MIR type of getInlineReturnTypeSet.
631
    MIRType getInlineReturnType();
632
633
    // Array natives.
634
    InliningResult inlineArray(CallInfo& callInfo);
635
    InliningResult inlineArrayIsArray(CallInfo& callInfo);
636
    InliningResult inlineArrayPopShift(CallInfo& callInfo, MArrayPopShift::Mode mode);
637
    InliningResult inlineArrayPush(CallInfo& callInfo);
638
    InliningResult inlineArraySlice(CallInfo& callInfo);
639
    InliningResult inlineArrayJoin(CallInfo& callInfo);
640
641
    // Boolean natives.
642
    InliningResult inlineBoolean(CallInfo& callInfo);
643
644
    // Iterator intrinsics.
645
    InliningResult inlineNewIterator(CallInfo& callInfo, MNewIterator::Type type);
646
647
    // Math natives.
648
    InliningResult inlineMathAbs(CallInfo& callInfo);
649
    InliningResult inlineMathFloor(CallInfo& callInfo);
650
    InliningResult inlineMathCeil(CallInfo& callInfo);
651
    InliningResult inlineMathClz32(CallInfo& callInfo);
652
    InliningResult inlineMathRound(CallInfo& callInfo);
653
    InliningResult inlineMathSqrt(CallInfo& callInfo);
654
    InliningResult inlineMathAtan2(CallInfo& callInfo);
655
    InliningResult inlineMathHypot(CallInfo& callInfo);
656
    InliningResult inlineMathMinMax(CallInfo& callInfo, bool max);
657
    InliningResult inlineMathPow(CallInfo& callInfo);
658
    InliningResult inlineMathRandom(CallInfo& callInfo);
659
    InliningResult inlineMathImul(CallInfo& callInfo);
660
    InliningResult inlineMathFRound(CallInfo& callInfo);
661
    InliningResult inlineMathTrunc(CallInfo& callInfo);
662
    InliningResult inlineMathSign(CallInfo& callInfo);
663
    InliningResult inlineMathFunction(CallInfo& callInfo, MMathFunction::Function function);
664
665
    // String natives.
666
    InliningResult inlineStringObject(CallInfo& callInfo);
667
    InliningResult inlineStrCharCodeAt(CallInfo& callInfo);
668
    InliningResult inlineConstantCharCodeAt(CallInfo& callInfo);
669
    InliningResult inlineStrFromCharCode(CallInfo& callInfo);
670
    InliningResult inlineStrFromCodePoint(CallInfo& callInfo);
671
    InliningResult inlineStrCharAt(CallInfo& callInfo);
672
    InliningResult inlineStringConvertCase(CallInfo& callInfo, MStringConvertCase::Mode mode);
673
674
    // String intrinsics.
675
    InliningResult inlineStringReplaceString(CallInfo& callInfo);
676
    InliningResult inlineConstantStringSplitString(CallInfo& callInfo);
677
    InliningResult inlineStringSplitString(CallInfo& callInfo);
678
679
    // Reflect natives.
680
    InliningResult inlineReflectGetPrototypeOf(CallInfo& callInfo);
681
682
    // RegExp intrinsics.
683
    InliningResult inlineRegExpMatcher(CallInfo& callInfo);
684
    InliningResult inlineRegExpSearcher(CallInfo& callInfo);
685
    InliningResult inlineRegExpTester(CallInfo& callInfo);
686
    InliningResult inlineIsRegExpObject(CallInfo& callInfo);
687
    InliningResult inlineRegExpPrototypeOptimizable(CallInfo& callInfo);
688
    InliningResult inlineRegExpInstanceOptimizable(CallInfo& callInfo);
689
    InliningResult inlineGetFirstDollarIndex(CallInfo& callInfo);
690
691
    // Object natives and intrinsics.
692
    InliningResult inlineObject(CallInfo& callInfo);
693
    InliningResult inlineObjectCreate(CallInfo& callInfo);
694
    InliningResult inlineObjectIs(CallInfo& callInfo);
695
    InliningResult inlineObjectToString(CallInfo& callInfo);
696
    InliningResult inlineDefineDataProperty(CallInfo& callInfo);
697
698
    // Atomics natives.
699
    InliningResult inlineAtomicsCompareExchange(CallInfo& callInfo);
700
    InliningResult inlineAtomicsExchange(CallInfo& callInfo);
701
    InliningResult inlineAtomicsLoad(CallInfo& callInfo);
702
    InliningResult inlineAtomicsStore(CallInfo& callInfo);
703
    InliningResult inlineAtomicsBinop(CallInfo& callInfo, InlinableNative target);
704
    InliningResult inlineAtomicsIsLockFree(CallInfo& callInfo);
705
706
    // Slot intrinsics.
707
    InliningResult inlineUnsafeSetReservedSlot(CallInfo& callInfo);
708
    InliningResult inlineUnsafeGetReservedSlot(CallInfo& callInfo,
709
                                               MIRType knownValueType);
710
711
    // Map and Set intrinsics.
712
    InliningResult inlineGetNextEntryForIterator(CallInfo& callInfo,
713
                                                 MGetNextEntryForIterator::Mode mode);
714
715
    // ArrayBuffer intrinsics.
716
    InliningResult inlineArrayBufferByteLength(CallInfo& callInfo);
717
    InliningResult inlinePossiblyWrappedArrayBufferByteLength(CallInfo& callInfo);
718
719
    // TypedArray intrinsics.
720
    enum WrappingBehavior { AllowWrappedTypedArrays, RejectWrappedTypedArrays };
721
    InliningResult inlineTypedArray(CallInfo& callInfo, Native native);
722
    InliningResult inlineIsTypedArrayHelper(CallInfo& callInfo, WrappingBehavior wrappingBehavior);
723
    InliningResult inlineIsTypedArray(CallInfo& callInfo);
724
    InliningResult inlineIsPossiblyWrappedTypedArray(CallInfo& callInfo);
725
    InliningResult inlineTypedArrayLength(CallInfo& callInfo);
726
    InliningResult inlinePossiblyWrappedTypedArrayLength(CallInfo& callInfo);
727
    InliningResult inlineSetDisjointTypedElements(CallInfo& callInfo);
728
729
    // TypedObject intrinsics and natives.
730
    InliningResult inlineObjectIsTypeDescr(CallInfo& callInfo);
731
    InliningResult inlineSetTypedObjectOffset(CallInfo& callInfo);
732
    InliningResult inlineConstructTypedObject(CallInfo& callInfo, TypeDescr* target);
733
734
    // Utility intrinsics.
735
    InliningResult inlineIsCallable(CallInfo& callInfo);
736
    InliningResult inlineIsConstructor(CallInfo& callInfo);
737
    InliningResult inlineIsObject(CallInfo& callInfo);
738
    InliningResult inlineToObject(CallInfo& callInfo);
739
    InliningResult inlineIsCrossRealmArrayConstructor(CallInfo& callInfo);
740
    InliningResult inlineToInteger(CallInfo& callInfo);
741
    InliningResult inlineToString(CallInfo& callInfo);
742
    InliningResult inlineDump(CallInfo& callInfo);
743
    InliningResult inlineHasClass(CallInfo& callInfo, const Class* clasp,
744
                                  const Class* clasp2 = nullptr,
745
                                  const Class* clasp3 = nullptr,
746
                                  const Class* clasp4 = nullptr);
747
    InliningResult inlineGuardToClass(CallInfo& callInfo, const Class* clasp);
748
    InliningResult inlineIsConstructing(CallInfo& callInfo);
749
    InliningResult inlineSubstringKernel(CallInfo& callInfo);
750
    InliningResult inlineObjectHasPrototype(CallInfo& callInfo);
751
    InliningResult inlineFinishBoundFunctionInit(CallInfo& callInfo);
752
    InliningResult inlineIsPackedArray(CallInfo& callInfo);
753
    InliningResult inlineWasmCall(CallInfo& callInfo, JSFunction* target);
754
755
    // Testing functions.
756
    InliningResult inlineBailout(CallInfo& callInfo);
757
    InliningResult inlineAssertFloat32(CallInfo& callInfo);
758
    InliningResult inlineAssertRecoveredOnBailout(CallInfo& callInfo);
759
760
    // Bind function.
761
    InliningResult inlineBoundFunction(CallInfo& callInfo, JSFunction* target);
762
763
    // Main inlining functions
764
    InliningResult inlineNativeCall(CallInfo& callInfo, JSFunction* target);
765
    InliningResult inlineNativeGetter(CallInfo& callInfo, JSFunction* target);
766
    InliningResult inlineNonFunctionCall(CallInfo& callInfo, JSObject* target);
767
    InliningResult inlineScriptedCall(CallInfo& callInfo, JSFunction* target);
768
    InliningResult inlineSingleCall(CallInfo& callInfo, JSObject* target);
769
770
    // Call functions
771
    InliningResult inlineCallsite(const InliningTargets& targets, CallInfo& callInfo);
772
    AbortReasonOr<Ok> inlineCalls(CallInfo& callInfo, const InliningTargets& targets,
773
                                  BoolVector& choiceSet, MGetPropertyCache* maybeCache);
774
775
    // Inlining helpers.
776
    AbortReasonOr<Ok> inlineGenericFallback(const mozilla::Maybe<CallTargets>& targets,
777
                                            CallInfo& callInfo,
778
                                            MBasicBlock* dispatchBlock);
779
    AbortReasonOr<Ok> inlineObjectGroupFallback(const mozilla::Maybe<CallTargets>& targets,
780
                                                CallInfo& callInfo, MBasicBlock* dispatchBlock,
781
                                                MObjectGroupDispatch* dispatch,
782
                                                MGetPropertyCache* cache,
783
                                                MBasicBlock** fallbackTarget);
784
785
    enum AtomicCheckResult {
786
        DontCheckAtomicResult,
787
        DoCheckAtomicResult
788
    };
789
790
    bool atomicsMeetsPreconditions(CallInfo& callInfo, Scalar::Type* arrayElementType,
791
                                   bool* requiresDynamicCheck,
792
                                   AtomicCheckResult checkResult=DoCheckAtomicResult);
793
    void atomicsCheckBounds(CallInfo& callInfo, MInstruction** elements, MDefinition** index);
794
795
    bool testNeedsArgumentCheck(JSFunction* target, CallInfo& callInfo);
796
797
    AbortReasonOr<MCall*> makeCallHelper(const mozilla::Maybe<CallTargets>& targets,
798
                                         CallInfo& callInfo);
799
    AbortReasonOr<Ok> makeCall(const mozilla::Maybe<CallTargets>& targets, CallInfo& callInfo);
800
    AbortReasonOr<Ok> makeCall(JSFunction* target, CallInfo& callInfo);
801
802
    MDefinition* patchInlinedReturn(CallInfo& callInfo, MBasicBlock* exit, MBasicBlock* bottom);
803
    MDefinition* patchInlinedReturns(CallInfo& callInfo, MIRGraphReturns& returns,
804
                                     MBasicBlock* bottom);
805
    MDefinition* specializeInlinedReturn(MDefinition* rdef, MBasicBlock* exit);
806
807
    NativeObject* commonPrototypeWithGetterSetter(TemporaryTypeSet* types, PropertyName* name,
808
                                                  bool isGetter, JSFunction* getterOrSetter,
809
                                                  bool* guardGlobal);
810
    void freezePropertiesForCommonPrototype(TemporaryTypeSet* types, PropertyName* name,
811
                                            JSObject* foundProto, bool allowEmptyTypesForGlobal = false);
812
    /*
813
     * Callers must pass a non-null globalGuard if they pass a non-null globalShape.
814
     */
815
    bool testCommonGetterSetter(TemporaryTypeSet* types, PropertyName* name,
816
                                bool isGetter, JSFunction* getterOrSetter,
817
                                MDefinition** guard, Shape* globalShape = nullptr,
818
                                MDefinition** globalGuard = nullptr);
819
    AbortReasonOr<bool> testShouldDOMCall(TypeSet* inTypes,
820
                                          JSFunction* func, JSJitInfo::OpType opType);
821
822
    MDefinition*
823
    addShapeGuardsForGetterSetter(MDefinition* obj, JSObject* holder, Shape* holderShape,
824
                                  const BaselineInspector::ReceiverVector& receivers,
825
                                  const BaselineInspector::ObjectGroupVector& convertUnboxedGroups,
826
                                  bool isOwnProperty);
827
828
    AbortReasonOr<Ok> annotateGetPropertyCache(MDefinition* obj, PropertyName* name,
829
                                               MGetPropertyCache* getPropCache,
830
                                               TemporaryTypeSet* objTypes,
831
                                               TemporaryTypeSet* pushedTypes);
832
833
    MGetPropertyCache* getInlineableGetPropertyCache(CallInfo& callInfo);
834
835
    JSObject* testGlobalLexicalBinding(PropertyName* name);
836
837
    JSObject* testSingletonProperty(JSObject* obj, jsid id);
838
    JSObject* testSingletonPropertyTypes(MDefinition* obj, jsid id);
839
840
    AbortReasonOr<bool> testNotDefinedProperty(MDefinition* obj, jsid id, bool ownProperty = false);
841
842
    uint32_t getDefiniteSlot(TemporaryTypeSet* types, jsid id, uint32_t* pnfixed);
843
    MDefinition* convertUnboxedObjects(MDefinition* obj);
844
    MDefinition* convertUnboxedObjects(MDefinition* obj,
845
                                       const BaselineInspector::ObjectGroupVector& list);
846
    uint32_t getUnboxedOffset(TemporaryTypeSet* types, jsid id,
847
                              JSValueType* punboxedType);
848
    MInstruction* loadUnboxedProperty(MDefinition* obj, size_t offset, JSValueType unboxedType,
849
                                      BarrierKind barrier, TemporaryTypeSet* types);
850
    MInstruction* loadUnboxedValue(MDefinition* elements, size_t elementsOffset,
851
                                   MDefinition* scaledOffset, JSValueType unboxedType,
852
                                   BarrierKind barrier, TemporaryTypeSet* types);
853
    MInstruction* storeUnboxedProperty(MDefinition* obj, size_t offset, JSValueType unboxedType,
854
                                       MDefinition* value);
855
    MInstruction* storeUnboxedValue(MDefinition* obj,
856
                                    MDefinition* elements, int32_t elementsOffset,
857
                                    MDefinition* scaledOffset, JSValueType unboxedType,
858
                                    MDefinition* value, bool preBarrier = true);
859
    AbortReasonOr<Ok> checkPreliminaryGroups(MDefinition *obj);
860
    AbortReasonOr<Ok> freezePropTypeSets(TemporaryTypeSet* types,
861
                                         JSObject* foundProto, PropertyName* name);
862
    bool canInlinePropertyOpShapes(const BaselineInspector::ReceiverVector& receivers);
863
864
    TemporaryTypeSet* bytecodeTypes(jsbytecode* pc);
865
866
    // Use one of the below methods for updating the current block, rather than
867
    // updating |current| directly. setCurrent() should only be used in cases
868
    // where the block cannot have phis whose type needs to be computed.
869
870
98
    AbortReasonOr<Ok> setCurrentAndSpecializePhis(MBasicBlock* block) {
871
98
        if (block) {
872
98
            if (!block->specializePhis(alloc())) {
873
0
                return abort(AbortReason::Alloc);
874
0
            }
875
98
        }
876
98
        setCurrent(block);
877
98
        return Ok();
878
98
    }
879
880
112
    void setCurrent(MBasicBlock* block) {
881
112
        current = block;
882
112
    }
883
884
    // A builder is inextricably tied to a particular script.
885
    JSScript* script_;
886
887
    // script->hasIonScript() at the start of the compilation. Used to avoid
888
    // calling hasIonScript() from background compilation threads.
889
    bool scriptHasIonScript_;
890
891
    // If off thread compilation is successful, the final code generator is
892
    // attached here. Code has been generated, but not linked (there is not yet
893
    // an IonScript). This is heap allocated, and must be explicitly destroyed,
894
    // performed by FinishOffThreadBuilder().
895
    CodeGenerator* backgroundCodegen_;
896
897
    // Some aborts are actionable (e.g., using an unsupported bytecode). When
898
    // optimization tracking is enabled, the location and message of the abort
899
    // are recorded here so they may be propagated to the script's
900
    // corresponding JitcodeGlobalEntry::BaselineEntry.
901
    JSScript* actionableAbortScript_;
902
    jsbytecode* actionableAbortPc_;
903
    const char* actionableAbortMessage_;
904
905
    MRootList* rootList_;
906
907
  public:
908
14
    void setRootList(MRootList& rootList) {
909
14
        MOZ_ASSERT(!rootList_);
910
14
        rootList_ = &rootList;
911
14
    }
912
    void clearForBackEnd();
913
    JSObject* checkNurseryObject(JSObject* obj);
914
915
764
    JSScript* script() const { return script_; }
916
0
    bool scriptHasIonScript() const { return scriptHasIonScript_; }
917
918
28
    CodeGenerator* backgroundCodegen() const { return backgroundCodegen_; }
919
14
    void setBackgroundCodegen(CodeGenerator* codegen) { backgroundCodegen_ = codegen; }
920
921
339
    CompilerConstraintList* constraints() {
922
339
        return constraints_;
923
339
    }
924
925
0
    bool isInlineBuilder() const {
926
0
        return callerBuilder_ != nullptr;
927
0
    }
928
929
98
    const JSAtomState& names() { return realm->runtime()->names(); }
930
931
0
    bool hadActionableAbort() const {
932
0
        MOZ_ASSERT(!actionableAbortScript_ ||
933
0
                   (actionableAbortPc_ && actionableAbortMessage_));
934
0
        return actionableAbortScript_ != nullptr;
935
0
    }
936
937
0
    TraceLoggerThread *traceLogger() {
938
0
        return TraceLoggerForCurrentThread();
939
0
    }
940
941
    void actionableAbortLocationAndMessage(JSScript** abortScript, jsbytecode** abortPc,
942
                                           const char** abortMessage)
943
0
    {
944
0
        MOZ_ASSERT(hadActionableAbort());
945
0
        *abortScript = actionableAbortScript_;
946
0
        *abortPc = actionableAbortPc_;
947
0
        *abortMessage = actionableAbortMessage_;
948
0
    }
949
950
    void trace(JSTracer* trc);
951
952
  private:
953
    AbortReasonOr<Ok> init();
954
955
    JSContext* analysisContext;
956
    BaselineFrameInspector* baselineFrame_;
957
958
    // Constraints for recording dependencies on type information.
959
    CompilerConstraintList* constraints_;
960
961
    TemporaryTypeSet* thisTypes;
962
    TemporaryTypeSet* argTypes;
963
    TemporaryTypeSet* typeArray;
964
    uint32_t typeArrayHint;
965
    uint32_t* bytecodeTypeMap;
966
967
    EnvironmentCoordinateNameCache envCoordinateNameCache;
968
969
    jsbytecode* pc;
970
    MBasicBlock* current;
971
    uint32_t loopDepth_;
972
    Vector<MBasicBlock*, 0, JitAllocPolicy> blockWorklist;
973
    const CFGBlock* cfgCurrent;
974
    const ControlFlowGraph* cfg;
975
976
    Vector<BytecodeSite*, 0, JitAllocPolicy> trackedOptimizationSites_;
977
978
672
    BytecodeSite* bytecodeSite(jsbytecode* pc) {
979
672
        MOZ_ASSERT(info().inlineScriptTree()->script()->containsPC(pc));
980
672
        // See comment in maybeTrackedOptimizationSite.
981
672
        if (isOptimizationTrackingEnabled()) {
982
0
            if (BytecodeSite* site = maybeTrackedOptimizationSite(pc)) {
983
0
                return site;
984
0
            }
985
672
        }
986
672
        return new(alloc()) BytecodeSite(info().inlineScriptTree(), pc);
987
672
    }
988
989
    BytecodeSite* maybeTrackedOptimizationSite(jsbytecode* pc);
990
991
    MDefinition* lexicalCheck_;
992
993
0
    void setLexicalCheck(MDefinition* lexical) {
994
0
        MOZ_ASSERT(!lexicalCheck_);
995
0
        lexicalCheck_ = lexical;
996
0
    }
997
0
    MDefinition* takeLexicalCheck() {
998
0
        MDefinition* lexical = lexicalCheck_;
999
0
        lexicalCheck_ = nullptr;
1000
0
        return lexical;
1001
0
    }
1002
1003
    /* Information used for inline-call builders. */
1004
    MResumePoint* callerResumePoint_;
1005
0
    jsbytecode* callerPC() {
1006
0
        return callerResumePoint_ ? callerResumePoint_->pc() : nullptr;
1007
0
    }
1008
    IonBuilder* callerBuilder_;
1009
1010
    IonBuilder* outermostBuilder();
1011
1012
    struct LoopHeader {
1013
        jsbytecode* pc;
1014
        MBasicBlock* header;
1015
1016
        LoopHeader(jsbytecode* pc, MBasicBlock* header)
1017
          : pc(pc), header(header)
1018
0
        {}
1019
    };
1020
1021
    Vector<MDefinition*, 2, JitAllocPolicy> iterators_;
1022
    Vector<LoopHeader, 0, JitAllocPolicy> loopHeaders_;
1023
    Vector<MBasicBlock*, 0, JitAllocPolicy> loopHeaderStack_;
1024
#ifdef DEBUG
1025
    Vector<const CFGBlock*, 0, JitAllocPolicy> cfgLoopHeaderStack_;
1026
#endif
1027
1028
    BaselineInspector* inspector;
1029
1030
    size_t inliningDepth_;
1031
1032
    // Total bytecode length of all inlined scripts. Only tracked for the
1033
    // outermost builder.
1034
    size_t inlinedBytecodeLength_;
1035
1036
    // Cutoff to disable compilation if excessive time is spent reanalyzing
1037
    // loop bodies to compute a fixpoint of the types for loop variables.
1038
    static const size_t MAX_LOOP_RESTARTS = 40;
1039
    size_t numLoopRestarts_;
1040
1041
    // True if script->failedBoundsCheck is set for the current script or
1042
    // an outer script.
1043
    bool failedBoundsCheck_;
1044
1045
    // True if script->failedShapeGuard is set for the current script or
1046
    // an outer script.
1047
    bool failedShapeGuard_;
1048
1049
    // True if script->failedLexicalCheck_ is set for the current script or
1050
    // an outer script.
1051
    bool failedLexicalCheck_;
1052
1053
#ifdef DEBUG
1054
    // If this script uses the lazy arguments object.
1055
    bool hasLazyArguments_;
1056
#endif
1057
1058
    // If this is an inline builder, the call info for the builder.
1059
    const CallInfo* inlineCallInfo_;
1060
1061
    // When compiling a call with multiple targets, we are first creating a
1062
    // MGetPropertyCache.  This MGetPropertyCache is following the bytecode, and
1063
    // is used to recover the JSFunction.  In some cases, the Type of the object
1064
    // which own the property is enough for dispatching to the right function.
1065
    // In such cases we do not have read the property, except when the type
1066
    // object is unknown.
1067
    //
1068
    // As an optimization, we can dispatch a call based on the object group,
1069
    // without doing the MGetPropertyCache.  This is what is achieved by
1070
    // |IonBuilder::inlineCalls|.  As we might not know all the functions, we
1071
    // are adding a fallback path, where this MGetPropertyCache would be moved
1072
    // into.
1073
    //
1074
    // In order to build the fallback path, we have to capture a resume point
1075
    // ahead, for the potential fallback path.  This resume point is captured
1076
    // while building MGetPropertyCache.  It is capturing the state of Baseline
1077
    // before the execution of the MGetPropertyCache, such as we can safely do
1078
    // it in the fallback path.
1079
    //
1080
    // This field is used to discard the resume point if it is not used for
1081
    // building a fallback path.
1082
1083
    // Discard the prior resume point while setting a new MGetPropertyCache.
1084
    void replaceMaybeFallbackFunctionGetter(MGetPropertyCache* cache);
1085
1086
    // Discard the MGetPropertyCache if it is handled by WrapMGetPropertyCache.
1087
14
    void keepFallbackFunctionGetter(MGetPropertyCache* cache) {
1088
14
        if (cache == maybeFallbackFunctionGetter_) {
1089
14
            maybeFallbackFunctionGetter_ = nullptr;
1090
14
        }
1091
14
    }
1092
1093
    MGetPropertyCache* maybeFallbackFunctionGetter_;
1094
1095
    bool needsPostBarrier(MDefinition* value);
1096
1097
    // Used in tracking outcomes of optimization strategies for devtools.
1098
    void startTrackingOptimizations();
1099
1100
    // The track* methods below are called often. Do not combine them with the
1101
    // unchecked variants, despite the unchecked variants having no other
1102
    // callers.
1103
    void trackTypeInfo(JS::TrackedTypeSite site, MIRType mirType,
1104
                       TemporaryTypeSet* typeSet)
1105
98
    {
1106
98
        if (MOZ_UNLIKELY(current->trackedSite()->hasOptimizations())) {
1107
0
            trackTypeInfoUnchecked(site, mirType, typeSet);
1108
0
        }
1109
98
    }
1110
14
    void trackTypeInfo(JS::TrackedTypeSite site, JSObject* obj) {
1111
14
        if (MOZ_UNLIKELY(current->trackedSite()->hasOptimizations())) {
1112
0
            trackTypeInfoUnchecked(site, obj);
1113
0
        }
1114
14
    }
1115
0
    void trackTypeInfo(CallInfo& callInfo) {
1116
0
        if (MOZ_UNLIKELY(current->trackedSite()->hasOptimizations())) {
1117
0
            trackTypeInfoUnchecked(callInfo);
1118
0
        }
1119
0
    }
1120
1.17k
    void trackOptimizationAttempt(JS::TrackedStrategy strategy) {
1121
1.17k
        if (MOZ_UNLIKELY(current->trackedSite()->hasOptimizations())) {
1122
0
            trackOptimizationAttemptUnchecked(strategy);
1123
0
        }
1124
1.17k
    }
1125
0
    void amendOptimizationAttempt(uint32_t index) {
1126
0
        if (MOZ_UNLIKELY(current->trackedSite()->hasOptimizations())) {
1127
0
            amendOptimizationAttemptUnchecked(index);
1128
0
        }
1129
0
    }
1130
755
    void trackOptimizationOutcome(JS::TrackedOutcome outcome) {
1131
755
        if (MOZ_UNLIKELY(current->trackedSite()->hasOptimizations())) {
1132
0
            trackOptimizationOutcomeUnchecked(outcome);
1133
0
        }
1134
755
    }
1135
51
    void trackOptimizationSuccess() {
1136
51
        if (MOZ_UNLIKELY(current->trackedSite()->hasOptimizations())) {
1137
0
            trackOptimizationSuccessUnchecked();
1138
0
        }
1139
51
    }
1140
14
    void trackInlineSuccess(InliningStatus status = InliningStatus_Inlined) {
1141
14
        if (MOZ_UNLIKELY(current->trackedSite()->hasOptimizations())) {
1142
0
            trackInlineSuccessUnchecked(status);
1143
0
        }
1144
14
    }
1145
1146
84
    bool forceInlineCaches() {
1147
84
        return MOZ_UNLIKELY(JitOptions.forceInlineCaches);
1148
84
    }
1149
1150
    // Out-of-line variants that don't check if optimization tracking is
1151
    // enabled.
1152
    void trackTypeInfoUnchecked(JS::TrackedTypeSite site, MIRType mirType,
1153
                                TemporaryTypeSet* typeSet);
1154
    void trackTypeInfoUnchecked(JS::TrackedTypeSite site, JSObject* obj);
1155
    void trackTypeInfoUnchecked(CallInfo& callInfo);
1156
    void trackOptimizationAttemptUnchecked(JS::TrackedStrategy strategy);
1157
    void amendOptimizationAttemptUnchecked(uint32_t index);
1158
    void trackOptimizationOutcomeUnchecked(JS::TrackedOutcome outcome);
1159
    void trackOptimizationSuccessUnchecked();
1160
    void trackInlineSuccessUnchecked(InliningStatus status);
1161
1162
  public:
1163
1164
    // This is only valid for IonBuilders that have moved to background
1165
    size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
1166
};
1167
1168
class CallInfo
1169
{
1170
    MDefinition* fun_;
1171
    MDefinition* thisArg_;
1172
    MDefinition* newTargetArg_;
1173
    MDefinitionVector args_;
1174
    // If non-empty, this corresponds to the stack prior any implicit inlining
1175
    // such as before JSOP_FUNAPPLY.
1176
    MDefinitionVector priorArgs_;
1177
1178
    bool constructing_:1;
1179
1180
    // True if the caller does not use the return value.
1181
    bool ignoresReturnValue_:1;
1182
1183
    bool setter_:1;
1184
    bool apply_:1;
1185
1186
  public:
1187
    CallInfo(TempAllocator& alloc, jsbytecode* pc, bool constructing, bool ignoresReturnValue)
1188
      : fun_(nullptr),
1189
        thisArg_(nullptr),
1190
        newTargetArg_(nullptr),
1191
        args_(alloc),
1192
        priorArgs_(alloc),
1193
        constructing_(constructing),
1194
        ignoresReturnValue_(ignoresReturnValue),
1195
        setter_(false),
1196
        apply_(JSOp(*pc) == JSOP_FUNAPPLY)
1197
70
    { }
1198
1199
0
    MOZ_MUST_USE bool init(CallInfo& callInfo) {
1200
0
        MOZ_ASSERT(constructing_ == callInfo.constructing());
1201
0
1202
0
        fun_ = callInfo.fun();
1203
0
        thisArg_ = callInfo.thisArg();
1204
0
        ignoresReturnValue_ = callInfo.ignoresReturnValue();
1205
0
1206
0
        if (constructing()) {
1207
0
            newTargetArg_ = callInfo.getNewTarget();
1208
0
        }
1209
0
1210
0
        if (!args_.appendAll(callInfo.argv())) {
1211
0
            return false;
1212
0
        }
1213
0
1214
0
        return true;
1215
0
    }
1216
1217
70
    MOZ_MUST_USE bool init(MBasicBlock* current, uint32_t argc) {
1218
70
        MOZ_ASSERT(args_.empty());
1219
70
1220
70
        // Get the arguments in the right order
1221
70
        if (!args_.reserve(argc)) {
1222
0
            return false;
1223
0
        }
1224
70
1225
70
        if (constructing()) {
1226
0
            setNewTarget(current->pop());
1227
0
        }
1228
70
1229
126
        for (int32_t i = argc; i > 0; i--) {
1230
56
            args_.infallibleAppend(current->peek(-i));
1231
56
        }
1232
70
        current->popn(argc);
1233
70
1234
70
        // Get |this| and |fun|
1235
70
        setThis(current->pop());
1236
70
        setFun(current->pop());
1237
70
1238
70
        return true;
1239
70
    }
1240
1241
    // Before doing any pop to the stack, capture whatever flows into the
1242
    // instruction, such that we can restore it later.
1243
    AbortReasonOr<Ok> savePriorCallStack(MIRGenerator* mir, MBasicBlock* current, size_t peekDepth);
1244
1245
0
    void popPriorCallStack(MBasicBlock* current) {
1246
0
        if (priorArgs_.empty()) {
1247
0
            popCallStack(current);
1248
0
        } else {
1249
0
            current->popn(priorArgs_.length());
1250
0
        }
1251
0
    }
1252
1253
0
    AbortReasonOr<Ok> pushPriorCallStack(MIRGenerator* mir, MBasicBlock* current) {
1254
0
        if (priorArgs_.empty()) {
1255
0
            return pushCallStack(mir, current);
1256
0
        }
1257
0
        for (MDefinition* def : priorArgs_) {
1258
0
            current->push(def);
1259
0
        }
1260
0
        return Ok();
1261
0
    }
1262
1263
0
    void popCallStack(MBasicBlock* current) {
1264
0
        current->popn(numFormals());
1265
0
    }
1266
1267
0
    AbortReasonOr<Ok> pushCallStack(MIRGenerator* mir, MBasicBlock* current) {
1268
0
        // Ensure sufficient space in the slots: needed for inlining from FUNAPPLY.
1269
0
        if (apply_) {
1270
0
            uint32_t depth = current->stackDepth() + numFormals();
1271
0
            if (depth > current->nslots()) {
1272
0
                if (!current->increaseSlots(depth - current->nslots())) {
1273
0
                    return mir->abort(AbortReason::Alloc);
1274
0
                }
1275
0
            }
1276
0
        }
1277
0
1278
0
        current->push(fun());
1279
0
        current->push(thisArg());
1280
0
1281
0
        for (uint32_t i = 0; i < argc(); i++) {
1282
0
            current->push(getArg(i));
1283
0
        }
1284
0
1285
0
        if (constructing()) {
1286
0
            current->push(getNewTarget());
1287
0
        }
1288
0
1289
0
        return Ok();
1290
0
    }
1291
1292
280
    uint32_t argc() const {
1293
280
        return args_.length();
1294
280
    }
1295
0
    uint32_t numFormals() const {
1296
0
        return argc() + 2 + constructing();
1297
0
    }
1298
1299
0
    MOZ_MUST_USE bool setArgs(const MDefinitionVector& args) {
1300
0
        MOZ_ASSERT(args_.empty());
1301
0
        return args_.appendAll(args);
1302
0
    }
1303
1304
0
    MDefinitionVector& argv() {
1305
0
        return args_;
1306
0
    }
1307
1308
0
    const MDefinitionVector& argv() const {
1309
0
        return args_;
1310
0
    }
1311
1312
56
    MDefinition* getArg(uint32_t i) const {
1313
56
        MOZ_ASSERT(i < argc());
1314
56
        return args_[i];
1315
56
    }
1316
1317
0
    MDefinition* getArgWithDefault(uint32_t i, MDefinition* defaultValue) const {
1318
0
        if (i < argc()) {
1319
0
            return args_[i];
1320
0
        }
1321
0
1322
0
        return defaultValue;
1323
0
    }
1324
1325
0
    void setArg(uint32_t i, MDefinition* def) {
1326
0
        MOZ_ASSERT(i < argc());
1327
0
        args_[i] = def;
1328
0
    }
1329
1330
98
    MDefinition* thisArg() const {
1331
98
        MOZ_ASSERT(thisArg_);
1332
98
        return thisArg_;
1333
98
    }
1334
1335
70
    void setThis(MDefinition* thisArg) {
1336
70
        thisArg_ = thisArg;
1337
70
    }
1338
1339
392
    bool constructing() const {
1340
392
        return constructing_;
1341
392
    }
1342
1343
70
    bool ignoresReturnValue() const {
1344
70
        return ignoresReturnValue_;
1345
70
    }
1346
1347
0
    void setNewTarget(MDefinition* newTarget) {
1348
0
        MOZ_ASSERT(constructing());
1349
0
        newTargetArg_ = newTarget;
1350
0
    }
1351
0
    MDefinition* getNewTarget() const {
1352
0
        MOZ_ASSERT(newTargetArg_);
1353
0
        return newTargetArg_;
1354
0
    }
1355
1356
0
    bool isSetter() const {
1357
0
        return setter_;
1358
0
    }
1359
0
    void markAsSetter() {
1360
0
        setter_ = true;
1361
0
    }
1362
1363
98
    MDefinition* fun() const {
1364
98
        MOZ_ASSERT(fun_);
1365
98
        return fun_;
1366
98
    }
1367
1368
84
    void setFun(MDefinition* fun) {
1369
84
        fun_ = fun;
1370
84
    }
1371
1372
0
    void setImplicitlyUsedUnchecked() {
1373
0
        fun_->setImplicitlyUsedUnchecked();
1374
0
        thisArg_->setImplicitlyUsedUnchecked();
1375
0
        if (newTargetArg_) {
1376
0
            newTargetArg_->setImplicitlyUsedUnchecked();
1377
0
        }
1378
0
        for (uint32_t i = 0; i < argc(); i++) {
1379
0
            getArg(i)->setImplicitlyUsedUnchecked();
1380
0
        }
1381
0
    }
1382
};
1383
1384
} // namespace jit
1385
} // namespace js
1386
1387
#endif /* jit_IonBuilder_h */