LCOV - code coverage report
Current view: directory - js/src/methodjit - Compiler.h (source / functions) Found Hit Coverage
Test: app.info Lines: 138 135 97.8 %
Date: 2012-06-02 Functions: 59 58 98.3 %

       1                 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2                 :  * vim: set ts=4 sw=4 et tw=99:
       3                 :  *
       4                 :  * ***** BEGIN LICENSE BLOCK *****
       5                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       6                 :  *
       7                 :  * The contents of this file are subject to the Mozilla Public License Version
       8                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       9                 :  * the License. You may obtain a copy of the License at
      10                 :  * http://www.mozilla.org/MPL/
      11                 :  *
      12                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      13                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      14                 :  * for the specific language governing rights and limitations under the
      15                 :  * License.
      16                 :  *
      17                 :  * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
      18                 :  * May 28, 2008.
      19                 :  *
      20                 :  * The Initial Developer of the Original Code is
      21                 :  *   Brendan Eich <brendan@mozilla.org>
      22                 :  *
      23                 :  * Contributor(s):
      24                 :  *   David Anderson <danderson@mozilla.com>
      25                 :  *   David Mandelin <dmandelin@mozilla.com>
      26                 :  *
      27                 :  * Alternatively, the contents of this file may be used under the terms of
      28                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      29                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      30                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      31                 :  * of those above. If you wish to allow use of your version of this file only
      32                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      33                 :  * use your version of this file under the terms of the MPL, indicate your
      34                 :  * decision by deleting the provisions above and replace them with the notice
      35                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      36                 :  * the provisions above, a recipient may use your version of this file under
      37                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      38                 :  *
      39                 :  * ***** END LICENSE BLOCK ***** */
      40                 : #if !defined jsjaeger_compiler_h__ && defined JS_METHODJIT
      41                 : #define jsjaeger_compiler_h__
      42                 : 
      43                 : #include "jsanalyze.h"
      44                 : #include "jscntxt.h"
      45                 : #include "MethodJIT.h"
      46                 : #include "CodeGenIncludes.h"
      47                 : #include "BaseCompiler.h"
      48                 : #include "StubCompiler.h"
      49                 : #include "MonoIC.h"
      50                 : #include "PolyIC.h"
      51                 : 
      52                 : namespace js {
      53                 : namespace mjit {
      54                 : 
      55                 : /*
      56                 :  * Patch for storing call site and rejoin site return addresses at, for
      57                 :  * redirecting the return address in InvariantFailure.
      58                 :  */
      59                 : struct InvariantCodePatch {
      60                 :     bool hasPatch;
      61                 :     JSC::MacroAssembler::DataLabelPtr codePatch;
      62         5053912 :     InvariantCodePatch() : hasPatch(false) {}
      63                 : };
      64                 : 
      65                 : struct JSActiveFrame {
      66                 :     JSActiveFrame *parent;
      67                 :     jsbytecode *parentPC;
      68                 :     JSScript *script;
      69                 : 
      70                 :     /*
      71                 :      * Index into inlineFrames or OUTER_FRAME, matches this frame's index in
      72                 :      * the cross script SSA.
      73                 :      */
      74                 :     uint32_t inlineIndex;
      75                 : 
      76                 :     /* JIT code generation tracking state */
      77                 :     size_t mainCodeStart;
      78                 :     size_t stubCodeStart;
      79                 :     size_t mainCodeEnd;
      80                 :     size_t stubCodeEnd;
      81                 :     size_t inlinePCOffset;
      82                 : 
      83                 :     JSActiveFrame();
      84                 : };
      85                 : 
      86                 : class Compiler : public BaseCompiler
      87                 : {
      88                 :     friend class StubCompiler;
      89                 : 
      90          239807 :     struct BranchPatch {
      91          198463 :         BranchPatch(const Jump &j, jsbytecode *pc, uint32_t inlineIndex)
      92          198463 :           : jump(j), pc(pc), inlineIndex(inlineIndex)
      93          198463 :         { }
      94                 : 
      95                 :         Jump jump;
      96                 :         jsbytecode *pc;
      97                 :         uint32_t inlineIndex;
      98                 :     };
      99                 : 
     100                 : #if defined JS_MONOIC
     101          408882 :     struct GlobalNameICInfo {
     102                 :         Label fastPathStart;
     103                 :         Call slowPathCall;
     104                 :         DataLabelPtr shape;
     105                 :         DataLabelPtr addrLabel;
     106                 : 
     107          408880 :         void copyTo(ic::GlobalNameIC &to, JSC::LinkBuffer &full, JSC::LinkBuffer &stub) {
     108          408880 :             to.fastPathStart = full.locationOf(fastPathStart);
     109                 : 
     110          408880 :             int offset = full.locationOf(shape) - to.fastPathStart;
     111          408880 :             to.shapeOffset = offset;
     112          408880 :             JS_ASSERT(to.shapeOffset == offset);
     113                 : 
     114          408880 :             to.slowPathCall = stub.locationOf(slowPathCall);
     115          408880 :         }
     116                 :     };
     117                 : 
     118         1374318 :     struct GetGlobalNameICInfo : public GlobalNameICInfo {
     119                 :         Label load;
     120                 :     };
     121                 : 
     122           63572 :     struct SetGlobalNameICInfo : public GlobalNameICInfo {
     123                 :         Label slowPathStart;
     124                 :         Label fastPathRejoin;
     125                 :         DataLabel32 store;
     126                 :         Jump shapeGuardJump;
     127                 :         ValueRemat vr;
     128                 :         RegisterID objReg;
     129                 :         RegisterID shapeReg;
     130                 :         bool objConst;
     131                 :     };
     132                 : 
     133           25913 :     struct EqualityGenInfo {
     134                 :         DataLabelPtr addrLabel;
     135                 :         Label stubEntry;
     136                 :         Call stubCall;
     137                 :         BoolStub stub;
     138                 :         MaybeJump jumpToStub;
     139                 :         Label fallThrough;
     140                 :         jsbytecode *jumpTarget;
     141                 :         bool trampoline;
     142                 :         Label trampolineStart;
     143                 :         ValueRemat lvr, rvr;
     144                 :         Assembler::Condition cond;
     145                 :         JSC::MacroAssembler::RegisterID tempReg;
     146                 :     };
     147                 : 
     148                 :     /* InlineFrameAssembler wants to see this. */
     149                 :   public:
     150          356950 :     struct CallGenInfo {
     151                 :         /*
     152                 :          * These members map to members in CallICInfo. See that structure for
     153                 :          * more comments.
     154                 :          */
     155                 :         uint32_t     callIndex;
     156                 :         DataLabelPtr funGuard;
     157                 :         Jump         funJump;
     158                 :         Jump         hotJump;
     159                 :         Call         oolCall;
     160                 :         Label        joinPoint;
     161                 :         Label        slowJoinPoint;
     162                 :         Label        slowPathStart;
     163                 :         Label        hotPathLabel;
     164                 :         DataLabelPtr addrLabel1;
     165                 :         DataLabelPtr addrLabel2;
     166                 :         Jump         oolJump;
     167                 :         Label        icCall;
     168                 :         RegisterID   funObjReg;
     169                 :         FrameSize    frameSize;
     170                 :         bool         typeMonitored;
     171                 :     };
     172                 : 
     173                 :   private:
     174                 : #endif
     175                 : 
     176                 :     /*
     177                 :      * Writes of call return addresses which needs to be delayed until the final
     178                 :      * absolute address of the join point is known.
     179                 :      */
     180          308568 :     struct CallPatchInfo {
     181          438549 :         CallPatchInfo() : hasFastNcode(false), hasSlowNcode(false), joinSlow(false) {}
     182                 :         Label joinPoint;
     183                 :         DataLabelPtr fastNcodePatch;
     184                 :         DataLabelPtr slowNcodePatch;
     185                 :         bool hasFastNcode;
     186                 :         bool hasSlowNcode;
     187                 :         bool joinSlow;
     188                 :     };
     189                 : 
     190                 :     struct BaseICInfo {
     191          850622 :         BaseICInfo(JSOp op) : op(op), canCallHook(false), forcedTypeBarrier(false)
     192          850622 :         { }
     193                 :         Label fastPathStart;
     194                 :         Label fastPathRejoin;
     195                 :         Label slowPathStart;
     196                 :         Call slowPathCall;
     197                 :         DataLabelPtr paramAddr;
     198                 :         JSOp op;
     199                 :         bool canCallHook;
     200                 :         bool forcedTypeBarrier;
     201                 : 
     202          850596 :         void copyTo(ic::BaseIC &to, JSC::LinkBuffer &full, JSC::LinkBuffer &stub) {
     203          850596 :             to.fastPathStart = full.locationOf(fastPathStart);
     204          850596 :             to.fastPathRejoin = full.locationOf(fastPathRejoin);
     205          850596 :             to.slowPathStart = stub.locationOf(slowPathStart);
     206          850596 :             to.slowPathCall = stub.locationOf(slowPathCall);
     207          850596 :             to.canCallHook = canCallHook;
     208          850596 :             to.forcedTypeBarrier = forcedTypeBarrier;
     209          850596 :             to.op = op;
     210          850596 :             JS_ASSERT(to.op == op);
     211          850596 :         }
     212                 :     };
     213                 : 
     214           24345 :     struct GetElementICInfo : public BaseICInfo {
     215           21695 :         GetElementICInfo(JSOp op) : BaseICInfo(op)
     216           21695 :         { }
     217                 :         RegisterID  typeReg;
     218                 :         RegisterID  objReg;
     219                 :         ValueRemat  id;
     220                 :         MaybeJump   typeGuard;
     221                 :         Jump        shapeGuard;
     222                 :     };
     223                 : 
     224            6244 :     struct SetElementICInfo : public BaseICInfo {
     225            5692 :         SetElementICInfo(JSOp op) : BaseICInfo(op)
     226            5692 :         { }
     227                 :         RegisterID  objReg;
     228                 :         StateRemat  objRemat;
     229                 :         ValueRemat  vr;
     230                 :         Jump        capacityGuard;
     231                 :         Jump        shapeGuard;
     232                 :         Jump        holeGuard;
     233                 :         Int32Key    key;
     234                 :         uint32_t    volatileMask;
     235                 :     };
     236                 : 
     237         1671743 :     struct PICGenInfo : public BaseICInfo {
     238          823235 :         PICGenInfo(ic::PICInfo::Kind kind, JSOp op)
     239          823235 :           : BaseICInfo(op), kind(kind), typeMonitored(false)
     240          823235 :         { }
     241                 :         ic::PICInfo::Kind kind;
     242                 :         Label typeCheck;
     243                 :         RegisterID shapeReg;
     244                 :         RegisterID objReg;
     245                 :         RegisterID typeReg;
     246                 :         Label shapeGuard;
     247                 :         jsbytecode *pc;
     248                 :         PropertyName *name;
     249                 :         bool hasTypeCheck;
     250                 :         bool typeMonitored;
     251                 :         types::TypeSet *rhsTypes;
     252                 :         ValueRemat vr;
     253                 :         union {
     254                 :             ic::GetPropLabels getPropLabels_;
     255                 :             ic::SetPropLabels setPropLabels_;
     256                 :             ic::BindNameLabels bindNameLabels_;
     257                 :             ic::ScopeNameLabels scopeNameLabels_;
     258                 :         };
     259                 : 
     260          887238 :         ic::GetPropLabels &getPropLabels() {
     261          887238 :             JS_ASSERT(kind == ic::PICInfo::GET);
     262          887238 :             return getPropLabels_;
     263                 :         }
     264           66156 :         ic::SetPropLabels &setPropLabels() {
     265           66156 :             JS_ASSERT(kind == ic::PICInfo::SET || kind == ic::PICInfo::SETMETHOD);
     266           66156 :             return setPropLabels_;
     267                 :         }
     268           14222 :         ic::BindNameLabels &bindNameLabels() {
     269           14222 :             JS_ASSERT(kind == ic::PICInfo::BIND);
     270           14222 :             return bindNameLabels_;
     271                 :         }
     272          678828 :         ic::ScopeNameLabels &scopeNameLabels() {
     273               0 :             JS_ASSERT(kind == ic::PICInfo::NAME ||
     274          678828 :                       kind == ic::PICInfo::XNAME);
     275          678828 :             return scopeNameLabels_;
     276                 :         }
     277                 : 
     278          823209 :         void copySimpleMembersTo(ic::PICInfo &ic) {
     279          823209 :             ic.kind = kind;
     280          823209 :             ic.shapeReg = shapeReg;
     281          823209 :             ic.objReg = objReg;
     282          823209 :             ic.name = name;
     283          823209 :             if (ic.isSet()) {
     284           33078 :                 ic.u.vr = vr;
     285          790131 :             } else if (ic.isGet()) {
     286          443609 :                 ic.u.get.typeReg = typeReg;
     287          443609 :                 ic.u.get.hasTypeCheck = hasTypeCheck;
     288                 :             }
     289          823209 :             ic.typeMonitored = typeMonitored;
     290          823209 :             ic.rhsTypes = rhsTypes;
     291          823209 :             if (ic.isGet())
     292          443609 :                 ic.setLabels(getPropLabels());
     293          379600 :             else if (ic.isSet())
     294           33078 :                 ic.setLabels(setPropLabels());
     295          346522 :             else if (ic.isBind())
     296            7111 :                 ic.setLabels(bindNameLabels());
     297          339411 :             else if (ic.isScopeName())
     298          339411 :                 ic.setLabels(scopeNameLabels());
     299          823209 :         }
     300                 : 
     301                 :     };
     302                 : 
     303                 :     struct Defs {
     304                 :         Defs(uint32_t ndefs)
     305                 :           : ndefs(ndefs)
     306                 :         { }
     307                 :         uint32_t ndefs;
     308                 :     };
     309                 : 
     310        11200524 :     struct InternalCallSite {
     311                 :         uint32_t returnOffset;
     312                 :         DataLabelPtr inlinePatch;
     313                 :         uint32_t inlineIndex;
     314                 :         jsbytecode *inlinepc;
     315                 :         RejoinState rejoin;
     316                 :         bool ool;
     317                 :         Label loopJumpLabel;
     318                 :         InvariantCodePatch loopPatch;
     319                 : 
     320         5053912 :         InternalCallSite(uint32_t returnOffset,
     321                 :                          uint32_t inlineIndex, jsbytecode *inlinepc,
     322                 :                          RejoinState rejoin, bool ool)
     323                 :           : returnOffset(returnOffset),
     324                 :             inlineIndex(inlineIndex), inlinepc(inlinepc),
     325         5053912 :             rejoin(rejoin), ool(ool)
     326         5053912 :         { }
     327                 :     };
     328                 : 
     329               0 :     struct DoublePatch {
     330                 :         double d;
     331                 :         DataLabelPtr label;
     332                 :         bool ool;
     333                 :     };
     334                 : 
     335             548 :     struct JumpTable {
     336                 :         DataLabelPtr label;
     337                 :         size_t offsetIndex;
     338                 :     };
     339                 : 
     340            2087 :     struct JumpTableEdge {
     341                 :         uint32_t source;
     342                 :         uint32_t target;
     343                 :     };
     344                 : 
     345              10 :     struct ChunkJumpTableEdge {
     346                 :         JumpTableEdge edge;
     347                 :         void **jumpTableEntry;
     348                 :     };
     349                 : 
     350           69024 :     struct LoopEntry {
     351                 :         uint32_t pcOffset;
     352                 :         Label label;
     353                 :     };
     354                 : 
     355                 :     /*
     356                 :      * Information about the current type of an argument or local in the
     357                 :      * script. The known type tag of these types is cached when possible to
     358                 :      * avoid generating duplicate dependency constraints.
     359                 :      */
     360                 :     class VarType {
     361                 :         JSValueType type;
     362                 :         types::TypeSet *types;
     363                 : 
     364                 :       public:
     365          376194 :         void setTypes(types::TypeSet *types) {
     366          376194 :             this->types = types;
     367          376194 :             this->type = JSVAL_TYPE_MISSING;
     368          376194 :         }
     369                 : 
     370                 :         types::TypeSet *getTypes() { return types; }
     371                 : 
     372          647477 :         JSValueType getTypeTag(JSContext *cx) {
     373          647477 :             if (type == JSVAL_TYPE_MISSING)
     374          214072 :                 type = types ? types->getKnownTypeTag(cx) : JSVAL_TYPE_UNKNOWN;
     375          647477 :             return type;
     376                 :         }
     377                 :     };
     378                 : 
     379            3596 :     struct OutgoingChunkEdge {
     380                 :         uint32_t source;
     381                 :         uint32_t target;
     382                 : 
     383                 : #ifdef JS_CPU_X64
     384                 :         Label sourceTrampoline;
     385                 : #endif
     386                 : 
     387                 :         Jump fastJump;
     388                 :         MaybeJump slowJump;
     389                 :     };
     390                 : 
     391                 :     struct SlotType
     392                 :     {
     393                 :         uint32_t slot;
     394                 :         VarType vt;
     395                 :         SlotType(uint32_t slot, VarType vt) : slot(slot), vt(vt) {}
     396                 :     };
     397                 : 
     398                 :     JSScript *outerScript;
     399                 :     unsigned chunkIndex;
     400                 :     bool isConstructing;
     401                 :     ChunkDescriptor outerChunk;
     402                 : 
     403                 :     /* SSA information for the outer script and all frames we will be inlining. */
     404                 :     analyze::CrossScriptSSA ssa;
     405                 : 
     406                 :     GlobalObject *globalObj;
     407                 :     const HeapSlot *globalSlots;  /* Original slots pointer. */
     408                 : 
     409                 :     Assembler masm;
     410                 :     FrameState frame;
     411                 : 
     412                 :     /*
     413                 :      * State for the current stack frame, and links to its parents going up to
     414                 :      * the outermost script.
     415                 :      */
     416                 : 
     417                 : public:
     418                 :     struct ActiveFrame : public JSActiveFrame {
     419                 :         Label *jumpMap;
     420                 : 
     421                 :         /* Current types for non-escaping vars in the script. */
     422                 :         VarType *varTypes;
     423                 : 
     424                 :         /* State for managing return from inlined frames. */
     425                 :         bool needReturnValue;          /* Return value will be used. */
     426                 :         bool syncReturnValue;          /* Return value should be fully synced. */
     427                 :         bool returnValueDouble;        /* Return value should be a double. */
     428                 :         bool returnSet;                /* Whether returnRegister is valid. */
     429                 :         AnyRegisterID returnRegister;  /* Register holding return value. */
     430                 :         const FrameEntry *returnEntry; /* Entry copied by return value. */
     431                 :         Vector<Jump, 4, CompilerAllocPolicy> *returnJumps;
     432                 : 
     433                 :         /*
     434                 :          * Snapshot of the heap state to use after the call, in case
     435                 :          * there are multiple return paths the inlined frame could take.
     436                 :          */
     437                 :         RegisterAllocation *exitState;
     438                 : 
     439                 :         ActiveFrame(JSContext *cx);
     440                 :         ~ActiveFrame();
     441                 :     };
     442                 : 
     443                 : private:
     444                 :     ActiveFrame *a;
     445                 :     ActiveFrame *outer;
     446                 : 
     447                 :     JSScript *script;
     448                 :     analyze::ScriptAnalysis *analysis;
     449                 :     jsbytecode *PC;
     450                 : 
     451                 :     LoopState *loop;
     452                 : 
     453                 :     /* State spanning all stack frames. */
     454                 : 
     455                 :     js::Vector<ActiveFrame*, 4, CompilerAllocPolicy> inlineFrames;
     456                 :     js::Vector<BranchPatch, 64, CompilerAllocPolicy> branchPatches;
     457                 : #if defined JS_MONOIC
     458                 :     js::Vector<GetGlobalNameICInfo, 16, CompilerAllocPolicy> getGlobalNames;
     459                 :     js::Vector<SetGlobalNameICInfo, 16, CompilerAllocPolicy> setGlobalNames;
     460                 :     js::Vector<CallGenInfo, 64, CompilerAllocPolicy> callICs;
     461                 :     js::Vector<EqualityGenInfo, 64, CompilerAllocPolicy> equalityICs;
     462                 : #endif
     463                 : #if defined JS_POLYIC
     464                 :     js::Vector<PICGenInfo, 16, CompilerAllocPolicy> pics;
     465                 :     js::Vector<GetElementICInfo, 16, CompilerAllocPolicy> getElemICs;
     466                 :     js::Vector<SetElementICInfo, 16, CompilerAllocPolicy> setElemICs;
     467                 : #endif
     468                 :     js::Vector<CallPatchInfo, 64, CompilerAllocPolicy> callPatches;
     469                 :     js::Vector<InternalCallSite, 64, CompilerAllocPolicy> callSites;
     470                 :     js::Vector<DoublePatch, 16, CompilerAllocPolicy> doubleList;
     471                 :     js::Vector<uint32_t> fixedIntToDoubleEntries;
     472                 :     js::Vector<uint32_t> fixedDoubleToAnyEntries;
     473                 :     js::Vector<JumpTable, 16> jumpTables;
     474                 :     js::Vector<JumpTableEdge, 16> jumpTableEdges;
     475                 :     js::Vector<LoopEntry, 16> loopEntries;
     476                 :     js::Vector<OutgoingChunkEdge, 16> chunkEdges;
     477                 :     StubCompiler stubcc;
     478                 :     Label invokeLabel;
     479                 :     Label arityLabel;
     480                 :     Label argsCheckLabel;
     481                 : #ifdef JS_MONOIC
     482                 :     Label argsCheckStub;
     483                 :     Label argsCheckFallthrough;
     484                 :     Jump argsCheckJump;
     485                 : #endif
     486                 :     bool debugMode_;
     487                 :     bool inlining_;
     488                 :     bool hasGlobalReallocation;
     489                 :     bool oomInVector;       // True if we have OOM'd appending to a vector. 
     490                 :     bool overflowICSpace;   // True if we added a constant pool in a reserved space.
     491                 :     uint64_t gcNumber;
     492                 :     enum { NoApplyTricks, LazyArgsObj } applyTricks;
     493                 :     PCLengthEntry *pcLengths;
     494                 : 
     495         2681820 :     Compiler *thisFromCtor() { return this; }
     496                 : 
     497                 :     friend class CompilerAllocPolicy;
     498                 :   public:
     499                 :     Compiler(JSContext *cx, JSScript *outerScript, unsigned chunkIndex, bool isConstructing);
     500                 :     ~Compiler();
     501                 : 
     502                 :     CompileStatus compile();
     503                 : 
     504         3581621 :     Label getLabel() { return masm.label(); }
     505                 :     bool knownJump(jsbytecode *pc);
     506                 :     Label labelOf(jsbytecode *target, uint32_t inlineIndex);
     507                 :     void addCallSite(const InternalCallSite &callSite);
     508                 :     void addReturnSite();
     509                 :     void inlineStubCall(void *stub, RejoinState rejoin, Uses uses);
     510                 : 
     511         1085104 :     bool debugMode() { return debugMode_; }
     512          835365 :     bool inlining() { return inlining_; }
     513            4933 :     bool constructing() { return isConstructing; }
     514                 : 
     515         4762722 :     jsbytecode *outerPC() {
     516         4762722 :         if (a == outer)
     517         4735629 :             return PC;
     518           27093 :         ActiveFrame *scan = a;
     519           68096 :         while (scan && scan->parent != outer)
     520           13910 :             scan = static_cast<ActiveFrame *>(scan->parent);
     521           27093 :         return scan->parentPC;
     522                 :     }
     523                 : 
     524         1301921 :     JITScript *outerJIT() {
     525         1301921 :         return outerScript->getJIT(isConstructing);
     526                 :     }
     527                 : 
     528          520572 :     ChunkDescriptor &outerChunkRef() {
     529          520572 :         return outerJIT()->chunkDescriptor(chunkIndex);
     530                 :     }
     531                 : 
     532          579577 :     bool bytecodeInChunk(jsbytecode *pc) {
     533                 :         return (unsigned(pc - outerScript->code) >= outerChunk.begin)
     534          579577 :             && (unsigned(pc - outerScript->code) < outerChunk.end);
     535                 :     }
     536                 : 
     537         3666774 :     jsbytecode *inlinePC() { return PC; }
     538         3870802 :     uint32_t inlineIndex() { return a->inlineIndex; }
     539                 : 
     540           31291 :     Assembler &getAssembler(bool ool) { return ool ? stubcc.masm : masm; }
     541                 : 
     542            8231 :     InvariantCodePatch *getInvariantPatch(unsigned index) {
     543            8231 :         return &callSites[index].loopPatch;
     544                 :     }
     545            8588 :     jsbytecode *getInvariantPC(unsigned index) {
     546            8588 :         return callSites[index].inlinepc;
     547                 :     }
     548                 : 
     549           16523 :     bool activeFrameHasMultipleExits() {
     550           16523 :         ActiveFrame *na = a;
     551           33225 :         while (na->parent) {
     552             200 :             if (na->exitState)
     553              21 :                 return true;
     554             179 :             na = static_cast<ActiveFrame *>(na->parent);
     555                 :         }
     556           16502 :         return false;
     557                 :     }
     558                 : 
     559                 :   private:
     560                 :     CompileStatus performCompilation();
     561                 :     CompileStatus generatePrologue();
     562                 :     CompileStatus generateMethod();
     563                 :     CompileStatus generateEpilogue();
     564                 :     CompileStatus finishThisUp();
     565                 :     CompileStatus pushActiveFrame(JSScript *script, uint32_t argc);
     566                 :     void popActiveFrame();
     567                 :     void updatePCCounters(jsbytecode *pc, Label *start, bool *updated);
     568                 :     void updatePCTypes(jsbytecode *pc, FrameEntry *fe);
     569                 :     void updateArithCounters(jsbytecode *pc, FrameEntry *fe,
     570                 :                              JSValueType firstUseType, JSValueType secondUseType);
     571                 :     void updateElemCounters(jsbytecode *pc, FrameEntry *obj, FrameEntry *id);
     572                 :     void bumpPropCounter(jsbytecode *pc, int counter);
     573                 : 
     574                 :     /* Analysis helpers. */
     575                 :     CompileStatus prepareInferenceTypes(JSScript *script, ActiveFrame *a);
     576                 :     void ensureDoubleArguments();
     577                 :     void markUndefinedLocal(uint32_t offset, uint32_t i);
     578                 :     void markUndefinedLocals();
     579                 :     void fixDoubleTypes(jsbytecode *target);
     580                 :     void watchGlobalReallocation();
     581                 :     void updateVarType();
     582                 :     void updateJoinVarTypes();
     583                 :     void restoreVarType();
     584                 :     JSValueType knownPushedType(uint32_t pushed);
     585                 :     bool mayPushUndefined(uint32_t pushed);
     586                 :     types::TypeSet *pushedTypeSet(uint32_t which);
     587                 :     bool monitored(jsbytecode *pc);
     588                 :     bool hasTypeBarriers(jsbytecode *pc);
     589                 :     bool testSingletonProperty(JSObject *obj, jsid id);
     590                 :     bool testSingletonPropertyTypes(FrameEntry *top, jsid id, bool *testObject);
     591                 :     CompileStatus addInlineFrame(JSScript *script, uint32_t depth, uint32_t parent, jsbytecode *parentpc);
     592                 :     CompileStatus scanInlineCalls(uint32_t index, uint32_t depth);
     593                 :     CompileStatus checkAnalysis(JSScript *script);
     594                 : 
     595         1640188 :     struct BarrierState {
     596                 :         MaybeJump jump;
     597                 :         RegisterID typeReg;
     598                 :         RegisterID dataReg;
     599                 :     };
     600                 : 
     601                 :     MaybeJump trySingleTypeTest(types::TypeSet *types, RegisterID typeReg);
     602                 :     Jump addTypeTest(types::TypeSet *types, RegisterID typeReg, RegisterID dataReg);
     603                 :     BarrierState pushAddressMaybeBarrier(Address address, JSValueType type, bool reuseBase,
     604                 :                                          bool testUndefined = false);
     605                 :     BarrierState testBarrier(RegisterID typeReg, RegisterID dataReg,
     606                 :                              bool testUndefined = false, bool testReturn = false,
     607                 :                              bool force = false);
     608                 :     void finishBarrier(const BarrierState &barrier, RejoinState rejoin, uint32_t which);
     609                 : 
     610                 :     void testPushedType(RejoinState rejoin, int which, bool ool = true);
     611                 : 
     612                 :     /* Non-emitting helpers. */
     613                 :     void pushSyncedEntry(uint32_t pushed);
     614                 :     bool jumpInScript(Jump j, jsbytecode *pc);
     615                 :     bool compareTwoValues(JSContext *cx, JSOp op, const Value &lhs, const Value &rhs);
     616                 :     bool canUseApplyTricks();
     617                 : 
     618                 :     /* Emitting helpers. */
     619                 :     bool constantFoldBranch(jsbytecode *target, bool taken);
     620                 :     bool emitStubCmpOp(BoolStub stub, jsbytecode *target, JSOp fused);
     621                 :     bool iter(unsigned flags);
     622                 :     void iterNext(ptrdiff_t offset);
     623                 :     bool iterMore(jsbytecode *target);
     624                 :     void iterEnd();
     625                 :     MaybeJump loadDouble(FrameEntry *fe, FPRegisterID *fpReg, bool *allocated);
     626                 : #ifdef JS_POLYIC
     627                 :     void passICAddress(BaseICInfo *ic);
     628                 : #endif
     629                 : #ifdef JS_MONOIC
     630                 :     void passMICAddress(GlobalNameICInfo &mic);
     631                 : #endif
     632                 :     bool constructThis();
     633                 :     void ensureDouble(FrameEntry *fe);
     634                 : 
     635                 :     /*
     636                 :      * Ensure fe is an integer, truncating from double if necessary, or jump to
     637                 :      * the slow path per uses.
     638                 :      */
     639                 :     void ensureInteger(FrameEntry *fe, Uses uses);
     640                 : 
     641                 :     /* Convert fe from a double to integer (per ValueToECMAInt32) in place. */
     642                 :     void truncateDoubleToInt32(FrameEntry *fe, Uses uses);
     643                 : 
     644                 :     /*
     645                 :      * Try to convert a double fe to an integer, with no truncation performed,
     646                 :      * or jump to the slow path per uses.
     647                 :      */
     648                 :     void tryConvertInteger(FrameEntry *fe, Uses uses);
     649                 : 
     650                 :     /* Opcode handlers. */
     651                 :     bool jumpAndRun(Jump j, jsbytecode *target,
     652                 :                     Jump *slow = NULL, bool *trampoline = NULL,
     653                 :                     bool fallthrough = false);
     654                 :     bool startLoop(jsbytecode *head, Jump entry, jsbytecode *entryTarget);
     655                 :     bool finishLoop(jsbytecode *head);
     656                 :     inline bool shouldStartLoop(jsbytecode *head);
     657                 :     void jsop_bindname(PropertyName *name);
     658                 :     void jsop_setglobal(uint32_t index);
     659                 :     void jsop_getprop_slow(PropertyName *name, bool forPrototype = false);
     660                 :     void jsop_getarg(uint32_t slot);
     661                 :     void jsop_setarg(uint32_t slot, bool popped);
     662                 :     void jsop_this();
     663                 :     void emitReturn(FrameEntry *fe);
     664                 :     void emitFinalReturn(Assembler &masm);
     665                 :     void loadReturnValue(Assembler *masm, FrameEntry *fe);
     666                 :     void emitReturnValue(Assembler *masm, FrameEntry *fe);
     667                 :     void emitInlineReturnValue(FrameEntry *fe);
     668                 :     void dispatchCall(VoidPtrStubUInt32 stub, uint32_t argc);
     669                 :     void interruptCheckHelper();
     670                 :     void recompileCheckHelper();
     671                 :     void emitUncachedCall(uint32_t argc, bool callingNew);
     672                 :     void checkCallApplySpeculation(uint32_t callImmArgc, uint32_t speculatedArgc,
     673                 :                                    FrameEntry *origCallee, FrameEntry *origThis,
     674                 :                                    MaybeRegisterID origCalleeType, RegisterID origCalleeData,
     675                 :                                    MaybeRegisterID origThisType, RegisterID origThisData,
     676                 :                                    Jump *uncachedCallSlowRejoin, CallPatchInfo *uncachedCallPatch);
     677                 :     bool inlineCallHelper(uint32_t argc, bool callingNew, FrameSize &callFrameSize);
     678                 :     void fixPrimitiveReturn(Assembler *masm, FrameEntry *fe);
     679                 :     void jsop_getgname(uint32_t index);
     680                 :     void jsop_getgname_slow(uint32_t index);
     681                 :     void jsop_setgname(PropertyName *name, bool popGuaranteed);
     682                 :     void jsop_setgname_slow(PropertyName *name);
     683                 :     void jsop_bindgname();
     684                 :     void jsop_setelem_slow();
     685                 :     void jsop_getelem_slow();
     686                 :     bool jsop_getprop(PropertyName *name, JSValueType type,
     687                 :                       bool typeCheck = true, bool forPrototype = false);
     688                 :     bool jsop_getprop_dispatch(PropertyName *name);
     689                 :     bool jsop_setprop(PropertyName *name, bool popGuaranteed);
     690                 :     void jsop_setprop_slow(PropertyName *name);
     691                 :     bool jsop_instanceof();
     692                 :     void jsop_name(PropertyName *name, JSValueType type);
     693                 :     bool jsop_xname(PropertyName *name);
     694                 :     void enterBlock(StaticBlockObject *block);
     695                 :     void leaveBlock();
     696                 :     void emitEval(uint32_t argc);
     697                 :     void jsop_arguments(RejoinState rejoin);
     698                 :     bool jsop_tableswitch(jsbytecode *pc);
     699                 : 
     700                 :     /* Fast arithmetic. */
     701                 :     bool jsop_binary_slow(JSOp op, VoidStub stub, JSValueType type, FrameEntry *lhs, FrameEntry *rhs);
     702                 :     bool jsop_binary(JSOp op, VoidStub stub, JSValueType type, types::TypeSet *typeSet);
     703                 :     void jsop_binary_full(FrameEntry *lhs, FrameEntry *rhs, JSOp op, VoidStub stub,
     704                 :                           JSValueType type, bool cannotOverflow, bool ignoreOverflow);
     705                 :     void jsop_binary_full_simple(FrameEntry *fe, JSOp op, VoidStub stub,
     706                 :                                  JSValueType type);
     707                 :     void jsop_binary_double(FrameEntry *lhs, FrameEntry *rhs, JSOp op, VoidStub stub,
     708                 :                             JSValueType type);
     709                 :     void slowLoadConstantDouble(Assembler &masm, FrameEntry *fe,
     710                 :                                 FPRegisterID fpreg);
     711                 :     void maybeJumpIfNotInt32(Assembler &masm, MaybeJump &mj, FrameEntry *fe,
     712                 :                              MaybeRegisterID &mreg);
     713                 :     void maybeJumpIfNotDouble(Assembler &masm, MaybeJump &mj, FrameEntry *fe,
     714                 :                               MaybeRegisterID &mreg);
     715                 :     bool jsop_relational(JSOp op, BoolStub stub, jsbytecode *target, JSOp fused);
     716                 :     bool jsop_relational_full(JSOp op, BoolStub stub, jsbytecode *target, JSOp fused);
     717                 :     bool jsop_relational_double(JSOp op, BoolStub stub, jsbytecode *target, JSOp fused);
     718                 :     bool jsop_relational_int(JSOp op, jsbytecode *target, JSOp fused);
     719                 : 
     720                 :     void emitLeftDoublePath(FrameEntry *lhs, FrameEntry *rhs, FrameState::BinaryAlloc &regs,
     721                 :                             MaybeJump &lhsNotDouble, MaybeJump &rhsNotNumber,
     722                 :                             MaybeJump &lhsUnknownDone);
     723                 :     void emitRightDoublePath(FrameEntry *lhs, FrameEntry *rhs, FrameState::BinaryAlloc &regs,
     724                 :                              MaybeJump &rhsNotNumber2);
     725                 :     bool tryBinaryConstantFold(JSContext *cx, FrameState &frame, JSOp op,
     726                 :                                FrameEntry *lhs, FrameEntry *rhs, Value *vp);
     727                 : 
     728                 :     /* Fast opcodes. */
     729                 :     void jsop_bitop(JSOp op);
     730                 :     bool jsop_mod();
     731                 :     void jsop_neg();
     732                 :     void jsop_bitnot();
     733                 :     void jsop_not();
     734                 :     void jsop_typeof();
     735                 :     bool booleanJumpScript(JSOp op, jsbytecode *target);
     736                 :     bool jsop_ifneq(JSOp op, jsbytecode *target);
     737                 :     bool jsop_andor(JSOp op, jsbytecode *target);
     738                 :     bool jsop_arginc(JSOp op, uint32_t slot);
     739                 :     bool jsop_localinc(JSOp op, uint32_t slot);
     740                 :     bool jsop_newinit();
     741                 :     bool jsop_regexp();
     742                 :     void jsop_initmethod();
     743                 :     void jsop_initprop();
     744                 :     void jsop_initelem();
     745                 :     void jsop_setelem_dense();
     746                 : #ifdef JS_METHODJIT_TYPED_ARRAY
     747                 :     void jsop_setelem_typed(int atype);
     748                 :     void convertForTypedArray(int atype, ValueRemat *vr, bool *allocated);
     749                 : #endif
     750                 :     bool jsop_setelem(bool popGuaranteed);
     751                 :     bool jsop_getelem();
     752                 :     void jsop_getelem_dense(bool isPacked);
     753                 :     void jsop_getelem_args();
     754                 : #ifdef JS_METHODJIT_TYPED_ARRAY
     755                 :     bool jsop_getelem_typed(int atype);
     756                 : #endif
     757                 :     void jsop_toid();
     758                 :     bool isCacheableBaseAndIndex(FrameEntry *obj, FrameEntry *id);
     759                 :     void jsop_stricteq(JSOp op);
     760                 :     bool jsop_equality(JSOp op, BoolStub stub, jsbytecode *target, JSOp fused);
     761                 :     CompileStatus jsop_equality_obj_obj(JSOp op, jsbytecode *target, JSOp fused);
     762                 :     bool jsop_equality_int_string(JSOp op, BoolStub stub, jsbytecode *target, JSOp fused);
     763                 :     void jsop_pos();
     764                 :     void jsop_in();
     765                 : 
     766                 :     static inline Assembler::Condition
     767           69435 :     GetCompareCondition(JSOp op, JSOp fused)
     768                 :     {
     769           69435 :         bool ifeq = fused == JSOP_IFEQ;
     770           69435 :         switch (op) {
     771                 :           case JSOP_GT:
     772            4925 :             return ifeq ? Assembler::LessThanOrEqual : Assembler::GreaterThan;
     773                 :           case JSOP_GE:
     774            7031 :             return ifeq ? Assembler::LessThan : Assembler::GreaterThanOrEqual;
     775                 :           case JSOP_LT:
     776           52707 :             return ifeq ? Assembler::GreaterThanOrEqual : Assembler::LessThan;
     777                 :           case JSOP_LE:
     778            4361 :             return ifeq ? Assembler::GreaterThan : Assembler::LessThanOrEqual;
     779                 :           case JSOP_STRICTEQ:
     780                 :           case JSOP_EQ:
     781             286 :             return ifeq ? Assembler::NotEqual : Assembler::Equal;
     782                 :           case JSOP_STRICTNE:
     783                 :           case JSOP_NE:
     784             125 :             return ifeq ? Assembler::Equal : Assembler::NotEqual;
     785                 :           default:
     786               0 :             JS_NOT_REACHED("unrecognized op");
     787                 :             return Assembler::Equal;
     788                 :         }
     789                 :     }
     790                 : 
     791                 :     static inline Assembler::Condition
     792           76256 :     GetStubCompareCondition(JSOp fused)
     793                 :     {
     794           76256 :         return fused == JSOP_IFEQ ? Assembler::Zero : Assembler::NonZero;
     795                 :     }
     796                 : 
     797                 :     /* Fast builtins. */
     798                 :     JSObject *pushedSingleton(unsigned pushed);
     799                 :     CompileStatus callArrayBuiltin(uint32_t argc, bool callingNew);
     800                 :     CompileStatus inlineNativeFunction(uint32_t argc, bool callingNew);
     801                 :     CompileStatus inlineScriptedFunction(uint32_t argc, bool callingNew);
     802                 :     CompileStatus compileMathAbsInt(FrameEntry *arg);
     803                 :     CompileStatus compileMathAbsDouble(FrameEntry *arg);
     804                 :     CompileStatus compileMathSqrt(FrameEntry *arg);
     805                 :     CompileStatus compileMathMinMaxDouble(FrameEntry *arg1, FrameEntry *arg2, 
     806                 :                                           Assembler::DoubleCondition cond); 
     807                 :     CompileStatus compileMathMinMaxInt(FrameEntry *arg1, FrameEntry *arg2, 
     808                 :                                        Assembler::Condition cond);                                       
     809                 :     CompileStatus compileMathPowSimple(FrameEntry *arg1, FrameEntry *arg2);
     810                 :     CompileStatus compileArrayPush(FrameEntry *thisv, FrameEntry *arg);
     811                 :     CompileStatus compileArrayConcat(types::TypeSet *thisTypes, types::TypeSet *argTypes,
     812                 :                                      FrameEntry *thisValue, FrameEntry *argValue);
     813                 :     CompileStatus compileArrayPopShift(FrameEntry *thisv, bool isPacked, bool isArrayPop);
     814                 :     CompileStatus compileArrayWithLength(uint32_t argc);
     815                 :     CompileStatus compileArrayWithArgs(uint32_t argc);
     816                 : 
     817                 :     enum RoundingMode { Floor, Round };
     818                 :     CompileStatus compileRound(FrameEntry *arg, RoundingMode mode);
     819                 : 
     820                 :     enum GetCharMode { GetChar, GetCharCode };
     821                 :     CompileStatus compileGetChar(FrameEntry *thisValue, FrameEntry *arg, GetCharMode mode);
     822                 :     
     823                 :     CompileStatus compileStringFromCode(FrameEntry *arg);
     824                 :     CompileStatus compileParseInt(JSValueType argType, uint32_t argc);
     825                 : 
     826                 :     void prepareStubCall(Uses uses);
     827                 :     Call emitStubCall(void *ptr, DataLabelPtr *pinline);
     828                 : };
     829                 : 
     830                 : // Given a stub call, emits the call into the inline assembly path. rejoin
     831                 : // indicates how to rejoin should this call trigger expansion/discarding.
     832                 : #define INLINE_STUBCALL(stub, rejoin)                                       \
     833                 :     inlineStubCall(JS_FUNC_TO_DATA_PTR(void *, (stub)), rejoin, Uses(0))
     834                 : #define INLINE_STUBCALL_USES(stub, rejoin, uses)                            \
     835                 :     inlineStubCall(JS_FUNC_TO_DATA_PTR(void *, (stub)), rejoin, uses)
     836                 : 
     837                 : // Given a stub call, emits the call into the out-of-line assembly path.
     838                 : // Unlike the INLINE_STUBCALL variant, this returns the Call offset.
     839                 : #define OOL_STUBCALL(stub, rejoin)                                          \
     840                 :     stubcc.emitStubCall(JS_FUNC_TO_DATA_PTR(void *, (stub)), rejoin, Uses(0))
     841                 : #define OOL_STUBCALL_USES(stub, rejoin, uses)                               \
     842                 :     stubcc.emitStubCall(JS_FUNC_TO_DATA_PTR(void *, (stub)), rejoin, uses)
     843                 : 
     844                 : // Same as OOL_STUBCALL, but specifies a slot depth.
     845                 : #define OOL_STUBCALL_LOCAL_SLOTS(stub, rejoin, slots)                       \
     846                 :     stubcc.emitStubCall(JS_FUNC_TO_DATA_PTR(void *, (stub)), rejoin, Uses(0), (slots))
     847                 : 
     848                 : } /* namespace js */
     849                 : } /* namespace mjit */
     850                 : 
     851                 : #endif
     852                 : 

Generated by: LCOV version 1.7