js/src/jit/IonBuilder.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
michael@0 2 * vim: set ts=8 sts=4 et sw=4 tw=99:
michael@0 3 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #ifndef jit_IonBuilder_h
michael@0 8 #define jit_IonBuilder_h
michael@0 9
michael@0 10 #ifdef JS_ION
michael@0 11
michael@0 12 // This file declares the data structures for building a MIRGraph from a
michael@0 13 // JSScript.
michael@0 14
michael@0 15 #include "jit/BytecodeAnalysis.h"
michael@0 16 #include "jit/IonOptimizationLevels.h"
michael@0 17 #include "jit/MIR.h"
michael@0 18 #include "jit/MIRGenerator.h"
michael@0 19 #include "jit/MIRGraph.h"
michael@0 20 #include "jit/TypeDescrSet.h"
michael@0 21
michael@0 22 namespace js {
michael@0 23 namespace jit {
michael@0 24
michael@0 25 class CodeGenerator;
michael@0 26 class CallInfo;
michael@0 27 class BaselineInspector;
michael@0 28 class BaselineFrameInspector;
michael@0 29
michael@0 30 // Records information about a baseline frame for compilation that is stable
michael@0 31 // when later used off thread.
michael@0 32 BaselineFrameInspector *
michael@0 33 NewBaselineFrameInspector(TempAllocator *temp, BaselineFrame *frame, CompileInfo *info);
michael@0 34
michael@0 35 class IonBuilder : public MIRGenerator
michael@0 36 {
michael@0 37 enum ControlStatus {
michael@0 38 ControlStatus_Error,
michael@0 39 ControlStatus_Abort,
michael@0 40 ControlStatus_Ended, // There is no continuation/join point.
michael@0 41 ControlStatus_Joined, // Created a join node.
michael@0 42 ControlStatus_Jumped, // Parsing another branch at the same level.
michael@0 43 ControlStatus_None // No control flow.
michael@0 44 };
michael@0 45
michael@0 46 enum SetElemSafety {
michael@0 47 // Normal write like a[b] = c.
michael@0 48 SetElem_Normal,
michael@0 49
michael@0 50 // Write due to UnsafePutElements:
michael@0 51 // - assumed to be in bounds,
michael@0 52 // - not checked for data races
michael@0 53 SetElem_Unsafe,
michael@0 54 };
michael@0 55
michael@0 56 struct DeferredEdge : public TempObject
michael@0 57 {
michael@0 58 MBasicBlock *block;
michael@0 59 DeferredEdge *next;
michael@0 60
michael@0 61 DeferredEdge(MBasicBlock *block, DeferredEdge *next)
michael@0 62 : block(block), next(next)
michael@0 63 { }
michael@0 64 };
michael@0 65
michael@0 66 struct ControlFlowInfo {
michael@0 67 // Entry in the cfgStack.
michael@0 68 uint32_t cfgEntry;
michael@0 69
michael@0 70 // Label that continues go to.
michael@0 71 jsbytecode *continuepc;
michael@0 72
michael@0 73 ControlFlowInfo(uint32_t cfgEntry, jsbytecode *continuepc)
michael@0 74 : cfgEntry(cfgEntry),
michael@0 75 continuepc(continuepc)
michael@0 76 { }
michael@0 77 };
michael@0 78
michael@0 79 // To avoid recursion, the bytecode analyzer uses a stack where each entry
michael@0 80 // is a small state machine. As we encounter branches or jumps in the
michael@0 81 // bytecode, we push information about the edges on the stack so that the
michael@0 82 // CFG can be built in a tree-like fashion.
michael@0 83 struct CFGState {
michael@0 84 enum State {
michael@0 85 IF_TRUE, // if() { }, no else.
michael@0 86 IF_TRUE_EMPTY_ELSE, // if() { }, empty else
michael@0 87 IF_ELSE_TRUE, // if() { X } else { }
michael@0 88 IF_ELSE_FALSE, // if() { } else { X }
michael@0 89 DO_WHILE_LOOP_BODY, // do { x } while ()
michael@0 90 DO_WHILE_LOOP_COND, // do { } while (x)
michael@0 91 WHILE_LOOP_COND, // while (x) { }
michael@0 92 WHILE_LOOP_BODY, // while () { x }
michael@0 93 FOR_LOOP_COND, // for (; x;) { }
michael@0 94 FOR_LOOP_BODY, // for (; ;) { x }
michael@0 95 FOR_LOOP_UPDATE, // for (; ; x) { }
michael@0 96 TABLE_SWITCH, // switch() { x }
michael@0 97 COND_SWITCH_CASE, // switch() { case X: ... }
michael@0 98 COND_SWITCH_BODY, // switch() { case ...: X }
michael@0 99 AND_OR, // && x, || x
michael@0 100 LABEL, // label: x
michael@0 101 TRY // try { x } catch(e) { }
michael@0 102 };
michael@0 103
michael@0 104 State state; // Current state of this control structure.
michael@0 105 jsbytecode *stopAt; // Bytecode at which to stop the processing loop.
michael@0 106
michael@0 107 // For if structures, this contains branch information.
michael@0 108 union {
michael@0 109 struct {
michael@0 110 MBasicBlock *ifFalse;
michael@0 111 jsbytecode *falseEnd;
michael@0 112 MBasicBlock *ifTrue; // Set when the end of the true path is reached.
michael@0 113 MTest *test;
michael@0 114 } branch;
michael@0 115 struct {
michael@0 116 // Common entry point.
michael@0 117 MBasicBlock *entry;
michael@0 118
michael@0 119 // Whether OSR is being performed for this loop.
michael@0 120 bool osr;
michael@0 121
michael@0 122 // Position of where the loop body starts and ends.
michael@0 123 jsbytecode *bodyStart;
michael@0 124 jsbytecode *bodyEnd;
michael@0 125
michael@0 126 // pc immediately after the loop exits.
michael@0 127 jsbytecode *exitpc;
michael@0 128
michael@0 129 // pc for 'continue' jumps.
michael@0 130 jsbytecode *continuepc;
michael@0 131
michael@0 132 // Common exit point. Created lazily, so it may be nullptr.
michael@0 133 MBasicBlock *successor;
michael@0 134
michael@0 135 // Deferred break and continue targets.
michael@0 136 DeferredEdge *breaks;
michael@0 137 DeferredEdge *continues;
michael@0 138
michael@0 139 // Initial state, in case loop processing is restarted.
michael@0 140 State initialState;
michael@0 141 jsbytecode *initialPc;
michael@0 142 jsbytecode *initialStopAt;
michael@0 143 jsbytecode *loopHead;
michael@0 144
michael@0 145 // For-loops only.
michael@0 146 jsbytecode *condpc;
michael@0 147 jsbytecode *updatepc;
michael@0 148 jsbytecode *updateEnd;
michael@0 149 } loop;
michael@0 150 struct {
michael@0 151 // pc immediately after the switch.
michael@0 152 jsbytecode *exitpc;
michael@0 153
michael@0 154 // Deferred break and continue targets.
michael@0 155 DeferredEdge *breaks;
michael@0 156
michael@0 157 // MIR instruction
michael@0 158 MTableSwitch *ins;
michael@0 159
michael@0 160 // The number of current successor that get mapped into a block.
michael@0 161 uint32_t currentBlock;
michael@0 162
michael@0 163 } tableswitch;
michael@0 164 struct {
michael@0 165 // Vector of body blocks to process after the cases.
michael@0 166 FixedList<MBasicBlock *> *bodies;
michael@0 167
michael@0 168 // When processing case statements, this counter points at the
michael@0 169 // last uninitialized body. When processing bodies, this
michael@0 170 // counter targets the next body to process.
michael@0 171 uint32_t currentIdx;
michael@0 172
michael@0 173 // Remember the block index of the default case.
michael@0 174 jsbytecode *defaultTarget;
michael@0 175 uint32_t defaultIdx;
michael@0 176
michael@0 177 // Block immediately after the switch.
michael@0 178 jsbytecode *exitpc;
michael@0 179 DeferredEdge *breaks;
michael@0 180 } condswitch;
michael@0 181 struct {
michael@0 182 DeferredEdge *breaks;
michael@0 183 } label;
michael@0 184 struct {
michael@0 185 MBasicBlock *successor;
michael@0 186 } try_;
michael@0 187 };
michael@0 188
michael@0 189 inline bool isLoop() const {
michael@0 190 switch (state) {
michael@0 191 case DO_WHILE_LOOP_COND:
michael@0 192 case DO_WHILE_LOOP_BODY:
michael@0 193 case WHILE_LOOP_COND:
michael@0 194 case WHILE_LOOP_BODY:
michael@0 195 case FOR_LOOP_COND:
michael@0 196 case FOR_LOOP_BODY:
michael@0 197 case FOR_LOOP_UPDATE:
michael@0 198 return true;
michael@0 199 default:
michael@0 200 return false;
michael@0 201 }
michael@0 202 }
michael@0 203
michael@0 204 static CFGState If(jsbytecode *join, MTest *test);
michael@0 205 static CFGState IfElse(jsbytecode *trueEnd, jsbytecode *falseEnd, MTest *test);
michael@0 206 static CFGState AndOr(jsbytecode *join, MBasicBlock *joinStart);
michael@0 207 static CFGState TableSwitch(jsbytecode *exitpc, MTableSwitch *ins);
michael@0 208 static CFGState CondSwitch(IonBuilder *builder, jsbytecode *exitpc, jsbytecode *defaultTarget);
michael@0 209 static CFGState Label(jsbytecode *exitpc);
michael@0 210 static CFGState Try(jsbytecode *exitpc, MBasicBlock *successor);
michael@0 211 };
michael@0 212
michael@0 213 static int CmpSuccessors(const void *a, const void *b);
michael@0 214
michael@0 215 public:
michael@0 216 IonBuilder(JSContext *analysisContext, CompileCompartment *comp,
michael@0 217 const JitCompileOptions &options, TempAllocator *temp,
michael@0 218 MIRGraph *graph, types::CompilerConstraintList *constraints,
michael@0 219 BaselineInspector *inspector, CompileInfo *info,
michael@0 220 const OptimizationInfo *optimizationInfo, BaselineFrameInspector *baselineFrame,
michael@0 221 size_t inliningDepth = 0, uint32_t loopDepth = 0);
michael@0 222
michael@0 223 bool build();
michael@0 224 bool buildInline(IonBuilder *callerBuilder, MResumePoint *callerResumePoint,
michael@0 225 CallInfo &callInfo);
michael@0 226
michael@0 227 private:
michael@0 228 bool traverseBytecode();
michael@0 229 ControlStatus snoopControlFlow(JSOp op);
michael@0 230 bool processIterators();
michael@0 231 bool inspectOpcode(JSOp op);
michael@0 232 uint32_t readIndex(jsbytecode *pc);
michael@0 233 JSAtom *readAtom(jsbytecode *pc);
michael@0 234 bool abort(const char *message, ...);
michael@0 235 void spew(const char *message);
michael@0 236
michael@0 237 JSFunction *getSingleCallTarget(types::TemporaryTypeSet *calleeTypes);
michael@0 238 bool getPolyCallTargets(types::TemporaryTypeSet *calleeTypes, bool constructing,
michael@0 239 ObjectVector &targets, uint32_t maxTargets, bool *gotLambda);
michael@0 240
michael@0 241 void popCfgStack();
michael@0 242 DeferredEdge *filterDeadDeferredEdges(DeferredEdge *edge);
michael@0 243 bool processDeferredContinues(CFGState &state);
michael@0 244 ControlStatus processControlEnd();
michael@0 245 ControlStatus processCfgStack();
michael@0 246 ControlStatus processCfgEntry(CFGState &state);
michael@0 247 ControlStatus processIfEnd(CFGState &state);
michael@0 248 ControlStatus processIfElseTrueEnd(CFGState &state);
michael@0 249 ControlStatus processIfElseFalseEnd(CFGState &state);
michael@0 250 ControlStatus processDoWhileBodyEnd(CFGState &state);
michael@0 251 ControlStatus processDoWhileCondEnd(CFGState &state);
michael@0 252 ControlStatus processWhileCondEnd(CFGState &state);
michael@0 253 ControlStatus processWhileBodyEnd(CFGState &state);
michael@0 254 ControlStatus processForCondEnd(CFGState &state);
michael@0 255 ControlStatus processForBodyEnd(CFGState &state);
michael@0 256 ControlStatus processForUpdateEnd(CFGState &state);
michael@0 257 ControlStatus processNextTableSwitchCase(CFGState &state);
michael@0 258 ControlStatus processCondSwitchCase(CFGState &state);
michael@0 259 ControlStatus processCondSwitchBody(CFGState &state);
michael@0 260 ControlStatus processSwitchBreak(JSOp op);
michael@0 261 ControlStatus processSwitchEnd(DeferredEdge *breaks, jsbytecode *exitpc);
michael@0 262 ControlStatus processAndOrEnd(CFGState &state);
michael@0 263 ControlStatus processLabelEnd(CFGState &state);
michael@0 264 ControlStatus processTryEnd(CFGState &state);
michael@0 265 ControlStatus processReturn(JSOp op);
michael@0 266 ControlStatus processThrow();
michael@0 267 ControlStatus processContinue(JSOp op);
michael@0 268 ControlStatus processBreak(JSOp op, jssrcnote *sn);
michael@0 269 ControlStatus maybeLoop(JSOp op, jssrcnote *sn);
michael@0 270 bool pushLoop(CFGState::State state, jsbytecode *stopAt, MBasicBlock *entry, bool osr,
michael@0 271 jsbytecode *loopHead, jsbytecode *initialPc,
michael@0 272 jsbytecode *bodyStart, jsbytecode *bodyEnd, jsbytecode *exitpc,
michael@0 273 jsbytecode *continuepc = nullptr);
michael@0 274 bool analyzeNewLoopTypes(MBasicBlock *entry, jsbytecode *start, jsbytecode *end);
michael@0 275
michael@0 276 MBasicBlock *addBlock(MBasicBlock *block, uint32_t loopDepth);
michael@0 277 MBasicBlock *newBlock(MBasicBlock *predecessor, jsbytecode *pc);
michael@0 278 MBasicBlock *newBlock(MBasicBlock *predecessor, jsbytecode *pc, uint32_t loopDepth);
michael@0 279 MBasicBlock *newBlock(MBasicBlock *predecessor, jsbytecode *pc, MResumePoint *priorResumePoint);
michael@0 280 MBasicBlock *newBlockPopN(MBasicBlock *predecessor, jsbytecode *pc, uint32_t popped);
michael@0 281 MBasicBlock *newBlockAfter(MBasicBlock *at, MBasicBlock *predecessor, jsbytecode *pc);
michael@0 282 MBasicBlock *newOsrPreheader(MBasicBlock *header, jsbytecode *loopEntry);
michael@0 283 MBasicBlock *newPendingLoopHeader(MBasicBlock *predecessor, jsbytecode *pc, bool osr, bool canOsr,
michael@0 284 unsigned stackPhiCount);
michael@0 285 MBasicBlock *newBlock(jsbytecode *pc) {
michael@0 286 return newBlock(nullptr, pc);
michael@0 287 }
michael@0 288 MBasicBlock *newBlockAfter(MBasicBlock *at, jsbytecode *pc) {
michael@0 289 return newBlockAfter(at, nullptr, pc);
michael@0 290 }
michael@0 291
michael@0 292 // Given a list of pending breaks, creates a new block and inserts a Goto
michael@0 293 // linking each break to the new block.
michael@0 294 MBasicBlock *createBreakCatchBlock(DeferredEdge *edge, jsbytecode *pc);
michael@0 295
michael@0 296 // Finishes loops that do not actually loop, containing only breaks and
michael@0 297 // returns or a do while loop with a condition that is constant false.
michael@0 298 ControlStatus processBrokenLoop(CFGState &state);
michael@0 299
michael@0 300 // Computes loop phis, places them in all successors of a loop, then
michael@0 301 // handles any pending breaks.
michael@0 302 ControlStatus finishLoop(CFGState &state, MBasicBlock *successor);
michael@0 303
michael@0 304 // Incorporates a type/typeSet into an OSR value for a loop, after the loop
michael@0 305 // body has been processed.
michael@0 306 bool addOsrValueTypeBarrier(uint32_t slot, MInstruction **def,
michael@0 307 MIRType type, types::TemporaryTypeSet *typeSet);
michael@0 308 bool maybeAddOsrTypeBarriers();
michael@0 309
michael@0 310 // Restarts processing of a loop if the type information at its header was
michael@0 311 // incomplete.
michael@0 312 ControlStatus restartLoop(CFGState state);
michael@0 313
michael@0 314 void assertValidLoopHeadOp(jsbytecode *pc);
michael@0 315
michael@0 316 ControlStatus forLoop(JSOp op, jssrcnote *sn);
michael@0 317 ControlStatus whileOrForInLoop(jssrcnote *sn);
michael@0 318 ControlStatus doWhileLoop(JSOp op, jssrcnote *sn);
michael@0 319 ControlStatus tableSwitch(JSOp op, jssrcnote *sn);
michael@0 320 ControlStatus condSwitch(JSOp op, jssrcnote *sn);
michael@0 321
michael@0 322 // Please see the Big Honkin' Comment about how resume points work in
michael@0 323 // IonBuilder.cpp, near the definition for this function.
michael@0 324 bool resume(MInstruction *ins, jsbytecode *pc, MResumePoint::Mode mode);
michael@0 325 bool resumeAt(MInstruction *ins, jsbytecode *pc);
michael@0 326 bool resumeAfter(MInstruction *ins);
michael@0 327 bool maybeInsertResume();
michael@0 328
michael@0 329 void insertRecompileCheck();
michael@0 330
michael@0 331 void initParameters();
michael@0 332 void rewriteParameter(uint32_t slotIdx, MDefinition *param, int32_t argIndex);
michael@0 333 void rewriteParameters();
michael@0 334 bool initScopeChain(MDefinition *callee = nullptr);
michael@0 335 bool initArgumentsObject();
michael@0 336 bool pushConstant(const Value &v);
michael@0 337
michael@0 338 MConstant *constant(const Value &v);
michael@0 339 MConstant *constantInt(int32_t i);
michael@0 340
michael@0 341 // Filter the type information at tests
michael@0 342 bool filterTypesAtTest(MTest *test);
michael@0 343
michael@0 344 // Add a guard which ensure that the set of type which goes through this
michael@0 345 // generated code correspond to the observed types for the bytecode.
michael@0 346 bool pushTypeBarrier(MDefinition *def, types::TemporaryTypeSet *observed, bool needBarrier);
michael@0 347
michael@0 348 // As pushTypeBarrier, but will compute the needBarrier boolean itself based
michael@0 349 // on observed and the JSFunction that we're planning to call. The
michael@0 350 // JSFunction must be a DOM method or getter.
michael@0 351 bool pushDOMTypeBarrier(MInstruction *ins, types::TemporaryTypeSet *observed, JSFunction* func);
michael@0 352
michael@0 353 // If definiteType is not known or def already has the right type, just
michael@0 354 // returns def. Otherwise, returns an MInstruction that has that definite
michael@0 355 // type, infallibly unboxing ins as needed. The new instruction will be
michael@0 356 // added to |current| in this case.
michael@0 357 MDefinition *ensureDefiniteType(MDefinition* def, MIRType definiteType);
michael@0 358
michael@0 359 // Creates a MDefinition based on the given def improved with type as TypeSet.
michael@0 360 MDefinition *ensureDefiniteTypeSet(MDefinition* def, types::TemporaryTypeSet *types);
michael@0 361
michael@0 362 JSObject *getSingletonPrototype(JSFunction *target);
michael@0 363
michael@0 364 MDefinition *createThisScripted(MDefinition *callee);
michael@0 365 MDefinition *createThisScriptedSingleton(JSFunction *target, MDefinition *callee);
michael@0 366 MDefinition *createThis(JSFunction *target, MDefinition *callee);
michael@0 367 MInstruction *createDeclEnvObject(MDefinition *callee, MDefinition *scopeObj);
michael@0 368 MInstruction *createCallObject(MDefinition *callee, MDefinition *scopeObj);
michael@0 369
michael@0 370 MDefinition *walkScopeChain(unsigned hops);
michael@0 371
michael@0 372 MInstruction *addConvertElementsToDoubles(MDefinition *elements);
michael@0 373 MInstruction *addBoundsCheck(MDefinition *index, MDefinition *length);
michael@0 374 MInstruction *addShapeGuard(MDefinition *obj, Shape *const shape, BailoutKind bailoutKind);
michael@0 375
michael@0 376 MDefinition *convertShiftToMaskForStaticTypedArray(MDefinition *id,
michael@0 377 ArrayBufferView::ViewType viewType);
michael@0 378
michael@0 379 bool invalidatedIdempotentCache();
michael@0 380
michael@0 381 bool hasStaticScopeObject(ScopeCoordinate sc, JSObject **pcall);
michael@0 382 bool loadSlot(MDefinition *obj, size_t slot, size_t nfixed, MIRType rvalType,
michael@0 383 bool barrier, types::TemporaryTypeSet *types);
michael@0 384 bool loadSlot(MDefinition *obj, Shape *shape, MIRType rvalType,
michael@0 385 bool barrier, types::TemporaryTypeSet *types);
michael@0 386 bool storeSlot(MDefinition *obj, size_t slot, size_t nfixed,
michael@0 387 MDefinition *value, bool needsBarrier,
michael@0 388 MIRType slotType = MIRType_None);
michael@0 389 bool storeSlot(MDefinition *obj, Shape *shape, MDefinition *value, bool needsBarrier,
michael@0 390 MIRType slotType = MIRType_None);
michael@0 391
michael@0 392 // jsop_getprop() helpers.
michael@0 393 bool getPropTryArgumentsLength(bool *emitted);
michael@0 394 bool getPropTryConstant(bool *emitted, PropertyName *name,
michael@0 395 types::TemporaryTypeSet *types);
michael@0 396 bool getPropTryDefiniteSlot(bool *emitted, PropertyName *name,
michael@0 397 bool barrier, types::TemporaryTypeSet *types);
michael@0 398 bool getPropTryCommonGetter(bool *emitted, PropertyName *name,
michael@0 399 types::TemporaryTypeSet *types);
michael@0 400 bool getPropTryInlineAccess(bool *emitted, PropertyName *name,
michael@0 401 bool barrier, types::TemporaryTypeSet *types);
michael@0 402 bool getPropTryTypedObject(bool *emitted, PropertyName *name,
michael@0 403 types::TemporaryTypeSet *resultTypes);
michael@0 404 bool getPropTryScalarPropOfTypedObject(bool *emitted,
michael@0 405 int32_t fieldOffset,
michael@0 406 TypeDescrSet fieldTypeReprs,
michael@0 407 types::TemporaryTypeSet *resultTypes);
michael@0 408 bool getPropTryComplexPropOfTypedObject(bool *emitted,
michael@0 409 int32_t fieldOffset,
michael@0 410 TypeDescrSet fieldTypeReprs,
michael@0 411 size_t fieldIndex,
michael@0 412 types::TemporaryTypeSet *resultTypes);
michael@0 413 bool getPropTryCache(bool *emitted, PropertyName *name,
michael@0 414 bool barrier, types::TemporaryTypeSet *types);
michael@0 415 bool needsToMonitorMissingProperties(types::TemporaryTypeSet *types);
michael@0 416
michael@0 417 // jsop_setprop() helpers.
michael@0 418 bool setPropTryCommonSetter(bool *emitted, MDefinition *obj,
michael@0 419 PropertyName *name, MDefinition *value);
michael@0 420 bool setPropTryCommonDOMSetter(bool *emitted, MDefinition *obj,
michael@0 421 MDefinition *value, JSFunction *setter,
michael@0 422 bool isDOM);
michael@0 423 bool setPropTryDefiniteSlot(bool *emitted, MDefinition *obj,
michael@0 424 PropertyName *name, MDefinition *value,
michael@0 425 bool barrier, types::TemporaryTypeSet *objTypes);
michael@0 426 bool setPropTryInlineAccess(bool *emitted, MDefinition *obj,
michael@0 427 PropertyName *name, MDefinition *value, bool barrier,
michael@0 428 types::TemporaryTypeSet *objTypes);
michael@0 429 bool setPropTryTypedObject(bool *emitted, MDefinition *obj,
michael@0 430 PropertyName *name, MDefinition *value);
michael@0 431 bool setPropTryScalarPropOfTypedObject(bool *emitted,
michael@0 432 MDefinition *obj,
michael@0 433 int32_t fieldOffset,
michael@0 434 MDefinition *value,
michael@0 435 TypeDescrSet fieldTypeReprs);
michael@0 436 bool setPropTryCache(bool *emitted, MDefinition *obj,
michael@0 437 PropertyName *name, MDefinition *value,
michael@0 438 bool barrier, types::TemporaryTypeSet *objTypes);
michael@0 439
michael@0 440 // binary data lookup helpers.
michael@0 441 bool lookupTypeDescrSet(MDefinition *typedObj,
michael@0 442 TypeDescrSet *out);
michael@0 443 bool typeSetToTypeDescrSet(types::TemporaryTypeSet *types,
michael@0 444 TypeDescrSet *out);
michael@0 445 bool lookupTypedObjectField(MDefinition *typedObj,
michael@0 446 PropertyName *name,
michael@0 447 int32_t *fieldOffset,
michael@0 448 TypeDescrSet *fieldTypeReprs,
michael@0 449 size_t *fieldIndex);
michael@0 450 MDefinition *loadTypedObjectType(MDefinition *value);
michael@0 451 void loadTypedObjectData(MDefinition *typedObj,
michael@0 452 MDefinition *offset,
michael@0 453 bool canBeNeutered,
michael@0 454 MDefinition **owner,
michael@0 455 MDefinition **ownerOffset);
michael@0 456 void loadTypedObjectElements(MDefinition *typedObj,
michael@0 457 MDefinition *offset,
michael@0 458 int32_t unit,
michael@0 459 bool canBeNeutered,
michael@0 460 MDefinition **ownerElements,
michael@0 461 MDefinition **ownerScaledOffset);
michael@0 462 MDefinition *typeObjectForElementFromArrayStructType(MDefinition *typedObj);
michael@0 463 MDefinition *typeObjectForFieldFromStructType(MDefinition *type,
michael@0 464 size_t fieldIndex);
michael@0 465 bool storeScalarTypedObjectValue(MDefinition *typedObj,
michael@0 466 MDefinition *offset,
michael@0 467 ScalarTypeDescr::Type type,
michael@0 468 bool canBeNeutered,
michael@0 469 bool racy,
michael@0 470 MDefinition *value);
michael@0 471 bool checkTypedObjectIndexInBounds(int32_t elemSize,
michael@0 472 MDefinition *obj,
michael@0 473 MDefinition *index,
michael@0 474 TypeDescrSet objTypeDescrs,
michael@0 475 MDefinition **indexAsByteOffset,
michael@0 476 bool *canBeNeutered);
michael@0 477 bool pushDerivedTypedObject(bool *emitted,
michael@0 478 MDefinition *obj,
michael@0 479 MDefinition *offset,
michael@0 480 TypeDescrSet derivedTypeDescrs,
michael@0 481 MDefinition *derivedTypeObj,
michael@0 482 bool canBeNeutered);
michael@0 483 bool pushScalarLoadFromTypedObject(bool *emitted,
michael@0 484 MDefinition *obj,
michael@0 485 MDefinition *offset,
michael@0 486 ScalarTypeDescr::Type type,
michael@0 487 bool canBeNeutered);
michael@0 488 MDefinition *neuterCheck(MDefinition *obj);
michael@0 489
michael@0 490 // jsop_setelem() helpers.
michael@0 491 bool setElemTryTypedArray(bool *emitted, MDefinition *object,
michael@0 492 MDefinition *index, MDefinition *value);
michael@0 493 bool setElemTryTypedObject(bool *emitted, MDefinition *obj,
michael@0 494 MDefinition *index, MDefinition *value);
michael@0 495 bool setElemTryTypedStatic(bool *emitted, MDefinition *object,
michael@0 496 MDefinition *index, MDefinition *value);
michael@0 497 bool setElemTryDense(bool *emitted, MDefinition *object,
michael@0 498 MDefinition *index, MDefinition *value);
michael@0 499 bool setElemTryArguments(bool *emitted, MDefinition *object,
michael@0 500 MDefinition *index, MDefinition *value);
michael@0 501 bool setElemTryCache(bool *emitted, MDefinition *object,
michael@0 502 MDefinition *index, MDefinition *value);
michael@0 503 bool setElemTryScalarElemOfTypedObject(bool *emitted,
michael@0 504 MDefinition *obj,
michael@0 505 MDefinition *index,
michael@0 506 TypeDescrSet objTypeReprs,
michael@0 507 MDefinition *value,
michael@0 508 TypeDescrSet elemTypeReprs,
michael@0 509 int32_t elemSize);
michael@0 510
michael@0 511 // jsop_getelem() helpers.
michael@0 512 bool getElemTryDense(bool *emitted, MDefinition *obj, MDefinition *index);
michael@0 513 bool getElemTryTypedStatic(bool *emitted, MDefinition *obj, MDefinition *index);
michael@0 514 bool getElemTryTypedArray(bool *emitted, MDefinition *obj, MDefinition *index);
michael@0 515 bool getElemTryTypedObject(bool *emitted, MDefinition *obj, MDefinition *index);
michael@0 516 bool getElemTryString(bool *emitted, MDefinition *obj, MDefinition *index);
michael@0 517 bool getElemTryArguments(bool *emitted, MDefinition *obj, MDefinition *index);
michael@0 518 bool getElemTryArgumentsInlined(bool *emitted, MDefinition *obj, MDefinition *index);
michael@0 519 bool getElemTryCache(bool *emitted, MDefinition *obj, MDefinition *index);
michael@0 520 bool getElemTryScalarElemOfTypedObject(bool *emitted,
michael@0 521 MDefinition *obj,
michael@0 522 MDefinition *index,
michael@0 523 TypeDescrSet objTypeReprs,
michael@0 524 TypeDescrSet elemTypeReprs,
michael@0 525 int32_t elemSize);
michael@0 526 bool getElemTryComplexElemOfTypedObject(bool *emitted,
michael@0 527 MDefinition *obj,
michael@0 528 MDefinition *index,
michael@0 529 TypeDescrSet objTypeReprs,
michael@0 530 TypeDescrSet elemTypeReprs,
michael@0 531 int32_t elemSize);
michael@0 532
michael@0 533 enum BoundsChecking { DoBoundsCheck, SkipBoundsCheck };
michael@0 534
michael@0 535 // Add instructions to compute a typed array's length and data. Also
michael@0 536 // optionally convert |*index| into a bounds-checked definition, if
michael@0 537 // requested.
michael@0 538 //
michael@0 539 // If you only need the array's length, use addTypedArrayLength below.
michael@0 540 void addTypedArrayLengthAndData(MDefinition *obj,
michael@0 541 BoundsChecking checking,
michael@0 542 MDefinition **index,
michael@0 543 MInstruction **length, MInstruction **elements);
michael@0 544
michael@0 545 // Add an instruction to compute a typed array's length to the current
michael@0 546 // block. If you also need the typed array's data, use the above method
michael@0 547 // instead.
michael@0 548 MInstruction *addTypedArrayLength(MDefinition *obj) {
michael@0 549 MInstruction *length;
michael@0 550 addTypedArrayLengthAndData(obj, SkipBoundsCheck, nullptr, &length, nullptr);
michael@0 551 return length;
michael@0 552 }
michael@0 553
michael@0 554
michael@0 555 MDefinition *getCallee();
michael@0 556
michael@0 557 bool jsop_add(MDefinition *left, MDefinition *right);
michael@0 558 bool jsop_bitnot();
michael@0 559 bool jsop_bitop(JSOp op);
michael@0 560 bool jsop_binary(JSOp op);
michael@0 561 bool jsop_binary(JSOp op, MDefinition *left, MDefinition *right);
michael@0 562 bool jsop_pos();
michael@0 563 bool jsop_neg();
michael@0 564 bool jsop_setarg(uint32_t arg);
michael@0 565 bool jsop_defvar(uint32_t index);
michael@0 566 bool jsop_deffun(uint32_t index);
michael@0 567 bool jsop_notearg();
michael@0 568 bool jsop_funcall(uint32_t argc);
michael@0 569 bool jsop_funapply(uint32_t argc);
michael@0 570 bool jsop_funapplyarguments(uint32_t argc);
michael@0 571 bool jsop_call(uint32_t argc, bool constructing);
michael@0 572 bool jsop_eval(uint32_t argc);
michael@0 573 bool jsop_ifeq(JSOp op);
michael@0 574 bool jsop_try();
michael@0 575 bool jsop_label();
michael@0 576 bool jsop_condswitch();
michael@0 577 bool jsop_andor(JSOp op);
michael@0 578 bool jsop_dup2();
michael@0 579 bool jsop_loophead(jsbytecode *pc);
michael@0 580 bool jsop_compare(JSOp op);
michael@0 581 bool getStaticName(JSObject *staticObject, PropertyName *name, bool *psucceeded);
michael@0 582 bool setStaticName(JSObject *staticObject, PropertyName *name);
michael@0 583 bool jsop_getgname(PropertyName *name);
michael@0 584 bool jsop_getname(PropertyName *name);
michael@0 585 bool jsop_intrinsic(PropertyName *name);
michael@0 586 bool jsop_bindname(PropertyName *name);
michael@0 587 bool jsop_getelem();
michael@0 588 bool jsop_getelem_dense(MDefinition *obj, MDefinition *index);
michael@0 589 bool jsop_getelem_typed(MDefinition *obj, MDefinition *index, ScalarTypeDescr::Type arrayType);
michael@0 590 bool jsop_setelem();
michael@0 591 bool jsop_setelem_dense(types::TemporaryTypeSet::DoubleConversion conversion,
michael@0 592 SetElemSafety safety,
michael@0 593 MDefinition *object, MDefinition *index, MDefinition *value);
michael@0 594 bool jsop_setelem_typed(ScalarTypeDescr::Type arrayType,
michael@0 595 SetElemSafety safety,
michael@0 596 MDefinition *object, MDefinition *index, MDefinition *value);
michael@0 597 bool jsop_setelem_typed_object(ScalarTypeDescr::Type arrayType,
michael@0 598 SetElemSafety safety, bool racy,
michael@0 599 MDefinition *object, MDefinition *index, MDefinition *value);
michael@0 600 bool jsop_length();
michael@0 601 bool jsop_length_fastPath();
michael@0 602 bool jsop_arguments();
michael@0 603 bool jsop_arguments_length();
michael@0 604 bool jsop_arguments_getelem();
michael@0 605 bool jsop_runonce();
michael@0 606 bool jsop_rest();
michael@0 607 bool jsop_not();
michael@0 608 bool jsop_getprop(PropertyName *name);
michael@0 609 bool jsop_setprop(PropertyName *name);
michael@0 610 bool jsop_delprop(PropertyName *name);
michael@0 611 bool jsop_delelem();
michael@0 612 bool jsop_newarray(uint32_t count);
michael@0 613 bool jsop_newobject();
michael@0 614 bool jsop_initelem();
michael@0 615 bool jsop_initelem_array();
michael@0 616 bool jsop_initelem_getter_setter();
michael@0 617 bool jsop_mutateproto();
michael@0 618 bool jsop_initprop(PropertyName *name);
michael@0 619 bool jsop_initprop_getter_setter(PropertyName *name);
michael@0 620 bool jsop_regexp(RegExpObject *reobj);
michael@0 621 bool jsop_object(JSObject *obj);
michael@0 622 bool jsop_lambda(JSFunction *fun);
michael@0 623 bool jsop_lambda_arrow(JSFunction *fun);
michael@0 624 bool jsop_this();
michael@0 625 bool jsop_typeof();
michael@0 626 bool jsop_toid();
michael@0 627 bool jsop_iter(uint8_t flags);
michael@0 628 bool jsop_iternext();
michael@0 629 bool jsop_itermore();
michael@0 630 bool jsop_iterend();
michael@0 631 bool jsop_in();
michael@0 632 bool jsop_in_dense();
michael@0 633 bool jsop_instanceof();
michael@0 634 bool jsop_getaliasedvar(ScopeCoordinate sc);
michael@0 635 bool jsop_setaliasedvar(ScopeCoordinate sc);
michael@0 636
michael@0 637 /* Inlining. */
michael@0 638
michael@0 639 enum InliningStatus
michael@0 640 {
michael@0 641 InliningStatus_Error,
michael@0 642 InliningStatus_NotInlined,
michael@0 643 InliningStatus_Inlined
michael@0 644 };
michael@0 645
michael@0 646 enum InliningDecision
michael@0 647 {
michael@0 648 InliningDecision_Error,
michael@0 649 InliningDecision_Inline,
michael@0 650 InliningDecision_DontInline
michael@0 651 };
michael@0 652
michael@0 653 static InliningDecision DontInline(JSScript *targetScript, const char *reason);
michael@0 654
michael@0 655 // Oracles.
michael@0 656 InliningDecision canInlineTarget(JSFunction *target, CallInfo &callInfo);
michael@0 657 InliningDecision makeInliningDecision(JSFunction *target, CallInfo &callInfo);
michael@0 658 bool selectInliningTargets(ObjectVector &targets, CallInfo &callInfo,
michael@0 659 BoolVector &choiceSet, uint32_t *numInlineable);
michael@0 660
michael@0 661 // Native inlining helpers.
michael@0 662 types::TemporaryTypeSet *getInlineReturnTypeSet();
michael@0 663 MIRType getInlineReturnType();
michael@0 664
michael@0 665 // Array natives.
michael@0 666 InliningStatus inlineArray(CallInfo &callInfo);
michael@0 667 InliningStatus inlineArrayPopShift(CallInfo &callInfo, MArrayPopShift::Mode mode);
michael@0 668 InliningStatus inlineArrayPush(CallInfo &callInfo);
michael@0 669 InliningStatus inlineArrayConcat(CallInfo &callInfo);
michael@0 670 InliningStatus inlineArraySplice(CallInfo &callInfo);
michael@0 671
michael@0 672 // Math natives.
michael@0 673 InliningStatus inlineMathAbs(CallInfo &callInfo);
michael@0 674 InliningStatus inlineMathFloor(CallInfo &callInfo);
michael@0 675 InliningStatus inlineMathCeil(CallInfo &callInfo);
michael@0 676 InliningStatus inlineMathRound(CallInfo &callInfo);
michael@0 677 InliningStatus inlineMathSqrt(CallInfo &callInfo);
michael@0 678 InliningStatus inlineMathAtan2(CallInfo &callInfo);
michael@0 679 InliningStatus inlineMathHypot(CallInfo &callInfo);
michael@0 680 InliningStatus inlineMathMinMax(CallInfo &callInfo, bool max);
michael@0 681 InliningStatus inlineMathPow(CallInfo &callInfo);
michael@0 682 InliningStatus inlineMathRandom(CallInfo &callInfo);
michael@0 683 InliningStatus inlineMathImul(CallInfo &callInfo);
michael@0 684 InliningStatus inlineMathFRound(CallInfo &callInfo);
michael@0 685 InliningStatus inlineMathFunction(CallInfo &callInfo, MMathFunction::Function function);
michael@0 686
michael@0 687 // String natives.
michael@0 688 InliningStatus inlineStringObject(CallInfo &callInfo);
michael@0 689 InliningStatus inlineStringSplit(CallInfo &callInfo);
michael@0 690 InliningStatus inlineStrCharCodeAt(CallInfo &callInfo);
michael@0 691 InliningStatus inlineStrFromCharCode(CallInfo &callInfo);
michael@0 692 InliningStatus inlineStrCharAt(CallInfo &callInfo);
michael@0 693 InliningStatus inlineStrReplace(CallInfo &callInfo);
michael@0 694
michael@0 695 // RegExp natives.
michael@0 696 InliningStatus inlineRegExpExec(CallInfo &callInfo);
michael@0 697 InliningStatus inlineRegExpTest(CallInfo &callInfo);
michael@0 698
michael@0 699 // Array intrinsics.
michael@0 700 InliningStatus inlineUnsafePutElements(CallInfo &callInfo);
michael@0 701 bool inlineUnsafeSetDenseArrayElement(CallInfo &callInfo, uint32_t base);
michael@0 702 bool inlineUnsafeSetTypedArrayElement(CallInfo &callInfo, uint32_t base,
michael@0 703 ScalarTypeDescr::Type arrayType);
michael@0 704 bool inlineUnsafeSetTypedObjectArrayElement(CallInfo &callInfo, uint32_t base,
michael@0 705 ScalarTypeDescr::Type arrayType);
michael@0 706 InliningStatus inlineNewDenseArray(CallInfo &callInfo);
michael@0 707 InliningStatus inlineNewDenseArrayForSequentialExecution(CallInfo &callInfo);
michael@0 708 InliningStatus inlineNewDenseArrayForParallelExecution(CallInfo &callInfo);
michael@0 709
michael@0 710 // Slot intrinsics.
michael@0 711 InliningStatus inlineUnsafeSetReservedSlot(CallInfo &callInfo);
michael@0 712 InliningStatus inlineUnsafeGetReservedSlot(CallInfo &callInfo);
michael@0 713
michael@0 714 // ForkJoin intrinsics
michael@0 715 InliningStatus inlineForkJoinGetSlice(CallInfo &callInfo);
michael@0 716
michael@0 717 // TypedObject intrinsics.
michael@0 718 InliningStatus inlineObjectIsTypeDescr(CallInfo &callInfo);
michael@0 719 InliningStatus inlineSetTypedObjectOffset(CallInfo &callInfo);
michael@0 720 bool elementAccessIsTypedObjectArrayOfScalarType(MDefinition* obj, MDefinition* id,
michael@0 721 ScalarTypeDescr::Type *arrayType);
michael@0 722
michael@0 723 // Utility intrinsics.
michael@0 724 InliningStatus inlineIsCallable(CallInfo &callInfo);
michael@0 725 InliningStatus inlineHaveSameClass(CallInfo &callInfo);
michael@0 726 InliningStatus inlineToObject(CallInfo &callInfo);
michael@0 727 InliningStatus inlineDump(CallInfo &callInfo);
michael@0 728 InliningStatus inlineHasClass(CallInfo &callInfo, const Class *clasp) {
michael@0 729 return inlineHasClasses(callInfo, clasp, nullptr);
michael@0 730 }
michael@0 731 InliningStatus inlineHasClasses(CallInfo &callInfo, const Class *clasp1, const Class *clasp2);
michael@0 732
michael@0 733 // Testing functions.
michael@0 734 InliningStatus inlineForceSequentialOrInParallelSection(CallInfo &callInfo);
michael@0 735 InliningStatus inlineBailout(CallInfo &callInfo);
michael@0 736 InliningStatus inlineAssertFloat32(CallInfo &callInfo);
michael@0 737
michael@0 738 // Bind function.
michael@0 739 InliningStatus inlineBoundFunction(CallInfo &callInfo, JSFunction *target);
michael@0 740
michael@0 741 // Main inlining functions
michael@0 742 InliningStatus inlineNativeCall(CallInfo &callInfo, JSFunction *target);
michael@0 743 bool inlineScriptedCall(CallInfo &callInfo, JSFunction *target);
michael@0 744 InliningStatus inlineSingleCall(CallInfo &callInfo, JSFunction *target);
michael@0 745
michael@0 746 // Call functions
michael@0 747 InliningStatus inlineCallsite(ObjectVector &targets, ObjectVector &originals,
michael@0 748 bool lambda, CallInfo &callInfo);
michael@0 749 bool inlineCalls(CallInfo &callInfo, ObjectVector &targets, ObjectVector &originals,
michael@0 750 BoolVector &choiceSet, MGetPropertyCache *maybeCache);
michael@0 751
michael@0 752 // Inlining helpers.
michael@0 753 bool inlineGenericFallback(JSFunction *target, CallInfo &callInfo, MBasicBlock *dispatchBlock,
michael@0 754 bool clonedAtCallsite);
michael@0 755 bool inlineTypeObjectFallback(CallInfo &callInfo, MBasicBlock *dispatchBlock,
michael@0 756 MTypeObjectDispatch *dispatch, MGetPropertyCache *cache,
michael@0 757 MBasicBlock **fallbackTarget);
michael@0 758
michael@0 759 bool testNeedsArgumentCheck(JSFunction *target, CallInfo &callInfo);
michael@0 760
michael@0 761 MDefinition *makeCallsiteClone(JSFunction *target, MDefinition *fun);
michael@0 762 MCall *makeCallHelper(JSFunction *target, CallInfo &callInfo, bool cloneAtCallsite);
michael@0 763 bool makeCall(JSFunction *target, CallInfo &callInfo, bool cloneAtCallsite);
michael@0 764
michael@0 765 MDefinition *patchInlinedReturn(CallInfo &callInfo, MBasicBlock *exit, MBasicBlock *bottom);
michael@0 766 MDefinition *patchInlinedReturns(CallInfo &callInfo, MIRGraphReturns &returns,
michael@0 767 MBasicBlock *bottom);
michael@0 768
michael@0 769 bool objectsHaveCommonPrototype(types::TemporaryTypeSet *types, PropertyName *name,
michael@0 770 bool isGetter, JSObject *foundProto);
michael@0 771 void freezePropertiesForCommonPrototype(types::TemporaryTypeSet *types, PropertyName *name,
michael@0 772 JSObject *foundProto);
michael@0 773 MDefinition *testCommonGetterSetter(types::TemporaryTypeSet *types, PropertyName *name,
michael@0 774 bool isGetter, JSObject *foundProto, Shape *lastProperty);
michael@0 775 bool testShouldDOMCall(types::TypeSet *inTypes,
michael@0 776 JSFunction *func, JSJitInfo::OpType opType);
michael@0 777
michael@0 778 bool annotateGetPropertyCache(MDefinition *obj, MGetPropertyCache *getPropCache,
michael@0 779 types::TemporaryTypeSet *objTypes,
michael@0 780 types::TemporaryTypeSet *pushedTypes);
michael@0 781
michael@0 782 MGetPropertyCache *getInlineableGetPropertyCache(CallInfo &callInfo);
michael@0 783
michael@0 784 JSObject *testSingletonProperty(JSObject *obj, PropertyName *name);
michael@0 785 bool testSingletonPropertyTypes(MDefinition *obj, JSObject *singleton, PropertyName *name,
michael@0 786 bool *testObject, bool *testString);
michael@0 787 bool getDefiniteSlot(types::TemporaryTypeSet *types, PropertyName *name,
michael@0 788 types::HeapTypeSetKey *property);
michael@0 789 bool freezePropTypeSets(types::TemporaryTypeSet *types,
michael@0 790 JSObject *foundProto, PropertyName *name);
michael@0 791
michael@0 792 types::TemporaryTypeSet *bytecodeTypes(jsbytecode *pc);
michael@0 793
michael@0 794 // Use one of the below methods for updating the current block, rather than
michael@0 795 // updating |current| directly. setCurrent() should only be used in cases
michael@0 796 // where the block cannot have phis whose type needs to be computed.
michael@0 797
michael@0 798 bool setCurrentAndSpecializePhis(MBasicBlock *block) {
michael@0 799 if (block) {
michael@0 800 if (!block->specializePhis())
michael@0 801 return false;
michael@0 802 }
michael@0 803 setCurrent(block);
michael@0 804 return true;
michael@0 805 }
michael@0 806
michael@0 807 void setCurrent(MBasicBlock *block) {
michael@0 808 current = block;
michael@0 809 }
michael@0 810
michael@0 811 // A builder is inextricably tied to a particular script.
michael@0 812 JSScript *script_;
michael@0 813
michael@0 814 // If off thread compilation is successful, the final code generator is
michael@0 815 // attached here. Code has been generated, but not linked (there is not yet
michael@0 816 // an IonScript). This is heap allocated, and must be explicitly destroyed,
michael@0 817 // performed by FinishOffThreadBuilder().
michael@0 818 CodeGenerator *backgroundCodegen_;
michael@0 819
michael@0 820 public:
michael@0 821 void clearForBackEnd();
michael@0 822
michael@0 823 JSScript *script() const { return script_; }
michael@0 824
michael@0 825 CodeGenerator *backgroundCodegen() const { return backgroundCodegen_; }
michael@0 826 void setBackgroundCodegen(CodeGenerator *codegen) { backgroundCodegen_ = codegen; }
michael@0 827
michael@0 828 AbortReason abortReason() { return abortReason_; }
michael@0 829
michael@0 830 TypeDescrSetHash *getOrCreateDescrSetHash(); // fallible
michael@0 831
michael@0 832 types::CompilerConstraintList *constraints() {
michael@0 833 return constraints_;
michael@0 834 }
michael@0 835
michael@0 836 bool isInlineBuilder() const {
michael@0 837 return callerBuilder_ != nullptr;
michael@0 838 }
michael@0 839
michael@0 840 const JSAtomState &names() { return compartment->runtime()->names(); }
michael@0 841
michael@0 842 private:
michael@0 843 bool init();
michael@0 844
michael@0 845 JSContext *analysisContext;
michael@0 846 BaselineFrameInspector *baselineFrame_;
michael@0 847 AbortReason abortReason_;
michael@0 848 TypeDescrSetHash *descrSetHash_;
michael@0 849
michael@0 850 // Constraints for recording dependencies on type information.
michael@0 851 types::CompilerConstraintList *constraints_;
michael@0 852
michael@0 853 // Basic analysis information about the script.
michael@0 854 BytecodeAnalysis analysis_;
michael@0 855 BytecodeAnalysis &analysis() {
michael@0 856 return analysis_;
michael@0 857 }
michael@0 858
michael@0 859 types::TemporaryTypeSet *thisTypes, *argTypes, *typeArray;
michael@0 860 uint32_t typeArrayHint;
michael@0 861 uint32_t *bytecodeTypeMap;
michael@0 862
michael@0 863 GSNCache gsn;
michael@0 864 ScopeCoordinateNameCache scopeCoordinateNameCache;
michael@0 865
michael@0 866 jsbytecode *pc;
michael@0 867 MBasicBlock *current;
michael@0 868 uint32_t loopDepth_;
michael@0 869
michael@0 870 /* Information used for inline-call builders. */
michael@0 871 MResumePoint *callerResumePoint_;
michael@0 872 jsbytecode *callerPC() {
michael@0 873 return callerResumePoint_ ? callerResumePoint_->pc() : nullptr;
michael@0 874 }
michael@0 875 IonBuilder *callerBuilder_;
michael@0 876
michael@0 877 bool oom() {
michael@0 878 abortReason_ = AbortReason_Alloc;
michael@0 879 return false;
michael@0 880 }
michael@0 881
michael@0 882 struct LoopHeader {
michael@0 883 jsbytecode *pc;
michael@0 884 MBasicBlock *header;
michael@0 885
michael@0 886 LoopHeader(jsbytecode *pc, MBasicBlock *header)
michael@0 887 : pc(pc), header(header)
michael@0 888 {}
michael@0 889 };
michael@0 890
michael@0 891 Vector<CFGState, 8, IonAllocPolicy> cfgStack_;
michael@0 892 Vector<ControlFlowInfo, 4, IonAllocPolicy> loops_;
michael@0 893 Vector<ControlFlowInfo, 0, IonAllocPolicy> switches_;
michael@0 894 Vector<ControlFlowInfo, 2, IonAllocPolicy> labels_;
michael@0 895 Vector<MInstruction *, 2, IonAllocPolicy> iterators_;
michael@0 896 Vector<LoopHeader, 0, IonAllocPolicy> loopHeaders_;
michael@0 897 BaselineInspector *inspector;
michael@0 898
michael@0 899 size_t inliningDepth_;
michael@0 900
michael@0 901 // Cutoff to disable compilation if excessive time is spent reanalyzing
michael@0 902 // loop bodies to compute a fixpoint of the types for loop variables.
michael@0 903 static const size_t MAX_LOOP_RESTARTS = 40;
michael@0 904 size_t numLoopRestarts_;
michael@0 905
michael@0 906 // True if script->failedBoundsCheck is set for the current script or
michael@0 907 // an outer script.
michael@0 908 bool failedBoundsCheck_;
michael@0 909
michael@0 910 // True if script->failedShapeGuard is set for the current script or
michael@0 911 // an outer script.
michael@0 912 bool failedShapeGuard_;
michael@0 913
michael@0 914 // Has an iterator other than 'for in'.
michael@0 915 bool nonStringIteration_;
michael@0 916
michael@0 917 // If this script can use a lazy arguments object, it will be pre-created
michael@0 918 // here.
michael@0 919 MInstruction *lazyArguments_;
michael@0 920
michael@0 921 // If this is an inline builder, the call info for the builder.
michael@0 922 const CallInfo *inlineCallInfo_;
michael@0 923 };
michael@0 924
michael@0 925 class CallInfo
michael@0 926 {
michael@0 927 MDefinition *fun_;
michael@0 928 MDefinition *thisArg_;
michael@0 929 MDefinitionVector args_;
michael@0 930
michael@0 931 bool constructing_;
michael@0 932 bool setter_;
michael@0 933
michael@0 934 public:
michael@0 935 CallInfo(TempAllocator &alloc, bool constructing)
michael@0 936 : fun_(nullptr),
michael@0 937 thisArg_(nullptr),
michael@0 938 args_(alloc),
michael@0 939 constructing_(constructing),
michael@0 940 setter_(false)
michael@0 941 { }
michael@0 942
michael@0 943 bool init(CallInfo &callInfo) {
michael@0 944 JS_ASSERT(constructing_ == callInfo.constructing());
michael@0 945
michael@0 946 fun_ = callInfo.fun();
michael@0 947 thisArg_ = callInfo.thisArg();
michael@0 948
michael@0 949 if (!args_.appendAll(callInfo.argv()))
michael@0 950 return false;
michael@0 951
michael@0 952 return true;
michael@0 953 }
michael@0 954
michael@0 955 bool init(MBasicBlock *current, uint32_t argc) {
michael@0 956 JS_ASSERT(args_.empty());
michael@0 957
michael@0 958 // Get the arguments in the right order
michael@0 959 if (!args_.reserve(argc))
michael@0 960 return false;
michael@0 961 for (int32_t i = argc; i > 0; i--)
michael@0 962 args_.infallibleAppend(current->peek(-i));
michael@0 963 current->popn(argc);
michael@0 964
michael@0 965 // Get |this| and |fun|
michael@0 966 setThis(current->pop());
michael@0 967 setFun(current->pop());
michael@0 968
michael@0 969 return true;
michael@0 970 }
michael@0 971
michael@0 972 void popFormals(MBasicBlock *current) {
michael@0 973 current->popn(numFormals());
michael@0 974 }
michael@0 975
michael@0 976 void pushFormals(MBasicBlock *current) {
michael@0 977 current->push(fun());
michael@0 978 current->push(thisArg());
michael@0 979
michael@0 980 for (uint32_t i = 0; i < argc(); i++)
michael@0 981 current->push(getArg(i));
michael@0 982 }
michael@0 983
michael@0 984 uint32_t argc() const {
michael@0 985 return args_.length();
michael@0 986 }
michael@0 987 uint32_t numFormals() const {
michael@0 988 return argc() + 2;
michael@0 989 }
michael@0 990
michael@0 991 void setArgs(MDefinitionVector *args) {
michael@0 992 JS_ASSERT(args_.empty());
michael@0 993 args_.appendAll(*args);
michael@0 994 }
michael@0 995
michael@0 996 MDefinitionVector &argv() {
michael@0 997 return args_;
michael@0 998 }
michael@0 999
michael@0 1000 const MDefinitionVector &argv() const {
michael@0 1001 return args_;
michael@0 1002 }
michael@0 1003
michael@0 1004 MDefinition *getArg(uint32_t i) const {
michael@0 1005 JS_ASSERT(i < argc());
michael@0 1006 return args_[i];
michael@0 1007 }
michael@0 1008
michael@0 1009 void setArg(uint32_t i, MDefinition *def) {
michael@0 1010 JS_ASSERT(i < argc());
michael@0 1011 args_[i] = def;
michael@0 1012 }
michael@0 1013
michael@0 1014 MDefinition *thisArg() const {
michael@0 1015 JS_ASSERT(thisArg_);
michael@0 1016 return thisArg_;
michael@0 1017 }
michael@0 1018
michael@0 1019 void setThis(MDefinition *thisArg) {
michael@0 1020 thisArg_ = thisArg;
michael@0 1021 }
michael@0 1022
michael@0 1023 bool constructing() const {
michael@0 1024 return constructing_;
michael@0 1025 }
michael@0 1026
michael@0 1027 bool isSetter() const {
michael@0 1028 return setter_;
michael@0 1029 }
michael@0 1030 void markAsSetter() {
michael@0 1031 setter_ = true;
michael@0 1032 }
michael@0 1033
michael@0 1034 MDefinition *fun() const {
michael@0 1035 JS_ASSERT(fun_);
michael@0 1036 return fun_;
michael@0 1037 }
michael@0 1038
michael@0 1039 void setFun(MDefinition *fun) {
michael@0 1040 fun_ = fun;
michael@0 1041 }
michael@0 1042
michael@0 1043 void setImplicitlyUsedUnchecked() {
michael@0 1044 fun_->setImplicitlyUsedUnchecked();
michael@0 1045 thisArg_->setImplicitlyUsedUnchecked();
michael@0 1046 for (uint32_t i = 0; i < argc(); i++)
michael@0 1047 getArg(i)->setImplicitlyUsedUnchecked();
michael@0 1048 }
michael@0 1049 };
michael@0 1050
michael@0 1051 bool TypeSetIncludes(types::TypeSet *types, MIRType input, types::TypeSet *inputTypes);
michael@0 1052
michael@0 1053 bool NeedsPostBarrier(CompileInfo &info, MDefinition *value);
michael@0 1054
michael@0 1055 } // namespace jit
michael@0 1056 } // namespace js
michael@0 1057
michael@0 1058 #endif // JS_ION
michael@0 1059
michael@0 1060 #endif /* jit_IonBuilder_h */

mercurial