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-04-07 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         1392539 : FrameState::addToTracker(FrameEntry *fe)
      50                 : {
      51         1392539 :     JS_ASSERT(!fe->isTracked());
      52         1392539 :     fe->track(tracker.nentries);
      53         1392539 :     tracker.add(fe);
      54         1392539 : }
      55                 : 
      56                 : inline FrameEntry *
      57         6343940 : FrameState::peek(int32_t depth)
      58                 : {
      59         6343940 :     JS_ASSERT(depth < 0);
      60         6343940 :     JS_ASSERT(a->sp + depth >= a->spBase);
      61         6343940 :     FrameEntry *fe = a->sp + depth;
      62         6343940 :     if (!fe->isTracked()) {
      63           51996 :         addToTracker(fe);
      64           51996 :         fe->resetSynced();
      65                 :     }
      66         6343940 :     return fe;
      67                 : }
      68                 : 
      69                 : inline void
      70          914400 : FrameState::popn(uint32_t n)
      71                 : {
      72         2895017 :     for (uint32_t i = 0; i < n; i++)
      73         1980617 :         pop();
      74          914400 : }
      75                 : 
      76                 : inline bool
      77          466293 : FrameState::haveSameBacking(FrameEntry *lhs, FrameEntry *rhs)
      78                 : {
      79          466293 :     if (lhs->isCopy())
      80           56624 :         lhs = lhs->copyOf();
      81          466293 :     if (rhs->isCopy())
      82           12541 :         rhs = rhs->copyOf();
      83          466293 :     return lhs == rhs;
      84                 : }
      85                 : 
      86                 : inline FrameEntry *
      87           19268 : FrameState::getTemporary(uint32_t which)
      88                 : {
      89           19268 :     JS_ASSERT(which < TEMPORARY_LIMIT);
      90                 : 
      91           19268 :     FrameEntry *fe = temporaries + which;
      92           19268 :     JS_ASSERT(fe < temporariesTop);
      93                 : 
      94           19268 :     return getOrTrack(uint32_t(fe - entries));
      95                 : }
      96                 : 
      97                 : inline AnyRegisterID
      98         3217690 : FrameState::allocReg(uint32_t mask)
      99                 : {
     100         3217690 :     if (freeRegs.hasRegInMask(mask)) {
     101         3151881 :         AnyRegisterID reg = freeRegs.takeAnyReg(mask);
     102         3151881 :         modifyReg(reg);
     103         3151881 :         return reg;
     104                 :     }
     105                 : 
     106           65809 :     AnyRegisterID reg = evictSomeReg(mask);
     107           65809 :     modifyReg(reg);
     108           65809 :     return reg;
     109                 : }
     110                 : 
     111                 : inline JSC::MacroAssembler::RegisterID
     112         2393614 : FrameState::allocReg()
     113                 : {
     114         2393614 :     return allocReg(Registers::AvailRegs).reg();
     115                 : }
     116                 : 
     117                 : inline JSC::MacroAssembler::FPRegisterID
     118          814982 : FrameState::allocFPReg()
     119                 : {
     120          814982 :     return allocReg(Registers::AvailFPRegs).fpreg();
     121                 : }
     122                 : 
     123                 : inline AnyRegisterID
     124          671477 : FrameState::allocAndLoadReg(FrameEntry *fe, bool fp, RematInfo::RematType type)
     125                 : {
     126          671477 :     AnyRegisterID reg;
     127          671477 :     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          724720 :     if (loop && freeRegs.hasRegInMask(loop->getLoopRegs() & mask) &&
     138           36755 :         type == RematInfo::DATA && isOuterSlot(fe) && !cc.activeFrameHasMultipleExits() &&
     139           16488 :         fe->lastLoop < loop->headOffset()) {
     140           16187 :         reg = freeRegs.takeAnyReg(loop->getLoopRegs() & mask);
     141           16187 :         regstate(reg).associate(fe, RematInfo::DATA);
     142           16187 :         fe->lastLoop = loop->headOffset();
     143           16187 :         loop->setLoopReg(reg, fe);
     144           16187 :         return reg;
     145                 :     }
     146                 : 
     147          655290 :     if (!freeRegs.empty(mask))
     148          631348 :         reg = freeRegs.takeAnyReg(mask);
     149                 :     else
     150           23942 :         reg = evictSomeReg(mask);
     151          655290 :     modifyReg(reg);
     152                 : 
     153          655290 :     if (fp)
     154            1164 :         masm.loadDouble(addressOf(fe), reg.fpreg());
     155          654126 :     else if (type == RematInfo::TYPE)
     156          426286 :         masm.loadTypeTag(addressOf(fe), reg.reg());
     157                 :     else
     158          227840 :         masm.loadPayload(addressOf(fe), reg.reg());
     159                 : 
     160          655290 :     regstate(reg).associate(fe, type);
     161          655290 :     return reg;
     162                 : }
     163                 : 
     164                 : inline void
     165         4437994 : FrameState::modifyReg(AnyRegisterID reg)
     166                 : {
     167         4437994 :     if (loop)
     168          864688 :         loop->clearLoopReg(reg);
     169         4437994 : }
     170                 : 
     171                 : inline void
     172            5894 : FrameState::convertInt32ToDouble(Assembler &masm, FrameEntry *fe, FPRegisterID fpreg) const
     173                 : {
     174            5894 :     JS_ASSERT(!fe->isConstant());
     175                 : 
     176            5894 :     if (fe->isCopy())
     177            1020 :         fe = fe->copyOf();
     178                 :     
     179            5894 :     if (fe->data.inRegister())
     180            5165 :         masm.convertInt32ToDouble(fe->data.reg(), fpreg);
     181                 :     else
     182             729 :         masm.convertInt32ToDouble(masm.payloadOf(addressOf(fe)), fpreg);
     183            5894 : }
     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         3590816 : FrameState::pop()
     195                 : {
     196         3590816 :     JS_ASSERT(a->sp > a->spBase);
     197                 : 
     198         3590816 :     FrameEntry *fe = --a->sp;
     199         3590816 :     if (!fe->isTracked())
     200           44547 :         return;
     201                 : 
     202         3546269 :     forgetAllRegs(fe);
     203         3546269 :     fe->type.invalidate();
     204         3546269 :     fe->data.invalidate();
     205         3546269 :     fe->clear();
     206                 : 
     207         3546269 :     extraArray[fe - entries].reset();
     208                 : }
     209                 : 
     210                 : inline void
     211         1273100 : FrameState::freeReg(AnyRegisterID reg)
     212                 : {
     213         1273100 :     JS_ASSERT(!regstate(reg).usedBy());
     214                 : 
     215         1273100 :     freeRegs.putReg(reg);
     216         1273100 : }
     217                 : 
     218                 : inline void
     219         2963588 : 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         2963588 :     JS_ASSERT_IF(regstate(reg).fe(), !regstate(reg).fe()->isCopy());
     226                 : 
     227         2963588 :     if (!regstate(reg).isPinned()) {
     228         2762925 :         regstate(reg).forget();
     229         2762925 :         freeRegs.putReg(reg);
     230                 :     }
     231         2963588 : }
     232                 : 
     233                 : inline FrameEntry *
     234         3635895 : FrameState::rawPush()
     235                 : {
     236         3635895 :     JS_ASSERT(a->sp < temporaries);
     237         3635895 :     FrameEntry *fe = a->sp++;
     238                 : 
     239         3635895 :     if (!fe->isTracked())
     240          895340 :         addToTracker(fe);
     241         3635895 :     fe->type.invalidate();
     242         3635895 :     fe->data.invalidate();
     243         3635895 :     fe->clear();
     244                 : 
     245         3635895 :     extraArray[fe - entries].reset();
     246                 : 
     247         3635895 :     return fe;
     248                 : }
     249                 : 
     250                 : inline void
     251         1194305 : FrameState::push(const Value &v)
     252                 : {
     253         1194305 :     FrameEntry *fe = rawPush();
     254         1194305 :     fe->setConstant(v);
     255         1194305 : }
     256                 : 
     257                 : inline void
     258         1282938 : FrameState::pushSynced(JSValueType type)
     259                 : {
     260         1282938 :     FrameEntry *fe = rawPush();
     261                 : 
     262         1282938 :     fe->resetSynced();
     263         1282938 :     if (type != JSVAL_TYPE_UNKNOWN) {
     264           32360 :         fe->setType(type);
     265           32360 :         if (type == JSVAL_TYPE_DOUBLE)
     266             257 :             masm.ensureInMemoryDouble(addressOf(fe));
     267                 :     }
     268         1282938 : }
     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          263029 : 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          263029 :     bool free = freeRegs.hasReg(address.base);
     301          263029 :     bool needsPin = !free && regstate(address.base).fe();
     302          263029 :     if (free)
     303            2105 :         freeRegs.takeReg(address.base);
     304          263029 :     if (needsPin)
     305            3714 :         pinReg(address.base);
     306                 : 
     307          263029 :     RegisterID typeReg = allocReg();
     308                 : 
     309          263029 :     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          263029 :     if (free)
     315            2105 :         freeRegs.putReg(address.base);
     316          263029 :     if (needsPin)
     317            3714 :         unpinReg(address.base);
     318                 : 
     319          263029 :     RegisterID dataReg = reuseBase ? address.base : allocReg();
     320          263029 :     masm.loadPayload(address, dataReg);
     321                 : 
     322                 : #endif
     323                 : 
     324          263029 :     *ptypeReg = typeReg;
     325          263029 :     *pdataReg = dataReg;
     326          263029 : }
     327                 : 
     328                 : inline void
     329          232500 : FrameState::push(Address address, JSValueType knownType, bool reuseBase)
     330                 : {
     331          232500 :     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          231456 :     if (knownType != JSVAL_TYPE_UNKNOWN) {
     341           60180 :         RegisterID dataReg = reuseBase ? address.base : allocReg();
     342           60180 :         masm.loadPayload(address, dataReg);
     343           60180 :         pushTypedPayload(knownType, dataReg);
     344           60180 :         return;
     345                 :     }
     346                 : 
     347                 :     RegisterID typeReg, dataReg;
     348          171276 :     loadIntoRegisters(address, reuseBase, &typeReg, &dataReg);
     349                 : 
     350          171276 :     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          965278 : FrameState::storeRegs(int32_t depth, RegisterID type, RegisterID data, JSValueType knownType)
     366                 : {
     367          965278 :     FrameEntry *fe = peek(depth);
     368          965278 :     forgetEntry(fe);
     369          965278 :     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          965278 :     JS_ASSERT(!freeRegs.hasReg(type) && !freeRegs.hasReg(data));
     376                 : 
     377          965278 :     if (knownType == JSVAL_TYPE_UNKNOWN) {
     378          845086 :         fe->type.setRegister(type);
     379          845086 :         fe->data.setRegister(data);
     380          845086 :         regstate(type).associate(fe, RematInfo::TYPE);
     381          845086 :         regstate(data).associate(fe, RematInfo::DATA);
     382          845086 :         return Registers::FPConversionTemp;
     383                 :     }
     384                 : 
     385          120192 :     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          110040 :     freeReg(type);
     397          110040 :     fe->setType(knownType);
     398          110040 :     fe->data.setRegister(data);
     399          110040 :     regstate(data).associate(fe, RematInfo::DATA);
     400          110040 :     return Registers::FPConversionTemp;
     401                 : }
     402                 : 
     403                 : inline JSC::MacroAssembler::FPRegisterID
     404          965278 : FrameState::pushRegs(RegisterID type, RegisterID data, JSValueType knownType)
     405                 : {
     406          965278 :     pushSynced(JSVAL_TYPE_UNKNOWN);
     407          965278 :     return storeRegs(-1, type, data, knownType);
     408                 : }
     409                 : 
     410                 : inline void
     411           90561 : FrameState::reloadEntry(Assembler &masm, Address address, FrameEntry *fe)
     412                 : {
     413           90561 :     if (fe->data.inRegister()) {
     414           89729 :         if (fe->type.inRegister()) {
     415           61567 :             masm.loadValueAsComponents(address, fe->type.reg(), fe->data.reg());
     416                 :         } else {
     417           28162 :             JS_ASSERT(fe->isTypeKnown());
     418           28162 :             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           90561 : }
     425                 : 
     426                 : inline void
     427          300727 : FrameState::pushTypedPayload(JSValueType type, RegisterID payload)
     428                 : {
     429          300727 :     JS_ASSERT(type != JSVAL_TYPE_DOUBLE);
     430          300727 :     JS_ASSERT(!freeRegs.hasReg(payload));
     431                 : 
     432          300727 :     FrameEntry *fe = rawPush();
     433                 : 
     434          300727 :     fe->resetUnsynced();
     435          300727 :     fe->setType(type);
     436          300727 :     fe->data.setRegister(payload);
     437          300727 :     regstate(payload).associate(fe, RematInfo::DATA);
     438          300727 : }
     439                 : 
     440                 : inline void
     441          334105 : FrameState::pushNumber(RegisterID payload, bool asInt32)
     442                 : {
     443          334105 :     JS_ASSERT(!freeRegs.hasReg(payload));
     444                 : 
     445          334105 :     FrameEntry *fe = rawPush();
     446                 : 
     447          334105 :     if (asInt32) {
     448          333846 :         if (!fe->type.synced())
     449           32604 :             masm.storeTypeTag(ImmType(JSVAL_TYPE_INT32), addressOf(fe));
     450          333846 :         fe->type.setMemory();
     451                 :     } else {
     452             259 :         fe->type.setMemory();
     453                 :     }
     454                 : 
     455          334105 :     fe->data.unsync();
     456          334105 :     fe->data.setRegister(payload);
     457          334105 :     regstate(payload).associate(fe, RematInfo::DATA);
     458          334105 : }
     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            4416 : FrameState::pushUntypedPayload(JSValueType type, RegisterID payload)
     475                 : {
     476            4416 :     JS_ASSERT(!freeRegs.hasReg(payload));
     477                 : 
     478            4416 :     FrameEntry *fe = rawPush();
     479                 : 
     480            4416 :     masm.storeTypeTag(ImmType(type), addressOf(fe));
     481                 : 
     482                 :     /* The forceful type sync will assert otherwise. */
     483                 : #ifdef DEBUG
     484            4416 :     fe->type.unsync();
     485                 : #endif
     486            4416 :     fe->type.setMemory();
     487            4416 :     fe->data.unsync();
     488            4416 :     fe->data.setRegister(payload);
     489            4416 :     regstate(payload).associate(fe, RematInfo::DATA);
     490            4416 : }
     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          659532 : FrameState::tempRegForType(FrameEntry *fe)
     529                 : {
     530          659532 :     if (fe->isCopy())
     531           59325 :         fe = fe->copyOf();
     532                 : 
     533          659532 :     JS_ASSERT(!fe->type.isConstant());
     534                 : 
     535          659532 :     if (fe->type.inRegister())
     536          234392 :         return fe->type.reg();
     537                 : 
     538                 :     /* :XXX: X86 */
     539                 : 
     540          425140 :     RegisterID reg = allocAndLoadReg(fe, false, RematInfo::TYPE).reg();
     541          425140 :     fe->type.setRegister(reg);
     542          425140 :     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          656099 : FrameState::tempRegForData(FrameEntry *fe)
     583                 : {
     584          656099 :     JS_ASSERT(!fe->isConstant());
     585          656099 :     JS_ASSERT(!fe->isType(JSVAL_TYPE_DOUBLE));
     586                 : 
     587          656099 :     if (fe->isCopy())
     588           76710 :         fe = fe->copyOf();
     589                 : 
     590          656099 :     if (fe->data.inRegister())
     591          414293 :         return fe->data.reg();
     592                 : 
     593          241806 :     RegisterID reg = allocAndLoadReg(fe, false, RematInfo::DATA).reg();
     594          241806 :     fe->data.setRegister(reg);
     595          241806 :     return reg;
     596                 : }
     597                 : 
     598                 : inline void
     599          253715 : FrameState::forgetMismatchedObject(FrameEntry *fe)
     600                 : {
     601          253715 :     if (fe->isNotType(JSVAL_TYPE_OBJECT)) {
     602            1360 :         if (fe->isCopied()) {
     603               1 :             syncFe(fe);
     604               1 :             uncopy(fe);
     605               1 :             fe->resetSynced();
     606                 :         } else {
     607            1359 :             syncAndForgetFe(fe);
     608                 :         }
     609            1360 :         fe->clear();
     610                 :     }
     611                 : 
     612          253715 :     if (fe->isConstant()) {
     613           33691 :         RegisterID reg = allocReg();
     614           33691 :         regstate(reg).associate(fe, RematInfo::DATA);
     615                 : 
     616           33691 :         masm.move(JSC::MacroAssembler::ImmPtr(&fe->getValue().toObject()), reg);
     617           33691 :         fe->data.setRegister(reg);
     618                 :     }
     619          253715 : }
     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            1631 :         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            4970 : FrameState::tempRegInMaskForData(FrameEntry *fe, uint32_t mask)
     642                 : {
     643            4970 :     JS_ASSERT(!fe->isConstant());
     644            4970 :     JS_ASSERT_IF(fe->isType(JSVAL_TYPE_DOUBLE), !(mask & ~Registers::AvailFPRegs));
     645            4970 :     JS_ASSERT_IF(!fe->isType(JSVAL_TYPE_DOUBLE), !(mask & ~Registers::AvailRegs));
     646                 : 
     647            4970 :     if (fe->isCopy())
     648             593 :         fe = fe->copyOf();
     649                 : 
     650            4970 :     AnyRegisterID reg;
     651            4970 :     if (fe->data.inRegister() || fe->data.inFPRegister()) {
     652            4237 :         AnyRegisterID old;
     653            4237 :         if (fe->data.inRegister())
     654            4156 :             old = fe->data.reg();
     655                 :         else
     656              81 :             old = fe->data.fpreg();
     657            4237 :         if (Registers::maskReg(old) & mask)
     658            2508 :             return old;
     659                 : 
     660                 :         /* Keep the old register pinned. */
     661            1729 :         regstate(old).forget();
     662            1729 :         reg = allocReg(mask);
     663            1729 :         if (reg.isReg())
     664            1729 :             masm.move(old.reg(), reg.reg());
     665                 :         else
     666               0 :             masm.moveDouble(old.fpreg(), reg.fpreg());
     667            1729 :         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            2462 :     regstate(reg).associate(fe, RematInfo::DATA);
     676            2462 :     if (reg.isReg())
     677            2462 :         fe->data.setRegister(reg.reg());
     678                 :     else
     679               0 :         fe->data.setFPRegister(reg.fpreg());
     680            2462 :     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          110555 : FrameState::shouldAvoidTypeRemat(FrameEntry *fe)
     704                 : {
     705          110555 :     return !fe->isCopy() && fe->type.inMemory();
     706                 : }
     707                 : 
     708                 : inline bool
     709           14303 : FrameState::shouldAvoidDataRemat(FrameEntry *fe)
     710                 : {
     711           14303 :     return !fe->isCopy() && fe->data.inMemory();
     712                 : }
     713                 : 
     714                 : inline void
     715           55484 : FrameState::ensureFeSynced(const FrameEntry *fe, Assembler &masm) const
     716                 : {
     717           55484 :     Address to = addressOf(fe);
     718           55484 :     const FrameEntry *backing = fe;
     719           55484 :     if (fe->isCopy())
     720            2862 :         backing = fe->copyOf();
     721                 : 
     722           55484 :     if (backing->isType(JSVAL_TYPE_DOUBLE)) {
     723           52564 :         if (fe->data.synced()) {
     724                 :             /* Entries representing known doubles can't be partially synced. */
     725            6886 :             JS_ASSERT(fe->type.synced());
     726            6886 :             return;
     727                 :         }
     728           45678 :         if (backing->isConstant()) {
     729           10944 :             masm.storeValue(backing->getValue(), to);
     730           34734 :         } else if (backing->data.inFPRegister()) {
     731           33807 :             masm.storeDouble(backing->data.fpreg(), to);
     732                 :         } else {
     733                 :             /* Use a temporary so the entry can be synced without allocating a register. */
     734             927 :             JS_ASSERT(backing->data.inMemory() && backing != fe);
     735             927 :             masm.loadDouble(addressOf(backing), Registers::FPConversionTemp);
     736             927 :             masm.storeDouble(Registers::FPConversionTemp, to);
     737                 :         }
     738           45678 :         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            2920 :     ensureDataSynced(fe, masm);
     759            2920 :     ensureTypeSynced(fe, masm);
     760                 : }
     761                 : 
     762                 : inline void
     763         7074474 : FrameState::ensureTypeSynced(const FrameEntry *fe, Assembler &masm) const
     764                 : {
     765         7074474 :     if (fe->type.synced())
     766         3184212 :         return;
     767                 : 
     768         3890262 :     Address to = addressOf(fe);
     769         3890262 :     const FrameEntry *backing = fe;
     770         3890262 :     if (fe->isCopy())
     771          325652 :         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         3890262 :     if (backing->isConstant())
     792         1228329 :         masm.storeTypeTag(ImmTag(backing->getKnownTag()), to);
     793         2661933 :     else if (backing->isTypeKnown())
     794          764744 :         masm.storeTypeTag(ImmType(backing->getKnownType()), to); 
     795                 :     else
     796         1897189 :         masm.storeTypeTag(backing->type.reg(), to);
     797                 : }
     798                 : 
     799                 : inline void
     800         7257695 : FrameState::ensureDataSynced(const FrameEntry *fe, Assembler &masm) const
     801                 : {
     802         7257695 :     if (fe->data.synced())
     803         2441355 :         return;
     804                 : 
     805         4816340 :     Address to = addressOf(fe);
     806         4816340 :     const FrameEntry *backing = fe;
     807         4816340 :     if (fe->isCopy())
     808          325880 :         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         4816340 :     if (backing->isConstant())
     821         1228493 :         masm.storePayload(ImmPayload(backing->getPayload()), to);
     822                 :     else
     823         3587847 :         masm.storePayload(backing->data.reg(), to);
     824                 : #endif
     825                 : }
     826                 : 
     827                 : inline void
     828         2881727 : FrameState::syncFe(FrameEntry *fe)
     829                 : {
     830         2881727 :     if (fe->type.synced() && fe->data.synced())
     831         2132505 :         return;
     832                 : 
     833          749222 :     FrameEntry *backing = fe;
     834          749222 :     if (fe->isCopy())
     835           80811 :         backing = fe->copyOf();
     836                 : 
     837          749222 :     if (backing->isType(JSVAL_TYPE_DOUBLE)) {
     838           12142 :         if (!backing->isConstant())
     839            7754 :             tempFPRegForData(backing);
     840           12142 :         ensureFeSynced(fe, masm);
     841                 : 
     842           12142 :         if (!fe->type.synced())
     843           12142 :             fe->type.sync();
     844           12142 :         if (!fe->data.synced())
     845           12142 :             fe->data.sync();
     846           12142 :         return;
     847                 :     }
     848                 : 
     849          737080 :     bool needTypeReg = !fe->type.synced() && backing->type.inMemory();
     850          737080 :     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          737080 :     if (needTypeReg && !needDataReg) {
     855             780 :         syncData(fe);
     856             780 :         syncType(fe);
     857                 :     } else {
     858          736300 :         syncType(fe);
     859          736300 :         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            3929 : FrameState::syncAndForgetFe(FrameEntry *fe, bool markSynced)
     903                 : {
     904            3929 :     if (markSynced) {
     905            2256 :         if (!fe->type.synced())
     906            1848 :             fe->type.sync();
     907            2256 :         if (!fe->data.synced())
     908            1848 :             fe->data.sync();
     909                 :     }
     910                 : 
     911            3929 :     syncFe(fe);
     912            3929 :     forgetAllRegs(fe);
     913            3929 :     fe->type.setMemory();
     914            3929 :     fe->data.setMemory();
     915            3929 : }
     916                 : 
     917                 : inline JSC::MacroAssembler::Address
     918           29343 : FrameState::loadNameAddress(const analyze::ScriptAnalysis::NameAccess &access, RegisterID reg)
     919                 : {
     920           29343 :     JS_ASSERT(access.script && access.nesting);
     921                 : 
     922           29343 :     masm.move(ImmPtr(access.basePointer()), reg);
     923           29343 :     masm.loadPtr(Address(reg), reg);
     924                 : 
     925           29343 :     return Address(reg, access.index * sizeof(Value));
     926                 : }
     927                 : 
     928                 : inline JSC::MacroAssembler::Address
     929           28831 : FrameState::loadNameAddress(const analyze::ScriptAnalysis::NameAccess &access)
     930                 : {
     931           28831 :     RegisterID reg = allocReg();
     932           28831 :     return loadNameAddress(access, reg);
     933                 : }
     934                 : 
     935                 : inline void
     936           10552 : 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           10552 :     if (loop)
     943            8659 :         fe->lastLoop = loop->headOffset();
     944           10552 : }
     945                 : 
     946                 : inline void
     947         1045852 : FrameState::syncType(FrameEntry *fe)
     948                 : {
     949         1045852 :     JS_ASSERT(!fe->isType(JSVAL_TYPE_DOUBLE));
     950                 : 
     951         1045852 :     FrameEntry *backing = fe;
     952         1045852 :     if (fe->isCopy())
     953           80003 :         backing = fe->copyOf();
     954                 : 
     955         1045852 :     if (!fe->type.synced() && backing->type.inMemory())
     956           45340 :         tempRegForType(backing);
     957                 : 
     958         1045852 :     ensureTypeSynced(fe, masm);
     959                 : 
     960         1045852 :     if (!fe->type.synced())
     961          951724 :         fe->type.sync();
     962         1045852 : }
     963                 : 
     964                 : inline void
     965         1196944 : FrameState::syncData(FrameEntry *fe)
     966                 : {
     967         1196944 :     JS_ASSERT(!fe->isType(JSVAL_TYPE_DOUBLE));
     968                 : 
     969         1196944 :     FrameEntry *backing = fe;
     970         1196944 :     if (fe->isCopy())
     971           80003 :         backing = fe->copyOf();
     972                 : 
     973         1196944 :     if (!fe->data.synced() && backing->data.inMemory())
     974           61110 :         tempRegForData(backing);
     975                 : 
     976         1196944 :     ensureDataSynced(fe, masm);
     977                 : 
     978         1196944 :     if (!fe->data.synced())
     979          964662 :         fe->data.sync();
     980         1196944 : }
     981                 : 
     982                 : inline void
     983           40501 : 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           40501 :     if (!fe->data.synced())
     990             911 :         fe->data.sync();
     991           40501 :     if (!fe->type.synced())
     992             688 :         fe->type.sync();
     993           40501 : }
     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          101556 : FrameState::learnType(FrameEntry *fe, JSValueType type, bool unsync)
    1023                 : {
    1024          101556 :     JS_ASSERT(!fe->isType(JSVAL_TYPE_DOUBLE));
    1025          101556 :     JS_ASSERT(type != JSVAL_TYPE_UNKNOWN);
    1026                 : 
    1027          101556 :     if (fe->isCopy())
    1028               0 :         fe = fe->copyOf();
    1029                 : 
    1030          101556 :     if (type == JSVAL_TYPE_DOUBLE)
    1031             810 :         JS_ASSERT(!fe->data.inRegister());
    1032                 :     else
    1033          100746 :         JS_ASSERT(!fe->data.inFPRegister());
    1034                 : 
    1035          101556 :     if (fe->type.inRegister())
    1036            2285 :         forgetReg(fe->type.reg());
    1037          101556 :     fe->setType(type);
    1038          101556 :     if (unsync)
    1039            1871 :         fe->type.unsync();
    1040          101556 : }
    1041                 : 
    1042                 : inline void
    1043            5249 : FrameState::learnType(FrameEntry *fe, JSValueType type, RegisterID data)
    1044                 : {
    1045            5249 :     JS_ASSERT(!fe->isCopied());
    1046            5249 :     JS_ASSERT(type != JSVAL_TYPE_UNKNOWN && type != JSVAL_TYPE_DOUBLE);
    1047                 : 
    1048            5249 :     forgetAllRegs(fe);
    1049            5249 :     fe->clear();
    1050                 : 
    1051            5249 :     fe->type.setConstant();
    1052            5249 :     fe->knownType = type;
    1053                 : 
    1054            5249 :     fe->data.setRegister(data);
    1055            5249 :     regstate(data).associate(fe, RematInfo::DATA);
    1056                 : 
    1057            5249 :     fe->data.unsync();
    1058            5249 :     fe->type.unsync();
    1059            5249 : }
    1060                 : 
    1061                 : inline int32_t
    1062        14031378 : 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        14031378 :     JS_ASSERT(fe >= a->callee_ && fe <= a->sp);
    1074                 : 
    1075        14031378 :     if (fe >= a->locals)
    1076        13475080 :         return StackFrame::offsetOfFixed(uint32_t(fe - a->locals));
    1077          556298 :     if (fe >= a->args)
    1078          376569 :         return StackFrame::offsetOfFormalArg(a->script->function(), uint32_t(fe - a->args));
    1079          179729 :     if (fe == a->this_)
    1080          158419 :         return StackFrame::offsetOfThis(a->script->function());
    1081           21310 :     if (fe == a->callee_)
    1082           21310 :         return StackFrame::offsetOfCallee(a->script->function());
    1083               0 :     JS_NOT_REACHED("Bad fe");
    1084                 :     return 0;
    1085                 : }
    1086                 : 
    1087                 : inline JSC::MacroAssembler::Address
    1088        14060167 : FrameState::addressOf(const FrameEntry *fe) const
    1089                 : {
    1090        14060167 :     if (isTemporary(fe)) {
    1091                 :         /*
    1092                 :          * Temporary addresses are common to the outermost loop, and are shared
    1093                 :          * by all active frames.
    1094                 :          */
    1095           28789 :         return Address(JSFrameReg, (loop->temporariesStart + fe - temporaries) * sizeof(Value));
    1096                 :     }
    1097                 : 
    1098        14031378 :     ActiveFrame *na = a;
    1099        28248279 :     while (fe < na->callee_)
    1100          185523 :         na = na->parent;
    1101                 : 
    1102        14031378 :     int32_t offset = frameOffset(fe, na);
    1103        14031378 :     return Address(JSFrameReg, offset + (na->depth * sizeof(Value)));
    1104                 : }
    1105                 : 
    1106                 : inline uint32_t
    1107          535675 : FrameState::frameSlot(ActiveFrame *a, const FrameEntry *fe) const
    1108                 : {
    1109          535675 :     if (isTemporary(fe))
    1110            2525 :         return fe - entries;
    1111                 : 
    1112          533150 :     JS_ASSERT(fe >= a->callee_ && fe < a->sp);
    1113                 : 
    1114          533150 :     if (fe >= a->locals)
    1115          499509 :         return analyze::LocalSlot(a->script, fe - a->locals);
    1116           33641 :     if (fe >= a->args)
    1117           28650 :         return analyze::ArgSlot(fe - a->args);
    1118            4991 :     if (fe == a->this_)
    1119            4991 :         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            4188 : FrameState::addressForDataRemat(const FrameEntry *fe) const
    1136                 : {
    1137            4188 :     if (fe->isCopy() && !fe->data.synced())
    1138            1349 :         fe = fe->copyOf();
    1139            4188 :     JS_ASSERT(fe->data.synced());
    1140            4188 :     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           26918 : FrameState::testInt32(Assembler::Condition cond, FrameEntry *fe)
    1163                 : {
    1164           26918 :     JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
    1165           26918 :     if (shouldAvoidTypeRemat(fe))
    1166            4424 :         return masm.testInt32(cond, addressOf(fe));
    1167           22494 :     return masm.testInt32(cond, tempRegForType(fe));
    1168                 : }
    1169                 : 
    1170                 : inline JSC::MacroAssembler::Jump
    1171            2913 : FrameState::testPrimitive(Assembler::Condition cond, FrameEntry *fe)
    1172                 : {
    1173            2913 :     JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
    1174            2913 :     if (shouldAvoidTypeRemat(fe))
    1175             261 :         return masm.testPrimitive(cond, addressOf(fe));
    1176            2652 :     return masm.testPrimitive(cond, tempRegForType(fe));
    1177                 : }
    1178                 : 
    1179                 : inline JSC::MacroAssembler::Jump
    1180           40127 : FrameState::testObject(Assembler::Condition cond, FrameEntry *fe)
    1181                 : {
    1182           40127 :     JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
    1183           40127 :     if (shouldAvoidTypeRemat(fe))
    1184            4251 :         return masm.testObject(cond, addressOf(fe));
    1185           35876 :     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            3430 : FrameState::testDouble(Assembler::Condition cond, FrameEntry *fe)
    1198                 : {
    1199            3430 :     JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
    1200            3430 :     if (shouldAvoidTypeRemat(fe))
    1201               0 :         return masm.testDouble(cond, addressOf(fe));
    1202            3430 :     return masm.testDouble(cond, tempRegForType(fe));
    1203                 : }
    1204                 : 
    1205                 : inline JSC::MacroAssembler::Jump
    1206           24920 : FrameState::testBoolean(Assembler::Condition cond, FrameEntry *fe)
    1207                 : {
    1208           24920 :     JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
    1209           24920 :     if (shouldAvoidTypeRemat(fe))
    1210           22860 :         return masm.testBoolean(cond, addressOf(fe));
    1211            2060 :     return masm.testBoolean(cond, tempRegForType(fe));
    1212                 : }
    1213                 : 
    1214                 : inline JSC::MacroAssembler::Jump
    1215             158 : FrameState::testString(Assembler::Condition cond, FrameEntry *fe)
    1216                 : {
    1217             158 :     JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
    1218             158 :     if (shouldAvoidTypeRemat(fe))
    1219               2 :         return masm.testString(cond, addressOf(fe));
    1220             156 :     return masm.testString(cond, tempRegForType(fe));
    1221                 : }
    1222                 : 
    1223                 : inline FrameEntry *
    1224         2919048 : FrameState::getOrTrack(uint32_t index)
    1225                 : {
    1226         2919048 :     FrameEntry *fe = &entries[index];
    1227         2919048 :     if (!fe->isTracked()) {
    1228          444246 :         addToTracker(fe);
    1229          444246 :         fe->resetSynced();
    1230                 :     }
    1231         2919048 :     return fe;
    1232                 : }
    1233                 : 
    1234                 : inline FrameEntry *
    1235         1823022 : FrameState::getStack(uint32_t slot)
    1236                 : {
    1237         1823022 :     if (slot >= uint32_t(a->sp - a->spBase))
    1238            3455 :         return NULL;
    1239         1819567 :     return getOrTrack(uint32_t(a->spBase + slot - entries));
    1240                 : }
    1241                 : 
    1242                 : inline FrameEntry *
    1243          472232 : FrameState::getLocal(uint32_t slot)
    1244                 : {
    1245          472232 :     JS_ASSERT(slot < a->script->nslots);
    1246          472232 :     return getOrTrack(uint32_t(a->locals + slot - entries));
    1247                 : }
    1248                 : 
    1249                 : inline FrameEntry *
    1250           99695 : FrameState::getArg(uint32_t slot)
    1251                 : {
    1252           99695 :     JS_ASSERT(slot < a->script->function()->nargs);
    1253           99695 :     return getOrTrack(uint32_t(a->args + slot - entries));
    1254                 : }
    1255                 : 
    1256                 : inline FrameEntry *
    1257           68395 : FrameState::getThis()
    1258                 : {
    1259           68395 :     return getOrTrack(uint32_t(a->this_ - entries));
    1260                 : }
    1261                 : 
    1262                 : inline FrameEntry *
    1263          222659 : FrameState::getSlotEntry(uint32_t slot)
    1264                 : {
    1265          222659 :     JS_ASSERT(slot < analyze::TotalSlots(a->script));
    1266          222659 :     return getOrTrack(uint32_t(a->callee_ + slot - entries));
    1267                 : }
    1268                 : 
    1269                 : inline FrameEntry *
    1270             957 : FrameState::getCallee()
    1271                 : {
    1272                 :     // Callee can only be used in function code, and it's always an object.
    1273             957 :     JS_ASSERT(a->script->function());
    1274             957 :     FrameEntry *fe = a->callee_;
    1275             957 :     if (!fe->isTracked()) {
    1276             957 :         addToTracker(fe);
    1277             957 :         fe->resetSynced();
    1278             957 :         fe->setType(JSVAL_TYPE_OBJECT);
    1279                 :     }
    1280             957 :     return fe;
    1281                 : }
    1282                 : 
    1283                 : inline void
    1284          188209 : FrameState::unpinKilledReg(AnyRegisterID reg)
    1285                 : {
    1286          188209 :     regstate(reg).unpinUnsafe();
    1287          188209 :     freeRegs.putReg(reg);
    1288          188209 : }
    1289                 : 
    1290                 : inline void
    1291         4895455 : FrameState::forgetAllRegs(FrameEntry *fe)
    1292                 : {
    1293         4895455 :     if (fe->isCopy())
    1294          645393 :         return;
    1295         4250062 :     if (fe->type.inRegister())
    1296          921527 :         forgetReg(fe->type.reg());
    1297         4250062 :     if (fe->data.inRegister())
    1298         1221348 :         forgetReg(fe->data.reg());
    1299         4250062 :     if (fe->data.inFPRegister())
    1300           12107 :         forgetReg(fe->data.fpreg());
    1301                 : }
    1302                 : 
    1303                 : inline void
    1304           66723 : FrameState::swapInTracker(FrameEntry *lhs, FrameEntry *rhs)
    1305                 : {
    1306           66723 :     uint32_t li = lhs->trackerIndex();
    1307           66723 :     uint32_t ri = rhs->trackerIndex();
    1308           66723 :     JS_ASSERT(tracker[li] == lhs);
    1309           66723 :     JS_ASSERT(tracker[ri] == rhs);
    1310           66723 :     tracker.entries[ri] = lhs;
    1311           66723 :     tracker.entries[li] = rhs;
    1312           66723 :     lhs->index_ = ri;
    1313           66723 :     rhs->index_ = li;
    1314           66723 : }
    1315                 : 
    1316                 : inline void
    1317           89964 : FrameState::dup()
    1318                 : {
    1319           89964 :     dupAt(-1);
    1320           89964 : }
    1321                 : 
    1322                 : inline void
    1323           84041 : FrameState::dup2()
    1324                 : {
    1325           84041 :     FrameEntry *lhs = peek(-2);
    1326           84041 :     FrameEntry *rhs = peek(-1);
    1327           84041 :     pushCopyOf(lhs);
    1328           84041 :     pushCopyOf(rhs);
    1329           84041 : }
    1330                 : 
    1331                 : inline void
    1332          118555 : FrameState::dupAt(int32_t n)
    1333                 : {
    1334          118555 :     JS_ASSERT(n < 0);
    1335          118555 :     FrameEntry *fe = peek(n);
    1336          118555 :     pushCopyOf(fe);
    1337          118555 : }
    1338                 : 
    1339                 : inline void
    1340             235 : FrameState::syncAt(int32_t n)
    1341                 : {
    1342             235 :     JS_ASSERT(n < 0);
    1343             235 :     FrameEntry *fe = peek(n);
    1344             235 :     syncFe(fe);
    1345             235 : }
    1346                 : 
    1347                 : inline void
    1348          273627 : FrameState::pushLocal(uint32_t n)
    1349                 : {
    1350          273627 :     FrameEntry *fe = getLocal(n);
    1351          273627 :     if (!a->analysis->slotEscapes(analyze::LocalSlot(a->script, n))) {
    1352          113653 :         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          159974 :         if (fe->isTracked() && n < a->script->nfixed)
    1361          123515 :             JS_ASSERT(fe->data.inMemory());
    1362                 : #endif
    1363          159974 :         if (n >= a->script->nfixed)
    1364           36459 :             syncFe(fe);
    1365          159974 :         JSValueType type = fe->isTypeKnown() ? fe->getKnownType() : JSVAL_TYPE_UNKNOWN;
    1366          159974 :         push(addressOf(fe), type);
    1367                 :     }
    1368          273627 : }
    1369                 : 
    1370                 : inline void
    1371           96924 : FrameState::pushArg(uint32_t n)
    1372                 : {
    1373           96924 :     FrameEntry *fe = getArg(n);
    1374           96924 :     if (!a->analysis->slotEscapes(analyze::ArgSlot(n))) {
    1375           50605 :         pushCopyOf(fe);
    1376                 :     } else {
    1377                 : #ifdef DEBUG
    1378           46319 :         if (fe->isTracked())
    1379           46319 :             JS_ASSERT(fe->data.inMemory());
    1380                 : #endif
    1381           46319 :         JSValueType type = fe->isTypeKnown() ? fe->getKnownType() : JSVAL_TYPE_UNKNOWN;
    1382           46319 :         push(addressOf(fe), type);
    1383                 :     }
    1384           96924 : }
    1385                 : 
    1386                 : inline void
    1387             957 : FrameState::pushCallee()
    1388                 : {
    1389             957 :     FrameEntry *fe = getCallee();
    1390             957 :     pushCopyOf(fe);
    1391             957 : }
    1392                 : 
    1393                 : inline void
    1394           58906 : FrameState::pushThis()
    1395                 : {
    1396           58906 :     FrameEntry *fe = getThis();
    1397           58906 :     pushCopyOf(fe);
    1398           58906 : }
    1399                 : 
    1400                 : void
    1401            7759 : 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            7759 :     FrameEntry *fe = getThis();
    1407            7759 :     if (fe->isCopy())
    1408              41 :         fe = fe->copyOf();
    1409            7759 :     learnType(fe, JSVAL_TYPE_OBJECT, unsync);
    1410            7759 : }
    1411                 : 
    1412                 : void
    1413             161 : FrameState::setThis(RegisterID reg)
    1414                 : {
    1415             161 :     FrameEntry *fe = getThis();
    1416             161 :     JS_ASSERT(!fe->isCopy());
    1417             161 :     learnType(fe, JSVAL_TYPE_OBJECT, reg);
    1418             161 : }
    1419                 : 
    1420                 : void
    1421            1077 : FrameState::syncThis()
    1422                 : {
    1423            1077 :     FrameEntry *fe = getThis();
    1424            1077 :     syncFe(fe);
    1425            1077 : }
    1426                 : 
    1427                 : inline bool
    1428          376716 : FrameState::isConstructorThis(const FrameEntry *fe) const
    1429                 : {
    1430          376716 :     return isThis(fe) && cc.constructing();
    1431                 : }
    1432                 : 
    1433                 : inline void
    1434           23335 : FrameState::leaveBlock(uint32_t n)
    1435                 : {
    1436           23335 :     popn(n);
    1437           23335 : }
    1438                 : 
    1439                 : inline void
    1440           17698 : FrameState::enterBlock(uint32_t n)
    1441                 : {
    1442                 :     /* expect that tracker has 0 entries, for now. */
    1443           17698 :     JS_ASSERT(!tracker.nentries);
    1444           17698 :     JS_ASSERT(uint32_t(a->sp + n - a->locals) <= a->script->nslots);
    1445                 : 
    1446           17698 :     a->sp += n;
    1447           17698 : }
    1448                 : 
    1449                 : inline void
    1450                 : FrameState::eviscerate(FrameEntry *fe)
    1451                 : {
    1452                 :     forgetAllRegs(fe);
    1453                 :     fe->resetUnsynced();
    1454                 : }
    1455                 : 
    1456                 : inline StateRemat
    1457            5703 : FrameState::dataRematInfo(const FrameEntry *fe) const
    1458                 : {
    1459            5703 :     if (fe->isCopy())
    1460            2272 :         fe = fe->copyOf();
    1461                 : 
    1462            5703 :     if (fe->data.inRegister())
    1463            4378 :         return StateRemat::FromRegister(fe->data.reg());
    1464                 : 
    1465            1325 :     JS_ASSERT(fe->data.synced());
    1466            1325 :     return StateRemat::FromAddress(addressOf(fe));
    1467                 : }
    1468                 : 
    1469                 : inline void
    1470            7878 : FrameState::giveOwnRegs(FrameEntry *fe)
    1471                 : {
    1472            7878 :     JS_ASSERT(!fe->isConstant());
    1473            7878 :     JS_ASSERT(fe == peek(-1));
    1474                 : 
    1475            7878 :     if (!fe->isCopy())
    1476            7750 :         return;
    1477                 : 
    1478             128 :     RegisterID data = copyDataIntoReg(fe);
    1479             128 :     if (fe->isTypeKnown()) {
    1480               0 :         JSValueType type = fe->getKnownType();
    1481               0 :         pop();
    1482               0 :         pushTypedPayload(type, data);
    1483                 :     } else {
    1484             128 :         RegisterID type = copyTypeIntoReg(fe);
    1485             128 :         pop();
    1486             128 :         pushRegs(type, data, JSVAL_TYPE_UNKNOWN);
    1487                 :     }
    1488                 : }
    1489                 : 
    1490                 : inline void
    1491          988395 : FrameState::loadDouble(RegisterID t, RegisterID d, FrameEntry *fe, FPRegisterID fpreg,
    1492                 :                        Assembler &masm) const
    1493                 : {
    1494                 : #ifdef JS_CPU_X86
    1495          988395 :     masm.fastLoadDouble(d, t, fpreg);
    1496                 : #else
    1497                 :     loadDouble(fe, fpreg, masm);
    1498                 : #endif
    1499          988395 : }
    1500                 : 
    1501                 : inline bool
    1502           12212 : FrameState::tryFastDoubleLoad(FrameEntry *fe, FPRegisterID fpReg, Assembler &masm) const
    1503                 : {
    1504                 : #ifdef JS_CPU_X86
    1505           12212 :     if (!fe->isCopy() && fe->type.inRegister() && fe->data.inRegister()) {
    1506            7781 :         masm.fastLoadDouble(fe->data.reg(), fe->type.reg(), fpReg);
    1507            7781 :         return true;
    1508                 :     }
    1509                 : #endif
    1510            4431 :     return false;
    1511                 : }
    1512                 : 
    1513                 : inline void
    1514           10701 : FrameState::loadDouble(FrameEntry *fe, FPRegisterID fpReg, Assembler &masm) const
    1515                 : {
    1516           10701 :     if (fe->isCopy()) {
    1517            1511 :         FrameEntry *backing = fe->copyOf();
    1518            1511 :         if (tryFastDoubleLoad(fe, fpReg, masm)) 
    1519               0 :             return;
    1520            1511 :         fe = backing;
    1521                 :     }
    1522                 : 
    1523           10701 :     if (tryFastDoubleLoad(fe, fpReg, masm))
    1524            7781 :         return;
    1525                 : 
    1526            2920 :     ensureFeSynced(fe, masm);
    1527            2920 :     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           93225 :     PinRegAcrossSyncAndKill(FrameState &frame, RegisterID reg)
    1537           93225 :       : frame(frame), maybeReg(reg)
    1538                 :     {
    1539           93225 :         frame.pinReg(reg);
    1540           93225 :     }
    1541           93333 :     PinRegAcrossSyncAndKill(FrameState &frame, MaybeRegisterID maybeReg)
    1542           93333 :       : frame(frame), maybeReg(maybeReg)
    1543                 :     {
    1544           93333 :         if (maybeReg.isSet())
    1545           55144 :             frame.pinReg(maybeReg.reg());
    1546           93333 :     }
    1547          186558 :     ~PinRegAcrossSyncAndKill() {
    1548          186558 :         if (maybeReg.isSet())
    1549          148369 :             frame.unpinKilledReg(maybeReg.reg());
    1550          186558 :     }
    1551                 : };
    1552                 : 
    1553                 : } /* namespace mjit */
    1554                 : } /* namespace js */
    1555                 : 
    1556                 : #endif /* include */
    1557                 : 

Generated by: LCOV version 1.7