LCOV - code coverage report
Current view: directory - js/src/methodjit - FrameState-inl.h (source / functions) Found Hit Coverage
Test: app.info Lines: 711 672 94.5 %
Date: 2012-06-02 Functions: 92 89 96.7 %

       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                 :  *
      26                 :  * Alternatively, the contents of this file may be used under the terms of
      27                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      28                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      29                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      30                 :  * of those above. If you wish to allow use of your version of this file only
      31                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      32                 :  * use your version of this file under the terms of the MPL, indicate your
      33                 :  * decision by deleting the provisions above and replace them with the notice
      34                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      35                 :  * the provisions above, a recipient may use your version of this file under
      36                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      37                 :  *
      38                 :  * ***** END LICENSE BLOCK ***** */
      39                 : 
      40                 : #if !defined jsjaeger_framestate_inl_h__ && defined JS_METHODJIT
      41                 : #define jsjaeger_framestate_inl_h__
      42                 : 
      43                 : #include "methodjit/LoopState.h"
      44                 : 
      45                 : namespace js {
      46                 : namespace mjit {
      47                 : 
      48                 : inline void
      49         2606451 : FrameState::addToTracker(FrameEntry *fe)
      50                 : {
      51         2606451 :     JS_ASSERT(!fe->isTracked());
      52         2606451 :     fe->track(tracker.nentries);
      53         2606451 :     tracker.add(fe);
      54         2606451 : }
      55                 : 
      56                 : inline FrameEntry *
      57        18389190 : FrameState::peek(int32_t depth)
      58                 : {
      59        18389190 :     JS_ASSERT(depth < 0);
      60        18389190 :     JS_ASSERT(a->sp + depth >= a->spBase);
      61        18389190 :     FrameEntry *fe = a->sp + depth;
      62        18389190 :     if (!fe->isTracked()) {
      63          124678 :         addToTracker(fe);
      64          124678 :         fe->resetSynced();
      65                 :     }
      66        18389190 :     return fe;
      67                 : }
      68                 : 
      69                 : inline void
      70         2319276 : FrameState::popn(uint32_t n)
      71                 : {
      72         6860189 :     for (uint32_t i = 0; i < n; i++)
      73         4540913 :         pop();
      74         2319276 : }
      75                 : 
      76                 : inline bool
      77          743618 : FrameState::haveSameBacking(FrameEntry *lhs, FrameEntry *rhs)
      78                 : {
      79          743618 :     if (lhs->isCopy())
      80          274317 :         lhs = lhs->copyOf();
      81          743618 :     if (rhs->isCopy())
      82           22217 :         rhs = rhs->copyOf();
      83          743618 :     return lhs == rhs;
      84                 : }
      85                 : 
      86                 : inline FrameEntry *
      87           18962 : FrameState::getTemporary(uint32_t which)
      88                 : {
      89           18962 :     JS_ASSERT(which < TEMPORARY_LIMIT);
      90                 : 
      91           18962 :     FrameEntry *fe = temporaries + which;
      92           18962 :     JS_ASSERT(fe < temporariesTop);
      93                 : 
      94           18962 :     return getOrTrack(uint32_t(fe - entries));
      95                 : }
      96                 : 
      97                 : inline AnyRegisterID
      98         5709435 : FrameState::allocReg(uint32_t mask)
      99                 : {
     100         5709435 :     if (freeRegs.hasRegInMask(mask)) {
     101         5592855 :         AnyRegisterID reg = freeRegs.takeAnyReg(mask);
     102         5592855 :         modifyReg(reg);
     103         5592855 :         return reg;
     104                 :     }
     105                 : 
     106          116580 :     AnyRegisterID reg = evictSomeReg(mask);
     107          116580 :     modifyReg(reg);
     108          116580 :     return reg;
     109                 : }
     110                 : 
     111                 : inline JSC::MacroAssembler::RegisterID
     112         4343970 : FrameState::allocReg()
     113                 : {
     114         4343970 :     return allocReg(Registers::AvailRegs).reg();
     115                 : }
     116                 : 
     117                 : inline JSC::MacroAssembler::FPRegisterID
     118         1336759 : FrameState::allocFPReg()
     119                 : {
     120         1336759 :     return allocReg(Registers::AvailFPRegs).fpreg();
     121                 : }
     122                 : 
     123                 : inline AnyRegisterID
     124         2053131 : FrameState::allocAndLoadReg(FrameEntry *fe, bool fp, RematInfo::RematType type)
     125                 : {
     126         2053131 :     AnyRegisterID reg;
     127         2053131 :     uint32_t mask = fp ? (uint32_t) Registers::AvailFPRegs : (uint32_t) Registers::AvailRegs;
     128                 : 
     129                 :     /*
     130                 :      * Decide whether to retroactively mark a register as holding the entry
     131                 :      * at the start of the current loop. We can do this if (a) the register has
     132                 :      * not been touched since the start of the loop (it is in loopRegs), (b)
     133                 :      * the entry has also not been written to or already had a loop register
     134                 :      * assigned, and (c) we are not in an inline call with multiple callees or
     135                 :      * exit points --- we won't pick up the new loop register when restoring.
     136                 :      */
     137         2106672 :     if (loop && freeRegs.hasRegInMask(loop->getLoopRegs() & mask) &&
     138           37039 :         type == RematInfo::DATA && isOuterSlot(fe) && !cc.activeFrameHasMultipleExits() &&
     139           16502 :         fe->lastLoop < loop->headOffset()) {
     140           16201 :         reg = freeRegs.takeAnyReg(loop->getLoopRegs() & mask);
     141           16201 :         regstate(reg).associate(fe, RematInfo::DATA);
     142           16201 :         fe->lastLoop = loop->headOffset();
     143           16201 :         loop->setLoopReg(reg, fe);
     144           16201 :         return reg;
     145                 :     }
     146                 : 
     147         2036930 :     if (!freeRegs.empty(mask))
     148         1979369 :         reg = freeRegs.takeAnyReg(mask);
     149                 :     else
     150           57561 :         reg = evictSomeReg(mask);
     151         2036930 :     modifyReg(reg);
     152                 : 
     153         2036930 :     if (fp)
     154            1164 :         masm.loadDouble(addressOf(fe), reg.fpreg());
     155         2035766 :     else if (type == RematInfo::TYPE)
     156         1188299 :         masm.loadTypeTag(addressOf(fe), reg.reg());
     157                 :     else
     158          847467 :         masm.loadPayload(addressOf(fe), reg.reg());
     159                 : 
     160         2036930 :     regstate(reg).associate(fe, type);
     161         2036930 :     return reg;
     162                 : }
     163                 : 
     164                 : inline void
     165         8536492 : FrameState::modifyReg(AnyRegisterID reg)
     166                 : {
     167         8536492 :     if (loop)
     168          865512 :         loop->clearLoopReg(reg);
     169         8536492 : }
     170                 : 
     171                 : inline void
     172           11406 : FrameState::convertInt32ToDouble(Assembler &masm, FrameEntry *fe, FPRegisterID fpreg) const
     173                 : {
     174           11406 :     JS_ASSERT(!fe->isConstant());
     175                 : 
     176           11406 :     if (fe->isCopy())
     177            2294 :         fe = fe->copyOf();
     178                 :     
     179           11406 :     if (fe->data.inRegister())
     180            9396 :         masm.convertInt32ToDouble(fe->data.reg(), fpreg);
     181                 :     else
     182            2010 :         masm.convertInt32ToDouble(masm.payloadOf(addressOf(fe)), fpreg);
     183           11406 : }
     184                 : 
     185                 : inline bool
     186               0 : FrameState::peekTypeInRegister(FrameEntry *fe) const
     187                 : {
     188               0 :     if (fe->isCopy())
     189               0 :         fe = fe->copyOf();
     190               0 :     return fe->type.inRegister();
     191                 : }
     192                 : 
     193                 : inline void
     194         8845808 : FrameState::pop()
     195                 : {
     196         8845808 :     JS_ASSERT(a->sp > a->spBase);
     197                 : 
     198         8845808 :     FrameEntry *fe = --a->sp;
     199         8845808 :     if (!fe->isTracked())
     200           62972 :         return;
     201                 : 
     202         8782836 :     forgetAllRegs(fe);
     203         8782836 :     fe->type.invalidate();
     204         8782836 :     fe->data.invalidate();
     205         8782836 :     fe->clear();
     206                 : 
     207         8782836 :     extraArray[fe - entries].reset();
     208                 : }
     209                 : 
     210                 : inline void
     211         1885716 : FrameState::freeReg(AnyRegisterID reg)
     212                 : {
     213         1885716 :     JS_ASSERT(!regstate(reg).usedBy());
     214                 : 
     215         1885716 :     freeRegs.putReg(reg);
     216         1885716 : }
     217                 : 
     218                 : inline void
     219         6339139 : FrameState::forgetReg(AnyRegisterID reg)
     220                 : {
     221                 :     /*
     222                 :      * Important: Do not touch the fe here. We can peephole optimize away
     223                 :      * loads and stores by re-using the contents of old FEs.
     224                 :      */
     225         6339139 :     JS_ASSERT_IF(regstate(reg).fe(), !regstate(reg).fe()->isCopy());
     226                 : 
     227         6339139 :     if (!regstate(reg).isPinned()) {
     228         5959565 :         regstate(reg).forget();
     229         5959565 :         freeRegs.putReg(reg);
     230                 :     }
     231         6339139 : }
     232                 : 
     233                 : inline FrameEntry *
     234         8909577 : FrameState::rawPush()
     235                 : {
     236         8909577 :     JS_ASSERT(a->sp < temporaries);
     237         8909577 :     FrameEntry *fe = a->sp++;
     238                 : 
     239         8909577 :     if (!fe->isTracked())
     240         1748169 :         addToTracker(fe);
     241         8909577 :     fe->type.invalidate();
     242         8909577 :     fe->data.invalidate();
     243         8909577 :     fe->clear();
     244                 : 
     245         8909577 :     extraArray[fe - entries].reset();
     246                 : 
     247         8909577 :     return fe;
     248                 : }
     249                 : 
     250                 : inline void
     251         1701936 : FrameState::push(const Value &v)
     252                 : {
     253         1701936 :     FrameEntry *fe = rawPush();
     254         1701936 :     fe->setConstant(v);
     255         1701936 : }
     256                 : 
     257                 : inline void
     258         2718445 : FrameState::pushSynced(JSValueType type)
     259                 : {
     260         2718445 :     FrameEntry *fe = rawPush();
     261                 : 
     262         2718445 :     fe->resetSynced();
     263         2718445 :     if (type != JSVAL_TYPE_UNKNOWN) {
     264           94421 :         fe->setType(type);
     265           94421 :         if (type == JSVAL_TYPE_DOUBLE)
     266             257 :             masm.ensureInMemoryDouble(addressOf(fe));
     267                 :     }
     268         2718445 : }
     269                 : 
     270                 : inline void
     271                 : FrameState::pushSynced(JSValueType type, RegisterID reg)
     272                 : {
     273                 :     FrameEntry *fe = rawPush();
     274                 : 
     275                 :     fe->resetUnsynced();
     276                 :     fe->type.sync();
     277                 :     fe->data.sync();
     278                 :     fe->setType(type);
     279                 :     fe->data.setRegister(reg);
     280                 :     regstate(reg).associate(fe, RematInfo::DATA);
     281                 : }
     282                 : 
     283                 : inline void
     284          410902 : FrameState::loadIntoRegisters(Address address, bool reuseBase,
     285                 :                               RegisterID *ptypeReg, RegisterID *pdataReg)
     286                 : {
     287                 : 
     288                 : #ifdef JS_PUNBOX64
     289                 : 
     290                 :     // It's okay if either of these clobbers address.base, since we guarantee
     291                 :     // eviction will not physically clobber. It's also safe, on x64, for
     292                 :     // loadValueAsComponents() to take either type or data regs as address.base.
     293                 :     RegisterID typeReg = allocReg();
     294                 :     RegisterID dataReg = reuseBase ? address.base : allocReg();
     295                 :     masm.loadValueAsComponents(address, typeReg, dataReg);
     296                 : 
     297                 : #elif JS_NUNBOX32
     298                 : 
     299                 :     // Prevent us from clobbering this reg.
     300          410902 :     bool free = freeRegs.hasReg(address.base);
     301          410902 :     bool needsPin = !free && regstate(address.base).fe();
     302          410902 :     if (free)
     303            2107 :         freeRegs.takeReg(address.base);
     304          410902 :     if (needsPin)
     305            3756 :         pinReg(address.base);
     306                 : 
     307          410902 :     RegisterID typeReg = allocReg();
     308                 : 
     309          410902 :     masm.loadTypeTag(address, typeReg);
     310                 : 
     311                 :     // Allow re-use of the base register. This could avoid a spill, and
     312                 :     // is safe because the following allocReg() won't actually emit any
     313                 :     // writes to the register.
     314          410902 :     if (free)
     315            2107 :         freeRegs.putReg(address.base);
     316          410902 :     if (needsPin)
     317            3756 :         unpinReg(address.base);
     318                 : 
     319          410902 :     RegisterID dataReg = reuseBase ? address.base : allocReg();
     320          410902 :     masm.loadPayload(address, dataReg);
     321                 : 
     322                 : #endif
     323                 : 
     324          410902 :     *ptypeReg = typeReg;
     325          410902 :     *pdataReg = dataReg;
     326          410902 : }
     327                 : 
     328                 : inline void
     329          381621 : FrameState::push(Address address, JSValueType knownType, bool reuseBase)
     330                 : {
     331          381621 :     if (knownType == JSVAL_TYPE_DOUBLE) {
     332            1044 :         FPRegisterID fpreg = allocFPReg();
     333            1044 :         masm.moveInt32OrDouble(address, fpreg);
     334            1044 :         pushDouble(fpreg);
     335            1044 :         if (reuseBase)
     336             696 :             freeReg(address.base);
     337            1044 :         return;
     338                 :     }
     339                 : 
     340          380577 :     if (knownType != JSVAL_TYPE_UNKNOWN) {
     341           61335 :         RegisterID dataReg = reuseBase ? address.base : allocReg();
     342           61335 :         masm.loadPayload(address, dataReg);
     343           61335 :         pushTypedPayload(knownType, dataReg);
     344           61335 :         return;
     345                 :     }
     346                 : 
     347                 :     RegisterID typeReg, dataReg;
     348          319242 :     loadIntoRegisters(address, reuseBase, &typeReg, &dataReg);
     349                 : 
     350          319242 :     pushRegs(typeReg, dataReg, JSVAL_TYPE_UNKNOWN);
     351                 : }
     352                 : 
     353                 : inline void
     354               0 : FrameState::pushWord(Address address, JSValueType knownType, bool reuseBase)
     355                 : {
     356               0 :     JS_ASSERT(knownType != JSVAL_TYPE_DOUBLE);
     357               0 :     JS_ASSERT(knownType != JSVAL_TYPE_UNKNOWN);
     358                 : 
     359               0 :     RegisterID dataReg = reuseBase ? address.base : allocReg();
     360               0 :     masm.loadPtr(address, dataReg);
     361               0 :     pushTypedPayload(knownType, dataReg);
     362               0 : }
     363                 : 
     364                 : inline JSC::MacroAssembler::FPRegisterID
     365         1899892 : FrameState::storeRegs(int32_t depth, RegisterID type, RegisterID data, JSValueType knownType)
     366                 : {
     367         1899892 :     FrameEntry *fe = peek(depth);
     368         1899892 :     forgetEntry(fe);
     369         1899892 :     fe->resetUnsynced();
     370                 : 
     371                 :     /*
     372                 :      * Even if the type or data gets freed due to knownType or a double result,
     373                 :      * neither register should be clobbered (see Compiler::testBarrier).
     374                 :      */
     375         1899892 :     JS_ASSERT(!freeRegs.hasReg(type) && !freeRegs.hasReg(data));
     376                 : 
     377         1899892 :     if (knownType == JSVAL_TYPE_UNKNOWN) {
     378         1780078 :         fe->type.setRegister(type);
     379         1780078 :         fe->data.setRegister(data);
     380         1780078 :         regstate(type).associate(fe, RematInfo::TYPE);
     381         1780078 :         regstate(data).associate(fe, RematInfo::DATA);
     382         1780078 :         return Registers::FPConversionTemp;
     383                 :     }
     384                 : 
     385          119814 :     if (knownType == JSVAL_TYPE_DOUBLE) {
     386           10152 :         FPRegisterID fpreg = allocFPReg();
     387           10152 :         masm.moveInt32OrDouble(data, type, addressOf(fe), fpreg);
     388           10152 :         fe->setType(JSVAL_TYPE_DOUBLE);
     389           10152 :         fe->data.setFPRegister(fpreg);
     390           10152 :         regstate(fpreg).associate(fe, RematInfo::DATA);
     391           10152 :         freeReg(type);
     392           10152 :         freeReg(data);
     393           10152 :         return fpreg;
     394                 :     }
     395                 : 
     396          109662 :     freeReg(type);
     397          109662 :     fe->setType(knownType);
     398          109662 :     fe->data.setRegister(data);
     399          109662 :     regstate(data).associate(fe, RematInfo::DATA);
     400          109662 :     return Registers::FPConversionTemp;
     401                 : }
     402                 : 
     403                 : inline JSC::MacroAssembler::FPRegisterID
     404         1899892 : FrameState::pushRegs(RegisterID type, RegisterID data, JSValueType knownType)
     405                 : {
     406         1899892 :     pushSynced(JSVAL_TYPE_UNKNOWN);
     407         1899892 :     return storeRegs(-1, type, data, knownType);
     408                 : }
     409                 : 
     410                 : inline void
     411          147359 : FrameState::reloadEntry(Assembler &masm, Address address, FrameEntry *fe)
     412                 : {
     413          147359 :     if (fe->data.inRegister()) {
     414          146527 :         if (fe->type.inRegister()) {
     415          118693 :             masm.loadValueAsComponents(address, fe->type.reg(), fe->data.reg());
     416                 :         } else {
     417           27834 :             JS_ASSERT(fe->isTypeKnown());
     418           27834 :             masm.loadPayload(address, fe->data.reg());
     419                 :         }
     420                 :     } else {
     421             832 :         JS_ASSERT(fe->data.inFPRegister());
     422             832 :         masm.moveInt32OrDouble(address, fe->data.fpreg());
     423                 :     }
     424          147359 : }
     425                 : 
     426                 : inline void
     427          296829 : FrameState::pushTypedPayload(JSValueType type, RegisterID payload)
     428                 : {
     429          296829 :     JS_ASSERT(type != JSVAL_TYPE_DOUBLE);
     430          296829 :     JS_ASSERT(!freeRegs.hasReg(payload));
     431                 : 
     432          296829 :     FrameEntry *fe = rawPush();
     433                 : 
     434          296829 :     fe->resetUnsynced();
     435          296829 :     fe->setType(type);
     436          296829 :     fe->data.setRegister(payload);
     437          296829 :     regstate(payload).associate(fe, RematInfo::DATA);
     438          296829 : }
     439                 : 
     440                 : inline void
     441          562451 : FrameState::pushNumber(RegisterID payload, bool asInt32)
     442                 : {
     443          562451 :     JS_ASSERT(!freeRegs.hasReg(payload));
     444                 : 
     445          562451 :     FrameEntry *fe = rawPush();
     446                 : 
     447          562451 :     if (asInt32) {
     448          559387 :         if (!fe->type.synced())
     449          251273 :             masm.storeTypeTag(ImmType(JSVAL_TYPE_INT32), addressOf(fe));
     450          559387 :         fe->type.setMemory();
     451                 :     } else {
     452            3064 :         fe->type.setMemory();
     453                 :     }
     454                 : 
     455          562451 :     fe->data.unsync();
     456          562451 :     fe->data.setRegister(payload);
     457          562451 :     regstate(payload).associate(fe, RematInfo::DATA);
     458          562451 : }
     459                 : 
     460                 : inline void
     461                 : FrameState::pushInt32(RegisterID payload)
     462                 : {
     463                 :     FrameEntry *fe = rawPush();
     464                 : 
     465                 :     masm.storeTypeTag(ImmType(JSVAL_TYPE_INT32), addressOf(fe));
     466                 :     fe->type.setMemory();
     467                 : 
     468                 :     fe->data.unsync();
     469                 :     fe->data.setRegister(payload);
     470                 :     regstate(payload).associate(fe, RematInfo::DATA);
     471                 : }
     472                 : 
     473                 : inline void
     474            4630 : FrameState::pushUntypedPayload(JSValueType type, RegisterID payload)
     475                 : {
     476            4630 :     JS_ASSERT(!freeRegs.hasReg(payload));
     477                 : 
     478            4630 :     FrameEntry *fe = rawPush();
     479                 : 
     480            4630 :     masm.storeTypeTag(ImmType(type), addressOf(fe));
     481                 : 
     482                 :     /* The forceful type sync will assert otherwise. */
     483                 : #ifdef DEBUG
     484            4630 :     fe->type.unsync();
     485                 : #endif
     486            4630 :     fe->type.setMemory();
     487            4630 :     fe->data.unsync();
     488            4630 :     fe->data.setRegister(payload);
     489            4630 :     regstate(payload).associate(fe, RematInfo::DATA);
     490            4630 : }
     491                 : 
     492                 : inline void
     493                 : FrameState::pushUntypedValue(const Value &v)
     494                 : {
     495                 :     FrameEntry *fe = rawPush();
     496                 : 
     497                 :     masm.storeValue(v, addressOf(fe));
     498                 : 
     499                 :     /* The forceful type sync will assert otherwise. */
     500                 : #ifdef DEBUG
     501                 :     fe->type.unsync();
     502                 : #endif
     503                 :     fe->type.setMemory();
     504                 :     fe->data.unsync();
     505                 :     fe->data.setMemory();
     506                 : }
     507                 : 
     508                 : inline JSC::MacroAssembler::RegisterID
     509                 : FrameState::tempRegForType(FrameEntry *fe, RegisterID fallback)
     510                 : {
     511                 :     JS_ASSERT(!regstate(fallback).fe());
     512                 :     if (fe->isCopy())
     513                 :         fe = fe->copyOf();
     514                 : 
     515                 :     JS_ASSERT(!fe->type.isConstant());
     516                 : 
     517                 :     if (fe->type.inRegister())
     518                 :         return fe->type.reg();
     519                 : 
     520                 :     /* :XXX: X86 */
     521                 : 
     522                 :     masm.loadTypeTag(addressOf(fe), fallback);
     523                 :     return fallback;
     524                 : }
     525                 : 
     526                 : 
     527                 : inline JSC::MacroAssembler::RegisterID
     528         3289407 : FrameState::tempRegForType(FrameEntry *fe)
     529                 : {
     530         3289407 :     if (fe->isCopy())
     531          414748 :         fe = fe->copyOf();
     532                 : 
     533         3289407 :     JS_ASSERT(!fe->type.isConstant());
     534                 : 
     535         3289407 :     if (fe->type.inRegister())
     536         2102683 :         return fe->type.reg();
     537                 : 
     538                 :     /* :XXX: X86 */
     539                 : 
     540         1186724 :     RegisterID reg = allocAndLoadReg(fe, false, RematInfo::TYPE).reg();
     541         1186724 :     fe->type.setRegister(reg);
     542         1186724 :     return reg;
     543                 : }
     544                 : 
     545                 : inline void
     546               0 : FrameState::loadTypeIntoReg(const FrameEntry *fe, RegisterID reg)
     547                 : {
     548               0 :     if (fe->isCopy())
     549               0 :         fe = fe->copyOf();
     550                 : 
     551               0 :     JS_ASSERT(!fe->type.isConstant());
     552                 : 
     553               0 :     if (fe->type.inRegister()) {
     554               0 :         if (fe->type.reg() == reg)
     555               0 :             return;
     556               0 :         masm.move(fe->type.reg(), reg);
     557               0 :         return;
     558                 :     }
     559                 : 
     560               0 :     masm.loadTypeTag(addressOf(fe), reg);
     561                 : }
     562                 : 
     563                 : inline void
     564                 : FrameState::loadDataIntoReg(const FrameEntry *fe, RegisterID reg)
     565                 : {
     566                 :     if (fe->isCopy())
     567                 :         fe = fe->copyOf();
     568                 : 
     569                 :     JS_ASSERT(!fe->data.isConstant());
     570                 : 
     571                 :     if (fe->data.inRegister()) {
     572                 :         if (fe->data.reg() == reg)
     573                 :             return;
     574                 :         masm.move(fe->data.reg(), reg);
     575                 :         return;
     576                 :     }
     577                 : 
     578                 :     masm.loadPayload(addressOf(fe), reg);
     579                 : }
     580                 : 
     581                 : inline JSC::MacroAssembler::RegisterID
     582         2991331 : FrameState::tempRegForData(FrameEntry *fe)
     583                 : {
     584         2991331 :     JS_ASSERT(!fe->isConstant());
     585         2991331 :     JS_ASSERT(!fe->isType(JSVAL_TYPE_DOUBLE));
     586                 : 
     587         2991331 :     if (fe->isCopy())
     588          307831 :         fe = fe->copyOf();
     589                 : 
     590         2991331 :     if (fe->data.inRegister())
     591         2130214 :         return fe->data.reg();
     592                 : 
     593          861117 :     RegisterID reg = allocAndLoadReg(fe, false, RematInfo::DATA).reg();
     594          861117 :     fe->data.setRegister(reg);
     595          861117 :     return reg;
     596                 : }
     597                 : 
     598                 : inline void
     599         1096095 : FrameState::forgetMismatchedObject(FrameEntry *fe)
     600                 : {
     601         1096095 :     if (fe->isNotType(JSVAL_TYPE_OBJECT)) {
     602            1055 :         if (fe->isCopied()) {
     603               1 :             syncFe(fe);
     604               1 :             uncopy(fe);
     605               1 :             fe->resetSynced();
     606                 :         } else {
     607            1054 :             syncAndForgetFe(fe);
     608                 :         }
     609            1055 :         fe->clear();
     610                 :     }
     611                 : 
     612         1096095 :     if (fe->isConstant()) {
     613           32341 :         RegisterID reg = allocReg();
     614           32341 :         regstate(reg).associate(fe, RematInfo::DATA);
     615                 : 
     616           32341 :         masm.move(JSC::MacroAssembler::ImmPtr(&fe->getValue().toObject()), reg);
     617           32341 :         fe->data.setRegister(reg);
     618                 :     }
     619         1096095 : }
     620                 : 
     621                 : inline JSC::MacroAssembler::FPRegisterID
     622           23617 : FrameState::tempFPRegForData(FrameEntry *fe)
     623                 : {
     624           23617 :     JS_ASSERT(!fe->isConstant());
     625           23617 :     JS_ASSERT(fe->isType(JSVAL_TYPE_DOUBLE));
     626                 : 
     627           23617 :     if (fe->isCopy())
     628            1630 :         fe = fe->copyOf();
     629                 : 
     630           23617 :     JS_ASSERT(!fe->data.inRegister());
     631                 : 
     632           23617 :     if (fe->data.inFPRegister())
     633           22311 :         return fe->data.fpreg();
     634                 : 
     635            1306 :     FPRegisterID reg = allocAndLoadReg(fe, true, RematInfo::DATA).fpreg();
     636            1306 :     fe->data.setFPRegister(reg);
     637            1306 :     return reg;
     638                 : }
     639                 : 
     640                 : inline AnyRegisterID
     641            5126 : FrameState::tempRegInMaskForData(FrameEntry *fe, uint32_t mask)
     642                 : {
     643            5126 :     JS_ASSERT(!fe->isConstant());
     644            5126 :     JS_ASSERT_IF(fe->isType(JSVAL_TYPE_DOUBLE), !(mask & ~Registers::AvailFPRegs));
     645            5126 :     JS_ASSERT_IF(!fe->isType(JSVAL_TYPE_DOUBLE), !(mask & ~Registers::AvailRegs));
     646                 : 
     647            5126 :     if (fe->isCopy())
     648             593 :         fe = fe->copyOf();
     649                 : 
     650            5126 :     AnyRegisterID reg;
     651            5126 :     if (fe->data.inRegister() || fe->data.inFPRegister()) {
     652            4393 :         AnyRegisterID old;
     653            4393 :         if (fe->data.inRegister())
     654            4312 :             old = fe->data.reg();
     655                 :         else
     656              81 :             old = fe->data.fpreg();
     657            4393 :         if (Registers::maskReg(old) & mask)
     658            2569 :             return old;
     659                 : 
     660                 :         /* Keep the old register pinned. */
     661            1824 :         regstate(old).forget();
     662            1824 :         reg = allocReg(mask);
     663            1824 :         if (reg.isReg())
     664            1824 :             masm.move(old.reg(), reg.reg());
     665                 :         else
     666               0 :             masm.moveDouble(old.fpreg(), reg.fpreg());
     667            1824 :         freeReg(old);
     668                 :     } else {
     669             733 :         reg = allocReg(mask);
     670             733 :         if (reg.isReg())
     671             733 :             masm.loadPayload(addressOf(fe), reg.reg());
     672                 :         else
     673               0 :             masm.loadDouble(addressOf(fe), reg.fpreg());
     674                 :     }
     675            2557 :     regstate(reg).associate(fe, RematInfo::DATA);
     676            2557 :     if (reg.isReg())
     677            2557 :         fe->data.setRegister(reg.reg());
     678                 :     else
     679               0 :         fe->data.setFPRegister(reg.fpreg());
     680            2557 :     return reg;
     681                 : }
     682                 : 
     683                 : inline JSC::MacroAssembler::RegisterID
     684                 : FrameState::tempRegForData(FrameEntry *fe, RegisterID reg, Assembler &masm) const
     685                 : {
     686                 :     JS_ASSERT(!fe->data.isConstant());
     687                 : 
     688                 :     if (fe->isCopy())
     689                 :         fe = fe->copyOf();
     690                 : 
     691                 :     JS_ASSERT(!fe->data.inFPRegister());
     692                 : 
     693                 :     if (fe->data.inRegister()) {
     694                 :         JS_ASSERT(fe->data.reg() != reg);
     695                 :         return fe->data.reg();
     696                 :     } else {
     697                 :         masm.loadPayload(addressOf(fe), reg);
     698                 :         return reg;
     699                 :     }
     700                 : }
     701                 : 
     702                 : inline bool
     703          408044 : FrameState::shouldAvoidTypeRemat(FrameEntry *fe)
     704                 : {
     705          408044 :     return !fe->isCopy() && fe->type.inMemory();
     706                 : }
     707                 : 
     708                 : inline bool
     709           43275 : FrameState::shouldAvoidDataRemat(FrameEntry *fe)
     710                 : {
     711           43275 :     return !fe->isCopy() && fe->data.inMemory();
     712                 : }
     713                 : 
     714                 : inline void
     715           57314 : FrameState::ensureFeSynced(const FrameEntry *fe, Assembler &masm) const
     716                 : {
     717           57314 :     Address to = addressOf(fe);
     718           57314 :     const FrameEntry *backing = fe;
     719           57314 :     if (fe->isCopy())
     720            2916 :         backing = fe->copyOf();
     721                 : 
     722           57314 :     if (backing->isType(JSVAL_TYPE_DOUBLE)) {
     723           53093 :         if (fe->data.synced()) {
     724                 :             /* Entries representing known doubles can't be partially synced. */
     725            6954 :             JS_ASSERT(fe->type.synced());
     726            6954 :             return;
     727                 :         }
     728           46139 :         if (backing->isConstant()) {
     729           11296 :             masm.storeValue(backing->getValue(), to);
     730           34843 :         } else if (backing->data.inFPRegister()) {
     731           33902 :             masm.storeDouble(backing->data.fpreg(), to);
     732                 :         } else {
     733                 :             /* Use a temporary so the entry can be synced without allocating a register. */
     734             941 :             JS_ASSERT(backing->data.inMemory() && backing != fe);
     735             941 :             masm.loadDouble(addressOf(backing), Registers::FPConversionTemp);
     736             941 :             masm.storeDouble(Registers::FPConversionTemp, to);
     737                 :         }
     738           46139 :         return;
     739                 :     }
     740                 : 
     741                 : #if defined JS_PUNBOX64
     742                 :     /* If we can, sync the type and data in one go. */
     743                 :     if (!fe->data.synced() && !fe->type.synced()) {
     744                 :         if (backing->isConstant())
     745                 :             masm.storeValue(backing->getValue(), to);
     746                 :         else if (backing->isTypeKnown())
     747                 :             masm.storeValueFromComponents(ImmType(backing->getKnownType()), backing->data.reg(), to);
     748                 :         else
     749                 :             masm.storeValueFromComponents(backing->type.reg(), backing->data.reg(), to);
     750                 :         return;
     751                 :     }
     752                 : #endif
     753                 : 
     754                 :     /* 
     755                 :      * On x86_64, only one of the following two calls will have output,
     756                 :      * and a load will only occur if necessary.
     757                 :      */
     758            4221 :     ensureDataSynced(fe, masm);
     759            4221 :     ensureTypeSynced(fe, masm);
     760                 : }
     761                 : 
     762                 : inline void
     763        15484618 : FrameState::ensureTypeSynced(const FrameEntry *fe, Assembler &masm) const
     764                 : {
     765        15484618 :     if (fe->type.synced())
     766         7194530 :         return;
     767                 : 
     768         8290088 :     Address to = addressOf(fe);
     769         8290088 :     const FrameEntry *backing = fe;
     770         8290088 :     if (fe->isCopy())
     771         1261348 :         backing = fe->copyOf();
     772                 : 
     773                 : #if defined JS_PUNBOX64
     774                 :     /* Attempt to store the entire Value, to prevent a load. */
     775                 :     if (backing->isConstant()) {
     776                 :         masm.storeValue(backing->getValue(), to);
     777                 :         return;
     778                 :     }
     779                 : 
     780                 :     if (backing->data.inRegister()) {
     781                 :         RegisterID dreg = backing->data.reg();
     782                 :         if (backing->isTypeKnown())
     783                 :             masm.storeValueFromComponents(ImmType(backing->getKnownType()), dreg, to);
     784                 :         else
     785                 :             masm.storeValueFromComponents(backing->type.reg(), dreg, to);
     786                 :         return;
     787                 :     }
     788                 : #endif
     789                 : 
     790                 :     /* Store a double's type bits, even though !isTypeKnown(). */
     791         8290088 :     if (backing->isConstant())
     792         2375091 :         masm.storeTypeTag(ImmTag(backing->getKnownTag()), to);
     793         5914997 :     else if (backing->isTypeKnown())
     794          961858 :         masm.storeTypeTag(ImmType(backing->getKnownType()), to); 
     795                 :     else
     796         4953139 :         masm.storeTypeTag(backing->type.reg(), to);
     797                 : }
     798                 : 
     799                 : inline void
     800        15691826 : FrameState::ensureDataSynced(const FrameEntry *fe, Assembler &masm) const
     801                 : {
     802        15691826 :     if (fe->data.synced())
     803         6549051 :         return;
     804                 : 
     805         9142775 :     Address to = addressOf(fe);
     806         9142775 :     const FrameEntry *backing = fe;
     807         9142775 :     if (fe->isCopy())
     808         1261576 :         backing = fe->copyOf();
     809                 : 
     810                 : #if defined JS_PUNBOX64
     811                 :     if (backing->isConstant())
     812                 :         masm.storeValue(backing->getValue(), to);
     813                 :     else if (backing->isTypeKnown())
     814                 :         masm.storeValueFromComponents(ImmType(backing->getKnownType()), backing->data.reg(), to);
     815                 :     else if (backing->type.inRegister())
     816                 :         masm.storeValueFromComponents(backing->type.reg(), backing->data.reg(), to);
     817                 :     else
     818                 :         masm.storePayload(backing->data.reg(), to);
     819                 : #elif defined JS_NUNBOX32
     820         9142775 :     if (backing->isConstant())
     821         2375341 :         masm.storePayload(ImmPayload(backing->getPayload()), to);
     822                 :     else
     823         6767434 :         masm.storePayload(backing->data.reg(), to);
     824                 : #endif
     825                 : }
     826                 : 
     827                 : inline void
     828         6505789 : FrameState::syncFe(FrameEntry *fe)
     829                 : {
     830         6505789 :     if (fe->type.synced() && fe->data.synced())
     831         4520153 :         return;
     832                 : 
     833         1985636 :     FrameEntry *backing = fe;
     834         1985636 :     if (fe->isCopy())
     835          324682 :         backing = fe->copyOf();
     836                 : 
     837         1985636 :     if (backing->isType(JSVAL_TYPE_DOUBLE)) {
     838           12119 :         if (!backing->isConstant())
     839            7757 :             tempFPRegForData(backing);
     840           12119 :         ensureFeSynced(fe, masm);
     841                 : 
     842           12119 :         if (!fe->type.synced())
     843           12119 :             fe->type.sync();
     844           12119 :         if (!fe->data.synced())
     845           12119 :             fe->data.sync();
     846           12119 :         return;
     847                 :     }
     848                 : 
     849         1973517 :     bool needTypeReg = !fe->type.synced() && backing->type.inMemory();
     850         1973517 :     bool needDataReg = !fe->data.synced() && backing->data.inMemory();
     851                 : 
     852                 : #if defined JS_NUNBOX32
     853                 :     /* Determine an ordering that won't spill known regs. */
     854         1973517 :     if (needTypeReg && !needDataReg) {
     855            2731 :         syncData(fe);
     856            2731 :         syncType(fe);
     857                 :     } else {
     858         1970786 :         syncType(fe);
     859         1970786 :         syncData(fe);
     860                 :     }
     861                 : #elif defined JS_PUNBOX64
     862                 :     if (JS_UNLIKELY(needTypeReg && needDataReg)) {
     863                 :         /* Memory-to-memory moves can only occur for copies backed by memory. */
     864                 :         JS_ASSERT(backing != fe);
     865                 : 
     866                 :         /* Use ValueReg to do a whole-Value mem-to-mem move. */
     867                 :         masm.loadValue(addressOf(backing), Registers::ValueReg);
     868                 :         masm.storeValue(Registers::ValueReg, addressOf(fe));
     869                 :     } else {
     870                 :         /* Store in case unpinning is necessary. */
     871                 :         MaybeRegisterID pairReg;
     872                 : 
     873                 :         /* Get a register if necessary, without clobbering its pair. */
     874                 :         if (needTypeReg) {
     875                 :             if (backing->data.inRegister() && !regstate(backing->data.reg()).isPinned()) {
     876                 :                 pairReg = backing->data.reg();
     877                 :                 pinReg(backing->data.reg());
     878                 :             }
     879                 :             tempRegForType(backing);
     880                 :         } else if (needDataReg) {
     881                 :             if (backing->type.inRegister() && !regstate(backing->type.reg()).isPinned()) {
     882                 :                 pairReg = backing->type.reg();
     883                 :                 pinReg(backing->type.reg());
     884                 :             }
     885                 :             tempRegForData(backing);
     886                 :         }
     887                 : 
     888                 :         ensureFeSynced(fe, masm);
     889                 : 
     890                 :         if (pairReg.isSet())
     891                 :             unpinReg(pairReg.reg());
     892                 :     }
     893                 : 
     894                 :     if (!fe->type.synced())
     895                 :         fe->type.sync();
     896                 :     if (!fe->data.synced())
     897                 :         fe->data.sync();
     898                 : #endif
     899                 : }
     900                 : 
     901                 : inline void
     902            3687 : FrameState::syncAndForgetFe(FrameEntry *fe, bool markSynced)
     903                 : {
     904            3687 :     if (markSynced) {
     905            2319 :         if (!fe->type.synced())
     906            1911 :             fe->type.sync();
     907            2319 :         if (!fe->data.synced())
     908            1911 :             fe->data.sync();
     909                 :     }
     910                 : 
     911            3687 :     syncFe(fe);
     912            3687 :     forgetAllRegs(fe);
     913            3687 :     fe->type.setMemory();
     914            3687 :     fe->data.setMemory();
     915            3687 : }
     916                 : 
     917                 : inline JSC::MacroAssembler::Address
     918           28543 : FrameState::loadNameAddress(const analyze::ScriptAnalysis::NameAccess &access, RegisterID reg)
     919                 : {
     920           28543 :     JS_ASSERT(access.script && access.nesting);
     921                 : 
     922           28543 :     masm.move(ImmPtr(access.basePointer()), reg);
     923           28543 :     masm.loadPtr(Address(reg), reg);
     924                 : 
     925           28543 :     return Address(reg, access.index * sizeof(Value));
     926                 : }
     927                 : 
     928                 : inline JSC::MacroAssembler::Address
     929           28033 : FrameState::loadNameAddress(const analyze::ScriptAnalysis::NameAccess &access)
     930                 : {
     931           28033 :     RegisterID reg = allocReg();
     932           28033 :     return loadNameAddress(access, reg);
     933                 : }
     934                 : 
     935                 : inline void
     936           10643 : FrameState::forgetLoopReg(FrameEntry *fe)
     937                 : {
     938                 :     /*
     939                 :      * Don't use a loop register for fe in the active loop, as its underlying
     940                 :      * representation may have changed since the start of the loop.
     941                 :      */
     942           10643 :     if (loop)
     943            8750 :         fe->lastLoop = loop->headOffset();
     944           10643 : }
     945                 : 
     946                 : inline void
     947         3212742 : FrameState::syncType(FrameEntry *fe)
     948                 : {
     949         3212742 :     JS_ASSERT(!fe->isType(JSVAL_TYPE_DOUBLE));
     950                 : 
     951         3212742 :     FrameEntry *backing = fe;
     952         3212742 :     if (fe->isCopy())
     953          323874 :         backing = fe->copyOf();
     954                 : 
     955         3212742 :     if (!fe->type.synced() && backing->type.inMemory())
     956           64303 :         tempRegForType(backing);
     957                 : 
     958         3212742 :     ensureTypeSynced(fe, masm);
     959                 : 
     960         3212742 :     if (!fe->type.synced())
     961         3017595 :         fe->type.sync();
     962         3212742 : }
     963                 : 
     964                 : inline void
     965         3422678 : FrameState::syncData(FrameEntry *fe)
     966                 : {
     967         3422678 :     JS_ASSERT(!fe->isType(JSVAL_TYPE_DOUBLE));
     968                 : 
     969         3422678 :     FrameEntry *backing = fe;
     970         3422678 :     if (fe->isCopy())
     971          323874 :         backing = fe->copyOf();
     972                 : 
     973         3422678 :     if (!fe->data.synced() && backing->data.inMemory())
     974           82962 :         tempRegForData(backing);
     975                 : 
     976         3422678 :     ensureDataSynced(fe, masm);
     977                 : 
     978         3422678 :     if (!fe->data.synced())
     979         3018296 :         fe->data.sync();
     980         3422678 : }
     981                 : 
     982                 : inline void
     983           40950 : FrameState::fakeSync(FrameEntry *fe)
     984                 : {
     985                 :     /*
     986                 :      * If a frame entry's value will no longer be used, we can mark it as being
     987                 :      * synced without actually performing the sync: the value is not observed.
     988                 :      */
     989           40950 :     if (!fe->data.synced())
     990             909 :         fe->data.sync();
     991           40950 :     if (!fe->type.synced())
     992             686 :         fe->type.sync();
     993           40950 : }
     994                 : 
     995                 : inline void
     996             303 : FrameState::forgetType(FrameEntry *fe)
     997                 : {
     998                 :     /*
     999                 :      * The type may have been forgotten with an intervening storeLocal in the
    1000                 :      * presence of eval or closed variables. For defense in depth and to make
    1001                 :      * callers' lives simpler, bail out if the type is not known.
    1002                 :      */
    1003             303 :     if (!fe->isTypeKnown())
    1004               0 :         return;
    1005                 : 
    1006                 :     /*
    1007                 :      * Likewise, storeLocal() may have set this FE, with a known type,
    1008                 :      * to be a copy of another FE, which has an unknown type.
    1009                 :      */
    1010             303 :     if (fe->isCopy()) {
    1011               0 :         syncFe(fe);
    1012               0 :         fe->clear();
    1013               0 :         fe->resetSynced();
    1014               0 :         return;
    1015                 :     }
    1016                 : 
    1017             303 :     ensureTypeSynced(fe, masm);
    1018             303 :     fe->type.setMemory();
    1019                 : }
    1020                 : 
    1021                 : inline void
    1022          128872 : FrameState::learnType(FrameEntry *fe, JSValueType type, bool unsync)
    1023                 : {
    1024          128872 :     JS_ASSERT(!fe->isType(JSVAL_TYPE_DOUBLE));
    1025          128872 :     JS_ASSERT(type != JSVAL_TYPE_UNKNOWN);
    1026                 : 
    1027          128872 :     if (fe->isCopy())
    1028               0 :         fe = fe->copyOf();
    1029                 : 
    1030          128872 :     if (type == JSVAL_TYPE_DOUBLE)
    1031             810 :         JS_ASSERT(!fe->data.inRegister());
    1032                 :     else
    1033          128062 :         JS_ASSERT(!fe->data.inFPRegister());
    1034                 : 
    1035          128872 :     if (fe->type.inRegister())
    1036           29958 :         forgetReg(fe->type.reg());
    1037          128872 :     fe->setType(type);
    1038          128872 :     if (unsync)
    1039           29535 :         fe->type.unsync();
    1040          128872 : }
    1041                 : 
    1042                 : inline void
    1043            6032 : FrameState::learnType(FrameEntry *fe, JSValueType type, RegisterID data)
    1044                 : {
    1045            6032 :     JS_ASSERT(!fe->isCopied());
    1046            6032 :     JS_ASSERT(type != JSVAL_TYPE_UNKNOWN && type != JSVAL_TYPE_DOUBLE);
    1047                 : 
    1048            6032 :     forgetAllRegs(fe);
    1049            6032 :     fe->clear();
    1050                 : 
    1051            6032 :     fe->type.setConstant();
    1052            6032 :     fe->knownType = type;
    1053                 : 
    1054            6032 :     fe->data.setRegister(data);
    1055            6032 :     regstate(data).associate(fe, RematInfo::DATA);
    1056                 : 
    1057            6032 :     fe->data.unsync();
    1058            6032 :     fe->type.unsync();
    1059            6032 : }
    1060                 : 
    1061                 : inline int32_t
    1062        27503474 : FrameState::frameOffset(const FrameEntry *fe, ActiveFrame *a) const
    1063                 : {
    1064                 :     /*
    1065                 :      * The stored frame offsets for analysis temporaries are immediately above
    1066                 :      * the script's normal slots (and will thus be clobbered should a C++ or
    1067                 :      * scripted call push another frame). There must be enough room in the
    1068                 :      * reserved stack space.
    1069                 :      */
    1070                 :     JS_STATIC_ASSERT(StackSpace::STACK_JIT_EXTRA >= TEMPORARY_LIMIT);
    1071                 : 
    1072                 :     /* Note: fe == a->sp is allowed for addressOfTop */
    1073        27503474 :     JS_ASSERT(fe >= a->callee_ && fe <= a->sp);
    1074                 : 
    1075        27503474 :     if (fe >= a->locals)
    1076        26380562 :         return StackFrame::offsetOfFixed(uint32_t(fe - a->locals));
    1077         1122912 :     if (fe >= a->args)
    1078          630070 :         return StackFrame::offsetOfFormalArg(a->script->function(), uint32_t(fe - a->args));
    1079          492842 :     if (fe == a->this_)
    1080          464242 :         return StackFrame::offsetOfThis(a->script->function());
    1081           28600 :     if (fe == a->callee_)
    1082           28600 :         return StackFrame::offsetOfCallee(a->script->function());
    1083               0 :     JS_NOT_REACHED("Bad fe");
    1084                 :     return 0;
    1085                 : }
    1086                 : 
    1087                 : inline JSC::MacroAssembler::Address
    1088        27531750 : FrameState::addressOf(const FrameEntry *fe) const
    1089                 : {
    1090        27531750 :     if (isTemporary(fe)) {
    1091                 :         /*
    1092                 :          * Temporary addresses are common to the outermost loop, and are shared
    1093                 :          * by all active frames.
    1094                 :          */
    1095           28276 :         return Address(JSFrameReg, (loop->temporariesStart + fe - temporaries) * sizeof(Value));
    1096                 :     }
    1097                 : 
    1098        27503474 :     ActiveFrame *na = a;
    1099        55193273 :     while (fe < na->callee_)
    1100          186325 :         na = na->parent;
    1101                 : 
    1102        27503474 :     int32_t offset = frameOffset(fe, na);
    1103        27503474 :     return Address(JSFrameReg, offset + (na->depth * sizeof(Value)));
    1104                 : }
    1105                 : 
    1106                 : inline uint32_t
    1107          627305 : FrameState::frameSlot(ActiveFrame *a, const FrameEntry *fe) const
    1108                 : {
    1109          627305 :     if (isTemporary(fe))
    1110            2511 :         return fe - entries;
    1111                 : 
    1112          624794 :     JS_ASSERT(fe >= a->callee_ && fe < a->sp);
    1113                 : 
    1114          624794 :     if (fe >= a->locals)
    1115          589256 :         return analyze::LocalSlot(a->script, fe - a->locals);
    1116           35538 :     if (fe >= a->args)
    1117           30539 :         return analyze::ArgSlot(fe - a->args);
    1118            4999 :     if (fe == a->this_)
    1119            4999 :         return analyze::ThisSlot();
    1120               0 :     if (fe == a->callee_)
    1121               0 :         return analyze::CalleeSlot();
    1122               0 :     JS_NOT_REACHED("Bad fe");
    1123                 :     return 0;
    1124                 : }
    1125                 : 
    1126                 : inline JSC::MacroAssembler::Address
    1127             209 : FrameState::addressForInlineReturn()
    1128                 : {
    1129             209 :     if (a->callee_->isTracked())
    1130              27 :         discardFe(a->callee_);
    1131             209 :     return addressOf(a->callee_);
    1132                 : }
    1133                 : 
    1134                 : inline JSC::MacroAssembler::Address
    1135           11394 : FrameState::addressForDataRemat(const FrameEntry *fe) const
    1136                 : {
    1137           11394 :     if (fe->isCopy() && !fe->data.synced())
    1138            4043 :         fe = fe->copyOf();
    1139           11394 :     JS_ASSERT(fe->data.synced());
    1140           11394 :     return addressOf(fe);
    1141                 : }
    1142                 : 
    1143                 : inline JSC::MacroAssembler::Jump
    1144                 : FrameState::testNull(Assembler::Condition cond, FrameEntry *fe)
    1145                 : {
    1146                 :     JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
    1147                 :     if (shouldAvoidTypeRemat(fe))
    1148                 :         return masm.testNull(cond, addressOf(fe));
    1149                 :     return masm.testNull(cond, tempRegForType(fe));
    1150                 : }
    1151                 : 
    1152                 : inline JSC::MacroAssembler::Jump
    1153                 : FrameState::testUndefined(Assembler::Condition cond, FrameEntry *fe)
    1154                 : {
    1155                 :     JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
    1156                 :     if (shouldAvoidTypeRemat(fe))
    1157                 :         return masm.testUndefined(cond, addressOf(fe));
    1158                 :     return masm.testUndefined(cond, tempRegForType(fe));
    1159                 : }
    1160                 : 
    1161                 : inline JSC::MacroAssembler::Jump
    1162           47156 : FrameState::testInt32(Assembler::Condition cond, FrameEntry *fe)
    1163                 : {
    1164           47156 :     JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
    1165           47156 :     if (shouldAvoidTypeRemat(fe))
    1166            4565 :         return masm.testInt32(cond, addressOf(fe));
    1167           42591 :     return masm.testInt32(cond, tempRegForType(fe));
    1168                 : }
    1169                 : 
    1170                 : inline JSC::MacroAssembler::Jump
    1171            4509 : FrameState::testPrimitive(Assembler::Condition cond, FrameEntry *fe)
    1172                 : {
    1173            4509 :     JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
    1174            4509 :     if (shouldAvoidTypeRemat(fe))
    1175             334 :         return masm.testPrimitive(cond, addressOf(fe));
    1176            4175 :     return masm.testPrimitive(cond, tempRegForType(fe));
    1177                 : }
    1178                 : 
    1179                 : inline JSC::MacroAssembler::Jump
    1180           69429 : FrameState::testObject(Assembler::Condition cond, FrameEntry *fe)
    1181                 : {
    1182           69429 :     JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
    1183           69429 :     if (shouldAvoidTypeRemat(fe))
    1184            4296 :         return masm.testObject(cond, addressOf(fe));
    1185           65133 :     return masm.testObject(cond, tempRegForType(fe));
    1186                 : }
    1187                 : 
    1188                 : inline JSC::MacroAssembler::Jump
    1189                 : FrameState::testGCThing(FrameEntry *fe)
    1190                 : {
    1191                 :     if (shouldAvoidTypeRemat(fe))
    1192                 :         return masm.testGCThing(addressOf(fe));
    1193                 :     return masm.testGCThing(tempRegForType(fe));
    1194                 : }
    1195                 : 
    1196                 : inline JSC::MacroAssembler::Jump
    1197            8942 : FrameState::testDouble(Assembler::Condition cond, FrameEntry *fe)
    1198                 : {
    1199            8942 :     JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
    1200            8942 :     if (shouldAvoidTypeRemat(fe))
    1201               0 :         return masm.testDouble(cond, addressOf(fe));
    1202            8942 :     return masm.testDouble(cond, tempRegForType(fe));
    1203                 : }
    1204                 : 
    1205                 : inline JSC::MacroAssembler::Jump
    1206           70560 : FrameState::testBoolean(Assembler::Condition cond, FrameEntry *fe)
    1207                 : {
    1208           70560 :     JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
    1209           70560 :     if (shouldAvoidTypeRemat(fe))
    1210           68493 :         return masm.testBoolean(cond, addressOf(fe));
    1211            2067 :     return masm.testBoolean(cond, tempRegForType(fe));
    1212                 : }
    1213                 : 
    1214                 : inline JSC::MacroAssembler::Jump
    1215            1057 : FrameState::testString(Assembler::Condition cond, FrameEntry *fe)
    1216                 : {
    1217            1057 :     JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
    1218            1057 :     if (shouldAvoidTypeRemat(fe))
    1219               7 :         return masm.testString(cond, addressOf(fe));
    1220            1050 :     return masm.testString(cond, tempRegForType(fe));
    1221                 : }
    1222                 : 
    1223                 : inline FrameEntry *
    1224         3261726 : FrameState::getOrTrack(uint32_t index)
    1225                 : {
    1226         3261726 :     FrameEntry *fe = &entries[index];
    1227         3261726 :     if (!fe->isTracked()) {
    1228          730504 :         addToTracker(fe);
    1229          730504 :         fe->resetSynced();
    1230                 :     }
    1231         3261726 :     return fe;
    1232                 : }
    1233                 : 
    1234                 : inline FrameEntry *
    1235         1741192 : FrameState::getStack(uint32_t slot)
    1236                 : {
    1237         1741192 :     if (slot >= uint32_t(a->sp - a->spBase))
    1238            3451 :         return NULL;
    1239         1737741 :     return getOrTrack(uint32_t(a->spBase + slot - entries));
    1240                 : }
    1241                 : 
    1242                 : inline FrameEntry *
    1243          719887 : FrameState::getLocal(uint32_t slot)
    1244                 : {
    1245          719887 :     JS_ASSERT(slot < a->script->nslots);
    1246          719887 :     return getOrTrack(uint32_t(a->locals + slot - entries));
    1247                 : }
    1248                 : 
    1249                 : inline FrameEntry *
    1250          198993 : FrameState::getArg(uint32_t slot)
    1251                 : {
    1252          198993 :     JS_ASSERT(slot < a->script->function()->nargs);
    1253          198993 :     return getOrTrack(uint32_t(a->args + slot - entries));
    1254                 : }
    1255                 : 
    1256                 : inline FrameEntry *
    1257          146020 : FrameState::getThis()
    1258                 : {
    1259          146020 :     return getOrTrack(uint32_t(a->this_ - entries));
    1260                 : }
    1261                 : 
    1262                 : inline FrameEntry *
    1263          222912 : FrameState::getSlotEntry(uint32_t slot)
    1264                 : {
    1265          222912 :     JS_ASSERT(slot < analyze::TotalSlots(a->script));
    1266          222912 :     return getOrTrack(uint32_t(a->callee_ + slot - entries));
    1267                 : }
    1268                 : 
    1269                 : inline FrameEntry *
    1270            3733 : FrameState::getCallee()
    1271                 : {
    1272                 :     // Callee can only be used in function code, and it's always an object.
    1273            3733 :     JS_ASSERT(a->script->function());
    1274            3733 :     FrameEntry *fe = a->callee_;
    1275            3733 :     if (!fe->isTracked()) {
    1276            3100 :         addToTracker(fe);
    1277            3100 :         fe->resetSynced();
    1278            3100 :         fe->setType(JSVAL_TYPE_OBJECT);
    1279                 :     }
    1280            3733 :     return fe;
    1281                 : }
    1282                 : 
    1283                 : inline void
    1284          344290 : FrameState::unpinKilledReg(AnyRegisterID reg)
    1285                 : {
    1286          344290 :     regstate(reg).unpinUnsafe();
    1287          344290 :     freeRegs.putReg(reg);
    1288          344290 : }
    1289                 : 
    1290                 : inline void
    1291        12949281 : FrameState::forgetAllRegs(FrameEntry *fe)
    1292                 : {
    1293        12949281 :     if (fe->isCopy())
    1294         4265938 :         return;
    1295         8683343 :     if (fe->type.inRegister())
    1296         1345472 :         forgetReg(fe->type.reg());
    1297         8683343 :     if (fe->data.inRegister())
    1298         1664188 :         forgetReg(fe->data.reg());
    1299         8683343 :     if (fe->data.inFPRegister())
    1300           12105 :         forgetReg(fe->data.fpreg());
    1301                 : }
    1302                 : 
    1303                 : inline void
    1304          336834 : FrameState::swapInTracker(FrameEntry *lhs, FrameEntry *rhs)
    1305                 : {
    1306          336834 :     uint32_t li = lhs->trackerIndex();
    1307          336834 :     uint32_t ri = rhs->trackerIndex();
    1308          336834 :     JS_ASSERT(tracker[li] == lhs);
    1309          336834 :     JS_ASSERT(tracker[ri] == rhs);
    1310          336834 :     tracker.entries[ri] = lhs;
    1311          336834 :     tracker.entries[li] = rhs;
    1312          336834 :     lhs->index_ = ri;
    1313          336834 :     rhs->index_ = li;
    1314          336834 : }
    1315                 : 
    1316                 : inline void
    1317          365277 : FrameState::dup()
    1318                 : {
    1319          365277 :     dupAt(-1);
    1320          365277 : }
    1321                 : 
    1322                 : inline void
    1323          358437 : FrameState::dup2()
    1324                 : {
    1325          358437 :     FrameEntry *lhs = peek(-2);
    1326          358437 :     FrameEntry *rhs = peek(-1);
    1327          358437 :     pushCopyOf(lhs);
    1328          358437 :     pushCopyOf(rhs);
    1329          358437 : }
    1330                 : 
    1331                 : inline void
    1332         2514535 : FrameState::dupAt(int32_t n)
    1333                 : {
    1334         2514535 :     JS_ASSERT(n < 0);
    1335         2514535 :     FrameEntry *fe = peek(n);
    1336         2514535 :     pushCopyOf(fe);
    1337         2514535 : }
    1338                 : 
    1339                 : inline void
    1340             240 : FrameState::syncAt(int32_t n)
    1341                 : {
    1342             240 :     JS_ASSERT(n < 0);
    1343             240 :     FrameEntry *fe = peek(n);
    1344             240 :     syncFe(fe);
    1345             240 : }
    1346                 : 
    1347                 : inline void
    1348          432252 : FrameState::pushLocal(uint32_t n)
    1349                 : {
    1350          432252 :     FrameEntry *fe = getLocal(n);
    1351          432252 :     if (!a->analysis->slotEscapes(analyze::LocalSlot(a->script, n))) {
    1352          178915 :         pushCopyOf(fe);
    1353                 :     } else {
    1354                 : #ifdef DEBUG
    1355                 :         /*
    1356                 :          * We really want to assert on local variables, but in the presence of
    1357                 :          * SETLOCAL equivocation of stack slots, and let expressions, just
    1358                 :          * weakly assert on the fixed local vars.
    1359                 :          */
    1360          253337 :         if (fe->isTracked() && n < a->script->nfixed)
    1361          204581 :             JS_ASSERT(fe->data.inMemory());
    1362                 : #endif
    1363          253337 :         if (n >= a->script->nfixed)
    1364           48756 :             syncFe(fe);
    1365          253337 :         JSValueType type = fe->isTypeKnown() ? fe->getKnownType() : JSVAL_TYPE_UNKNOWN;
    1366          253337 :         push(addressOf(fe), type);
    1367                 :     }
    1368          432252 : }
    1369                 : 
    1370                 : inline void
    1371          194234 : FrameState::pushArg(uint32_t n)
    1372                 : {
    1373          194234 :     FrameEntry *fe = getArg(n);
    1374          194234 :     if (!a->analysis->slotEscapes(analyze::ArgSlot(n))) {
    1375           94802 :         pushCopyOf(fe);
    1376                 :     } else {
    1377                 : #ifdef DEBUG
    1378           99432 :         if (fe->isTracked())
    1379           99432 :             JS_ASSERT(fe->data.inMemory());
    1380                 : #endif
    1381           99432 :         JSValueType type = fe->isTypeKnown() ? fe->getKnownType() : JSVAL_TYPE_UNKNOWN;
    1382           99432 :         push(addressOf(fe), type);
    1383                 :     }
    1384          194234 : }
    1385                 : 
    1386                 : inline void
    1387            3733 : FrameState::pushCallee()
    1388                 : {
    1389            3733 :     FrameEntry *fe = getCallee();
    1390            3733 :     pushCopyOf(fe);
    1391            3733 : }
    1392                 : 
    1393                 : inline void
    1394          107791 : FrameState::pushThis()
    1395                 : {
    1396          107791 :     FrameEntry *fe = getThis();
    1397          107791 :     pushCopyOf(fe);
    1398          107791 : }
    1399                 : 
    1400                 : void
    1401           35416 : FrameState::learnThisIsObject(bool unsync)
    1402                 : {
    1403                 :     // If the 'this' object is a copy, this must be an inline frame, in which
    1404                 :     // case we will trigger recompilation if the 'this' entry isn't actually
    1405                 :     // an object (thus, it is OK to modify the backing directly).
    1406           35416 :     FrameEntry *fe = getThis();
    1407           35416 :     if (fe->isCopy())
    1408              41 :         fe = fe->copyOf();
    1409           35416 :     learnType(fe, JSVAL_TYPE_OBJECT, unsync);
    1410           35416 : }
    1411                 : 
    1412                 : void
    1413             160 : FrameState::setThis(RegisterID reg)
    1414                 : {
    1415             160 :     FrameEntry *fe = getThis();
    1416             160 :     JS_ASSERT(!fe->isCopy());
    1417             160 :     learnType(fe, JSVAL_TYPE_OBJECT, reg);
    1418             160 : }
    1419                 : 
    1420                 : void
    1421            1849 : FrameState::syncThis()
    1422                 : {
    1423            1849 :     FrameEntry *fe = getThis();
    1424            1849 :     syncFe(fe);
    1425            1849 : }
    1426                 : 
    1427                 : inline bool
    1428          370299 : FrameState::isConstructorThis(const FrameEntry *fe) const
    1429                 : {
    1430          370299 :     return isThis(fe) && cc.constructing();
    1431                 : }
    1432                 : 
    1433                 : inline void
    1434           28996 : FrameState::leaveBlock(uint32_t n)
    1435                 : {
    1436           28996 :     popn(n);
    1437           28996 : }
    1438                 : 
    1439                 : inline void
    1440           21204 : FrameState::enterBlock(uint32_t n)
    1441                 : {
    1442                 :     /* expect that tracker has 0 entries, for now. */
    1443           21204 :     JS_ASSERT(!tracker.nentries);
    1444           21204 :     JS_ASSERT(uint32_t(a->sp + n - a->locals) <= a->script->nslots);
    1445                 : 
    1446           21204 :     a->sp += n;
    1447           21204 : }
    1448                 : 
    1449                 : inline void
    1450                 : FrameState::eviscerate(FrameEntry *fe)
    1451                 : {
    1452                 :     forgetAllRegs(fe);
    1453                 :     fe->resetUnsynced();
    1454                 : }
    1455                 : 
    1456                 : inline StateRemat
    1457            5692 : FrameState::dataRematInfo(const FrameEntry *fe) const
    1458                 : {
    1459            5692 :     if (fe->isCopy())
    1460            2272 :         fe = fe->copyOf();
    1461                 : 
    1462            5692 :     if (fe->data.inRegister())
    1463            4373 :         return StateRemat::FromRegister(fe->data.reg());
    1464                 : 
    1465            1319 :     JS_ASSERT(fe->data.synced());
    1466            1319 :     return StateRemat::FromAddress(addressOf(fe));
    1467                 : }
    1468                 : 
    1469                 : inline void
    1470          201335 : FrameState::giveOwnRegs(FrameEntry *fe)
    1471                 : {
    1472          201335 :     JS_ASSERT(!fe->isConstant());
    1473          201335 :     JS_ASSERT(fe == peek(-1));
    1474                 : 
    1475          201335 :     if (!fe->isCopy())
    1476          201203 :         return;
    1477                 : 
    1478             132 :     RegisterID data = copyDataIntoReg(fe);
    1479             132 :     if (fe->isTypeKnown()) {
    1480               0 :         JSValueType type = fe->getKnownType();
    1481               0 :         pop();
    1482               0 :         pushTypedPayload(type, data);
    1483                 :     } else {
    1484             132 :         RegisterID type = copyTypeIntoReg(fe);
    1485             132 :         pop();
    1486             132 :         pushRegs(type, data, JSVAL_TYPE_UNKNOWN);
    1487                 :     }
    1488                 : }
    1489                 : 
    1490                 : inline void
    1491         1299276 : FrameState::loadDouble(RegisterID t, RegisterID d, FrameEntry *fe, FPRegisterID fpreg,
    1492                 :                        Assembler &masm) const
    1493                 : {
    1494                 : #ifdef JS_CPU_X86
    1495         1299276 :     masm.fastLoadDouble(d, t, fpreg);
    1496                 : #else
    1497                 :     loadDouble(fe, fpreg, masm);
    1498                 : #endif
    1499         1299276 : }
    1500                 : 
    1501                 : inline bool
    1502           19837 : FrameState::tryFastDoubleLoad(FrameEntry *fe, FPRegisterID fpReg, Assembler &masm) const
    1503                 : {
    1504                 : #ifdef JS_CPU_X86
    1505           19837 :     if (!fe->isCopy() && fe->type.inRegister() && fe->data.inRegister()) {
    1506           12802 :         masm.fastLoadDouble(fe->data.reg(), fe->type.reg(), fpReg);
    1507           12802 :         return true;
    1508                 :     }
    1509                 : #endif
    1510            7035 :     return false;
    1511                 : }
    1512                 : 
    1513                 : inline void
    1514           17023 : FrameState::loadDouble(FrameEntry *fe, FPRegisterID fpReg, Assembler &masm) const
    1515                 : {
    1516           17023 :     if (fe->isCopy()) {
    1517            2814 :         FrameEntry *backing = fe->copyOf();
    1518            2814 :         if (tryFastDoubleLoad(fe, fpReg, masm)) 
    1519               0 :             return;
    1520            2814 :         fe = backing;
    1521                 :     }
    1522                 : 
    1523           17023 :     if (tryFastDoubleLoad(fe, fpReg, masm))
    1524           12802 :         return;
    1525                 : 
    1526            4221 :     ensureFeSynced(fe, masm);
    1527            4221 :     masm.loadDouble(addressOf(fe), fpReg);
    1528                 : }
    1529                 : 
    1530                 : class PinRegAcrossSyncAndKill
    1531                 : {
    1532                 :     typedef JSC::MacroAssembler::RegisterID RegisterID;
    1533                 :     FrameState &frame;
    1534                 :     MaybeRegisterID maybeReg;
    1535                 :   public:
    1536          159020 :     PinRegAcrossSyncAndKill(FrameState &frame, RegisterID reg)
    1537          159020 :       : frame(frame), maybeReg(reg)
    1538                 :     {
    1539          159020 :         frame.pinReg(reg);
    1540          159020 :     }
    1541          150768 :     PinRegAcrossSyncAndKill(FrameState &frame, MaybeRegisterID maybeReg)
    1542          150768 :       : frame(frame), maybeReg(maybeReg)
    1543                 :     {
    1544          150768 :         if (maybeReg.isSet())
    1545          112852 :             frame.pinReg(maybeReg.reg());
    1546          150768 :     }
    1547          309788 :     ~PinRegAcrossSyncAndKill() {
    1548          309788 :         if (maybeReg.isSet())
    1549          271872 :             frame.unpinKilledReg(maybeReg.reg());
    1550          309788 :     }
    1551                 : };
    1552                 : 
    1553                 : } /* namespace mjit */
    1554                 : } /* namespace js */
    1555                 : 
    1556                 : #endif /* include */
    1557                 : 

Generated by: LCOV version 1.7