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