1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/src/jit/IonBuilder.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1060 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99: 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifndef jit_IonBuilder_h 1.11 +#define jit_IonBuilder_h 1.12 + 1.13 +#ifdef JS_ION 1.14 + 1.15 +// This file declares the data structures for building a MIRGraph from a 1.16 +// JSScript. 1.17 + 1.18 +#include "jit/BytecodeAnalysis.h" 1.19 +#include "jit/IonOptimizationLevels.h" 1.20 +#include "jit/MIR.h" 1.21 +#include "jit/MIRGenerator.h" 1.22 +#include "jit/MIRGraph.h" 1.23 +#include "jit/TypeDescrSet.h" 1.24 + 1.25 +namespace js { 1.26 +namespace jit { 1.27 + 1.28 +class CodeGenerator; 1.29 +class CallInfo; 1.30 +class BaselineInspector; 1.31 +class BaselineFrameInspector; 1.32 + 1.33 +// Records information about a baseline frame for compilation that is stable 1.34 +// when later used off thread. 1.35 +BaselineFrameInspector * 1.36 +NewBaselineFrameInspector(TempAllocator *temp, BaselineFrame *frame, CompileInfo *info); 1.37 + 1.38 +class IonBuilder : public MIRGenerator 1.39 +{ 1.40 + enum ControlStatus { 1.41 + ControlStatus_Error, 1.42 + ControlStatus_Abort, 1.43 + ControlStatus_Ended, // There is no continuation/join point. 1.44 + ControlStatus_Joined, // Created a join node. 1.45 + ControlStatus_Jumped, // Parsing another branch at the same level. 1.46 + ControlStatus_None // No control flow. 1.47 + }; 1.48 + 1.49 + enum SetElemSafety { 1.50 + // Normal write like a[b] = c. 1.51 + SetElem_Normal, 1.52 + 1.53 + // Write due to UnsafePutElements: 1.54 + // - assumed to be in bounds, 1.55 + // - not checked for data races 1.56 + SetElem_Unsafe, 1.57 + }; 1.58 + 1.59 + struct DeferredEdge : public TempObject 1.60 + { 1.61 + MBasicBlock *block; 1.62 + DeferredEdge *next; 1.63 + 1.64 + DeferredEdge(MBasicBlock *block, DeferredEdge *next) 1.65 + : block(block), next(next) 1.66 + { } 1.67 + }; 1.68 + 1.69 + struct ControlFlowInfo { 1.70 + // Entry in the cfgStack. 1.71 + uint32_t cfgEntry; 1.72 + 1.73 + // Label that continues go to. 1.74 + jsbytecode *continuepc; 1.75 + 1.76 + ControlFlowInfo(uint32_t cfgEntry, jsbytecode *continuepc) 1.77 + : cfgEntry(cfgEntry), 1.78 + continuepc(continuepc) 1.79 + { } 1.80 + }; 1.81 + 1.82 + // To avoid recursion, the bytecode analyzer uses a stack where each entry 1.83 + // is a small state machine. As we encounter branches or jumps in the 1.84 + // bytecode, we push information about the edges on the stack so that the 1.85 + // CFG can be built in a tree-like fashion. 1.86 + struct CFGState { 1.87 + enum State { 1.88 + IF_TRUE, // if() { }, no else. 1.89 + IF_TRUE_EMPTY_ELSE, // if() { }, empty else 1.90 + IF_ELSE_TRUE, // if() { X } else { } 1.91 + IF_ELSE_FALSE, // if() { } else { X } 1.92 + DO_WHILE_LOOP_BODY, // do { x } while () 1.93 + DO_WHILE_LOOP_COND, // do { } while (x) 1.94 + WHILE_LOOP_COND, // while (x) { } 1.95 + WHILE_LOOP_BODY, // while () { x } 1.96 + FOR_LOOP_COND, // for (; x;) { } 1.97 + FOR_LOOP_BODY, // for (; ;) { x } 1.98 + FOR_LOOP_UPDATE, // for (; ; x) { } 1.99 + TABLE_SWITCH, // switch() { x } 1.100 + COND_SWITCH_CASE, // switch() { case X: ... } 1.101 + COND_SWITCH_BODY, // switch() { case ...: X } 1.102 + AND_OR, // && x, || x 1.103 + LABEL, // label: x 1.104 + TRY // try { x } catch(e) { } 1.105 + }; 1.106 + 1.107 + State state; // Current state of this control structure. 1.108 + jsbytecode *stopAt; // Bytecode at which to stop the processing loop. 1.109 + 1.110 + // For if structures, this contains branch information. 1.111 + union { 1.112 + struct { 1.113 + MBasicBlock *ifFalse; 1.114 + jsbytecode *falseEnd; 1.115 + MBasicBlock *ifTrue; // Set when the end of the true path is reached. 1.116 + MTest *test; 1.117 + } branch; 1.118 + struct { 1.119 + // Common entry point. 1.120 + MBasicBlock *entry; 1.121 + 1.122 + // Whether OSR is being performed for this loop. 1.123 + bool osr; 1.124 + 1.125 + // Position of where the loop body starts and ends. 1.126 + jsbytecode *bodyStart; 1.127 + jsbytecode *bodyEnd; 1.128 + 1.129 + // pc immediately after the loop exits. 1.130 + jsbytecode *exitpc; 1.131 + 1.132 + // pc for 'continue' jumps. 1.133 + jsbytecode *continuepc; 1.134 + 1.135 + // Common exit point. Created lazily, so it may be nullptr. 1.136 + MBasicBlock *successor; 1.137 + 1.138 + // Deferred break and continue targets. 1.139 + DeferredEdge *breaks; 1.140 + DeferredEdge *continues; 1.141 + 1.142 + // Initial state, in case loop processing is restarted. 1.143 + State initialState; 1.144 + jsbytecode *initialPc; 1.145 + jsbytecode *initialStopAt; 1.146 + jsbytecode *loopHead; 1.147 + 1.148 + // For-loops only. 1.149 + jsbytecode *condpc; 1.150 + jsbytecode *updatepc; 1.151 + jsbytecode *updateEnd; 1.152 + } loop; 1.153 + struct { 1.154 + // pc immediately after the switch. 1.155 + jsbytecode *exitpc; 1.156 + 1.157 + // Deferred break and continue targets. 1.158 + DeferredEdge *breaks; 1.159 + 1.160 + // MIR instruction 1.161 + MTableSwitch *ins; 1.162 + 1.163 + // The number of current successor that get mapped into a block. 1.164 + uint32_t currentBlock; 1.165 + 1.166 + } tableswitch; 1.167 + struct { 1.168 + // Vector of body blocks to process after the cases. 1.169 + FixedList<MBasicBlock *> *bodies; 1.170 + 1.171 + // When processing case statements, this counter points at the 1.172 + // last uninitialized body. When processing bodies, this 1.173 + // counter targets the next body to process. 1.174 + uint32_t currentIdx; 1.175 + 1.176 + // Remember the block index of the default case. 1.177 + jsbytecode *defaultTarget; 1.178 + uint32_t defaultIdx; 1.179 + 1.180 + // Block immediately after the switch. 1.181 + jsbytecode *exitpc; 1.182 + DeferredEdge *breaks; 1.183 + } condswitch; 1.184 + struct { 1.185 + DeferredEdge *breaks; 1.186 + } label; 1.187 + struct { 1.188 + MBasicBlock *successor; 1.189 + } try_; 1.190 + }; 1.191 + 1.192 + inline bool isLoop() const { 1.193 + switch (state) { 1.194 + case DO_WHILE_LOOP_COND: 1.195 + case DO_WHILE_LOOP_BODY: 1.196 + case WHILE_LOOP_COND: 1.197 + case WHILE_LOOP_BODY: 1.198 + case FOR_LOOP_COND: 1.199 + case FOR_LOOP_BODY: 1.200 + case FOR_LOOP_UPDATE: 1.201 + return true; 1.202 + default: 1.203 + return false; 1.204 + } 1.205 + } 1.206 + 1.207 + static CFGState If(jsbytecode *join, MTest *test); 1.208 + static CFGState IfElse(jsbytecode *trueEnd, jsbytecode *falseEnd, MTest *test); 1.209 + static CFGState AndOr(jsbytecode *join, MBasicBlock *joinStart); 1.210 + static CFGState TableSwitch(jsbytecode *exitpc, MTableSwitch *ins); 1.211 + static CFGState CondSwitch(IonBuilder *builder, jsbytecode *exitpc, jsbytecode *defaultTarget); 1.212 + static CFGState Label(jsbytecode *exitpc); 1.213 + static CFGState Try(jsbytecode *exitpc, MBasicBlock *successor); 1.214 + }; 1.215 + 1.216 + static int CmpSuccessors(const void *a, const void *b); 1.217 + 1.218 + public: 1.219 + IonBuilder(JSContext *analysisContext, CompileCompartment *comp, 1.220 + const JitCompileOptions &options, TempAllocator *temp, 1.221 + MIRGraph *graph, types::CompilerConstraintList *constraints, 1.222 + BaselineInspector *inspector, CompileInfo *info, 1.223 + const OptimizationInfo *optimizationInfo, BaselineFrameInspector *baselineFrame, 1.224 + size_t inliningDepth = 0, uint32_t loopDepth = 0); 1.225 + 1.226 + bool build(); 1.227 + bool buildInline(IonBuilder *callerBuilder, MResumePoint *callerResumePoint, 1.228 + CallInfo &callInfo); 1.229 + 1.230 + private: 1.231 + bool traverseBytecode(); 1.232 + ControlStatus snoopControlFlow(JSOp op); 1.233 + bool processIterators(); 1.234 + bool inspectOpcode(JSOp op); 1.235 + uint32_t readIndex(jsbytecode *pc); 1.236 + JSAtom *readAtom(jsbytecode *pc); 1.237 + bool abort(const char *message, ...); 1.238 + void spew(const char *message); 1.239 + 1.240 + JSFunction *getSingleCallTarget(types::TemporaryTypeSet *calleeTypes); 1.241 + bool getPolyCallTargets(types::TemporaryTypeSet *calleeTypes, bool constructing, 1.242 + ObjectVector &targets, uint32_t maxTargets, bool *gotLambda); 1.243 + 1.244 + void popCfgStack(); 1.245 + DeferredEdge *filterDeadDeferredEdges(DeferredEdge *edge); 1.246 + bool processDeferredContinues(CFGState &state); 1.247 + ControlStatus processControlEnd(); 1.248 + ControlStatus processCfgStack(); 1.249 + ControlStatus processCfgEntry(CFGState &state); 1.250 + ControlStatus processIfEnd(CFGState &state); 1.251 + ControlStatus processIfElseTrueEnd(CFGState &state); 1.252 + ControlStatus processIfElseFalseEnd(CFGState &state); 1.253 + ControlStatus processDoWhileBodyEnd(CFGState &state); 1.254 + ControlStatus processDoWhileCondEnd(CFGState &state); 1.255 + ControlStatus processWhileCondEnd(CFGState &state); 1.256 + ControlStatus processWhileBodyEnd(CFGState &state); 1.257 + ControlStatus processForCondEnd(CFGState &state); 1.258 + ControlStatus processForBodyEnd(CFGState &state); 1.259 + ControlStatus processForUpdateEnd(CFGState &state); 1.260 + ControlStatus processNextTableSwitchCase(CFGState &state); 1.261 + ControlStatus processCondSwitchCase(CFGState &state); 1.262 + ControlStatus processCondSwitchBody(CFGState &state); 1.263 + ControlStatus processSwitchBreak(JSOp op); 1.264 + ControlStatus processSwitchEnd(DeferredEdge *breaks, jsbytecode *exitpc); 1.265 + ControlStatus processAndOrEnd(CFGState &state); 1.266 + ControlStatus processLabelEnd(CFGState &state); 1.267 + ControlStatus processTryEnd(CFGState &state); 1.268 + ControlStatus processReturn(JSOp op); 1.269 + ControlStatus processThrow(); 1.270 + ControlStatus processContinue(JSOp op); 1.271 + ControlStatus processBreak(JSOp op, jssrcnote *sn); 1.272 + ControlStatus maybeLoop(JSOp op, jssrcnote *sn); 1.273 + bool pushLoop(CFGState::State state, jsbytecode *stopAt, MBasicBlock *entry, bool osr, 1.274 + jsbytecode *loopHead, jsbytecode *initialPc, 1.275 + jsbytecode *bodyStart, jsbytecode *bodyEnd, jsbytecode *exitpc, 1.276 + jsbytecode *continuepc = nullptr); 1.277 + bool analyzeNewLoopTypes(MBasicBlock *entry, jsbytecode *start, jsbytecode *end); 1.278 + 1.279 + MBasicBlock *addBlock(MBasicBlock *block, uint32_t loopDepth); 1.280 + MBasicBlock *newBlock(MBasicBlock *predecessor, jsbytecode *pc); 1.281 + MBasicBlock *newBlock(MBasicBlock *predecessor, jsbytecode *pc, uint32_t loopDepth); 1.282 + MBasicBlock *newBlock(MBasicBlock *predecessor, jsbytecode *pc, MResumePoint *priorResumePoint); 1.283 + MBasicBlock *newBlockPopN(MBasicBlock *predecessor, jsbytecode *pc, uint32_t popped); 1.284 + MBasicBlock *newBlockAfter(MBasicBlock *at, MBasicBlock *predecessor, jsbytecode *pc); 1.285 + MBasicBlock *newOsrPreheader(MBasicBlock *header, jsbytecode *loopEntry); 1.286 + MBasicBlock *newPendingLoopHeader(MBasicBlock *predecessor, jsbytecode *pc, bool osr, bool canOsr, 1.287 + unsigned stackPhiCount); 1.288 + MBasicBlock *newBlock(jsbytecode *pc) { 1.289 + return newBlock(nullptr, pc); 1.290 + } 1.291 + MBasicBlock *newBlockAfter(MBasicBlock *at, jsbytecode *pc) { 1.292 + return newBlockAfter(at, nullptr, pc); 1.293 + } 1.294 + 1.295 + // Given a list of pending breaks, creates a new block and inserts a Goto 1.296 + // linking each break to the new block. 1.297 + MBasicBlock *createBreakCatchBlock(DeferredEdge *edge, jsbytecode *pc); 1.298 + 1.299 + // Finishes loops that do not actually loop, containing only breaks and 1.300 + // returns or a do while loop with a condition that is constant false. 1.301 + ControlStatus processBrokenLoop(CFGState &state); 1.302 + 1.303 + // Computes loop phis, places them in all successors of a loop, then 1.304 + // handles any pending breaks. 1.305 + ControlStatus finishLoop(CFGState &state, MBasicBlock *successor); 1.306 + 1.307 + // Incorporates a type/typeSet into an OSR value for a loop, after the loop 1.308 + // body has been processed. 1.309 + bool addOsrValueTypeBarrier(uint32_t slot, MInstruction **def, 1.310 + MIRType type, types::TemporaryTypeSet *typeSet); 1.311 + bool maybeAddOsrTypeBarriers(); 1.312 + 1.313 + // Restarts processing of a loop if the type information at its header was 1.314 + // incomplete. 1.315 + ControlStatus restartLoop(CFGState state); 1.316 + 1.317 + void assertValidLoopHeadOp(jsbytecode *pc); 1.318 + 1.319 + ControlStatus forLoop(JSOp op, jssrcnote *sn); 1.320 + ControlStatus whileOrForInLoop(jssrcnote *sn); 1.321 + ControlStatus doWhileLoop(JSOp op, jssrcnote *sn); 1.322 + ControlStatus tableSwitch(JSOp op, jssrcnote *sn); 1.323 + ControlStatus condSwitch(JSOp op, jssrcnote *sn); 1.324 + 1.325 + // Please see the Big Honkin' Comment about how resume points work in 1.326 + // IonBuilder.cpp, near the definition for this function. 1.327 + bool resume(MInstruction *ins, jsbytecode *pc, MResumePoint::Mode mode); 1.328 + bool resumeAt(MInstruction *ins, jsbytecode *pc); 1.329 + bool resumeAfter(MInstruction *ins); 1.330 + bool maybeInsertResume(); 1.331 + 1.332 + void insertRecompileCheck(); 1.333 + 1.334 + void initParameters(); 1.335 + void rewriteParameter(uint32_t slotIdx, MDefinition *param, int32_t argIndex); 1.336 + void rewriteParameters(); 1.337 + bool initScopeChain(MDefinition *callee = nullptr); 1.338 + bool initArgumentsObject(); 1.339 + bool pushConstant(const Value &v); 1.340 + 1.341 + MConstant *constant(const Value &v); 1.342 + MConstant *constantInt(int32_t i); 1.343 + 1.344 + // Filter the type information at tests 1.345 + bool filterTypesAtTest(MTest *test); 1.346 + 1.347 + // Add a guard which ensure that the set of type which goes through this 1.348 + // generated code correspond to the observed types for the bytecode. 1.349 + bool pushTypeBarrier(MDefinition *def, types::TemporaryTypeSet *observed, bool needBarrier); 1.350 + 1.351 + // As pushTypeBarrier, but will compute the needBarrier boolean itself based 1.352 + // on observed and the JSFunction that we're planning to call. The 1.353 + // JSFunction must be a DOM method or getter. 1.354 + bool pushDOMTypeBarrier(MInstruction *ins, types::TemporaryTypeSet *observed, JSFunction* func); 1.355 + 1.356 + // If definiteType is not known or def already has the right type, just 1.357 + // returns def. Otherwise, returns an MInstruction that has that definite 1.358 + // type, infallibly unboxing ins as needed. The new instruction will be 1.359 + // added to |current| in this case. 1.360 + MDefinition *ensureDefiniteType(MDefinition* def, MIRType definiteType); 1.361 + 1.362 + // Creates a MDefinition based on the given def improved with type as TypeSet. 1.363 + MDefinition *ensureDefiniteTypeSet(MDefinition* def, types::TemporaryTypeSet *types); 1.364 + 1.365 + JSObject *getSingletonPrototype(JSFunction *target); 1.366 + 1.367 + MDefinition *createThisScripted(MDefinition *callee); 1.368 + MDefinition *createThisScriptedSingleton(JSFunction *target, MDefinition *callee); 1.369 + MDefinition *createThis(JSFunction *target, MDefinition *callee); 1.370 + MInstruction *createDeclEnvObject(MDefinition *callee, MDefinition *scopeObj); 1.371 + MInstruction *createCallObject(MDefinition *callee, MDefinition *scopeObj); 1.372 + 1.373 + MDefinition *walkScopeChain(unsigned hops); 1.374 + 1.375 + MInstruction *addConvertElementsToDoubles(MDefinition *elements); 1.376 + MInstruction *addBoundsCheck(MDefinition *index, MDefinition *length); 1.377 + MInstruction *addShapeGuard(MDefinition *obj, Shape *const shape, BailoutKind bailoutKind); 1.378 + 1.379 + MDefinition *convertShiftToMaskForStaticTypedArray(MDefinition *id, 1.380 + ArrayBufferView::ViewType viewType); 1.381 + 1.382 + bool invalidatedIdempotentCache(); 1.383 + 1.384 + bool hasStaticScopeObject(ScopeCoordinate sc, JSObject **pcall); 1.385 + bool loadSlot(MDefinition *obj, size_t slot, size_t nfixed, MIRType rvalType, 1.386 + bool barrier, types::TemporaryTypeSet *types); 1.387 + bool loadSlot(MDefinition *obj, Shape *shape, MIRType rvalType, 1.388 + bool barrier, types::TemporaryTypeSet *types); 1.389 + bool storeSlot(MDefinition *obj, size_t slot, size_t nfixed, 1.390 + MDefinition *value, bool needsBarrier, 1.391 + MIRType slotType = MIRType_None); 1.392 + bool storeSlot(MDefinition *obj, Shape *shape, MDefinition *value, bool needsBarrier, 1.393 + MIRType slotType = MIRType_None); 1.394 + 1.395 + // jsop_getprop() helpers. 1.396 + bool getPropTryArgumentsLength(bool *emitted); 1.397 + bool getPropTryConstant(bool *emitted, PropertyName *name, 1.398 + types::TemporaryTypeSet *types); 1.399 + bool getPropTryDefiniteSlot(bool *emitted, PropertyName *name, 1.400 + bool barrier, types::TemporaryTypeSet *types); 1.401 + bool getPropTryCommonGetter(bool *emitted, PropertyName *name, 1.402 + types::TemporaryTypeSet *types); 1.403 + bool getPropTryInlineAccess(bool *emitted, PropertyName *name, 1.404 + bool barrier, types::TemporaryTypeSet *types); 1.405 + bool getPropTryTypedObject(bool *emitted, PropertyName *name, 1.406 + types::TemporaryTypeSet *resultTypes); 1.407 + bool getPropTryScalarPropOfTypedObject(bool *emitted, 1.408 + int32_t fieldOffset, 1.409 + TypeDescrSet fieldTypeReprs, 1.410 + types::TemporaryTypeSet *resultTypes); 1.411 + bool getPropTryComplexPropOfTypedObject(bool *emitted, 1.412 + int32_t fieldOffset, 1.413 + TypeDescrSet fieldTypeReprs, 1.414 + size_t fieldIndex, 1.415 + types::TemporaryTypeSet *resultTypes); 1.416 + bool getPropTryCache(bool *emitted, PropertyName *name, 1.417 + bool barrier, types::TemporaryTypeSet *types); 1.418 + bool needsToMonitorMissingProperties(types::TemporaryTypeSet *types); 1.419 + 1.420 + // jsop_setprop() helpers. 1.421 + bool setPropTryCommonSetter(bool *emitted, MDefinition *obj, 1.422 + PropertyName *name, MDefinition *value); 1.423 + bool setPropTryCommonDOMSetter(bool *emitted, MDefinition *obj, 1.424 + MDefinition *value, JSFunction *setter, 1.425 + bool isDOM); 1.426 + bool setPropTryDefiniteSlot(bool *emitted, MDefinition *obj, 1.427 + PropertyName *name, MDefinition *value, 1.428 + bool barrier, types::TemporaryTypeSet *objTypes); 1.429 + bool setPropTryInlineAccess(bool *emitted, MDefinition *obj, 1.430 + PropertyName *name, MDefinition *value, bool barrier, 1.431 + types::TemporaryTypeSet *objTypes); 1.432 + bool setPropTryTypedObject(bool *emitted, MDefinition *obj, 1.433 + PropertyName *name, MDefinition *value); 1.434 + bool setPropTryScalarPropOfTypedObject(bool *emitted, 1.435 + MDefinition *obj, 1.436 + int32_t fieldOffset, 1.437 + MDefinition *value, 1.438 + TypeDescrSet fieldTypeReprs); 1.439 + bool setPropTryCache(bool *emitted, MDefinition *obj, 1.440 + PropertyName *name, MDefinition *value, 1.441 + bool barrier, types::TemporaryTypeSet *objTypes); 1.442 + 1.443 + // binary data lookup helpers. 1.444 + bool lookupTypeDescrSet(MDefinition *typedObj, 1.445 + TypeDescrSet *out); 1.446 + bool typeSetToTypeDescrSet(types::TemporaryTypeSet *types, 1.447 + TypeDescrSet *out); 1.448 + bool lookupTypedObjectField(MDefinition *typedObj, 1.449 + PropertyName *name, 1.450 + int32_t *fieldOffset, 1.451 + TypeDescrSet *fieldTypeReprs, 1.452 + size_t *fieldIndex); 1.453 + MDefinition *loadTypedObjectType(MDefinition *value); 1.454 + void loadTypedObjectData(MDefinition *typedObj, 1.455 + MDefinition *offset, 1.456 + bool canBeNeutered, 1.457 + MDefinition **owner, 1.458 + MDefinition **ownerOffset); 1.459 + void loadTypedObjectElements(MDefinition *typedObj, 1.460 + MDefinition *offset, 1.461 + int32_t unit, 1.462 + bool canBeNeutered, 1.463 + MDefinition **ownerElements, 1.464 + MDefinition **ownerScaledOffset); 1.465 + MDefinition *typeObjectForElementFromArrayStructType(MDefinition *typedObj); 1.466 + MDefinition *typeObjectForFieldFromStructType(MDefinition *type, 1.467 + size_t fieldIndex); 1.468 + bool storeScalarTypedObjectValue(MDefinition *typedObj, 1.469 + MDefinition *offset, 1.470 + ScalarTypeDescr::Type type, 1.471 + bool canBeNeutered, 1.472 + bool racy, 1.473 + MDefinition *value); 1.474 + bool checkTypedObjectIndexInBounds(int32_t elemSize, 1.475 + MDefinition *obj, 1.476 + MDefinition *index, 1.477 + TypeDescrSet objTypeDescrs, 1.478 + MDefinition **indexAsByteOffset, 1.479 + bool *canBeNeutered); 1.480 + bool pushDerivedTypedObject(bool *emitted, 1.481 + MDefinition *obj, 1.482 + MDefinition *offset, 1.483 + TypeDescrSet derivedTypeDescrs, 1.484 + MDefinition *derivedTypeObj, 1.485 + bool canBeNeutered); 1.486 + bool pushScalarLoadFromTypedObject(bool *emitted, 1.487 + MDefinition *obj, 1.488 + MDefinition *offset, 1.489 + ScalarTypeDescr::Type type, 1.490 + bool canBeNeutered); 1.491 + MDefinition *neuterCheck(MDefinition *obj); 1.492 + 1.493 + // jsop_setelem() helpers. 1.494 + bool setElemTryTypedArray(bool *emitted, MDefinition *object, 1.495 + MDefinition *index, MDefinition *value); 1.496 + bool setElemTryTypedObject(bool *emitted, MDefinition *obj, 1.497 + MDefinition *index, MDefinition *value); 1.498 + bool setElemTryTypedStatic(bool *emitted, MDefinition *object, 1.499 + MDefinition *index, MDefinition *value); 1.500 + bool setElemTryDense(bool *emitted, MDefinition *object, 1.501 + MDefinition *index, MDefinition *value); 1.502 + bool setElemTryArguments(bool *emitted, MDefinition *object, 1.503 + MDefinition *index, MDefinition *value); 1.504 + bool setElemTryCache(bool *emitted, MDefinition *object, 1.505 + MDefinition *index, MDefinition *value); 1.506 + bool setElemTryScalarElemOfTypedObject(bool *emitted, 1.507 + MDefinition *obj, 1.508 + MDefinition *index, 1.509 + TypeDescrSet objTypeReprs, 1.510 + MDefinition *value, 1.511 + TypeDescrSet elemTypeReprs, 1.512 + int32_t elemSize); 1.513 + 1.514 + // jsop_getelem() helpers. 1.515 + bool getElemTryDense(bool *emitted, MDefinition *obj, MDefinition *index); 1.516 + bool getElemTryTypedStatic(bool *emitted, MDefinition *obj, MDefinition *index); 1.517 + bool getElemTryTypedArray(bool *emitted, MDefinition *obj, MDefinition *index); 1.518 + bool getElemTryTypedObject(bool *emitted, MDefinition *obj, MDefinition *index); 1.519 + bool getElemTryString(bool *emitted, MDefinition *obj, MDefinition *index); 1.520 + bool getElemTryArguments(bool *emitted, MDefinition *obj, MDefinition *index); 1.521 + bool getElemTryArgumentsInlined(bool *emitted, MDefinition *obj, MDefinition *index); 1.522 + bool getElemTryCache(bool *emitted, MDefinition *obj, MDefinition *index); 1.523 + bool getElemTryScalarElemOfTypedObject(bool *emitted, 1.524 + MDefinition *obj, 1.525 + MDefinition *index, 1.526 + TypeDescrSet objTypeReprs, 1.527 + TypeDescrSet elemTypeReprs, 1.528 + int32_t elemSize); 1.529 + bool getElemTryComplexElemOfTypedObject(bool *emitted, 1.530 + MDefinition *obj, 1.531 + MDefinition *index, 1.532 + TypeDescrSet objTypeReprs, 1.533 + TypeDescrSet elemTypeReprs, 1.534 + int32_t elemSize); 1.535 + 1.536 + enum BoundsChecking { DoBoundsCheck, SkipBoundsCheck }; 1.537 + 1.538 + // Add instructions to compute a typed array's length and data. Also 1.539 + // optionally convert |*index| into a bounds-checked definition, if 1.540 + // requested. 1.541 + // 1.542 + // If you only need the array's length, use addTypedArrayLength below. 1.543 + void addTypedArrayLengthAndData(MDefinition *obj, 1.544 + BoundsChecking checking, 1.545 + MDefinition **index, 1.546 + MInstruction **length, MInstruction **elements); 1.547 + 1.548 + // Add an instruction to compute a typed array's length to the current 1.549 + // block. If you also need the typed array's data, use the above method 1.550 + // instead. 1.551 + MInstruction *addTypedArrayLength(MDefinition *obj) { 1.552 + MInstruction *length; 1.553 + addTypedArrayLengthAndData(obj, SkipBoundsCheck, nullptr, &length, nullptr); 1.554 + return length; 1.555 + } 1.556 + 1.557 + 1.558 + MDefinition *getCallee(); 1.559 + 1.560 + bool jsop_add(MDefinition *left, MDefinition *right); 1.561 + bool jsop_bitnot(); 1.562 + bool jsop_bitop(JSOp op); 1.563 + bool jsop_binary(JSOp op); 1.564 + bool jsop_binary(JSOp op, MDefinition *left, MDefinition *right); 1.565 + bool jsop_pos(); 1.566 + bool jsop_neg(); 1.567 + bool jsop_setarg(uint32_t arg); 1.568 + bool jsop_defvar(uint32_t index); 1.569 + bool jsop_deffun(uint32_t index); 1.570 + bool jsop_notearg(); 1.571 + bool jsop_funcall(uint32_t argc); 1.572 + bool jsop_funapply(uint32_t argc); 1.573 + bool jsop_funapplyarguments(uint32_t argc); 1.574 + bool jsop_call(uint32_t argc, bool constructing); 1.575 + bool jsop_eval(uint32_t argc); 1.576 + bool jsop_ifeq(JSOp op); 1.577 + bool jsop_try(); 1.578 + bool jsop_label(); 1.579 + bool jsop_condswitch(); 1.580 + bool jsop_andor(JSOp op); 1.581 + bool jsop_dup2(); 1.582 + bool jsop_loophead(jsbytecode *pc); 1.583 + bool jsop_compare(JSOp op); 1.584 + bool getStaticName(JSObject *staticObject, PropertyName *name, bool *psucceeded); 1.585 + bool setStaticName(JSObject *staticObject, PropertyName *name); 1.586 + bool jsop_getgname(PropertyName *name); 1.587 + bool jsop_getname(PropertyName *name); 1.588 + bool jsop_intrinsic(PropertyName *name); 1.589 + bool jsop_bindname(PropertyName *name); 1.590 + bool jsop_getelem(); 1.591 + bool jsop_getelem_dense(MDefinition *obj, MDefinition *index); 1.592 + bool jsop_getelem_typed(MDefinition *obj, MDefinition *index, ScalarTypeDescr::Type arrayType); 1.593 + bool jsop_setelem(); 1.594 + bool jsop_setelem_dense(types::TemporaryTypeSet::DoubleConversion conversion, 1.595 + SetElemSafety safety, 1.596 + MDefinition *object, MDefinition *index, MDefinition *value); 1.597 + bool jsop_setelem_typed(ScalarTypeDescr::Type arrayType, 1.598 + SetElemSafety safety, 1.599 + MDefinition *object, MDefinition *index, MDefinition *value); 1.600 + bool jsop_setelem_typed_object(ScalarTypeDescr::Type arrayType, 1.601 + SetElemSafety safety, bool racy, 1.602 + MDefinition *object, MDefinition *index, MDefinition *value); 1.603 + bool jsop_length(); 1.604 + bool jsop_length_fastPath(); 1.605 + bool jsop_arguments(); 1.606 + bool jsop_arguments_length(); 1.607 + bool jsop_arguments_getelem(); 1.608 + bool jsop_runonce(); 1.609 + bool jsop_rest(); 1.610 + bool jsop_not(); 1.611 + bool jsop_getprop(PropertyName *name); 1.612 + bool jsop_setprop(PropertyName *name); 1.613 + bool jsop_delprop(PropertyName *name); 1.614 + bool jsop_delelem(); 1.615 + bool jsop_newarray(uint32_t count); 1.616 + bool jsop_newobject(); 1.617 + bool jsop_initelem(); 1.618 + bool jsop_initelem_array(); 1.619 + bool jsop_initelem_getter_setter(); 1.620 + bool jsop_mutateproto(); 1.621 + bool jsop_initprop(PropertyName *name); 1.622 + bool jsop_initprop_getter_setter(PropertyName *name); 1.623 + bool jsop_regexp(RegExpObject *reobj); 1.624 + bool jsop_object(JSObject *obj); 1.625 + bool jsop_lambda(JSFunction *fun); 1.626 + bool jsop_lambda_arrow(JSFunction *fun); 1.627 + bool jsop_this(); 1.628 + bool jsop_typeof(); 1.629 + bool jsop_toid(); 1.630 + bool jsop_iter(uint8_t flags); 1.631 + bool jsop_iternext(); 1.632 + bool jsop_itermore(); 1.633 + bool jsop_iterend(); 1.634 + bool jsop_in(); 1.635 + bool jsop_in_dense(); 1.636 + bool jsop_instanceof(); 1.637 + bool jsop_getaliasedvar(ScopeCoordinate sc); 1.638 + bool jsop_setaliasedvar(ScopeCoordinate sc); 1.639 + 1.640 + /* Inlining. */ 1.641 + 1.642 + enum InliningStatus 1.643 + { 1.644 + InliningStatus_Error, 1.645 + InliningStatus_NotInlined, 1.646 + InliningStatus_Inlined 1.647 + }; 1.648 + 1.649 + enum InliningDecision 1.650 + { 1.651 + InliningDecision_Error, 1.652 + InliningDecision_Inline, 1.653 + InliningDecision_DontInline 1.654 + }; 1.655 + 1.656 + static InliningDecision DontInline(JSScript *targetScript, const char *reason); 1.657 + 1.658 + // Oracles. 1.659 + InliningDecision canInlineTarget(JSFunction *target, CallInfo &callInfo); 1.660 + InliningDecision makeInliningDecision(JSFunction *target, CallInfo &callInfo); 1.661 + bool selectInliningTargets(ObjectVector &targets, CallInfo &callInfo, 1.662 + BoolVector &choiceSet, uint32_t *numInlineable); 1.663 + 1.664 + // Native inlining helpers. 1.665 + types::TemporaryTypeSet *getInlineReturnTypeSet(); 1.666 + MIRType getInlineReturnType(); 1.667 + 1.668 + // Array natives. 1.669 + InliningStatus inlineArray(CallInfo &callInfo); 1.670 + InliningStatus inlineArrayPopShift(CallInfo &callInfo, MArrayPopShift::Mode mode); 1.671 + InliningStatus inlineArrayPush(CallInfo &callInfo); 1.672 + InliningStatus inlineArrayConcat(CallInfo &callInfo); 1.673 + InliningStatus inlineArraySplice(CallInfo &callInfo); 1.674 + 1.675 + // Math natives. 1.676 + InliningStatus inlineMathAbs(CallInfo &callInfo); 1.677 + InliningStatus inlineMathFloor(CallInfo &callInfo); 1.678 + InliningStatus inlineMathCeil(CallInfo &callInfo); 1.679 + InliningStatus inlineMathRound(CallInfo &callInfo); 1.680 + InliningStatus inlineMathSqrt(CallInfo &callInfo); 1.681 + InliningStatus inlineMathAtan2(CallInfo &callInfo); 1.682 + InliningStatus inlineMathHypot(CallInfo &callInfo); 1.683 + InliningStatus inlineMathMinMax(CallInfo &callInfo, bool max); 1.684 + InliningStatus inlineMathPow(CallInfo &callInfo); 1.685 + InliningStatus inlineMathRandom(CallInfo &callInfo); 1.686 + InliningStatus inlineMathImul(CallInfo &callInfo); 1.687 + InliningStatus inlineMathFRound(CallInfo &callInfo); 1.688 + InliningStatus inlineMathFunction(CallInfo &callInfo, MMathFunction::Function function); 1.689 + 1.690 + // String natives. 1.691 + InliningStatus inlineStringObject(CallInfo &callInfo); 1.692 + InliningStatus inlineStringSplit(CallInfo &callInfo); 1.693 + InliningStatus inlineStrCharCodeAt(CallInfo &callInfo); 1.694 + InliningStatus inlineStrFromCharCode(CallInfo &callInfo); 1.695 + InliningStatus inlineStrCharAt(CallInfo &callInfo); 1.696 + InliningStatus inlineStrReplace(CallInfo &callInfo); 1.697 + 1.698 + // RegExp natives. 1.699 + InliningStatus inlineRegExpExec(CallInfo &callInfo); 1.700 + InliningStatus inlineRegExpTest(CallInfo &callInfo); 1.701 + 1.702 + // Array intrinsics. 1.703 + InliningStatus inlineUnsafePutElements(CallInfo &callInfo); 1.704 + bool inlineUnsafeSetDenseArrayElement(CallInfo &callInfo, uint32_t base); 1.705 + bool inlineUnsafeSetTypedArrayElement(CallInfo &callInfo, uint32_t base, 1.706 + ScalarTypeDescr::Type arrayType); 1.707 + bool inlineUnsafeSetTypedObjectArrayElement(CallInfo &callInfo, uint32_t base, 1.708 + ScalarTypeDescr::Type arrayType); 1.709 + InliningStatus inlineNewDenseArray(CallInfo &callInfo); 1.710 + InliningStatus inlineNewDenseArrayForSequentialExecution(CallInfo &callInfo); 1.711 + InliningStatus inlineNewDenseArrayForParallelExecution(CallInfo &callInfo); 1.712 + 1.713 + // Slot intrinsics. 1.714 + InliningStatus inlineUnsafeSetReservedSlot(CallInfo &callInfo); 1.715 + InliningStatus inlineUnsafeGetReservedSlot(CallInfo &callInfo); 1.716 + 1.717 + // ForkJoin intrinsics 1.718 + InliningStatus inlineForkJoinGetSlice(CallInfo &callInfo); 1.719 + 1.720 + // TypedObject intrinsics. 1.721 + InliningStatus inlineObjectIsTypeDescr(CallInfo &callInfo); 1.722 + InliningStatus inlineSetTypedObjectOffset(CallInfo &callInfo); 1.723 + bool elementAccessIsTypedObjectArrayOfScalarType(MDefinition* obj, MDefinition* id, 1.724 + ScalarTypeDescr::Type *arrayType); 1.725 + 1.726 + // Utility intrinsics. 1.727 + InliningStatus inlineIsCallable(CallInfo &callInfo); 1.728 + InliningStatus inlineHaveSameClass(CallInfo &callInfo); 1.729 + InliningStatus inlineToObject(CallInfo &callInfo); 1.730 + InliningStatus inlineDump(CallInfo &callInfo); 1.731 + InliningStatus inlineHasClass(CallInfo &callInfo, const Class *clasp) { 1.732 + return inlineHasClasses(callInfo, clasp, nullptr); 1.733 + } 1.734 + InliningStatus inlineHasClasses(CallInfo &callInfo, const Class *clasp1, const Class *clasp2); 1.735 + 1.736 + // Testing functions. 1.737 + InliningStatus inlineForceSequentialOrInParallelSection(CallInfo &callInfo); 1.738 + InliningStatus inlineBailout(CallInfo &callInfo); 1.739 + InliningStatus inlineAssertFloat32(CallInfo &callInfo); 1.740 + 1.741 + // Bind function. 1.742 + InliningStatus inlineBoundFunction(CallInfo &callInfo, JSFunction *target); 1.743 + 1.744 + // Main inlining functions 1.745 + InliningStatus inlineNativeCall(CallInfo &callInfo, JSFunction *target); 1.746 + bool inlineScriptedCall(CallInfo &callInfo, JSFunction *target); 1.747 + InliningStatus inlineSingleCall(CallInfo &callInfo, JSFunction *target); 1.748 + 1.749 + // Call functions 1.750 + InliningStatus inlineCallsite(ObjectVector &targets, ObjectVector &originals, 1.751 + bool lambda, CallInfo &callInfo); 1.752 + bool inlineCalls(CallInfo &callInfo, ObjectVector &targets, ObjectVector &originals, 1.753 + BoolVector &choiceSet, MGetPropertyCache *maybeCache); 1.754 + 1.755 + // Inlining helpers. 1.756 + bool inlineGenericFallback(JSFunction *target, CallInfo &callInfo, MBasicBlock *dispatchBlock, 1.757 + bool clonedAtCallsite); 1.758 + bool inlineTypeObjectFallback(CallInfo &callInfo, MBasicBlock *dispatchBlock, 1.759 + MTypeObjectDispatch *dispatch, MGetPropertyCache *cache, 1.760 + MBasicBlock **fallbackTarget); 1.761 + 1.762 + bool testNeedsArgumentCheck(JSFunction *target, CallInfo &callInfo); 1.763 + 1.764 + MDefinition *makeCallsiteClone(JSFunction *target, MDefinition *fun); 1.765 + MCall *makeCallHelper(JSFunction *target, CallInfo &callInfo, bool cloneAtCallsite); 1.766 + bool makeCall(JSFunction *target, CallInfo &callInfo, bool cloneAtCallsite); 1.767 + 1.768 + MDefinition *patchInlinedReturn(CallInfo &callInfo, MBasicBlock *exit, MBasicBlock *bottom); 1.769 + MDefinition *patchInlinedReturns(CallInfo &callInfo, MIRGraphReturns &returns, 1.770 + MBasicBlock *bottom); 1.771 + 1.772 + bool objectsHaveCommonPrototype(types::TemporaryTypeSet *types, PropertyName *name, 1.773 + bool isGetter, JSObject *foundProto); 1.774 + void freezePropertiesForCommonPrototype(types::TemporaryTypeSet *types, PropertyName *name, 1.775 + JSObject *foundProto); 1.776 + MDefinition *testCommonGetterSetter(types::TemporaryTypeSet *types, PropertyName *name, 1.777 + bool isGetter, JSObject *foundProto, Shape *lastProperty); 1.778 + bool testShouldDOMCall(types::TypeSet *inTypes, 1.779 + JSFunction *func, JSJitInfo::OpType opType); 1.780 + 1.781 + bool annotateGetPropertyCache(MDefinition *obj, MGetPropertyCache *getPropCache, 1.782 + types::TemporaryTypeSet *objTypes, 1.783 + types::TemporaryTypeSet *pushedTypes); 1.784 + 1.785 + MGetPropertyCache *getInlineableGetPropertyCache(CallInfo &callInfo); 1.786 + 1.787 + JSObject *testSingletonProperty(JSObject *obj, PropertyName *name); 1.788 + bool testSingletonPropertyTypes(MDefinition *obj, JSObject *singleton, PropertyName *name, 1.789 + bool *testObject, bool *testString); 1.790 + bool getDefiniteSlot(types::TemporaryTypeSet *types, PropertyName *name, 1.791 + types::HeapTypeSetKey *property); 1.792 + bool freezePropTypeSets(types::TemporaryTypeSet *types, 1.793 + JSObject *foundProto, PropertyName *name); 1.794 + 1.795 + types::TemporaryTypeSet *bytecodeTypes(jsbytecode *pc); 1.796 + 1.797 + // Use one of the below methods for updating the current block, rather than 1.798 + // updating |current| directly. setCurrent() should only be used in cases 1.799 + // where the block cannot have phis whose type needs to be computed. 1.800 + 1.801 + bool setCurrentAndSpecializePhis(MBasicBlock *block) { 1.802 + if (block) { 1.803 + if (!block->specializePhis()) 1.804 + return false; 1.805 + } 1.806 + setCurrent(block); 1.807 + return true; 1.808 + } 1.809 + 1.810 + void setCurrent(MBasicBlock *block) { 1.811 + current = block; 1.812 + } 1.813 + 1.814 + // A builder is inextricably tied to a particular script. 1.815 + JSScript *script_; 1.816 + 1.817 + // If off thread compilation is successful, the final code generator is 1.818 + // attached here. Code has been generated, but not linked (there is not yet 1.819 + // an IonScript). This is heap allocated, and must be explicitly destroyed, 1.820 + // performed by FinishOffThreadBuilder(). 1.821 + CodeGenerator *backgroundCodegen_; 1.822 + 1.823 + public: 1.824 + void clearForBackEnd(); 1.825 + 1.826 + JSScript *script() const { return script_; } 1.827 + 1.828 + CodeGenerator *backgroundCodegen() const { return backgroundCodegen_; } 1.829 + void setBackgroundCodegen(CodeGenerator *codegen) { backgroundCodegen_ = codegen; } 1.830 + 1.831 + AbortReason abortReason() { return abortReason_; } 1.832 + 1.833 + TypeDescrSetHash *getOrCreateDescrSetHash(); // fallible 1.834 + 1.835 + types::CompilerConstraintList *constraints() { 1.836 + return constraints_; 1.837 + } 1.838 + 1.839 + bool isInlineBuilder() const { 1.840 + return callerBuilder_ != nullptr; 1.841 + } 1.842 + 1.843 + const JSAtomState &names() { return compartment->runtime()->names(); } 1.844 + 1.845 + private: 1.846 + bool init(); 1.847 + 1.848 + JSContext *analysisContext; 1.849 + BaselineFrameInspector *baselineFrame_; 1.850 + AbortReason abortReason_; 1.851 + TypeDescrSetHash *descrSetHash_; 1.852 + 1.853 + // Constraints for recording dependencies on type information. 1.854 + types::CompilerConstraintList *constraints_; 1.855 + 1.856 + // Basic analysis information about the script. 1.857 + BytecodeAnalysis analysis_; 1.858 + BytecodeAnalysis &analysis() { 1.859 + return analysis_; 1.860 + } 1.861 + 1.862 + types::TemporaryTypeSet *thisTypes, *argTypes, *typeArray; 1.863 + uint32_t typeArrayHint; 1.864 + uint32_t *bytecodeTypeMap; 1.865 + 1.866 + GSNCache gsn; 1.867 + ScopeCoordinateNameCache scopeCoordinateNameCache; 1.868 + 1.869 + jsbytecode *pc; 1.870 + MBasicBlock *current; 1.871 + uint32_t loopDepth_; 1.872 + 1.873 + /* Information used for inline-call builders. */ 1.874 + MResumePoint *callerResumePoint_; 1.875 + jsbytecode *callerPC() { 1.876 + return callerResumePoint_ ? callerResumePoint_->pc() : nullptr; 1.877 + } 1.878 + IonBuilder *callerBuilder_; 1.879 + 1.880 + bool oom() { 1.881 + abortReason_ = AbortReason_Alloc; 1.882 + return false; 1.883 + } 1.884 + 1.885 + struct LoopHeader { 1.886 + jsbytecode *pc; 1.887 + MBasicBlock *header; 1.888 + 1.889 + LoopHeader(jsbytecode *pc, MBasicBlock *header) 1.890 + : pc(pc), header(header) 1.891 + {} 1.892 + }; 1.893 + 1.894 + Vector<CFGState, 8, IonAllocPolicy> cfgStack_; 1.895 + Vector<ControlFlowInfo, 4, IonAllocPolicy> loops_; 1.896 + Vector<ControlFlowInfo, 0, IonAllocPolicy> switches_; 1.897 + Vector<ControlFlowInfo, 2, IonAllocPolicy> labels_; 1.898 + Vector<MInstruction *, 2, IonAllocPolicy> iterators_; 1.899 + Vector<LoopHeader, 0, IonAllocPolicy> loopHeaders_; 1.900 + BaselineInspector *inspector; 1.901 + 1.902 + size_t inliningDepth_; 1.903 + 1.904 + // Cutoff to disable compilation if excessive time is spent reanalyzing 1.905 + // loop bodies to compute a fixpoint of the types for loop variables. 1.906 + static const size_t MAX_LOOP_RESTARTS = 40; 1.907 + size_t numLoopRestarts_; 1.908 + 1.909 + // True if script->failedBoundsCheck is set for the current script or 1.910 + // an outer script. 1.911 + bool failedBoundsCheck_; 1.912 + 1.913 + // True if script->failedShapeGuard is set for the current script or 1.914 + // an outer script. 1.915 + bool failedShapeGuard_; 1.916 + 1.917 + // Has an iterator other than 'for in'. 1.918 + bool nonStringIteration_; 1.919 + 1.920 + // If this script can use a lazy arguments object, it will be pre-created 1.921 + // here. 1.922 + MInstruction *lazyArguments_; 1.923 + 1.924 + // If this is an inline builder, the call info for the builder. 1.925 + const CallInfo *inlineCallInfo_; 1.926 +}; 1.927 + 1.928 +class CallInfo 1.929 +{ 1.930 + MDefinition *fun_; 1.931 + MDefinition *thisArg_; 1.932 + MDefinitionVector args_; 1.933 + 1.934 + bool constructing_; 1.935 + bool setter_; 1.936 + 1.937 + public: 1.938 + CallInfo(TempAllocator &alloc, bool constructing) 1.939 + : fun_(nullptr), 1.940 + thisArg_(nullptr), 1.941 + args_(alloc), 1.942 + constructing_(constructing), 1.943 + setter_(false) 1.944 + { } 1.945 + 1.946 + bool init(CallInfo &callInfo) { 1.947 + JS_ASSERT(constructing_ == callInfo.constructing()); 1.948 + 1.949 + fun_ = callInfo.fun(); 1.950 + thisArg_ = callInfo.thisArg(); 1.951 + 1.952 + if (!args_.appendAll(callInfo.argv())) 1.953 + return false; 1.954 + 1.955 + return true; 1.956 + } 1.957 + 1.958 + bool init(MBasicBlock *current, uint32_t argc) { 1.959 + JS_ASSERT(args_.empty()); 1.960 + 1.961 + // Get the arguments in the right order 1.962 + if (!args_.reserve(argc)) 1.963 + return false; 1.964 + for (int32_t i = argc; i > 0; i--) 1.965 + args_.infallibleAppend(current->peek(-i)); 1.966 + current->popn(argc); 1.967 + 1.968 + // Get |this| and |fun| 1.969 + setThis(current->pop()); 1.970 + setFun(current->pop()); 1.971 + 1.972 + return true; 1.973 + } 1.974 + 1.975 + void popFormals(MBasicBlock *current) { 1.976 + current->popn(numFormals()); 1.977 + } 1.978 + 1.979 + void pushFormals(MBasicBlock *current) { 1.980 + current->push(fun()); 1.981 + current->push(thisArg()); 1.982 + 1.983 + for (uint32_t i = 0; i < argc(); i++) 1.984 + current->push(getArg(i)); 1.985 + } 1.986 + 1.987 + uint32_t argc() const { 1.988 + return args_.length(); 1.989 + } 1.990 + uint32_t numFormals() const { 1.991 + return argc() + 2; 1.992 + } 1.993 + 1.994 + void setArgs(MDefinitionVector *args) { 1.995 + JS_ASSERT(args_.empty()); 1.996 + args_.appendAll(*args); 1.997 + } 1.998 + 1.999 + MDefinitionVector &argv() { 1.1000 + return args_; 1.1001 + } 1.1002 + 1.1003 + const MDefinitionVector &argv() const { 1.1004 + return args_; 1.1005 + } 1.1006 + 1.1007 + MDefinition *getArg(uint32_t i) const { 1.1008 + JS_ASSERT(i < argc()); 1.1009 + return args_[i]; 1.1010 + } 1.1011 + 1.1012 + void setArg(uint32_t i, MDefinition *def) { 1.1013 + JS_ASSERT(i < argc()); 1.1014 + args_[i] = def; 1.1015 + } 1.1016 + 1.1017 + MDefinition *thisArg() const { 1.1018 + JS_ASSERT(thisArg_); 1.1019 + return thisArg_; 1.1020 + } 1.1021 + 1.1022 + void setThis(MDefinition *thisArg) { 1.1023 + thisArg_ = thisArg; 1.1024 + } 1.1025 + 1.1026 + bool constructing() const { 1.1027 + return constructing_; 1.1028 + } 1.1029 + 1.1030 + bool isSetter() const { 1.1031 + return setter_; 1.1032 + } 1.1033 + void markAsSetter() { 1.1034 + setter_ = true; 1.1035 + } 1.1036 + 1.1037 + MDefinition *fun() const { 1.1038 + JS_ASSERT(fun_); 1.1039 + return fun_; 1.1040 + } 1.1041 + 1.1042 + void setFun(MDefinition *fun) { 1.1043 + fun_ = fun; 1.1044 + } 1.1045 + 1.1046 + void setImplicitlyUsedUnchecked() { 1.1047 + fun_->setImplicitlyUsedUnchecked(); 1.1048 + thisArg_->setImplicitlyUsedUnchecked(); 1.1049 + for (uint32_t i = 0; i < argc(); i++) 1.1050 + getArg(i)->setImplicitlyUsedUnchecked(); 1.1051 + } 1.1052 +}; 1.1053 + 1.1054 +bool TypeSetIncludes(types::TypeSet *types, MIRType input, types::TypeSet *inputTypes); 1.1055 + 1.1056 +bool NeedsPostBarrier(CompileInfo &info, MDefinition *value); 1.1057 + 1.1058 +} // namespace jit 1.1059 +} // namespace js 1.1060 + 1.1061 +#endif // JS_ION 1.1062 + 1.1063 +#endif /* jit_IonBuilder_h */