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